From 3a509bb11acded0dfebbfcc740d85e0774b0769a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 10 Sep 2010 16:49:47 -0300 Subject: [media] Re-write the s921 frontend On our tests with Leadership ISDBT, the s921 frontend were not work. As its design contained some weird things, it ended to be easier to just re-write it, getting another frontend as an example (cx24123). As the old s921 driver weren't used, there's no regression. Some info from the old frontend were used as a way to double check the behavior that were noticed on the USB dumps retrieved from Leadership driver. Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 96b2701..00dbf1e 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -497,7 +497,7 @@ comment "ISDB-T (terrestrial) frontends" depends on DVB_CORE config DVB_S921 - tristate "Sharp S921 tuner" + tristate "Sharp S921 frontend" depends on DVB_CORE && I2C default m if DVB_FE_CUSTOMISE help diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 9a31985..48b9fd3 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -5,7 +5,6 @@ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ EXTRA_CFLAGS += -Idrivers/media/common/tuners/ -s921-objs := s921_module.o s921_core.o stb0899-objs = stb0899_drv.o stb0899_algo.o stv0900-objs = stv0900_core.o stv0900_sw.o au8522-objs = au8522_dig.o au8522_decoder.o diff --git a/drivers/media/dvb/frontends/s921.c b/drivers/media/dvb/frontends/s921.c new file mode 100644 index 0000000..ca0103d --- /dev/null +++ b/drivers/media/dvb/frontends/s921.c @@ -0,0 +1,548 @@ +/* + * Sharp VA3A5JZ921 One Seg Broadcast Module driver + * This device is labeled as just S. 921 at the top of the frontend can + * + * Copyright (C) 2009-2010 Mauro Carvalho Chehab + * Copyright (C) 2009-2010 Douglas Landgraf + * + * Developed for Leadership SBTVD 1seg device sold in Brazil + * + * Frontend module based on cx24123 driver, getting some info from + * the old s921 driver. + * + * FIXME: Need to port to DVB v5.2 API + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include + +#include "dvb_frontend.h" +#include "s921.h" + +static int debug = 1; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); + +#define rc(args...) do { \ + printk(KERN_ERR "s921: " args); \ +} while (0) + +#define dprintk(args...) \ + do { \ + if (debug) { \ + printk(KERN_DEBUG "s921: %s: ", __func__); \ + printk(args); \ + } \ + } while (0) + +struct s921_state { + struct i2c_adapter *i2c; + const struct s921_config *config; + + struct dvb_frontend frontend; + + /* The Demod can't easily provide these, we cache them */ + u32 currentfreq; +}; + +/* + * Various tuner defaults need to be established for a given frequency kHz. + * fixme: The bounds on the bands do not match the doc in real life. + * fixme: Some of them have been moved, other might need adjustment. + */ +static struct s921_bandselect_val { + u32 freq_low; + u8 band_reg; +} s921_bandselect[] = { + { 0, 0x7b }, + { 485140000, 0x5b }, + { 515140000, 0x3b }, + { 545140000, 0x1b }, + { 599140000, 0xfb }, + { 623140000, 0xdb }, + { 659140000, 0xbb }, + { 713140000, 0x9b }, +}; + +struct regdata { + u8 reg; + u8 data; +}; + +static struct regdata s921_init[] = { + { 0x01, 0x80 }, /* Probably, a reset sequence */ + { 0x01, 0x40 }, + { 0x01, 0x80 }, + { 0x01, 0x40 }, + + { 0x02, 0x00 }, + { 0x03, 0x40 }, + { 0x04, 0x01 }, + { 0x05, 0x00 }, + { 0x06, 0x00 }, + { 0x07, 0x00 }, + { 0x08, 0x00 }, + { 0x09, 0x00 }, + { 0x0a, 0x00 }, + { 0x0b, 0x5a }, + { 0x0c, 0x00 }, + { 0x0d, 0x00 }, + { 0x0f, 0x00 }, + { 0x13, 0x1b }, + { 0x14, 0x80 }, + { 0x15, 0x40 }, + { 0x17, 0x70 }, + { 0x18, 0x01 }, + { 0x19, 0x12 }, + { 0x1a, 0x01 }, + { 0x1b, 0x12 }, + { 0x1c, 0xa0 }, + { 0x1d, 0x00 }, + { 0x1e, 0x0a }, + { 0x1f, 0x08 }, + { 0x20, 0x40 }, + { 0x21, 0xff }, + { 0x22, 0x4c }, + { 0x23, 0x4e }, + { 0x24, 0x4c }, + { 0x25, 0x00 }, + { 0x26, 0x00 }, + { 0x27, 0xf4 }, + { 0x28, 0x60 }, + { 0x29, 0x88 }, + { 0x2a, 0x40 }, + { 0x2b, 0x40 }, + { 0x2c, 0xff }, + { 0x2d, 0x00 }, + { 0x2e, 0xff }, + { 0x2f, 0x00 }, + { 0x30, 0x20 }, + { 0x31, 0x06 }, + { 0x32, 0x0c }, + { 0x34, 0x0f }, + { 0x37, 0xfe }, + { 0x38, 0x00 }, + { 0x39, 0x63 }, + { 0x3a, 0x10 }, + { 0x3b, 0x10 }, + { 0x47, 0x00 }, + { 0x49, 0xe5 }, + { 0x4b, 0x00 }, + { 0x50, 0xc0 }, + { 0x52, 0x20 }, + { 0x54, 0x5a }, + { 0x55, 0x5b }, + { 0x56, 0x40 }, + { 0x57, 0x70 }, + { 0x5c, 0x50 }, + { 0x5d, 0x00 }, + { 0x62, 0x17 }, + { 0x63, 0x2f }, + { 0x64, 0x6f }, + { 0x68, 0x00 }, + { 0x69, 0x89 }, + { 0x6a, 0x00 }, + { 0x6b, 0x00 }, + { 0x6c, 0x00 }, + { 0x6d, 0x00 }, + { 0x6e, 0x00 }, + { 0x70, 0x10 }, + { 0x71, 0x00 }, + { 0x75, 0x00 }, + { 0x76, 0x30 }, + { 0x77, 0x01 }, + { 0xaf, 0x00 }, + { 0xb0, 0xa0 }, + { 0xb2, 0x3d }, + { 0xb3, 0x25 }, + { 0xb4, 0x8b }, + { 0xb5, 0x4b }, + { 0xb6, 0x3f }, + { 0xb7, 0xff }, + { 0xb8, 0xff }, + { 0xb9, 0xfc }, + { 0xba, 0x00 }, + { 0xbb, 0x00 }, + { 0xbc, 0x00 }, + { 0xd0, 0x30 }, + { 0xe4, 0x84 }, + { 0xf0, 0x48 }, + { 0xf1, 0x19 }, + { 0xf2, 0x5a }, + { 0xf3, 0x8e }, + { 0xf4, 0x2d }, + { 0xf5, 0x07 }, + { 0xf6, 0x5a }, + { 0xf7, 0xba }, + { 0xf8, 0xd7 }, +}; + +static struct regdata s921_prefreq[] = { + { 0x47, 0x60 }, + { 0x68, 0x00 }, + { 0x69, 0x89 }, + { 0xf0, 0x48 }, + { 0xf1, 0x19 }, +}; + +static struct regdata s921_postfreq[] = { + { 0xf5, 0xae }, + { 0xf6, 0xb7 }, + { 0xf7, 0xba }, + { 0xf8, 0xd7 }, + { 0x68, 0x0a }, + { 0x69, 0x09 }, +}; + +static int s921_i2c_writereg(struct s921_state *state, + u8 i2c_addr, int reg, int data) +{ + u8 buf[] = { reg, data }; + struct i2c_msg msg = { + .addr = i2c_addr, .flags = 0, .buf = buf, .len = 2 + }; + int rc; + + rc = i2c_transfer(state->i2c, &msg, 1); + if (rc != 1) { + printk("%s: writereg rcor(rc == %i, reg == 0x%02x," + " data == 0x%02x)\n", __func__, rc, reg, data); + return rc; + } + + return 0; +} + +static int s921_i2c_writeregdata(struct s921_state *state, u8 i2c_addr, + struct regdata *rd, int size) +{ + int i, rc; + + for (i = 0; i < size; i++) { + rc = s921_i2c_writereg(state, i2c_addr, rd[i].reg, rd[i].data); + if (rc < 0) + return rc; + } + return 0; +} + +static int s921_i2c_readreg(struct s921_state *state, u8 i2c_addr, u8 reg) +{ + u8 val; + int rc; + struct i2c_msg msg[] = { + { .addr = i2c_addr, .flags = 0, .buf = ®, .len = 1 }, + { .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 } + }; + + rc = i2c_transfer(state->i2c, msg, 2); + + if (rc != 2) { + rc("%s: reg=0x%x (rcor=%d)\n", __func__, reg, rc); + return rc; + } + + return val; +} + +#define s921_readreg(state, reg) \ + s921_i2c_readreg(state, state->config->demod_address, reg) +#define s921_writereg(state, reg, val) \ + s921_i2c_writereg(state, state->config->demod_address, reg, val) +#define s921_writeregdata(state, regdata) \ + s921_i2c_writeregdata(state, state->config->demod_address, \ + regdata, ARRAY_SIZE(regdata)) + +static int s921_pll_tune(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct s921_state *state = fe->demodulator_priv; + int band, rc, i; + unsigned long f_offset; + u8 f_switch; + u64 offset; + + dprintk("frequency=%i\n", p->frequency); + + for (band = 0; band < ARRAY_SIZE(s921_bandselect); band++) + if (p->frequency < s921_bandselect[band].freq_low) + break; + band--; + + if (band < 0) { + rc("%s: frequency out of range\n", __func__); + return -EINVAL; + } + + f_switch = s921_bandselect[band].band_reg; + + offset = ((u64)p->frequency) * 258; + do_div(offset, 6000000); + f_offset = ((unsigned long)offset) + 2321; + + rc = s921_writeregdata(state, s921_prefreq); + if (rc < 0) + return rc; + + rc = s921_writereg(state, 0xf2, (f_offset >> 8) & 0xff); + if (rc < 0) + return rc; + + rc = s921_writereg(state, 0xf3, f_offset & 0xff); + if (rc < 0) + return rc; + + rc = s921_writereg(state, 0xf4, f_switch); + if (rc < 0) + return rc; + + rc = s921_writeregdata(state, s921_postfreq); + if (rc < 0) + return rc; + + for (i = 0 ; i < 6; i++) { + rc = s921_readreg(state, 0x80); + dprintk("status 0x80: %02x\n", rc); + } + rc = s921_writereg(state, 0x01, 0x40); + if (rc < 0) + return rc; + + rc = s921_readreg(state, 0x01); + dprintk("status 0x01: %02x\n", rc); + + rc = s921_readreg(state, 0x80); + dprintk("status 0x80: %02x\n", rc); + + rc = s921_readreg(state, 0x80); + dprintk("status 0x80: %02x\n", rc); + + rc = s921_readreg(state, 0x32); + dprintk("status 0x32: %02x\n", rc); + + dprintk("pll tune band=%d, pll=%d\n", f_switch, (int)f_offset); + + return 0; +} + +static int s921_initfe(struct dvb_frontend *fe) +{ + struct s921_state *state = fe->demodulator_priv; + int rc; + + dprintk("\n"); + + rc = s921_writeregdata(state, s921_init); + if (rc < 0) + return rc; + + return 0; +} + +static int s921_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct s921_state *state = fe->demodulator_priv; + int regstatus, rc; + + *status = 0; + + rc = s921_readreg(state, 0x81); + if (rc < 0) + return rc; + + regstatus = rc << 8; + + rc = s921_readreg(state, 0x82); + if (rc < 0) + return rc; + + regstatus |= rc; + + dprintk("status = %04x\n", regstatus); + + /* Full Sync - We don't know what each bit means on regs 0x81/0x82 */ + if ((regstatus & 0xff) == 0x40) { + *status = FE_HAS_SIGNAL | + FE_HAS_CARRIER | + FE_HAS_VITERBI | + FE_HAS_SYNC | + FE_HAS_LOCK; + } else if (regstatus & 0x40) { + /* This is close to Full Sync, but not enough to get useful info */ + *status = FE_HAS_SIGNAL | + FE_HAS_CARRIER | + FE_HAS_VITERBI | + FE_HAS_SYNC; + } + + return 0; +} + +static int s921_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + fe_status_t status; + struct s921_state *state = fe->demodulator_priv; + int rc; + + /* FIXME: Use the proper register for it... 0x80? */ + rc = s921_read_status(fe, &status); + if (rc < 0) + return rc; + + *strength = (status & FE_HAS_LOCK) ? 0xffff : 0; + + dprintk("strength = 0x%04x\n", *strength); + + rc = s921_readreg(state, 0x01); + dprintk("status 0x01: %02x\n", rc); + + rc = s921_readreg(state, 0x80); + dprintk("status 0x80: %02x\n", rc); + + rc = s921_readreg(state, 0x32); + dprintk("status 0x32: %02x\n", rc); + + return 0; +} + +static int s921_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct s921_state *state = fe->demodulator_priv; + int rc; + + dprintk("\n"); + + /* FIXME: We don't know how to use non-auto mode */ + + rc = s921_pll_tune(fe, p); + if (rc < 0) + return rc; + + state->currentfreq = p->frequency; + + return 0; +} + +static int s921_get_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct s921_state *state = fe->demodulator_priv; + + /* FIXME: Probably it is possible to get it from regs f1 and f2 */ + p->frequency = state->currentfreq; + + return 0; +} + +static int s921_tune(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params, + unsigned int mode_flags, + unsigned int *delay, + fe_status_t *status) +{ + int rc = 0; + + dprintk("\n"); + + if (params != NULL) + rc = s921_set_frontend(fe, params); + + if (!(mode_flags & FE_TUNE_MODE_ONESHOT)) + s921_read_status(fe, status); + + return rc; +} + +static int s921_get_algo(struct dvb_frontend *fe) +{ + return 1; /* FE_ALGO_HW */ +} + +static void s921_release(struct dvb_frontend *fe) +{ + struct s921_state *state = fe->demodulator_priv; + + dprintk("\n"); + kfree(state); +} + +static struct dvb_frontend_ops s921_ops; + +struct dvb_frontend *s921_attach(const struct s921_config *config, + struct i2c_adapter *i2c) +{ + /* allocate memory for the internal state */ + struct s921_state *state = + kzalloc(sizeof(struct s921_state), GFP_KERNEL); + + dprintk("\n"); + if (state == NULL) { + rc("Unable to kzalloc\n"); + goto rcor; + } + + /* setup the state */ + state->config = config; + state->i2c = i2c; + + /* create dvb_frontend */ + memcpy(&state->frontend.ops, &s921_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + + return &state->frontend; + +rcor: + kfree(state); + + return NULL; +} +EXPORT_SYMBOL(s921_attach); + +static struct dvb_frontend_ops s921_ops = { + /* Use dib8000 values per default */ + .info = { + .name = "Sharp S921", + .type = FE_OFDM, + .frequency_min = 470000000, + /* + * Max should be 770MHz instead, according with Sharp docs, + * but Leadership doc says it works up to 806 MHz. This is + * required to get channel 69, used in Brazil + */ + .frequency_max = 806000000, + .frequency_tolerance = 0, + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | + FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | + FE_CAN_HIERARCHY_AUTO, + }, + + .release = s921_release, + + .init = s921_initfe, + .set_frontend = s921_set_frontend, + .get_frontend = s921_get_frontend, + .read_status = s921_read_status, + .read_signal_strength = s921_read_signal_strength, + .tune = s921_tune, + .get_frontend_algo = s921_get_algo, +}; + +MODULE_DESCRIPTION("DVB Frontend module for Sharp S921 hardware"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); +MODULE_AUTHOR("Douglas Landgraf "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/s921.h b/drivers/media/dvb/frontends/s921.h new file mode 100644 index 0000000..f220d82 --- /dev/null +++ b/drivers/media/dvb/frontends/s921.h @@ -0,0 +1,47 @@ +/* + * Sharp s921 driver + * + * Copyright (C) 2009 Mauro Carvalho Chehab + * Copyright (C) 2009 Douglas Landgraf + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#ifndef S921_H +#define S921_H + +#include + +struct s921_config { + /* the demodulator's i2c address */ + u8 demod_address; +}; + +#if defined(CONFIG_DVB_S921) || (defined(CONFIG_DVB_S921_MODULE) \ + && defined(MODULE)) +extern struct dvb_frontend *s921_attach(const struct s921_config *config, + struct i2c_adapter *i2c); +extern struct i2c_adapter *s921_get_tuner_i2c_adapter(struct dvb_frontend *); +#else +static inline struct dvb_frontend *s921_attach( + const struct s921_config *config, struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +static struct i2c_adapter * + s921_get_tuner_i2c_adapter(struct dvb_frontend *fe) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +#endif /* S921_H */ diff --git a/drivers/media/dvb/frontends/s921_core.c b/drivers/media/dvb/frontends/s921_core.c deleted file mode 100644 index 974b52b..0000000 --- a/drivers/media/dvb/frontends/s921_core.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Driver for Sharp s921 driver - * - * Copyright (C) 2008 Markus Rechberger - * - */ - - -#include -#include -#include -#include "s921_core.h" - -static int s921_isdb_init(struct s921_isdb_t *dev); -static int s921_isdb_set_parameters(struct s921_isdb_t *dev, struct s921_isdb_t_transmission_mode_params *params); -static int s921_isdb_tune(struct s921_isdb_t *dev, struct s921_isdb_t_tune_params *params); -static int s921_isdb_get_status(struct s921_isdb_t *dev, void *data); - -static u8 init_table[]={ 0x01, 0x40, 0x02, 0x00, 0x03, 0x40, 0x04, 0x01, - 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, - 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x5a, 0x0c, 0x00, - 0x0d, 0x00, 0x0f, 0x00, 0x13, 0x1b, 0x14, 0x80, - 0x15, 0x40, 0x17, 0x70, 0x18, 0x01, 0x19, 0x12, - 0x1a, 0x01, 0x1b, 0x12, 0x1c, 0xa0, 0x1d, 0x00, - 0x1e, 0x0a, 0x1f, 0x08, 0x20, 0x40, 0x21, 0xff, - 0x22, 0x4c, 0x23, 0x4e, 0x24, 0x4c, 0x25, 0x00, - 0x26, 0x00, 0x27, 0xf4, 0x28, 0x60, 0x29, 0x88, - 0x2a, 0x40, 0x2b, 0x40, 0x2c, 0xff, 0x2d, 0x00, - 0x2e, 0xff, 0x2f, 0x00, 0x30, 0x20, 0x31, 0x06, - 0x32, 0x0c, 0x34, 0x0f, 0x37, 0xfe, 0x38, 0x00, - 0x39, 0x63, 0x3a, 0x10, 0x3b, 0x10, 0x47, 0x00, - 0x49, 0xe5, 0x4b, 0x00, 0x50, 0xc0, 0x52, 0x20, - 0x54, 0x5a, 0x55, 0x5b, 0x56, 0x40, 0x57, 0x70, - 0x5c, 0x50, 0x5d, 0x00, 0x62, 0x17, 0x63, 0x2f, - 0x64, 0x6f, 0x68, 0x00, 0x69, 0x89, 0x6a, 0x00, - 0x6b, 0x00, 0x6c, 0x00, 0x6d, 0x00, 0x6e, 0x00, - 0x70, 0x00, 0x71, 0x00, 0x75, 0x00, 0x76, 0x30, - 0x77, 0x01, 0xaf, 0x00, 0xb0, 0xa0, 0xb2, 0x3d, - 0xb3, 0x25, 0xb4, 0x8b, 0xb5, 0x4b, 0xb6, 0x3f, - 0xb7, 0xff, 0xb8, 0xff, 0xb9, 0xfc, 0xba, 0x00, - 0xbb, 0x00, 0xbc, 0x00, 0xd0, 0x30, 0xe4, 0x84, - 0xf0, 0x48, 0xf1, 0x19, 0xf2, 0x5a, 0xf3, 0x8e, - 0xf4, 0x2d, 0xf5, 0x07, 0xf6, 0x5a, 0xf7, 0xba, - 0xf8, 0xd7 }; - -static u8 c_table[]={ 0x58, 0x8a, 0x7b, 0x59, 0x8c, 0x7b, 0x5a, 0x8e, 0x5b, - 0x5b, 0x90, 0x5b, 0x5c, 0x92, 0x5b, 0x5d, 0x94, 0x5b, - 0x5e, 0x96, 0x5b, 0x5f, 0x98, 0x3b, 0x60, 0x9a, 0x3b, - 0x61, 0x9c, 0x3b, 0x62, 0x9e, 0x3b, 0x63, 0xa0, 0x3b, - 0x64, 0xa2, 0x1b, 0x65, 0xa4, 0x1b, 0x66, 0xa6, 0x1b, - 0x67, 0xa8, 0x1b, 0x68, 0xaa, 0x1b, 0x69, 0xac, 0x1b, - 0x6a, 0xae, 0x1b, 0x6b, 0xb0, 0x1b, 0x6c, 0xb2, 0x1b, - 0x6d, 0xb4, 0xfb, 0x6e, 0xb6, 0xfb, 0x6f, 0xb8, 0xfb, - 0x70, 0xba, 0xfb, 0x71, 0xbc, 0xdb, 0x72, 0xbe, 0xdb, - 0x73, 0xc0, 0xdb, 0x74, 0xc2, 0xdb, 0x75, 0xc4, 0xdb, - 0x76, 0xc6, 0xdb, 0x77, 0xc8, 0xbb, 0x78, 0xca, 0xbb, - 0x79, 0xcc, 0xbb, 0x7a, 0xce, 0xbb, 0x7b, 0xd0, 0xbb, - 0x7c, 0xd2, 0xbb, 0x7d, 0xd4, 0xbb, 0x7e, 0xd6, 0xbb, - 0x7f, 0xd8, 0xbb, 0x80, 0xda, 0x9b, 0x81, 0xdc, 0x9b, - 0x82, 0xde, 0x9b, 0x83, 0xe0, 0x9b, 0x84, 0xe2, 0x9b, - 0x85, 0xe4, 0x9b, 0x86, 0xe6, 0x9b, 0x87, 0xe8, 0x9b, - 0x88, 0xea, 0x9b, 0x89, 0xec, 0x9b }; - -int s921_isdb_cmd(struct s921_isdb_t *dev, u32 cmd, void *data) { - switch(cmd) { - case ISDB_T_CMD_INIT: - s921_isdb_init(dev); - break; - case ISDB_T_CMD_SET_PARAM: - s921_isdb_set_parameters(dev, data); - break; - case ISDB_T_CMD_TUNE: - s921_isdb_tune(dev, data); - break; - case ISDB_T_CMD_GET_STATUS: - s921_isdb_get_status(dev, data); - break; - default: - printk("unhandled command\n"); - return -EINVAL; - } - return 0; -} - -static int s921_isdb_init(struct s921_isdb_t *dev) { - unsigned int i; - unsigned int ret; - printk("isdb_init\n"); - for (i = 0; i < sizeof(init_table); i+=2) { - ret = dev->i2c_write(dev->priv_dev, init_table[i], init_table[i+1]); - if (ret != 0) { - printk("i2c write failed\n"); - return ret; - } - } - return 0; -} - -static int s921_isdb_set_parameters(struct s921_isdb_t *dev, struct s921_isdb_t_transmission_mode_params *params) { - - int ret; - /* auto is sufficient for now, lateron this should be reflected in an extra interface */ - - - - ret = dev->i2c_write(dev->priv_dev, 0xb0, 0xa0); //mod_b2); - ret = dev->i2c_write(dev->priv_dev, 0xb2, 0x3d); //mod_b2); - - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xb3, 0x25); //mod_b3); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xb4, 0x8b); //mod_b4); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xb5, 0x4b); //mod_b5); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xb6, 0x3f); //mod_b6); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xb7, 0x3f); //mod_b7); - if (ret < 0) - return -EINVAL; - - return E_OK; -} - -static int s921_isdb_tune(struct s921_isdb_t *dev, struct s921_isdb_t_tune_params *params) { - - int ret; - int index; - - index = (params->frequency - 473143000)/6000000; - - if (index > 48) { - return -EINVAL; - } - - dev->i2c_write(dev->priv_dev, 0x47, 0x60); - - ret = dev->i2c_write(dev->priv_dev, 0x68, 0x00); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0x69, 0x89); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xf0, 0x48); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xf1, 0x19); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xf2, c_table[index*3]); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xf3, c_table[index*3+1]); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xf4, c_table[index*3+2]); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xf5, 0xae); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xf6, 0xb7); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xf7, 0xba); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xf8, 0xd7); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0x68, 0x0a); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0x69, 0x09); - if (ret < 0) - return -EINVAL; - - dev->i2c_write(dev->priv_dev, 0x01, 0x40); - return 0; -} - -static int s921_isdb_get_status(struct s921_isdb_t *dev, void *data) { - unsigned int *ret = (unsigned int*)data; - u8 ifagc_dt; - u8 rfagc_dt; - - mdelay(10); - ifagc_dt = dev->i2c_read(dev->priv_dev, 0x81); - rfagc_dt = dev->i2c_read(dev->priv_dev, 0x82); - if (rfagc_dt == 0x40) { - *ret = 1; - } - return 0; -} diff --git a/drivers/media/dvb/frontends/s921_core.h b/drivers/media/dvb/frontends/s921_core.h deleted file mode 100644 index de2f10a..0000000 --- a/drivers/media/dvb/frontends/s921_core.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef _S921_CORE_H -#define _S921_CORE_H -//#define u8 unsigned int -//#define u32 unsigned int - - - -//#define EINVAL -1 -#define E_OK 0 - -struct s921_isdb_t { - void *priv_dev; - int (*i2c_write)(void *dev, u8 reg, u8 val); - int (*i2c_read)(void *dev, u8 reg); -}; - -#define ISDB_T_CMD_INIT 0 -#define ISDB_T_CMD_SET_PARAM 1 -#define ISDB_T_CMD_TUNE 2 -#define ISDB_T_CMD_GET_STATUS 3 - -struct s921_isdb_t_tune_params { - u32 frequency; -}; - -struct s921_isdb_t_status { -}; - -struct s921_isdb_t_transmission_mode_params { - u8 mode; - u8 layer_a_mode; -#define ISDB_T_LA_MODE_1 0 -#define ISDB_T_LA_MODE_2 1 -#define ISDB_T_LA_MODE_3 2 - u8 layer_a_carrier_modulation; -#define ISDB_T_LA_CM_DQPSK 0 -#define ISDB_T_LA_CM_QPSK 1 -#define ISDB_T_LA_CM_16QAM 2 -#define ISDB_T_LA_CM_64QAM 3 -#define ISDB_T_LA_CM_NOLAYER 4 - u8 layer_a_code_rate; -#define ISDB_T_LA_CR_1_2 0 -#define ISDB_T_LA_CR_2_3 1 -#define ISDB_T_LA_CR_3_4 2 -#define ISDB_T_LA_CR_5_6 4 -#define ISDB_T_LA_CR_7_8 8 -#define ISDB_T_LA_CR_NOLAYER 16 - u8 layer_a_time_interleave; -#define ISDB_T_LA_TI_0 0 -#define ISDB_T_LA_TI_1 1 -#define ISDB_T_LA_TI_2 2 -#define ISDB_T_LA_TI_4 4 -#define ISDB_T_LA_TI_8 8 -#define ISDB_T_LA_TI_16 16 -#define ISDB_T_LA_TI_32 32 - u8 layer_a_nseg; - - u8 layer_b_mode; -#define ISDB_T_LB_MODE_1 0 -#define ISDB_T_LB_MODE_2 1 -#define ISDB_T_LB_MODE_3 2 - u8 layer_b_carrier_modulation; -#define ISDB_T_LB_CM_DQPSK 0 -#define ISDB_T_LB_CM_QPSK 1 -#define ISDB_T_LB_CM_16QAM 2 -#define ISDB_T_LB_CM_64QAM 3 -#define ISDB_T_LB_CM_NOLAYER 4 - u8 layer_b_code_rate; -#define ISDB_T_LB_CR_1_2 0 -#define ISDB_T_LB_CR_2_3 1 -#define ISDB_T_LB_CR_3_4 2 -#define ISDB_T_LB_CR_5_6 4 -#define ISDB_T_LB_CR_7_8 8 -#define ISDB_T_LB_CR_NOLAYER 16 - u8 layer_b_time_interleave; -#define ISDB_T_LB_TI_0 0 -#define ISDB_T_LB_TI_1 1 -#define ISDB_T_LB_TI_2 2 -#define ISDB_T_LB_TI_4 4 -#define ISDB_T_LB_TI_8 8 -#define ISDB_T_LB_TI_16 16 -#define ISDB_T_LB_TI_32 32 - u8 layer_b_nseg; - - u8 layer_c_mode; -#define ISDB_T_LC_MODE_1 0 -#define ISDB_T_LC_MODE_2 1 -#define ISDB_T_LC_MODE_3 2 - u8 layer_c_carrier_modulation; -#define ISDB_T_LC_CM_DQPSK 0 -#define ISDB_T_LC_CM_QPSK 1 -#define ISDB_T_LC_CM_16QAM 2 -#define ISDB_T_LC_CM_64QAM 3 -#define ISDB_T_LC_CM_NOLAYER 4 - u8 layer_c_code_rate; -#define ISDB_T_LC_CR_1_2 0 -#define ISDB_T_LC_CR_2_3 1 -#define ISDB_T_LC_CR_3_4 2 -#define ISDB_T_LC_CR_5_6 4 -#define ISDB_T_LC_CR_7_8 8 -#define ISDB_T_LC_CR_NOLAYER 16 - u8 layer_c_time_interleave; -#define ISDB_T_LC_TI_0 0 -#define ISDB_T_LC_TI_1 1 -#define ISDB_T_LC_TI_2 2 -#define ISDB_T_LC_TI_4 4 -#define ISDB_T_LC_TI_8 8 -#define ISDB_T_LC_TI_16 16 -#define ISDB_T_LC_TI_32 32 - u8 layer_c_nseg; -}; - -int s921_isdb_cmd(struct s921_isdb_t *dev, u32 cmd, void *data); -#endif diff --git a/drivers/media/dvb/frontends/s921_module.c b/drivers/media/dvb/frontends/s921_module.c deleted file mode 100644 index 0eefff6..0000000 --- a/drivers/media/dvb/frontends/s921_module.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Driver for Sharp s921 driver - * - * Copyright (C) 2008 Markus Rechberger - * - * All rights reserved. - * - */ - -#include -#include -#include -#include -#include "dvb_frontend.h" -#include "s921_module.h" -#include "s921_core.h" - -static unsigned int debug = 0; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug,"s921 debugging (default off)"); - -#define dprintk(fmt, args...) if (debug) do {\ - printk("s921 debug: " fmt, ##args); } while (0) - -struct s921_state -{ - struct dvb_frontend frontend; - fe_modulation_t current_modulation; - __u32 snr; - __u32 current_frequency; - __u8 addr; - struct s921_isdb_t dev; - struct i2c_adapter *i2c; -}; - -static int s921_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *param) { - struct s921_state *state = (struct s921_state *)fe->demodulator_priv; - struct s921_isdb_t_transmission_mode_params params; - struct s921_isdb_t_tune_params tune_params; - - tune_params.frequency = param->frequency; - s921_isdb_cmd(&state->dev, ISDB_T_CMD_SET_PARAM, ¶ms); - s921_isdb_cmd(&state->dev, ISDB_T_CMD_TUNE, &tune_params); - mdelay(100); - return 0; -} - -static int s921_init(struct dvb_frontend *fe) { - printk("s921 init\n"); - return 0; -} - -static int s921_sleep(struct dvb_frontend *fe) { - printk("s921 sleep\n"); - return 0; -} - -static int s921_read_status(struct dvb_frontend *fe, fe_status_t *status) -{ - struct s921_state *state = (struct s921_state *)fe->demodulator_priv; - unsigned int ret; - mdelay(5); - s921_isdb_cmd(&state->dev, ISDB_T_CMD_GET_STATUS, &ret); - *status = 0; - - printk("status: %02x\n", ret); - if (ret == 1) { - *status |= FE_HAS_CARRIER; - *status |= FE_HAS_VITERBI; - *status |= FE_HAS_LOCK; - *status |= FE_HAS_SYNC; - *status |= FE_HAS_SIGNAL; - } - - return 0; -} - -static int s921_read_ber(struct dvb_frontend *fe, __u32 *ber) -{ - dprintk("read ber\n"); - return 0; -} - -static int s921_read_snr(struct dvb_frontend *fe, __u16 *snr) -{ - dprintk("read snr\n"); - return 0; -} - -static int s921_read_ucblocks(struct dvb_frontend *fe, __u32 *ucblocks) -{ - dprintk("read ucblocks\n"); - return 0; -} - -static void s921_release(struct dvb_frontend *fe) -{ - struct s921_state *state = (struct s921_state *)fe->demodulator_priv; - kfree(state); -} - -static struct dvb_frontend_ops demod_s921={ - .info = { - .name = "SHARP S921", - .type = FE_OFDM, - .frequency_min = 473143000, - .frequency_max = 767143000, - .frequency_stepsize = 6000000, - .frequency_tolerance = 0, - .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | - FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | - FE_CAN_FEC_AUTO | - FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | - FE_CAN_MUTE_TS - }, - .init = s921_init, - .sleep = s921_sleep, - .set_frontend = s921_set_parameters, - .read_snr = s921_read_snr, - .read_ber = s921_read_ber, - .read_status = s921_read_status, - .read_ucblocks = s921_read_ucblocks, - .release = s921_release, -}; - -static int s921_write(void *dev, u8 reg, u8 val) { - struct s921_state *state = dev; - char buf[2]={reg,val}; - int err; - struct i2c_msg i2cmsgs = { - .addr = state->addr, - .flags = 0, - .len = 2, - .buf = buf - }; - - if((err = i2c_transfer(state->i2c, &i2cmsgs, 1))<0) { - printk("%s i2c_transfer error %d\n", __func__, err); - if (err < 0) - return err; - else - return -EREMOTEIO; - } - - return 0; -} - -static int s921_read(void *dev, u8 reg) { - struct s921_state *state = dev; - u8 b1; - int ret; - struct i2c_msg msg[2] = { { .addr = state->addr, - .flags = 0, - .buf = ®, .len = 1 }, - { .addr = state->addr, - .flags = I2C_M_RD, - .buf = &b1, .len = 1 } }; - - ret = i2c_transfer(state->i2c, msg, 2); - if (ret != 2) - return ret; - return b1; -} - -struct dvb_frontend* s921_attach(const struct s921_config *config, - struct i2c_adapter *i2c) -{ - - struct s921_state *state; - state = kzalloc(sizeof(struct s921_state), GFP_KERNEL); - if (state == NULL) - return NULL; - - state->addr = config->i2c_address; - state->i2c = i2c; - state->dev.i2c_write = &s921_write; - state->dev.i2c_read = &s921_read; - state->dev.priv_dev = state; - - s921_isdb_cmd(&state->dev, ISDB_T_CMD_INIT, NULL); - - memcpy(&state->frontend.ops, &demod_s921, sizeof(struct dvb_frontend_ops)); - state->frontend.demodulator_priv = state; - return &state->frontend; -} - -EXPORT_SYMBOL_GPL(s921_attach); -MODULE_AUTHOR("Markus Rechberger "); -MODULE_DESCRIPTION("Sharp S921 ISDB-T 1Seg"); -MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/s921_module.h b/drivers/media/dvb/frontends/s921_module.h deleted file mode 100644 index 7866042..0000000 --- a/drivers/media/dvb/frontends/s921_module.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Driver for DVB-T s921 demodulator - * - * Copyright (C) 2008 Markus Rechberger - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.= - */ - -#ifndef S921_MODULE_H -#define S921_MODULE_H - -#include -#include "s921_core.h" - -int s921_isdb_init(struct s921_isdb_t *dev); -int s921_isdb_cmd(struct s921_isdb_t *dev, u32 cmd, void *data); - -struct s921_config -{ - /* demodulator's I2C address */ - u8 i2c_address; -}; - -#if defined(CONFIG_DVB_S921) || (defined(CONFIG_DVB_S921_MODULE) && defined(MODULE)) -extern struct dvb_frontend* s921_attach(const struct s921_config *config, - struct i2c_adapter *i2c); -#else -static inline struct dvb_frontend* s921_attach(const struct s921_config *config, - struct i2c_adapter *i2c) -{ - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); - return NULL; -} -#endif /* CONFIG_DVB_S921 */ - -#endif /* S921_H */ -- cgit v0.10.2 From ca3dfd6a6f8364c1d51e548adb4564702f1141e9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 10 Sep 2010 17:29:14 -0300 Subject: [media] em28xx: Add support for Leadership ISDB-T This device uses an em2874B + Sharp 921 One Seg frontend. Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index ac2616a..3ca1ef7 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -1,5 +1,5 @@ 0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800] - 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2710,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2862,eb1a:2863,eb1a:2870,eb1a:2881,eb1a:2883,eb1a:2868] + 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2710,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2862,eb1a:2863,eb1a:2870,eb1a:2881,eb1a:2883,eb1a:2868,eb1a:2875] 2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036] 3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208] 4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200,2040:4201] diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 66aefd6..8d38c5f 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -37,6 +37,7 @@ config VIDEO_EM28XX_DVB select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE select DVB_TDA10023 if !DVB_FE_CUSTOMISE + select DVB_S921 if !DVB_FE_CUSTOMISE select VIDEOBUF_DVB ---help--- This adds support for DVB cards based on the diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index f7e9168..24caa851 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -268,6 +268,20 @@ static struct em28xx_reg_seq dikom_dk300_digital[] = { }; +/* Reset for the most [digital] boards */ +static struct em28xx_reg_seq leadership_digital[] = { + {EM2874_R80_GPIO, 0x70, 0xff, 10}, + { -1, -1, -1, -1}, +}; + +static struct em28xx_reg_seq leadership_reset[] = { + {EM2874_R80_GPIO, 0xf0, 0xff, 10}, + {EM2874_R80_GPIO, 0xb0, 0xff, 10}, + {EM2874_R80_GPIO, 0xf0, 0xff, 10}, + { -1, -1, -1, -1}, +}; + + /* * Board definitions */ @@ -1224,6 +1238,19 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE0, } }, }, + + [EM2874_LEADERSHIP_ISDBT] = { + .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | + EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_FREQ_100_KHZ, + .xclk = EM28XX_XCLK_FREQUENCY_10MHZ, + .name = "EM2874 Leadership ISDBT", + .tuner_type = TUNER_ABSENT, + .tuner_gpio = leadership_reset, + .dvb_gpio = leadership_digital, + .has_dvb = 1, + }, + [EM2880_BOARD_MSI_DIGIVOX_AD] = { .name = "MSI DigiVox A/D", .valid = EM28XX_BOARD_NOT_VALIDATED, @@ -1754,6 +1781,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2868), .driver_info = EM2820_BOARD_UNKNOWN }, + { USB_DEVICE(0xeb1a, 0x2875), + .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0xe300), .driver_info = EM2861_BOARD_KWORLD_PVRTV_300U }, { USB_DEVICE(0xeb1a, 0xe303), @@ -1873,6 +1902,7 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = { {0x77800080, EM2860_BOARD_TVP5150_REFERENCE_DESIGN, TUNER_ABSENT}, {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC}, {0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF}, + {0x6b800080, EM2874_LEADERSHIP_ISDBT, TUNER_ABSENT}, }; /* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */ @@ -2430,8 +2460,36 @@ void em28xx_card_setup(struct em28xx *dev) dev->board.is_webcam = 0; else dev->progressive = 1; - } else - em28xx_set_model(dev); + } + + if (!dev->board.is_webcam) { + switch (dev->model) { + case EM2820_BOARD_UNKNOWN: + case EM2800_BOARD_UNKNOWN: + /* + * The K-WORLD DVB-T 310U is detected as an MSI Digivox AD. + * + * This occurs because they share identical USB vendor and + * product IDs. + * + * What we do here is look up the EEPROM hash of the K-WORLD + * and if it is found then we decide that we do not have + * a DIGIVOX and reset the device to the K-WORLD instead. + * + * This solution is only valid if they do not share eeprom + * hash identities which has not been determined as yet. + */ + if (em28xx_hint_board(dev) < 0) + em28xx_errdev("Board not discovered\n"); + else { + em28xx_set_model(dev); + em28xx_pre_card_setup(dev); + } + break; + default: + em28xx_set_model(dev); + } + } em28xx_info("Identified as %s (card=%d)\n", dev->board.name, dev->model); @@ -2749,8 +2807,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, em28xx_pre_card_setup(dev); if (!dev->board.is_em2800) { - /* Sets I2C speed to 100 KHz */ - retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); + /* Resets I2C speed */ + em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed); if (retval < 0) { em28xx_errdev("%s: em28xx_write_regs_req failed!" " retval [%d]\n", diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 3ac8d30..c7c04bf 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -37,6 +37,7 @@ #include "mt352_priv.h" /* FIXME */ #include "tda1002x.h" #include "tda18271.h" +#include "s921.h" MODULE_DESCRIPTION("driver for em28xx based DVB cards"); MODULE_AUTHOR("Mauro Carvalho Chehab "); @@ -245,6 +246,10 @@ static struct lgdt3305_config em2870_lgdt3304_dev = { .qam_if_khz = 4000, }; +static struct s921_config sharp_isdbt = { + .demod_address = 0x30 >> 1 +}; + static struct zl10353_config em28xx_zl10353_with_xc3028 = { .demod_address = (0x1e >> 1), .no_tuner = 1, @@ -481,6 +486,7 @@ static int dvb_init(struct em28xx *dev) if (!dev->board.has_dvb) { /* This device does not support the extension */ + printk(KERN_INFO "em28xx_dvb: This device does not support the extension\n"); return 0; } @@ -496,6 +502,16 @@ static int dvb_init(struct em28xx *dev) em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); /* init frontend */ switch (dev->model) { + case EM2874_LEADERSHIP_ISDBT: + dvb->frontend = dvb_attach(s921_attach, + &sharp_isdbt, &dev->i2c_adap); + + if (!dvb->frontend) { + result = -EINVAL; + goto out_free; + } + + break; case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 6a75e6a..6a48043 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -117,6 +117,8 @@ #define EM2800_BOARD_VC211A 74 #define EM2882_BOARD_DIKOM_DK300 75 #define EM2870_BOARD_KWORLD_A340 76 +#define EM2874_LEADERSHIP_ISDBT 77 + /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v0.10.2 From b9ede79ada766eec535e1230970bd885489d5990 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Sep 2010 20:52:43 -0300 Subject: [media] add a driver for mb86a20s This adds the trivial bits to mb86a20s. As the driver won't touch at the channel/layer parameters, this may not be enough for receiving all channels, especially ISDB-Tsb, but the driver worked properly for receiving video channels on my tests. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 00dbf1e..ef3e43a 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -512,6 +512,14 @@ config DVB_DIB8000 A driver for DiBcom's DiB8000 ISDB-T/ISDB-Tsb demodulator. Say Y when you want to support this frontend. +config DVB_MB86A20S + tristate "Fujitsu mb86a20s" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A driver for Fujitsu mb86a20s ISDB-T/ISDB-Tsb demodulator. + Say Y when you want to support this frontend. + comment "Digital terrestrial only tuners/PLL" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 48b9fd3..b1d9525 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -81,4 +81,5 @@ obj-$(CONFIG_DVB_ISL6423) += isl6423.o obj-$(CONFIG_DVB_EC100) += ec100.o obj-$(CONFIG_DVB_DS3000) += ds3000.o obj-$(CONFIG_DVB_MB86A16) += mb86a16.o +obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o obj-$(CONFIG_DVB_IX2505V) += ix2505v.o diff --git a/drivers/media/dvb/frontends/mb86a20s.c b/drivers/media/dvb/frontends/mb86a20s.c new file mode 100644 index 0000000..1e6bec6 --- /dev/null +++ b/drivers/media/dvb/frontends/mb86a20s.c @@ -0,0 +1,584 @@ +/* + * Fujitu mb86a20s ISDB-T/ISDB-Tsb Module driver + * + * Copyright (C) 2010 Mauro Carvalho Chehab + * Copyright (C) 2009-2010 Douglas Landgraf + * + * FIXME: Need to port to DVB v5.2 API + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include + +#include "dvb_frontend.h" +#include "mb86a20s.h" + +static int debug = 1; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); + +#define rc(args...) do { \ + printk(KERN_ERR "mb86a20s: " args); \ +} while (0) + +#define dprintk(args...) \ + do { \ + if (debug) { \ + printk(KERN_DEBUG "mb86a20s: %s: ", __func__); \ + printk(args); \ + } \ + } while (0) + +struct mb86a20s_state { + struct i2c_adapter *i2c; + const struct mb86a20s_config *config; + + struct dvb_frontend frontend; + + + + +}; + +struct regdata { + u8 reg; + u8 data; +}; + +/* + * Initialization sequence: Use whatevere default values that PV SBTVD + * does on its initialisation, obtained via USB snoop + */ +static struct regdata mb86a20s_init[] = { + { 0x70, 0x0f }, + { 0x70, 0xff }, + { 0x08, 0x01 }, + { 0x09, 0x3e }, + { 0x50, 0xd1 }, + { 0x51, 0x22 }, + { 0x39, 0x01 }, + { 0x71, 0x00 }, + { 0x28, 0x2a }, + { 0x29, 0x00 }, + { 0x2a, 0xff }, + { 0x2b, 0x80 }, + { 0x28, 0x20 }, + { 0x29, 0x33 }, + { 0x2a, 0xdf }, + { 0x2b, 0xa9 }, + { 0x3b, 0x21 }, + { 0x3c, 0x3a }, + { 0x01, 0x0d }, + { 0x04, 0x08 }, + { 0x05, 0x05 }, + { 0x04, 0x0e }, + { 0x05, 0x00 }, + { 0x04, 0x0f }, + { 0x05, 0x14 }, + { 0x04, 0x0b }, + { 0x05, 0x8c }, + { 0x04, 0x00 }, + { 0x05, 0x00 }, + { 0x04, 0x01 }, + { 0x05, 0x07 }, + { 0x04, 0x02 }, + { 0x05, 0x0f }, + { 0x04, 0x03 }, + { 0x05, 0xa0 }, + { 0x04, 0x09 }, + { 0x05, 0x00 }, + { 0x04, 0x0a }, + { 0x05, 0xff }, + { 0x04, 0x27 }, + { 0x05, 0x64 }, + { 0x04, 0x28 }, + { 0x05, 0x00 }, + { 0x04, 0x1e }, + { 0x05, 0xff }, + { 0x04, 0x29 }, + { 0x05, 0x0a }, + { 0x04, 0x32 }, + { 0x05, 0x0a }, + { 0x04, 0x14 }, + { 0x05, 0x02 }, + { 0x04, 0x04 }, + { 0x05, 0x00 }, + { 0x04, 0x05 }, + { 0x05, 0x22 }, + { 0x04, 0x06 }, + { 0x05, 0x0e }, + { 0x04, 0x07 }, + { 0x05, 0xd8 }, + { 0x04, 0x12 }, + { 0x05, 0x00 }, + { 0x04, 0x13 }, + { 0x05, 0xff }, + { 0x52, 0x01 }, + { 0x50, 0xa7 }, + { 0x51, 0x00 }, + { 0x50, 0xa8 }, + { 0x51, 0xff }, + { 0x50, 0xa9 }, + { 0x51, 0xff }, + { 0x50, 0xaa }, + { 0x51, 0x00 }, + { 0x50, 0xab }, + { 0x51, 0xff }, + { 0x50, 0xac }, + { 0x51, 0xff }, + { 0x50, 0xad }, + { 0x51, 0x00 }, + { 0x50, 0xae }, + { 0x51, 0xff }, + { 0x50, 0xaf }, + { 0x51, 0xff }, + { 0x5e, 0x07 }, + { 0x50, 0xdc }, + { 0x51, 0x01 }, + { 0x50, 0xdd }, + { 0x51, 0xf4 }, + { 0x50, 0xde }, + { 0x51, 0x01 }, + { 0x50, 0xdf }, + { 0x51, 0xf4 }, + { 0x50, 0xe0 }, + { 0x51, 0x01 }, + { 0x50, 0xe1 }, + { 0x51, 0xf4 }, + { 0x50, 0xb0 }, + { 0x51, 0x07 }, + { 0x50, 0xb2 }, + { 0x51, 0xff }, + { 0x50, 0xb3 }, + { 0x51, 0xff }, + { 0x50, 0xb4 }, + { 0x51, 0xff }, + { 0x50, 0xb5 }, + { 0x51, 0xff }, + { 0x50, 0xb6 }, + { 0x51, 0xff }, + { 0x50, 0xb7 }, + { 0x51, 0xff }, + { 0x50, 0x50 }, + { 0x51, 0x02 }, + { 0x50, 0x51 }, + { 0x51, 0x04 }, + { 0x45, 0x04 }, + { 0x48, 0x04 }, + { 0x50, 0xd5 }, + { 0x51, 0x01 }, + { 0x50, 0xd6 }, + { 0x51, 0x1f }, + { 0x50, 0xd2 }, + { 0x51, 0x03 }, + { 0x50, 0xd7 }, + { 0x51, 0x3f }, + { 0x1c, 0x01 }, + { 0x28, 0x06 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x03 }, + { 0x28, 0x07 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x0d }, + { 0x28, 0x08 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x02 }, + { 0x28, 0x09 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x01 }, + { 0x28, 0x0a }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x21 }, + { 0x28, 0x0b }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x29 }, + { 0x28, 0x0c }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x16 }, + { 0x28, 0x0d }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x31 }, + { 0x28, 0x0e }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x0e }, + { 0x28, 0x0f }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x4e }, + { 0x28, 0x10 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x46 }, + { 0x28, 0x11 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x0f }, + { 0x28, 0x12 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x56 }, + { 0x28, 0x13 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x35 }, + { 0x28, 0x14 }, + { 0x29, 0x00 }, + { 0x2a, 0x01 }, + { 0x2b, 0xbe }, + { 0x28, 0x15 }, + { 0x29, 0x00 }, + { 0x2a, 0x01 }, + { 0x2b, 0x84 }, + { 0x28, 0x16 }, + { 0x29, 0x00 }, + { 0x2a, 0x03 }, + { 0x2b, 0xee }, + { 0x28, 0x17 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x98 }, + { 0x28, 0x18 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x9f }, + { 0x28, 0x19 }, + { 0x29, 0x00 }, + { 0x2a, 0x07 }, + { 0x2b, 0xb2 }, + { 0x28, 0x1a }, + { 0x29, 0x00 }, + { 0x2a, 0x06 }, + { 0x2b, 0xc2 }, + { 0x28, 0x1b }, + { 0x29, 0x00 }, + { 0x2a, 0x07 }, + { 0x2b, 0x4a }, + { 0x28, 0x1c }, + { 0x29, 0x00 }, + { 0x2a, 0x01 }, + { 0x2b, 0xbc }, + { 0x28, 0x1d }, + { 0x29, 0x00 }, + { 0x2a, 0x04 }, + { 0x2b, 0xba }, + { 0x28, 0x1e }, + { 0x29, 0x00 }, + { 0x2a, 0x06 }, + { 0x2b, 0x14 }, + { 0x50, 0x1e }, + { 0x51, 0x5d }, + { 0x50, 0x22 }, + { 0x51, 0x00 }, + { 0x50, 0x23 }, + { 0x51, 0xc8 }, + { 0x50, 0x24 }, + { 0x51, 0x00 }, + { 0x50, 0x25 }, + { 0x51, 0xf0 }, + { 0x50, 0x26 }, + { 0x51, 0x00 }, + { 0x50, 0x27 }, + { 0x51, 0xc3 }, + { 0x50, 0x39 }, + { 0x51, 0x02 }, + { 0x50, 0xd5 }, + { 0x51, 0x01 }, + { 0xd0, 0x00 }, +}; + +static struct regdata mb86a20s_reset_reception[] = { + { 0x70, 0xf0 }, + { 0x70, 0xff }, + { 0x08, 0x01 }, + { 0x08, 0x00 }, +}; + +static int mb86a20s_i2c_writereg(struct mb86a20s_state *state, + u8 i2c_addr, int reg, int data) +{ + u8 buf[] = { reg, data }; + struct i2c_msg msg = { + .addr = i2c_addr, .flags = 0, .buf = buf, .len = 2 + }; + int rc; + + rc = i2c_transfer(state->i2c, &msg, 1); + if (rc != 1) { + printk("%s: writereg rcor(rc == %i, reg == 0x%02x," + " data == 0x%02x)\n", __func__, rc, reg, data); + return rc; + } + + return 0; +} + +static int mb86a20s_i2c_writeregdata(struct mb86a20s_state *state, + u8 i2c_addr, struct regdata *rd, int size) +{ + int i, rc; + + for (i = 0; i < size; i++) { + rc = mb86a20s_i2c_writereg(state, i2c_addr, rd[i].reg, + rd[i].data); + if (rc < 0) + return rc; + } + return 0; +} + +static int mb86a20s_i2c_readreg(struct mb86a20s_state *state, + u8 i2c_addr, u8 reg) +{ + u8 val; + int rc; + struct i2c_msg msg[] = { + { .addr = i2c_addr, .flags = 0, .buf = ®, .len = 1 }, + { .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 } + }; + + rc = i2c_transfer(state->i2c, msg, 2); + + if (rc != 2) { + rc("%s: reg=0x%x (rcor=%d)\n", __func__, reg, rc); + return rc; + } + + return val; +} + +#define mb86a20s_readreg(state, reg) \ + mb86a20s_i2c_readreg(state, state->config->demod_address, reg) +#define mb86a20s_writereg(state, reg, val) \ + mb86a20s_i2c_writereg(state, state->config->demod_address, reg, val) +#define mb86a20s_writeregdata(state, regdata) \ + mb86a20s_i2c_writeregdata(state, state->config->demod_address, \ + regdata, ARRAY_SIZE(regdata)) + +static int mb86a20s_initfe(struct dvb_frontend *fe) +{ + struct mb86a20s_state *state = fe->demodulator_priv; + int rc; + + dprintk("\n"); + + /* Initialize the frontend */ + rc = mb86a20s_writeregdata(state, mb86a20s_init); + if (rc < 0) + return rc; + + return 0; +} + +static int mb86a20s_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + struct mb86a20s_state *state = fe->demodulator_priv; + unsigned rf_max, rf_min, rf; + u8 val; + + dprintk("\n"); + + /* Does a binary search to get RF strength */ + rf_max = 0xfff; + rf_min = 0; + do { + rf = (rf_max + rf_min) / 2; + mb86a20s_writereg(state, 0x04, 0x1f); + mb86a20s_writereg(state, 0x05, rf >> 8); + mb86a20s_writereg(state, 0x04, 0x20); + mb86a20s_writereg(state, 0x04, rf); + + val = mb86a20s_readreg(state, 0x02); + if (val & 0x08) + rf_min = (rf_max + rf_min) / 2; + else + rf_max = (rf_max + rf_min) / 2; + if (rf_max - rf_min < 4) { + *strength = (((rf_max + rf_min) / 2) * 65535) / 4095; + break; + } + } while (1); + + dprintk("signal strength = %d\n", *strength); + + return 0; +} + +static int mb86a20s_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct mb86a20s_state *state = fe->demodulator_priv; + u8 val; + + dprintk("\n"); + *status = 0; + + val = mb86a20s_readreg(state, 0x0a) & 0xf; + + if (val >= 2) + *status |= FE_HAS_SIGNAL; + + if (val >= 4) + *status |= FE_HAS_CARRIER; + + if (val >= 5) + *status |= FE_HAS_VITERBI; + + if (val >= 7) + *status |= FE_HAS_SYNC; + + if (val >= 8) /* Maybe 9? */ + *status |= FE_HAS_LOCK; + + dprintk("val = %d, status = 0x%02x\n", val, *status); + + return 0; +} + +static int mb86a20s_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct mb86a20s_state *state = fe->demodulator_priv; + int rc; + + dprintk("\n"); + + fe->ops.tuner_ops.set_params(fe, p); + rc = mb86a20s_writeregdata(state, mb86a20s_reset_reception); + + return rc; +} + +static int mb86a20s_get_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + + /* FIXME: For now, it does nothing */ + + fe->dtv_property_cache.bandwidth_hz = 6000000; + fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO; + fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO; + fe->dtv_property_cache.isdbt_partial_reception = 0; + + return 0; +} + +static int mb86a20s_tune(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params, + unsigned int mode_flags, + unsigned int *delay, + fe_status_t *status) +{ + int rc = 0; + + dprintk("\n"); + + if (params != NULL) + rc = mb86a20s_set_frontend(fe, params); + + if (!(mode_flags & FE_TUNE_MODE_ONESHOT)) + mb86a20s_read_status(fe, status); + + return rc; +} + +static void mb86a20s_release(struct dvb_frontend *fe) +{ + struct mb86a20s_state *state = fe->demodulator_priv; + + dprintk("\n"); + + kfree(state); +} + +static struct dvb_frontend_ops mb86a20s_ops; + +struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config, + struct i2c_adapter *i2c) +{ + u8 rev; + + /* allocate memory for the internal state */ + struct mb86a20s_state *state = + kzalloc(sizeof(struct mb86a20s_state), GFP_KERNEL); + + dprintk("\n"); + if (state == NULL) { + rc("Unable to kzalloc\n"); + goto error; + } + + /* setup the state */ + state->config = config; + state->i2c = i2c; + + /* create dvb_frontend */ + memcpy(&state->frontend.ops, &mb86a20s_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + + /* Check if it is a mb86a20s frontend */ + rev = mb86a20s_readreg(state, 0); + + if (rev == 0x13) { + printk(KERN_INFO "Detected a Fujitsu mb86a20s frontend\n"); + } else { + printk(KERN_ERR "Frontend revision %d is unknown - aborting.\n", + rev); + goto error; + } + + return &state->frontend; + +error: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(mb86a20s_attach); + +static struct dvb_frontend_ops mb86a20s_ops = { + /* Use dib8000 values per default */ + .info = { + .name = "Fujitsu mb86A20s", + .type = FE_OFDM, + .caps = FE_CAN_INVERSION_AUTO | FE_CAN_RECOVER | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | + FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_QAM_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO, + /* Actually, those values depend on the used tuner */ + .frequency_min = 45000000, + .frequency_max = 864000000, + .frequency_stepsize = 62500, + }, + + .release = mb86a20s_release, + + .init = mb86a20s_initfe, + .set_frontend = mb86a20s_set_frontend, + .get_frontend = mb86a20s_get_frontend, + .read_status = mb86a20s_read_status, + .read_signal_strength = mb86a20s_read_signal_strength, + .tune = mb86a20s_tune, +}; + +MODULE_DESCRIPTION("DVB Frontend module for Fujitsu mb86A20s hardware"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/mb86a20s.h b/drivers/media/dvb/frontends/mb86a20s.h new file mode 100644 index 0000000..e346198 --- /dev/null +++ b/drivers/media/dvb/frontends/mb86a20s.h @@ -0,0 +1,51 @@ +/* + * Fujitsu mb86a20s driver + * + * Copyright (C) 2010 Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#ifndef MB86A20S_H +#define MB86A20S_H + +#include + +/** + * struct mb86a20s_config - Define the per-device attributes of the frontend + * + * @demod_address: the demodulator's i2c address + */ + +struct mb86a20s_config { + u8 demod_address; +}; + +#if defined(CONFIG_DVB_MB86A20S) || (defined(CONFIG_DVB_MB86A20S_MODULE) \ + && defined(MODULE)) +extern struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config, + struct i2c_adapter *i2c); +extern struct i2c_adapter *mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *); +#else +static inline struct dvb_frontend *mb86a20s_attach( + const struct mb86a20s_config *config, struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +static struct i2c_adapter * + mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *fe) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +#endif /* MB86A20S */ -- cgit v0.10.2 From 9417bc6dd9de85944501f8f4ce8dd0e64135ca82 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 26 Sep 2010 20:44:31 -0300 Subject: [media] Add analog support for Pixelvied Hybrid SBTVD Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx231xx/cx231xx-avcore.c b/drivers/media/video/cx231xx/cx231xx-avcore.c index cf50faf..d52955c 100644 --- a/drivers/media/video/cx231xx/cx231xx-avcore.c +++ b/drivers/media/video/cx231xx/cx231xx-avcore.c @@ -354,6 +354,7 @@ int cx231xx_afe_update_power_control(struct cx231xx *dev, case CX231XX_BOARD_CNXT_VIDEO_GRABBER: case CX231XX_BOARD_HAUPPAUGE_EXETER: case CX231XX_BOARD_HAUPPAUGE_USBLIVE2: + case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: if (avmode == POLARIS_AVMODE_ANALOGT_TV) { while (afe_power_status != (FLD_PWRDN_TUNING_BIAS | FLD_PWRDN_ENABLE_PLL)) { diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 2c78d18..7dc7a89 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c @@ -395,6 +395,43 @@ struct cx231xx_board cx231xx_boards[] = { .gpio = 0, } }, }, + [CX231XX_BOARD_PV_PLAYTV_USB_HYBRID] = { + .name = "Pixelview PlayTV USB Hybrid", + .tuner_type = TUNER_NXP_TDA18271, + .tuner_addr = 0x60, + .decoder = CX231XX_AVDECODER, + .output_mode = OUT_MODE_VIP11, + .demod_xfer_mode = 0, + .ctl_pin_status_mask = 0xFFFFFFC4, + .agc_analog_digital_select_gpio = 0x00, /* According with PV cxPolaris.inf file */ + .tuner_sif_gpio = -1, + .tuner_scl_gpio = -1, + .tuner_sda_gpio = -1, + .gpio_pin_status_mask = 0x4001000, + .tuner_i2c_master = 2, + .demod_i2c_master = 1, + .has_dvb = 0, /* FIXME: need driver for mb86a20s */ + .demod_addr = 0x10, + .norm = V4L2_STD_PAL_M, + .input = {{ + .type = CX231XX_VMUX_TELEVISION, + .vmux = CX231XX_VIN_3_1, + .amux = CX231XX_AMUX_VIDEO, + .gpio = 0, + }, { + .type = CX231XX_VMUX_COMPOSITE1, + .vmux = CX231XX_VIN_2_1, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = 0, + }, { + .type = CX231XX_VMUX_SVIDEO, + .vmux = CX231XX_VIN_1_1 | + (CX231XX_VIN_1_2 << 8) | + CX25840_SVIDEO_ON, + .amux = CX231XX_AMUX_LINE_IN, + .gpio = 0, + } }, + }, }; const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); @@ -402,8 +439,6 @@ const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); struct usb_device_id cx231xx_id_table[] = { {USB_DEVICE(0x0572, 0x5A3C), .driver_info = CX231XX_BOARD_UNKNOWN}, - {USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000,0x4fff), - .driver_info = CX231XX_BOARD_UNKNOWN}, {USB_DEVICE(0x0572, 0x58A2), .driver_info = CX231XX_BOARD_CNXT_CARRAERA}, {USB_DEVICE(0x0572, 0x58A1), @@ -424,6 +459,8 @@ struct usb_device_id cx231xx_id_table[] = { .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER}, {USB_DEVICE(0x2040, 0xc200), .driver_info = CX231XX_BOARD_HAUPPAUGE_USBLIVE2}, + {USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000, 0x4001), + .driver_info = CX231XX_BOARD_PV_PLAYTV_USB_HYBRID}, {}, }; diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c index 4af46fc..5664bdf 100644 --- a/drivers/media/video/cx231xx/cx231xx-core.c +++ b/drivers/media/video/cx231xx/cx231xx-core.c @@ -719,6 +719,7 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) break; case CX231XX_BOARD_CNXT_RDE_253S: case CX231XX_BOARD_CNXT_RDU_253S: + case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1); break; case CX231XX_BOARD_HAUPPAUGE_EXETER: @@ -740,6 +741,7 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) case CX231XX_BOARD_CNXT_RDE_253S: case CX231XX_BOARD_CNXT_RDU_253S: case CX231XX_BOARD_HAUPPAUGE_EXETER: + case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0); break; default: @@ -1381,6 +1383,7 @@ int cx231xx_dev_init(struct cx231xx *dev) case CX231XX_BOARD_CNXT_RDE_253S: case CX231XX_BOARD_CNXT_RDU_253S: case CX231XX_BOARD_HAUPPAUGE_EXETER: + case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0); break; default: diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h index d067df9..8a7d0a4 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/video/cx231xx/cx231xx.h @@ -62,6 +62,7 @@ #define CX231XX_BOARD_CNXT_RDU_250 7 #define CX231XX_BOARD_HAUPPAUGE_EXETER 8 #define CX231XX_BOARD_HAUPPAUGE_USBLIVE2 9 +#define CX231XX_BOARD_PV_PLAYTV_USB_HYBRID 10 /* Limits minimum and default number of buffers */ #define CX231XX_MIN_BUF 4 -- cgit v0.10.2 From ede676c72d0b18f1c15300f7874370e771489a1c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Sep 2010 23:44:27 -0300 Subject: [media] add digital support for PV SBTVD hybrid Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/video/cx231xx/Kconfig index bb04914..bad836f 100644 --- a/drivers/media/video/cx231xx/Kconfig +++ b/drivers/media/video/cx231xx/Kconfig @@ -30,6 +30,8 @@ config VIDEO_CX231XX_DVB depends on VIDEO_CX231XX && DVB_CORE select VIDEOBUF_DVB select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_NXP18271 if !DVB_FE_CUSTOMISE + select DVB_MB86A20S if !DVB_FE_CUSTOMISE ---help--- This adds support for DVB cards based on the diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 7dc7a89..4d0ab45 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c @@ -410,7 +410,7 @@ struct cx231xx_board cx231xx_boards[] = { .gpio_pin_status_mask = 0x4001000, .tuner_i2c_master = 2, .demod_i2c_master = 1, - .has_dvb = 0, /* FIXME: need driver for mb86a20s */ + .has_dvb = 1, .demod_addr = 0x10, .norm = V4L2_STD_PAL_M, .input = {{ diff --git a/drivers/media/video/cx231xx/cx231xx-dvb.c b/drivers/media/video/cx231xx/cx231xx-dvb.c index 5feb3ee..b55e7e0 100644 --- a/drivers/media/video/cx231xx/cx231xx-dvb.c +++ b/drivers/media/video/cx231xx/cx231xx-dvb.c @@ -33,6 +33,7 @@ #include "tda18271.h" #include "s5h1411.h" #include "lgdt3305.h" +#include "mb86a20s.h" MODULE_DESCRIPTION("driver for cx231xx based DVB cards"); MODULE_AUTHOR("Srinivasa Deevi "); @@ -88,6 +89,11 @@ static struct tda18271_std_map cnxt_rde253s_tda18271_std_map = { .if_lvl = 1, .rfagc_top = 0x37, }, }; +static struct tda18271_std_map mb86a20s_tda18271_config = { + .dvbt_6 = { .if_freq = 3300, .agc_mode = 3, .std = 4, + .if_lvl = 7, .rfagc_top = 0x37, }, +}; + static struct tda18271_config cnxt_rde253s_tunerconfig = { .std_map = &cnxt_rde253s_tda18271_std_map, .gate = TDA18271_GATE_ANALOG, @@ -135,6 +141,16 @@ static struct tda18271_config hcw_tda18271_config = { .gate = TDA18271_GATE_DIGITAL, }; +static const struct mb86a20s_config pv_mb86a20s_config = { + .demod_address = 0x10, +}; + +static struct tda18271_config pv_tda18271_config = { + .std_map = &mb86a20s_tda18271_config, + .gate = TDA18271_GATE_DIGITAL, + .small_i2c = TDA18271_03_BYTE_CHUNK_INIT, +}; + static inline void print_err_status(struct cx231xx *dev, int packet, int status) { char *errmsg = "Unknown"; @@ -687,6 +703,29 @@ static int dvb_init(struct cx231xx *dev) &hcw_tda18271_config); break; + case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: + + printk(KERN_INFO "%s: looking for demod on i2c bus: %d\n", + __func__, i2c_adapter_id(&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap)); + + dev->dvb->frontend = dvb_attach(mb86a20s_attach, + &pv_mb86a20s_config, + &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap); + + if (dev->dvb->frontend == NULL) { + printk(DRIVER_NAME + ": Failed to attach mb86a20s demod\n"); + result = -EINVAL; + goto out_free; + } + + /* define general-purpose callback pointer */ + dvb->frontend->callback = cx231xx_tuner_callback; + + dvb_attach(tda18271_attach, dev->dvb->frontend, + 0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap, + &pv_tda18271_config); + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" -- cgit v0.10.2 From 55fa288deca4b17e539ba49a9b0d0ed474afa6f8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 29 Sep 2010 11:07:08 -0300 Subject: [media] cx231xx: use callback to set agc on PixelView Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 4d0ab45..400447f 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c @@ -34,6 +34,7 @@ #include #include "dvb-usb-ids.h" #include "xc5000.h" +#include "tda18271.h" #include "cx231xx.h" @@ -490,6 +491,16 @@ int cx231xx_tuner_callback(void *ptr, int component, int command, int arg) 1); msleep(10); } + } else if (dev->tuner_type == TUNER_NXP_TDA18271) { + switch (command) { + case TDA18271_CALLBACK_CMD_AGC_ENABLE: + if (dev->model == CX231XX_BOARD_PV_PLAYTV_USB_HYBRID) + rc = cx231xx_set_agc_analog_digital_mux_select(dev, arg); + break; + default: + rc = -EINVAL; + break; + } } return rc; } diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c index 5664bdf..d6028c9 100644 --- a/drivers/media/video/cx231xx/cx231xx-core.c +++ b/drivers/media/video/cx231xx/cx231xx-core.c @@ -719,7 +719,6 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) break; case CX231XX_BOARD_CNXT_RDE_253S: case CX231XX_BOARD_CNXT_RDU_253S: - case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1); break; case CX231XX_BOARD_HAUPPAUGE_EXETER: -- cgit v0.10.2 From 7572f9c5575c721f43b575a71fda1ecd896e0327 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 3 Oct 2010 16:48:49 -0300 Subject: [media] mb86a20s: add support for serial streams By comparing the traffic between Pixelview (cx23102-based and Kworld (saa7134-based), the only difference is at register 0xd5. After some tests, It seems that it is used to change mode between serial and parallel. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/mb86a20s.c b/drivers/media/dvb/frontends/mb86a20s.c index 1e6bec6..b4de8f1 100644 --- a/drivers/media/dvb/frontends/mb86a20s.c +++ b/drivers/media/dvb/frontends/mb86a20s.c @@ -43,10 +43,6 @@ struct mb86a20s_state { const struct mb86a20s_config *config; struct dvb_frontend frontend; - - - - }; struct regdata { @@ -175,7 +171,7 @@ static struct regdata mb86a20s_init[] = { { 0x45, 0x04 }, { 0x48, 0x04 }, { 0x50, 0xd5 }, - { 0x51, 0x01 }, + { 0x51, 0x01 }, /* Serial */ { 0x50, 0xd6 }, { 0x51, 0x1f }, { 0x50, 0xd2 }, @@ -376,6 +372,7 @@ static int mb86a20s_initfe(struct dvb_frontend *fe) { struct mb86a20s_state *state = fe->demodulator_priv; int rc; + u8 regD5 = 1; dprintk("\n"); @@ -384,6 +381,17 @@ static int mb86a20s_initfe(struct dvb_frontend *fe) if (rc < 0) return rc; + if (!state->config->is_serial) { + regD5 &= ~1; + + rc = mb86a20s_writereg(state, 0x50, 0xd5); + if (rc < 0) + return rc; + rc = mb86a20s_writereg(state, 0x51, regD5); + if (rc < 0) + return rc; + } + return 0; } diff --git a/drivers/media/dvb/frontends/mb86a20s.h b/drivers/media/dvb/frontends/mb86a20s.h index e346198..bf22e77 100644 --- a/drivers/media/dvb/frontends/mb86a20s.h +++ b/drivers/media/dvb/frontends/mb86a20s.h @@ -26,6 +26,7 @@ struct mb86a20s_config { u8 demod_address; + bool is_serial; }; #if defined(CONFIG_DVB_MB86A20S) || (defined(CONFIG_DVB_MB86A20S_MODULE) \ diff --git a/drivers/media/video/cx231xx/cx231xx-dvb.c b/drivers/media/video/cx231xx/cx231xx-dvb.c index b55e7e0..fe59a1c 100644 --- a/drivers/media/video/cx231xx/cx231xx-dvb.c +++ b/drivers/media/video/cx231xx/cx231xx-dvb.c @@ -143,6 +143,7 @@ static struct tda18271_config hcw_tda18271_config = { static const struct mb86a20s_config pv_mb86a20s_config = { .demod_address = 0x10, + .is_serial = true, }; static struct tda18271_config pv_tda18271_config = { -- cgit v0.10.2 From 68541cdaadecbc280cd50122f11fdbb249a2ae29 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 3 Oct 2010 05:27:59 -0300 Subject: [media] Add support for Kworld SBTVD board Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/mb86a20s.c b/drivers/media/dvb/frontends/mb86a20s.c index b4de8f1..d3ad3e7 100644 --- a/drivers/media/dvb/frontends/mb86a20s.c +++ b/drivers/media/dvb/frontends/mb86a20s.c @@ -376,6 +376,9 @@ static int mb86a20s_initfe(struct dvb_frontend *fe) dprintk("\n"); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + /* Initialize the frontend */ rc = mb86a20s_writeregdata(state, mb86a20s_init); if (rc < 0) @@ -392,6 +395,9 @@ static int mb86a20s_initfe(struct dvb_frontend *fe) return rc; } + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + return 0; } @@ -403,6 +409,9 @@ static int mb86a20s_read_signal_strength(struct dvb_frontend *fe, u16 *strength) dprintk("\n"); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + /* Does a binary search to get RF strength */ rf_max = 0xfff; rf_min = 0; @@ -426,6 +435,9 @@ static int mb86a20s_read_signal_strength(struct dvb_frontend *fe, u16 *strength) dprintk("signal strength = %d\n", *strength); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + return 0; } @@ -437,7 +449,11 @@ static int mb86a20s_read_status(struct dvb_frontend *fe, fe_status_t *status) dprintk("\n"); *status = 0; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); val = mb86a20s_readreg(state, 0x0a) & 0xf; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (val >= 2) *status |= FE_HAS_SIGNAL; @@ -467,8 +483,15 @@ static int mb86a20s_set_frontend(struct dvb_frontend *fe, dprintk("\n"); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); fe->ops.tuner_ops.set_params(fe, p); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); rc = mb86a20s_writeregdata(state, mb86a20s_reset_reception); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); return rc; } diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 1d4d0a4..58c8c03 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5176,6 +5176,47 @@ struct saa7134_board saa7134_boards[] = { .amux = 2, }, }, + [SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG] = { + .name = "Kworld PCI SBTVD/ISDB-T Full-Seg Hybrid", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_NXP_TDA18271, /* TUNER_PHILIPS_TDA8290 */ + .radio_type = UNSET, + .tuner_addr = 0x60, + .radio_addr = ADDR_UNSET, + .gpiomask = 0x8e054000, + .mpeg = SAA7134_MPEG_DVB, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, +#if 0 /* FIXME */ + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + .gpio = 0x200, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + .gpio = 0x200, +#endif + } }, +#if 0 + .radio = { + .name = name_radio, + .vmux = 1, + .amux = LINE1, + .gpio = 0x100, + }, +#endif + .mute = { + .name = name_mute, + .vmux = 0, + .amux = TV, + }, + }, [SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS] = { .name = "Avermedia AVerTV GO 007 FM Plus", .audio_clock = 0x00187de7, @@ -6615,6 +6656,12 @@ struct pci_device_id saa7134_pci_tbl[] = { }, { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x17de, + .subdevice = 0xb136, + .driver_data = SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x1461, /* Avermedia Technologies Inc */ .subdevice = 0xf31d, .driver_data = SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS, @@ -6831,6 +6878,23 @@ static inline int saa7134_tda18271_hvr11x0_toggle_agc(struct saa7134_dev *dev, return 0; } +static inline int saa7134_kworld_sbtvd_toggle_agc(struct saa7134_dev *dev, + enum tda18271_mode mode) +{ + /* toggle AGC switch through GPIO 27 */ + switch (mode) { + case TDA18271_ANALOG: + saa7134_set_gpio(dev, 27, 0); + break; + case TDA18271_DIGITAL: + saa7134_set_gpio(dev, 27, 1); + break; + default: + return -EINVAL; + } + return 0; +} + static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev, int command, int arg) { @@ -6843,6 +6907,9 @@ static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev, case SAA7134_BOARD_HAUPPAUGE_HVR1120: ret = saa7134_tda18271_hvr11x0_toggle_agc(dev, arg); break; + case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: + ret = saa7134_kworld_sbtvd_toggle_agc(dev, arg); + break; default: break; } @@ -6863,6 +6930,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev, case SAA7134_BOARD_HAUPPAUGE_HVR1150: case SAA7134_BOARD_HAUPPAUGE_HVR1120: case SAA7134_BOARD_AVERMEDIA_M733A: + case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: /* tda8290 + tda18271 */ ret = saa7134_tda8290_18271_callback(dev, command, arg); break; @@ -7541,6 +7609,47 @@ int saa7134_board_init2(struct saa7134_dev *dev) dev->name); break; } + case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: + { + struct i2c_msg msg = { .addr = 0x4b, .flags = 0 }; + int i; + static u8 buffer[][2] = { + {0x30, 0x31}, + {0xff, 0x00}, + {0x41, 0x03}, + {0x41, 0x1a}, + {0xff, 0x02}, + {0x34, 0x00}, + {0x45, 0x97}, + {0x45, 0xc1}, + }; + + saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x0000); + saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0000); + saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x0000); + saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000); + saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0000); + saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000); + saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x4000); + saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000); + saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0000); + saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000); + saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x4000); + + /* + * FIXME: identify what device is at addr 0x4b and what means + * this initialization + */ + for (i = 0; i < ARRAY_SIZE(buffer); i++) { + msg.buf = &buffer[i][0]; + msg.len = ARRAY_SIZE(buffer[0]); + if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) + printk(KERN_WARNING + "%s: Unable to enable tuner(%i).\n", + dev->name, i); + } + break; + } } /* switch() */ /* initialize tuner */ diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index d3b6a19..4e37b8b 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -305,6 +305,7 @@ struct saa7134_format { #define SAA7134_BOARD_BEHOLD_A7 179 #define SAA7134_BOARD_AVERMEDIA_M733A 180 #define SAA7134_BOARD_TECHNOTREND_BUDGET_T3000 181 +#define SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG 182 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 -- cgit v0.10.2 From f0551efc77b0f34a93a14d2bf96051612e352a39 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 3 Oct 2010 07:01:26 -0300 Subject: [media] Add DVB support for SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 58c8c03..ff23e6e 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5179,12 +5179,23 @@ struct saa7134_board saa7134_boards[] = { [SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG] = { .name = "Kworld PCI SBTVD/ISDB-T Full-Seg Hybrid", .audio_clock = 0x00187de7, +#if 0 + /* + * FIXME: Analog mode doesn't work, if digital is enabled. The proper + * fix is to use tda8290 driver, but Kworld seems to use an + * unsupported version of tda8295. + */ .tuner_type = TUNER_NXP_TDA18271, /* TUNER_PHILIPS_TDA8290 */ - .radio_type = UNSET, .tuner_addr = 0x60, +#else + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, +#endif + .radio_type = UNSET, .radio_addr = ADDR_UNSET, .gpiomask = 0x8e054000, .mpeg = SAA7134_MPEG_DVB, + .ts_type = SAA7134_MPEG_TS_PARALLEL, .inputs = { { .name = name_tv, .vmux = 1, @@ -7623,16 +7634,6 @@ int saa7134_board_init2(struct saa7134_dev *dev) {0x45, 0x97}, {0x45, 0xc1}, }; - - saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x0000); - saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0000); - saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x0000); - saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000); - saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0000); - saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000); - saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x4000); - saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000); - saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0000); saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000); saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x4000); diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index beb95e2..3315a48 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -52,6 +52,7 @@ #include "tda18271.h" #include "lgdt3305.h" #include "tda8290.h" +#include "mb86a20s.h" #include "zl10353.h" @@ -228,6 +229,20 @@ static struct mt352_config avermedia_xc3028_mt352_dev = { .demod_init = mt352_avermedia_xc3028_init, }; +static struct tda18271_std_map mb86a20s_tda18271_std_map = { + .dvbt_6 = { .if_freq = 3300, .agc_mode = 3, .std = 4, + .if_lvl = 7, .rfagc_top = 0x37, }, +}; + +static struct tda18271_config kworld_tda18271_config = { + .std_map = &mb86a20s_tda18271_std_map, + .gate = TDA18271_GATE_DIGITAL, +}; + +static const struct mb86a20s_config kworld_mb86a20s_config = { + .demod_address = 0x10, +}; + /* ================================================================== * tda1004x based DVB-T cards, helper functions */ @@ -608,6 +623,37 @@ static struct tda827x_config tda827x_cfg_2_sw42 = { /* ------------------------------------------------------------------ */ +static int __kworld_sbtvd_i2c_gate_ctrl(struct saa7134_dev *dev, int enable) +{ + unsigned char initmsg[] = {0x45, 0x97}; + unsigned char msg_enable[] = {0x45, 0xc1}; + unsigned char msg_disable[] = {0x45, 0x81}; + struct i2c_msg msg = {.addr = 0x4b, .flags = 0, .buf = initmsg, .len = 2}; + + if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) { + wprintk("could not access the I2C gate\n"); + return -EIO; + } + if (enable) + msg.buf = msg_enable; + else + msg.buf = msg_disable; + if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) { + wprintk("could not access the I2C gate\n"); + return -EIO; + } + msleep(20); + return 0; +} +static int kworld_sbtvd_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct saa7134_dev *dev = fe->dvb->priv; + + return __kworld_sbtvd_i2c_gate_ctrl(dev, enable); +} + +/* ------------------------------------------------------------------ */ + static struct tda1004x_config tda827x_lifeview_config = { .demod_address = 0x08, .invert = 1, @@ -1613,6 +1659,29 @@ static int dvb_init(struct saa7134_dev *dev) &dtv1000s_tda18271_config); } break; + case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: + __kworld_sbtvd_i2c_gate_ctrl(dev, 0); + saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x14000); + saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x14000); + msleep(20); + saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x54000); + saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x54000); + msleep(20); + fe0->dvb.frontend = dvb_attach(mb86a20s_attach, + &kworld_mb86a20s_config, + &dev->i2c_adap); + __kworld_sbtvd_i2c_gate_ctrl(dev, 1); + if (fe0->dvb.frontend != NULL) { + dvb_attach(tda18271_attach, fe0->dvb.frontend, + 0x60, &dev->i2c_adap, + &kworld_tda18271_config); + /* + * Only after success, it can initialize the gate, otherwise + * an OOPS will hit, due to kfree(fe0->dvb.frontend) + */ + fe0->dvb.frontend->ops.i2c_gate_ctrl = kworld_sbtvd_i2c_gate_ctrl; + } + break; default: wprintk("Huh? unknown DVB card?\n"); break; -- cgit v0.10.2 From 9ab66912e0cd671fbea1b99e8a37d11b14d50baf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 23 Oct 2010 13:28:33 -0300 Subject: [media] cx231xx: Add a driver for I2C-based IR Although cx231xx has a very good IR support, already supported by mceusb driver, some designs decided to add a separate I2C microcontroller chip in order to handle IR. Due to that, add a glue to ir-kbd-i2c is needed, in order to support those devices. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/video/cx231xx/Kconfig index bad836f..c37eac1 100644 --- a/drivers/media/video/cx231xx/Kconfig +++ b/drivers/media/video/cx231xx/Kconfig @@ -14,6 +14,19 @@ config VIDEO_CX231XX To compile this driver as a module, choose M here: the module will be called cx231xx +config VIDEO_CX231XX_RC + bool "Conexant cx231xx Remote Controller additional support" + depends on VIDEO_IR + depends on VIDEO_CX231XX + default y + ---help--- + cx231xx hardware has a builtin RX/TX support. However, a few + designs opted to not use it, but, instead, some other hardware. + This module enables the usage of those other hardware, like the + ones used with ISDB-T boards. + + On most cases, all you need for IR is mceusb module. + config VIDEO_CX231XX_ALSA tristate "Conexant Cx231xx ALSA audio module" depends on VIDEO_CX231XX && SND diff --git a/drivers/media/video/cx231xx/Makefile b/drivers/media/video/cx231xx/Makefile index a6bc4cc..2c24843 100644 --- a/drivers/media/video/cx231xx/Makefile +++ b/drivers/media/video/cx231xx/Makefile @@ -1,5 +1,6 @@ -cx231xx-objs := cx231xx-video.o cx231xx-i2c.o cx231xx-cards.o cx231xx-core.o \ - cx231xx-avcore.o cx231xx-417.o cx231xx-pcb-cfg.o cx231xx-vbi.o +cx231xx-y += cx231xx-video.o cx231xx-i2c.o cx231xx-cards.o cx231xx-core.o +cx231xx-y += cx231xx-avcore.o cx231xx-417.o cx231xx-pcb-cfg.o cx231xx-vbi.o +cx231xx-$(CONFIG_VIDEO_CX231XX_RC) += cx231xx-input.o cx231xx-alsa-objs := cx231xx-audio.o diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 400447f..0a06fca 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c @@ -663,8 +663,11 @@ void cx231xx_release_resources(struct cx231xx *dev) cx231xx_remove_from_devlist(dev); + /* Release I2C buses */ cx231xx_dev_uninit(dev); + cx231xx_ir_exit(dev); + usb_put_dev(dev->udev); /* Mark device as unused */ @@ -782,6 +785,8 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, goto fail_reg_devices; } + cx231xx_ir_init(dev); + cx231xx_init_extension(dev); return 0; diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c index d6028c9..44d124c 100644 --- a/drivers/media/video/cx231xx/cx231xx-core.c +++ b/drivers/media/video/cx231xx/cx231xx-core.c @@ -1289,7 +1289,7 @@ int cx231xx_dev_init(struct cx231xx *dev) /* Internal Master 3 Bus */ dev->i2c_bus[2].nr = 2; dev->i2c_bus[2].dev = dev; - dev->i2c_bus[2].i2c_period = I2C_SPEED_400K; /* 400kHz */ + dev->i2c_bus[2].i2c_period = I2C_SPEED_100K; /* 100kHz */ dev->i2c_bus[2].i2c_nostop = 0; dev->i2c_bus[2].i2c_reserve = 0; diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c new file mode 100644 index 0000000..6725244 --- /dev/null +++ b/drivers/media/video/cx231xx/cx231xx-input.c @@ -0,0 +1,122 @@ +/* + * cx231xx IR glue driver + * + * Copyright (C) 2010 Mauro Carvalho Chehab + * + * Polaris (cx231xx) has its support for IR's with a design close to MCE. + * however, a few designs are using an external I2C chip for IR, instead + * of using the one provided by the chip. + * This driver provides support for those extra devices + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include "cx231xx.h" +#include +#include + +#define MODULE_NAME "cx231xx-input" + +static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key, + u32 *ir_raw) +{ + u8 cmd; + + /* poll IR chip */ + if (1 != i2c_master_recv(ir->c, &cmd, 1)) + return -EIO; + + /* it seems that 0xFE indicates that a button is still hold + down, while 0xff indicates that no button is hold + down. 0xfe sequences are sometimes interrupted by 0xFF */ + + if (cmd == 0xff) + return 0; + + dev_dbg(&ir->input->dev, "scancode = %02x\n", cmd); + + *ir_key = cmd; + *ir_raw = cmd; + return 1; +} + +int cx231xx_ir_init(struct cx231xx *dev) +{ + struct input_dev *input_dev; + struct i2c_board_info info; + int rc; + u8 ir_i2c_bus; + + dev_dbg(&dev->udev->dev, "%s\n", __func__); + + /* Only initialize if a rc keycode map is defined */ + if (!cx231xx_boards[dev->model].rc_map) + return -ENODEV; + + input_dev = input_allocate_device(); + if (!input_dev) + return -ENOMEM; + + request_module("ir-kbd-i2c"); + + memset(&info, 0, sizeof(struct i2c_board_info)); + memset(&dev->ir.init_data, 0, sizeof(dev->ir.init_data)); + + dev->ir.input_dev = input_dev; + dev->ir.init_data.name = cx231xx_boards[dev->model].name; + dev->ir.props.priv = dev; + dev->ir.props.allowed_protos = IR_TYPE_NEC; + snprintf(dev->ir.name, sizeof(dev->ir.name), + "cx231xx IR (%s)", cx231xx_boards[dev->model].name); + usb_make_path(dev->udev, dev->ir.phys, sizeof(dev->ir.phys)); + strlcat(dev->ir.phys, "/input0", sizeof(dev->ir.phys)); + + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + info.platform_data = &dev->ir.init_data; + + input_dev->name = dev->ir.name; + input_dev->phys = dev->ir.phys; + input_dev->dev.parent = &dev->udev->dev; + input_dev->id.bustype = BUS_USB; + input_dev->id.version = 1; + input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); + input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); + + /* + * Board-dependent values + * + * For now, there's just one type of hardware design using + * an i2c device. + */ + dev->ir.init_data.get_key = get_key_isdbt; + dev->ir.init_data.ir_codes = cx231xx_boards[dev->model].rc_map; + /* The i2c micro-controller only outputs the cmd part of NEC protocol */ + dev->ir.props.scanmask = 0xff; + info.addr = 0x30; + + rc = ir_input_register(input_dev, cx231xx_boards[dev->model].rc_map, + &dev->ir.props, MODULE_NAME); + if (rc < 0) + return rc; + + /* Load and bind ir-kbd-i2c */ + ir_i2c_bus = cx231xx_boards[dev->model].ir_i2c_master; + i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info); + + return rc; +} + +void cx231xx_ir_exit(struct cx231xx *dev) +{ + if (dev->ir.input_dev) { + ir_input_unregister(dev->ir.input_dev); + dev->ir.input_dev = NULL; + } +} diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h index 8a7d0a4..a09cef4 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/video/cx231xx/cx231xx.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include "cx231xx-reg.h" @@ -345,6 +346,10 @@ struct cx231xx_board { /* i2c masters */ u8 tuner_i2c_master; u8 demod_i2c_master; + u8 ir_i2c_master; + + /* for devices with I2C chips for IR */ + char *rc_map; unsigned int max_range_640_480:1; unsigned int has_dvb:1; @@ -597,6 +602,17 @@ struct cx231xx_tsport { void *port_priv; }; +struct cx231xx_ir_t { + struct input_dev *input_dev; + char name[40]; + char phys[32]; + + struct ir_dev_props props; + + /* I2C keyboard data */ + struct IR_i2c_init_data init_data; +}; + /* main device struct */ struct cx231xx { /* generic device properties */ @@ -606,6 +622,9 @@ struct cx231xx { struct cx231xx_board board; + /* For I2C IR support */ + struct cx231xx_ir_t ir; + unsigned int stream_on:1; /* Locks streams */ unsigned int vbi_stream_on:1; /* Locks streams for VBI */ unsigned int has_audio_class:1; @@ -617,8 +636,6 @@ struct cx231xx { struct v4l2_subdev *sd_cx25840; struct v4l2_subdev *sd_tuner; - struct cx231xx_IR *ir; - struct work_struct wq_trigger; /* Trigger to start/stop audio for alsa module */ atomic_t stream_started; /* stream should be running if true */ @@ -955,6 +972,17 @@ int cx231xx_tuner_callback(void *ptr, int component, int command, int arg); extern int cx231xx_417_register(struct cx231xx *dev); extern void cx231xx_417_unregister(struct cx231xx *dev); +/* cx23885-input.c */ + +#if defined(CONFIG_VIDEO_CX231XX_RC) +int cx231xx_ir_init(struct cx231xx *dev); +void cx231xx_ir_exit(struct cx231xx *dev); +#else +#define cx231xx_ir_init(dev) (0) +#define cx231xx_ir_exit(dev) (0) +#endif + + /* printk macros */ #define cx231xx_err(fmt, arg...) do {\ -- cgit v0.10.2 From 1bc25f7d6c0f353d3c73252048fe03a3d8f0e6b8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 23 Oct 2010 13:35:58 -0300 Subject: [media] cx231xx: Add IR support for Pixelview Hybrid SBTVD Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 0a06fca..83772eb 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c @@ -411,6 +411,8 @@ struct cx231xx_board cx231xx_boards[] = { .gpio_pin_status_mask = 0x4001000, .tuner_i2c_master = 2, .demod_i2c_master = 1, + .ir_i2c_master = 2, + .rc_map = RC_MAP_PIXELVIEW_NEW, .has_dvb = 1, .demod_addr = 0x10, .norm = V4L2_STD_PAL_M, -- cgit v0.10.2 From c429e7b62a54bf34c1995b45faeaeb84104f1705 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 25 Oct 2010 23:44:25 -0300 Subject: [media] drivers/media: Removed unnecessary KERN_s from dprintk uses Converted if (debug >= 2) printk(KERN_DEBUG... to if debug >= 2) dprintk(...) Signed-off-by: Joe Perches Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/tuners/max2165.c b/drivers/media/common/tuners/max2165.c index 937e4b0..9883617 100644 --- a/drivers/media/common/tuners/max2165.c +++ b/drivers/media/common/tuners/max2165.c @@ -52,13 +52,12 @@ static int max2165_write_reg(struct max2165_priv *priv, u8 reg, u8 data) msg.addr = priv->config->i2c_address; if (debug >= 2) - printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n", - __func__, reg, data); + dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, data); ret = i2c_transfer(priv->i2c, &msg, 1); if (ret != 1) - dprintk(KERN_DEBUG "%s: error reg=0x%x, data=0x%x, ret=%i\n", + dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n", __func__, reg, data, ret); return (ret != 1) ? -EIO : 0; @@ -78,14 +77,13 @@ static int max2165_read_reg(struct max2165_priv *priv, u8 reg, u8 *p_data) ret = i2c_transfer(priv->i2c, msg, 2); if (ret != 2) { - dprintk(KERN_DEBUG "%s: error reg=0x%x, ret=%i\n", - __func__, reg, ret); + dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg, ret); return -EIO; } *p_data = b1[0]; if (debug >= 2) - printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n", + dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, b1[0]); return 0; } diff --git a/drivers/media/dvb/frontends/atbm8830.c b/drivers/media/dvb/frontends/atbm8830.c index 43aac2f..1539ea1 100644 --- a/drivers/media/dvb/frontends/atbm8830.c +++ b/drivers/media/dvb/frontends/atbm8830.c @@ -50,8 +50,7 @@ static int atbm8830_write_reg(struct atbm_state *priv, u16 reg, u8 data) msg2.addr = dev_addr; if (debug >= 2) - printk(KERN_DEBUG "%s: reg=0x%04X, data=0x%02X\n", - __func__, reg, data); + dprintk("%s: reg=0x%04X, data=0x%02X\n", __func__, reg, data); ret = i2c_transfer(priv->i2c, &msg1, 1); if (ret != 1) @@ -77,8 +76,7 @@ static int atbm8830_read_reg(struct atbm_state *priv, u16 reg, u8 *p_data) ret = i2c_transfer(priv->i2c, &msg1, 1); if (ret != 1) { - dprintk(KERN_DEBUG "%s: error reg=0x%04x, ret=%i\n", - __func__, reg, ret); + dprintk("%s: error reg=0x%04x, ret=%i\n", __func__, reg, ret); return -EIO; } @@ -88,7 +86,7 @@ static int atbm8830_read_reg(struct atbm_state *priv, u16 reg, u8 *p_data) *p_data = buf2[0]; if (debug >= 2) - printk(KERN_DEBUG "%s: reg=0x%04X, data=0x%02X\n", + dprintk("%s: reg=0x%04X, data=0x%02X\n", __func__, reg, buf2[0]); return 0; diff --git a/drivers/media/dvb/frontends/lgs8gxx.c b/drivers/media/dvb/frontends/lgs8gxx.c index 0fcddc4..1172b54 100644 --- a/drivers/media/dvb/frontends/lgs8gxx.c +++ b/drivers/media/dvb/frontends/lgs8gxx.c @@ -60,13 +60,12 @@ static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data) msg.addr += 0x02; if (debug >= 2) - printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n", - __func__, reg, data); + dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, data); ret = i2c_transfer(priv->i2c, &msg, 1); if (ret != 1) - dprintk(KERN_DEBUG "%s: error reg=0x%x, data=0x%x, ret=%i\n", + dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n", __func__, reg, data, ret); return (ret != 1) ? -1 : 0; @@ -91,15 +90,13 @@ static int lgs8gxx_read_reg(struct lgs8gxx_state *priv, u8 reg, u8 *p_data) ret = i2c_transfer(priv->i2c, msg, 2); if (ret != 2) { - dprintk(KERN_DEBUG "%s: error reg=0x%x, ret=%i\n", - __func__, reg, ret); + dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg, ret); return -1; } *p_data = b1[0]; if (debug >= 2) - printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n", - __func__, reg, b1[0]); + dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, b1[0]); return 0; } diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 46d31df..b6c682f 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -972,7 +972,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) an existing device. Weird... REVISIT: might no longer be needed */ rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); - dprintk(KERN_DEBUG "probe 0x%02x @ %s: %s\n", + dprintk("probe 0x%02x @ %s: %s\n", msg_msi.addr, dev->i2c_adap.name, (1 == rc) ? "yes" : "no"); break; diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index 3e7d2fd..57e646b 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -550,16 +550,16 @@ static int tvaudio_thread(void *data) } else if (0 != dev->last_carrier) { /* no carrier -- try last detected one as fallback */ carrier = dev->last_carrier; - dprintk(KERN_WARNING "%s/audio: audio carrier scan failed, " - "using %d.%03d MHz [last detected]\n", - dev->name, carrier/1000, carrier%1000); + dprintk("audio carrier scan failed, " + "using %d.%03d MHz [last detected]\n", + carrier/1000, carrier%1000); } else { /* no carrier + no fallback -- use default */ carrier = default_carrier; - dprintk(KERN_WARNING "%s/audio: audio carrier scan failed, " - "using %d.%03d MHz [default]\n", - dev->name, carrier/1000, carrier%1000); + dprintk("audio carrier scan failed, " + "using %d.%03d MHz [default]\n", + carrier/1000, carrier%1000); } tvaudio_setcarrier(dev,carrier,carrier); dev->automute = 0; -- cgit v0.10.2 From ea7c681e899bda3fceb37815d63d201c3b4be920 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 27 Oct 2010 10:55:00 -0300 Subject: [media] cafe_ccic: fix colorspace corruption on resume If you suspend and resume during video capture, the video colours are corrupted on resume. This is because the sensor is being unconditionally powered off during the resume path. Only power down during resume if the camera is not in use, and correctly reconfigure the sensor during resume. Fixes http://dev.laptop.org/ticket/10190 Signed-off-by: Daniel Drake Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 0dfff50..789087c 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -859,8 +859,6 @@ static int cafe_cam_configure(struct cafe_camera *cam) struct v4l2_mbus_framefmt mbus_fmt; int ret; - if (cam->state != S_IDLE) - return -EINVAL; v4l2_fill_mbus_format(&mbus_fmt, &cam->pix_format, cam->mbus_code); ret = sensor_call(cam, core, init, 0); if (ret == 0) @@ -2196,12 +2194,13 @@ static int cafe_pci_resume(struct pci_dev *pdev) return ret; } cafe_ctlr_init(cam); - cafe_ctlr_power_down(cam); mutex_lock(&cam->s_mutex); if (cam->users > 0) { cafe_ctlr_power_up(cam); __cafe_cam_reset(cam); + } else { + cafe_ctlr_power_down(cam); } mutex_unlock(&cam->s_mutex); -- cgit v0.10.2 From f23e6616ac2dc560db0ee8733024ebe90de9161a Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Wed, 27 Oct 2010 19:50:36 -0300 Subject: [media] lmed04: Improve frontend handling Improved frontend handling. Frontend now remains open at all times, with signal lock, snr & signal level polled from Interupt. Updated driver for DM04/QQBOX USB DVB-S BOXES to version 1.70. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c index d939fbb..3a32c65 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/drivers/media/dvb/dvb-usb/lmedm04.c @@ -112,7 +112,6 @@ struct lme2510_state { u8 i2c_tuner_gate_r; u8 i2c_tuner_addr; u8 stream_on; - u8 one_tune; void *buffer; struct urb *lme_urb; void *usb_buffer; @@ -182,15 +181,13 @@ static int lme2510_usb_talk(struct dvb_usb_device *d, return (ret < 0) ? -ENODEV : 0; } -static int lme2510_usb_talk_restart(struct dvb_usb_device *d, - u8 *wbuf, int wlen, u8 *rbuf, int rlen) { +static int lme2510_stream_restart(struct dvb_usb_device *d) +{ static u8 stream_on[] = LME_ST_ON_W; int ret; u8 rbuff[10]; - /*Send Normal Command*/ - ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); /*Restart Stream Command*/ - ret |= lme2510_usb_talk(d, stream_on, sizeof(stream_on), + ret = lme2510_usb_talk(d, stream_on, sizeof(stream_on), rbuff, sizeof(rbuff)); return ret; } @@ -254,11 +251,16 @@ static void lme2510_int_response(struct urb *lme_urb) case TUNER_S7395: /* Tweak for earlier firmware*/ if (ibuf[1] == 0x03) { + if (ibuf[2] > 1) + st->signal_lock = ibuf[2]; st->signal_level = ibuf[3]; st->signal_sn = ibuf[4]; } else { st->signal_level = ibuf[4]; st->signal_sn = ibuf[5]; + st->signal_lock = + (st->signal_lock & 0xf7) + + ((ibuf[2] & 0x01) << 0x03); } break; default: @@ -341,11 +343,10 @@ static int lme2510_msg(struct dvb_usb_device *d, st->signal_lock = rbuf[1]; if ((st->stream_on & 1) && (st->signal_lock & 0x10)) { - lme2510_usb_talk_restart(d, - wbuf, wlen, rbuf, rlen); + lme2510_stream_restart(d); st->i2c_talk_onoff = 0; } - msleep(80); + msleep(80); } } break; @@ -355,15 +356,12 @@ static int lme2510_msg(struct dvb_usb_device *d, st->signal_lock = rbuf[1]; if ((st->stream_on & 1) && (st->signal_lock & 0x8)) { - lme2510_usb_talk_restart(d, - wbuf, wlen, rbuf, rlen); + lme2510_stream_restart(d); st->i2c_talk_onoff = 0; } } if ((wbuf[3] != 0x6) & (wbuf[3] != 0x5)) msleep(5); - - } break; default: @@ -385,18 +383,16 @@ static int lme2510_msg(struct dvb_usb_device *d, rbuf[0] = 0x55; rbuf[1] = st->signal_sn; break; - /*DiSEqC functions as per TDA10086*/ - case 0x36: - case 0x48: - case 0x49: - case 0x4a: - case 0x4b: - case 0x4c: - case 0x4d: - if (wbuf[2] == 0x1c) - lme2510_usb_talk_restart(d, - wbuf, wlen, rbuf, rlen); + case 0x15: + case 0x16: + case 0x17: + case 0x18: + rbuf[0] = 0x55; + rbuf[1] = 0x00; + break; default: + lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); + st->i2c_talk_onoff = 1; break; } break; @@ -413,39 +409,22 @@ static int lme2510_msg(struct dvb_usb_device *d, break; case 0x24: rbuf[0] = 0x55; - rbuf[1] = (st->signal_level & 0x80) - ? 0 : st->signal_lock; - break; - case 0x6: - if (wbuf[2] == 0xd0) - lme2510_usb_talk(d, - wbuf, wlen, rbuf, rlen); - break; - case 0x1: - if (st->one_tune > 0) - break; - st->one_tune++; - st->i2c_talk_onoff = 1; - /*DiSEqC functions as per STV0288*/ - case 0x5: - case 0x7: - case 0x8: - case 0x9: - case 0xa: - case 0xb: - if (wbuf[2] == 0xd0) - lme2510_usb_talk_restart(d, - wbuf, wlen, rbuf, rlen); + rbuf[1] = st->signal_lock; break; - default: + case 0x2e: + case 0x26: + case 0x27: rbuf[0] = 0x55; rbuf[1] = 0x00; break; + default: + lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); + st->i2c_talk_onoff = 1; + break; } break; default: break; - } deb_info(4, "I2C From Interupt Message out(%02x) in(%02x)", @@ -548,35 +527,26 @@ static int lme2510_identify_state(struct usb_device *udev, static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) { struct lme2510_state *st = adap->dev->priv; - static u8 stream_on[] = LME_ST_ON_W; static u8 clear_reg_3[] = LME_CLEAR_PID; static u8 rbuf[1]; - static u8 timeout; - int ret = 0, len = 2, rlen = sizeof(rbuf); + int ret = 0, rlen = sizeof(rbuf); deb_info(1, "STM (%02x)", onoff); - if (onoff == 1) { - st->i2c_talk_onoff = 0; - timeout = 0; - /* wait for i2C to be free */ - while (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) { - timeout++; - if (timeout > 5) - return -ENODEV; - } - msleep(100); - ret |= lme2510_usb_talk(adap->dev, - stream_on, len, rbuf, rlen); + /* Streaming is started by FE_HAS_LOCK */ + if (onoff == 1) st->stream_on = 1; - st->one_tune = 0; - mutex_unlock(&adap->dev->i2c_mutex); - } else { + else { deb_info(1, "STM Steam Off"); + /* mutex is here only to avoid collision with I2C */ + ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); + ret |= lme2510_usb_talk(adap->dev, clear_reg_3, sizeof(clear_reg_3), rbuf, rlen); st->stream_on = 0; st->i2c_talk_onoff = 1; + + mutex_unlock(&adap->dev->i2c_mutex); } return (ret < 0) ? -ENODEV : 0; @@ -619,6 +589,7 @@ static int lme2510_int_service(struct dvb_usb_adapter *adap) ir_input_unregister(input_dev); input_free_device(input_dev); } + return (ret < 0) ? -ENODEV : 0; } @@ -668,6 +639,7 @@ static int lme2510_download_firmware(struct usb_device *dev, ret |= (data[0] == 0x88) ? 0 : -1; } } + usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x06, 0x80, 0x0200, 0x00, data, 0x0109, 1000); @@ -701,6 +673,7 @@ static void lme_coldreset(struct usb_device *dev) info("FRM Firmware Cold Reset"); ret |= lme2510_bulk_write(dev, data , len_in, 1); /*Cold Resetting*/ ret |= lme2510_bulk_read(dev, data, len_in, 1); + return; } @@ -712,6 +685,8 @@ static void lme_firmware_switch(struct usb_device *udev, int cold) char *firm_msg[] = {"Loading", "Switching to"}; int ret; + cold = (cold > 0) ? (cold & 1) : 0; + if (udev->descriptor.idProduct == 0x1122) return; @@ -740,22 +715,26 @@ static void lme_firmware_switch(struct usb_device *udev, int cold) cold = 0; break; } + release_firmware(fw); + if (cold) lme_coldreset(udev); + return; } static int lme2510_kill_urb(struct usb_data_stream *stream) { int i; + for (i = 0; i < stream->urbs_submitted; i++) { deb_info(3, "killing URB no. %d.", i); - /* stop the URB */ usb_kill_urb(stream->urb_list[i]); } stream->urbs_submitted = 0; + return 0; } @@ -783,18 +762,13 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { struct dvb_usb_adapter *adap = fe->dvb->priv; - struct lme2510_state *st = adap->dev->priv; static u8 voltage_low[] = LME_VOLTAGE_L; static u8 voltage_high[] = LME_VOLTAGE_H; - static u8 lnb_on[] = LNB_ON; - static u8 lnb_off[] = LNB_OFF; static u8 rbuf[1]; int ret = 0, len = 3, rlen = 1; - if (st->stream_on == 1) - return 0; - - ret |= lme2510_usb_talk(adap->dev, lnb_on, len, rbuf, rlen); + if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) + return -EAGAIN; switch (voltage) { case SEC_VOLTAGE_18: @@ -803,17 +777,15 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, break; case SEC_VOLTAGE_OFF: - ret |= lme2510_usb_talk(adap->dev, - lnb_off, len, rbuf, rlen); case SEC_VOLTAGE_13: default: ret |= lme2510_usb_talk(adap->dev, voltage_low, len, rbuf, rlen); break; + } + mutex_unlock(&adap->dev->i2c_mutex); - }; - st->i2c_talk_onoff = 1; return (ret < 0) ? -ENODEV : 0; } @@ -850,12 +822,14 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) if (dvb_usb_lme2510_firmware != 1) { dvb_usb_lme2510_firmware = 1; lme_firmware_switch(adap->dev->udev, 1); - } + } else /*stops LG/Sharp multi tuner problems*/ + dvb_usb_lme2510_firmware = 0; return 0; } kfree(adap->fe); adap->fe = NULL; } + st->i2c_gate = 5; adap->fe = dvb_attach(stv0288_attach, &lme_config, &adap->dev->i2c_adap); @@ -889,8 +863,23 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) static int lme2510_powerup(struct dvb_usb_device *d, int onoff) { struct lme2510_state *st = d->priv; + static u8 lnb_on[] = LNB_ON; + static u8 lnb_off[] = LNB_OFF; + static u8 rbuf[1]; + int ret, len = 3, rlen = 1; + + ret = mutex_lock_interruptible(&d->i2c_mutex); + + if (onoff) + ret |= lme2510_usb_talk(d, lnb_on, len, rbuf, rlen); + else + ret |= lme2510_usb_talk(d, lnb_off, len, rbuf, rlen); + st->i2c_talk_onoff = 1; - return 0; + + mutex_unlock(&d->i2c_mutex); + + return ret; } /* DVB USB Driver stuff */ @@ -1084,5 +1073,5 @@ module_exit(lme2510_module_exit); MODULE_AUTHOR("Malcolm Priestley "); MODULE_DESCRIPTION("LM2510(C) DVB-S USB2.0"); -MODULE_VERSION("1.60"); +MODULE_VERSION("1.70"); MODULE_LICENSE("GPL"); -- cgit v0.10.2 From afcd0806094d9ae0d944f30776edc075e4584b96 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Tue, 2 Nov 2010 18:02:08 -0300 Subject: [media] Documentation/lmedm04: Fix firmware extract information Corrected Firmware Information for LG on LME2510. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/dvb/lmedm04.txt b/Documentation/dvb/lmedm04.txt index e175784..6418865 100644 --- a/Documentation/dvb/lmedm04.txt +++ b/Documentation/dvb/lmedm04.txt @@ -46,7 +46,7 @@ and run Other LG firmware can be extracted manually from US280D.sys only found in windows/system32/driver. -dd if=US280D.sys ibs=1 skip=42616 count=3668 of=dvb-usb-lme2510-lg.fw +dd if=US280D.sys ibs=1 skip=42360 count=3924 of=dvb-usb-lme2510-lg.fw for DM04 LME2510C (LG Tuner) --------------------------- -- cgit v0.10.2 From 25ad9847ca09f744b4cfea362d339c8b5b49765c Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Thu, 4 Nov 2010 17:17:51 -0300 Subject: [media] lmedm04: change USB Timeouts to avoid troubles DM04/QQBOX USB Timing change. Improved timing to avoid USB corruptions on some systems. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c index 3a32c65..de7f1fb 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/drivers/media/dvb/dvb-usb/lmedm04.c @@ -124,7 +124,7 @@ static int lme2510_bulk_write(struct usb_device *dev, int ret, actual_l; ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe), - snd, len , &actual_l, 500); + snd, len , &actual_l, 100); return ret; } @@ -134,7 +134,7 @@ static int lme2510_bulk_read(struct usb_device *dev, int ret, actual_l; ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe), - rev, len , &actual_l, 500); + rev, len , &actual_l, 200); return ret; } @@ -166,7 +166,7 @@ static int lme2510_usb_talk(struct dvb_usb_device *d, ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01); - msleep(12); + msleep(10); ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01)); @@ -1073,5 +1073,5 @@ module_exit(lme2510_module_exit); MODULE_AUTHOR("Malcolm Priestley "); MODULE_DESCRIPTION("LM2510(C) DVB-S USB2.0"); -MODULE_VERSION("1.70"); +MODULE_VERSION("1.71"); MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 314b3e0881c6acb4f40e07565ac1a7798c7698a3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 26 Oct 2010 05:15:46 -0300 Subject: [media] gspca: submit interrupt urbs *after* isoc urbs Currently gspca supported usb-1.1 webcams for which we support the input button through an interrupt endpoint won't stream (not enough bandwidth error) when used through an USB-2.0 hub. After much debugging I've found out that the cause for this is that the ehci-sched.c schedeling code does not like it when there are already urb's scheduled when (large) isoc urbs are queued. By moving the submission of the interrupt urbs to after submitting the isoc urbs the camera starts working again through usb-2.0 hubs. Note that this does not fix isoc. streaming through a usb-hub while another 1.1 usb device (like the microphone of the same cam) is also active at the same time :( I've spend a long time analyzing the linux kernel ehci scheduler code, resulting in this (long) mail: http://www.spinics.net/lists/linux-usb/msg37982.html The conclusion of the following mail thread is that yes there are several issues when using usb-1.1 devices through a usb-2.0 hub, but these are not easily fixable in the current code. Fixing this in ehci-sched.c requires an almost full rewrite, which is not bound to happen anytime soon. So with this patch gspca driven usb-1.1 webcams will atleast work when connected through an usb-2.0 hub when the microphone is not used. As an added bonus this patch avoids extra destroy/create input urb cycles when we end up falling back to a lower speed alt setting because of bandwidth limitations. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 8fe8fb4..dbd63c5 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -676,13 +676,11 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) i, ep->desc.bEndpointAddress); gspca_dev->alt = i; /* memorize the current alt setting */ if (gspca_dev->nbalt > 1) { - gspca_input_destroy_urb(gspca_dev); ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); if (ret < 0) { err("set alt %d err %d", i, ret); ep = NULL; } - gspca_input_create_urb(gspca_dev); } return ep; } @@ -781,7 +779,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) if (!gspca_dev->present) { ret = -ENODEV; - goto out; + goto unlock; } /* reset the streaming variables */ @@ -802,8 +800,10 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) if (gspca_dev->sd_desc->isoc_init) { ret = gspca_dev->sd_desc->isoc_init(gspca_dev); if (ret < 0) - goto out; + goto unlock; } + + gspca_input_destroy_urb(gspca_dev); ep = get_ep(gspca_dev); if (ep == NULL) { ret = -EIO; @@ -873,6 +873,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) } } out: + gspca_input_create_urb(gspca_dev); +unlock: mutex_unlock(&gspca_dev->usb_lock); return ret; } -- cgit v0.10.2 From 2661da47daefd4f22f9fdc7e9294a1cb9edf515b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 26 Oct 2010 05:16:32 -0300 Subject: [media] gspca: only set gspca->int_urb if submitting it succeeds Currently alloc_and_submit_int_urb() is setting gspca->int_urb as soon as the allocation has succeeded, but if the subsequent submit fails, the urb gets destroyed. And then later will get destroyed again in gspca_input_destroy_urb() because gspca->int_urb is set, leading to a double free. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index dbd63c5..a089fca 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -224,12 +224,12 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev, buffer, buffer_len, int_irq, (void *)gspca_dev, interval); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - gspca_dev->int_urb = urb; ret = usb_submit_urb(urb, GFP_KERNEL); if (ret < 0) { PDEBUG(D_ERR, "submit int URB failed with error %i", ret); goto error_submit; } + gspca_dev->int_urb = urb; return ret; error_submit: -- cgit v0.10.2 From bc46bae6373c87897959c7aa8fb9f6c4218695b8 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 26 Oct 2010 11:18:59 -0300 Subject: [media] gspca_xirlink_cit: various usb bandwidth allocation improvements / fixes The following usb bandwidth allocation changes were made to the ibm netcam pro code: - Don't restart negotiation at max packet size on stop0, as that gets called by gspca_main during negotiation. Move this to sd_isoc_init. - Don't ask for full bandwidth when running at 160x120, that does not need full bandwidth - Make minimum acceptable bandwidth depend upon resolution [mchehab@redhat.com: Fix CodingStyle problems at switch statements] Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/xirlink_cit.c b/drivers/media/video/gspca/xirlink_cit.c index 8715577..daeda2c 100644 --- a/drivers/media/video/gspca/xirlink_cit.c +++ b/drivers/media/video/gspca/xirlink_cit.c @@ -2769,16 +2769,55 @@ static int sd_start(struct gspca_dev *gspca_dev) return 0; } +static int sd_isoc_init(struct gspca_dev *gspca_dev) +{ + struct usb_host_interface *alt; + int max_packet_size; + + switch (gspca_dev->width) { + case 160: + max_packet_size = 450; + break; + case 176: + max_packet_size = 600; + break; + default: + max_packet_size = 1022; + break; + } + + /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ + alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; + alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size); + + return 0; +} + static int sd_isoc_nego(struct gspca_dev *gspca_dev) { - int ret, packet_size; + int ret, packet_size, min_packet_size; struct usb_host_interface *alt; + switch (gspca_dev->width) { + case 160: + min_packet_size = 200; + break; + case 176: + min_packet_size = 266; + break; + default: + min_packet_size = 400; + break; + } + alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); - packet_size -= 100; - if (packet_size < 300) + if (packet_size <= min_packet_size) return -EIO; + + packet_size -= 100; + if (packet_size < min_packet_size) + packet_size = min_packet_size; alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size); ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); @@ -2796,15 +2835,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev) static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - struct usb_host_interface *alt; /* We cannot use gspca_dev->present here as that is not set when sd_init gets called and we get called from sd_init */ if (!gspca_dev->dev) return; - alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; - switch (sd->model) { case CIT_MODEL0: /* HDG windows does this, but it causes the cams autogain to @@ -2859,10 +2895,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev) restarting the stream after this */ /* cit_write_reg(gspca_dev, 0x0000, 0x0112); */ cit_write_reg(gspca_dev, 0x00c0, 0x0100); - - /* Start isoc bandwidth "negotiation" at max isoc bandwith - next stream start */ - alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(1022); break; } } @@ -3179,6 +3211,7 @@ static const struct sd_desc sd_desc_isoc_nego = { .config = sd_config, .init = sd_init, .start = sd_start, + .isoc_init = sd_isoc_init, .isoc_nego = sd_isoc_nego, .stopN = sd_stopN, .stop0 = sd_stop0, -- cgit v0.10.2 From 2c4e776aa370a7a1619c7ada0604e9003fe1d92a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 26 Oct 2010 17:21:33 -0300 Subject: [media] gspca_xirlink_cit: Frames have a 4 byte footer At least on the ibm netcam pro frames have a 4 byte footer, take this into account when calculating sizeimage. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/xirlink_cit.c b/drivers/media/video/gspca/xirlink_cit.c index daeda2c..157fbed 100644 --- a/drivers/media/video/gspca/xirlink_cit.c +++ b/drivers/media/video/gspca/xirlink_cit.c @@ -185,60 +185,60 @@ static const struct ctrl sd_ctrls[] = { static const struct v4l2_pix_format cif_yuv_mode[] = { {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 2, + .sizeimage = 176 * 144 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {352, 288, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 352, - .sizeimage = 352 * 288 * 3 / 2, + .sizeimage = 352 * 288 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, }; static const struct v4l2_pix_format vga_yuv_mode[] = { {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 2, + .sizeimage = 160 * 120 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 2, + .sizeimage = 320 * 240 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {640, 480, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 2, + .sizeimage = 640 * 480 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, }; static const struct v4l2_pix_format model0_mode[] = { {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 2, + .sizeimage = 160 * 120 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 2, + .sizeimage = 176 * 144 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 2, + .sizeimage = 320 * 240 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, }; static const struct v4l2_pix_format model2_mode[] = { {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 2, + .sizeimage = 160 * 120 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 2, + .sizeimage = 176 * 144 * 3 / 2 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {320, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, .bytesperline = 320, - .sizeimage = 320 * 240, + .sizeimage = 320 * 240 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, {352, 288, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, .bytesperline = 352, - .sizeimage = 352 * 288, + .sizeimage = 352 * 288 + 4, .colorspace = V4L2_COLORSPACE_SRGB}, }; -- cgit v0.10.2 From e0657be5615f666f261206ed62c3f0dc2527956e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 27 Oct 2010 06:38:07 -0300 Subject: [media] gspca_xirlink_cit: Add support camera button gspca_xirlink_cit: Add support camera button Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/xirlink_cit.c b/drivers/media/video/gspca/xirlink_cit.c index 157fbed..5b5039a 100644 --- a/drivers/media/video/gspca/xirlink_cit.c +++ b/drivers/media/video/gspca/xirlink_cit.c @@ -29,6 +29,7 @@ #define MODULE_NAME "xirlink-cit" +#include #include "gspca.h" MODULE_AUTHOR("Hans de Goede "); @@ -58,6 +59,7 @@ struct sd { #define CIT_MODEL4 4 #define CIT_IBM_NETCAM_PRO 5 u8 input_index; + u8 button_state; u8 stop_on_control_change; u8 sof_read; u8 sof_len; @@ -804,7 +806,7 @@ static int cit_write_reg(struct gspca_dev *gspca_dev, u16 value, u16 index) return 0; } -static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index) +static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index, int verbose) { struct usb_device *udev = gspca_dev->dev; __u8 *buf = gspca_dev->usb_buf; @@ -819,10 +821,8 @@ static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index) return res; } - PDEBUG(D_PROBE, - "Register %04x value: %02x %02x %02x %02x %02x %02x %02x %02x", - index, - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); + if (verbose) + PDEBUG(D_PROBE, "Register %04x value: %02x", index, buf[0]); return 0; } @@ -907,7 +907,7 @@ static void cit_Packet_Format1(struct gspca_dev *gspca_dev, u16 fkey, u16 val) cit_send_x_00_05(gspca_dev, 0x0089); cit_send_x_00(gspca_dev, fkey); cit_send_00_04_06(gspca_dev); - cit_read_reg(gspca_dev, 0x0126); + cit_read_reg(gspca_dev, 0x0126, 0); cit_send_FF_04_02(gspca_dev); } @@ -1074,12 +1074,12 @@ static int cit_init_model0(struct gspca_dev *gspca_dev) static int cit_init_ibm_netcam_pro(struct gspca_dev *gspca_dev) { - cit_read_reg(gspca_dev, 0x128); + cit_read_reg(gspca_dev, 0x128, 1); cit_write_reg(gspca_dev, 0x0003, 0x0133); cit_write_reg(gspca_dev, 0x0000, 0x0117); cit_write_reg(gspca_dev, 0x0008, 0x0123); cit_write_reg(gspca_dev, 0x0000, 0x0100); - cit_read_reg(gspca_dev, 0x0116); + cit_read_reg(gspca_dev, 0x0116, 0); cit_write_reg(gspca_dev, 0x0060, 0x0116); cit_write_reg(gspca_dev, 0x0002, 0x0112); cit_write_reg(gspca_dev, 0x0000, 0x0133); @@ -1098,7 +1098,7 @@ static int cit_init_ibm_netcam_pro(struct gspca_dev *gspca_dev) cit_write_reg(gspca_dev, 0x00ff, 0x0130); cit_write_reg(gspca_dev, 0xcd41, 0x0124); cit_write_reg(gspca_dev, 0xfffa, 0x0124); - cit_read_reg(gspca_dev, 0x0126); + cit_read_reg(gspca_dev, 0x0126, 1); cit_model3_Packet1(gspca_dev, 0x0000, 0x0000); cit_model3_Packet1(gspca_dev, 0x0000, 0x0001); @@ -1557,18 +1557,20 @@ static int cit_restart_stream(struct gspca_dev *gspca_dev) switch (sd->model) { case CIT_MODEL0: case CIT_MODEL1: - case CIT_MODEL3: - case CIT_IBM_NETCAM_PRO: cit_write_reg(gspca_dev, 0x0001, 0x0114); /* Fall through */ case CIT_MODEL2: case CIT_MODEL4: cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */ usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe); - /* This happens repeatedly while streaming with the ibm netcam - pro and the ibmcam driver did it for model3 after changing - settings, but it does not seem to have any effect. */ - /* cit_write_reg(gspca_dev, 0x0001, 0x0113); */ + break; + case CIT_MODEL3: + case CIT_IBM_NETCAM_PRO: + cit_write_reg(gspca_dev, 0x0001, 0x0114); + cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */ + usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe); + /* Clear button events from while we were not streaming */ + cit_write_reg(gspca_dev, 0x0001, 0x0113); break; } @@ -1680,23 +1682,23 @@ static int cit_start_model1(struct gspca_dev *gspca_dev) if (clock_div < 0) return clock_div; - cit_read_reg(gspca_dev, 0x0128); - cit_read_reg(gspca_dev, 0x0100); + cit_read_reg(gspca_dev, 0x0128, 1); + cit_read_reg(gspca_dev, 0x0100, 0); cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */ - cit_read_reg(gspca_dev, 0x0100); + cit_read_reg(gspca_dev, 0x0100, 0); cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */ - cit_read_reg(gspca_dev, 0x0100); + cit_read_reg(gspca_dev, 0x0100, 0); cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */ cit_write_reg(gspca_dev, 0x01, 0x0108); cit_write_reg(gspca_dev, 0x03, 0x0112); - cit_read_reg(gspca_dev, 0x0115); + cit_read_reg(gspca_dev, 0x0115, 0); cit_write_reg(gspca_dev, 0x06, 0x0115); - cit_read_reg(gspca_dev, 0x0116); + cit_read_reg(gspca_dev, 0x0116, 0); cit_write_reg(gspca_dev, 0x44, 0x0116); - cit_read_reg(gspca_dev, 0x0116); + cit_read_reg(gspca_dev, 0x0116, 0); cit_write_reg(gspca_dev, 0x40, 0x0116); - cit_read_reg(gspca_dev, 0x0115); + cit_read_reg(gspca_dev, 0x0115, 0); cit_write_reg(gspca_dev, 0x0e, 0x0115); cit_write_reg(gspca_dev, 0x19, 0x012c); @@ -1878,7 +1880,7 @@ static int cit_start_model2(struct gspca_dev *gspca_dev) int clock_div = 0; cit_write_reg(gspca_dev, 0x0000, 0x0100); /* LED on */ - cit_read_reg(gspca_dev, 0x0116); + cit_read_reg(gspca_dev, 0x0116, 0); cit_write_reg(gspca_dev, 0x0060, 0x0116); cit_write_reg(gspca_dev, 0x0002, 0x0112); cit_write_reg(gspca_dev, 0x00bc, 0x012c); @@ -2070,10 +2072,10 @@ static int cit_start_model3(struct gspca_dev *gspca_dev) /* HDG not in ibmcam driver, added to see if it helps with auto-detecting between model3 and ibm netcamera pro */ - cit_read_reg(gspca_dev, 0x128); + cit_read_reg(gspca_dev, 0x128, 1); cit_write_reg(gspca_dev, 0x0000, 0x0100); - cit_read_reg(gspca_dev, 0x0116); + cit_read_reg(gspca_dev, 0x0116, 0); cit_write_reg(gspca_dev, 0x0060, 0x0116); cit_write_reg(gspca_dev, 0x0002, 0x0112); cit_write_reg(gspca_dev, 0x0000, 0x0123); @@ -2083,7 +2085,7 @@ static int cit_start_model3(struct gspca_dev *gspca_dev) cit_write_reg(gspca_dev, 0x0060, 0x0116); cit_write_reg(gspca_dev, 0x0002, 0x0115); cit_write_reg(gspca_dev, 0x0003, 0x0115); - cit_read_reg(gspca_dev, 0x0115); + cit_read_reg(gspca_dev, 0x0115, 0); cit_write_reg(gspca_dev, 0x000b, 0x0115); /* TESTME HDG not in ibmcam driver, added to see if it helps with @@ -2096,7 +2098,7 @@ static int cit_start_model3(struct gspca_dev *gspca_dev) cit_write_reg(gspca_dev, 0x00ff, 0x0130); cit_write_reg(gspca_dev, 0xcd41, 0x0124); cit_write_reg(gspca_dev, 0xfffa, 0x0124); - cit_read_reg(gspca_dev, 0x0126); + cit_read_reg(gspca_dev, 0x0126, 1); } cit_model3_Packet1(gspca_dev, 0x000a, 0x0040); @@ -2293,7 +2295,7 @@ static int cit_start_model3(struct gspca_dev *gspca_dev) if (rca_input) { for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) { if (rca_initdata[i][0]) - cit_read_reg(gspca_dev, rca_initdata[i][2]); + cit_read_reg(gspca_dev, rca_initdata[i][2], 0); else cit_write_reg(gspca_dev, rca_initdata[i][1], rca_initdata[i][2]); @@ -2712,7 +2714,7 @@ static int cit_start_ibm_netcam_pro(struct gspca_dev *gspca_dev) if (rca_input) { for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) { if (rca_initdata[i][0]) - cit_read_reg(gspca_dev, rca_initdata[i][2]); + cit_read_reg(gspca_dev, rca_initdata[i][2], 0); else cit_write_reg(gspca_dev, rca_initdata[i][1], rca_initdata[i][2]); @@ -2851,7 +2853,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) break; case CIT_MODEL1: cit_send_FF_04_02(gspca_dev); - cit_read_reg(gspca_dev, 0x0100); + cit_read_reg(gspca_dev, 0x0100, 0); cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */ break; case CIT_MODEL2: @@ -2870,9 +2872,9 @@ static void sd_stop0(struct gspca_dev *gspca_dev) case CIT_MODEL3: cit_write_reg(gspca_dev, 0x0006, 0x012c); cit_model3_Packet1(gspca_dev, 0x0046, 0x0000); - cit_read_reg(gspca_dev, 0x0116); + cit_read_reg(gspca_dev, 0x0116, 0); cit_write_reg(gspca_dev, 0x0064, 0x0116); - cit_read_reg(gspca_dev, 0x0115); + cit_read_reg(gspca_dev, 0x0115, 0); cit_write_reg(gspca_dev, 0x0003, 0x0115); cit_write_reg(gspca_dev, 0x0008, 0x0123); cit_write_reg(gspca_dev, 0x0000, 0x0117); @@ -2897,6 +2899,15 @@ static void sd_stop0(struct gspca_dev *gspca_dev) cit_write_reg(gspca_dev, 0x00c0, 0x0100); break; } + +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) + /* If the last button state is pressed, release it now! */ + if (sd->button_state) { + input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); + input_sync(gspca_dev->input_dev); + sd->button_state = 0; + } +#endif } static u8 *cit_find_sof(struct gspca_dev *gspca_dev, u8 *data, int len) @@ -3190,6 +3201,38 @@ static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) +static void cit_check_button(struct gspca_dev *gspca_dev) +{ + int new_button_state; + struct sd *sd = (struct sd *)gspca_dev; + + switch (sd->model) { + case CIT_MODEL3: + case CIT_IBM_NETCAM_PRO: + break; + default: /* TEST ME unknown if this works on other models too */ + return; + } + + /* Read the button state */ + cit_read_reg(gspca_dev, 0x0113, 0); + new_button_state = !gspca_dev->usb_buf[0]; + + /* Tell the cam we've seen the button press, notice that this + is a nop (iow the cam keeps reporting pressed) until the + button is actually released. */ + if (new_button_state) + cit_write_reg(gspca_dev, 0x01, 0x0113); + + if (sd->button_state != new_button_state) { + input_report_key(gspca_dev->input_dev, KEY_CAMERA, + new_button_state); + input_sync(gspca_dev->input_dev); + sd->button_state = new_button_state; + } +} +#endif /* sub-driver description */ static const struct sd_desc sd_desc = { @@ -3202,6 +3245,10 @@ static const struct sd_desc sd_desc = { .stopN = sd_stopN, .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) + .dq_callback = cit_check_button, + .other_input = 1, +#endif }; static const struct sd_desc sd_desc_isoc_nego = { @@ -3216,6 +3263,10 @@ static const struct sd_desc sd_desc_isoc_nego = { .stopN = sd_stopN, .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) + .dq_callback = cit_check_button, + .other_input = 1, +#endif }; /* -- module initialisation -- */ -- cgit v0.10.2 From 614d06917de2823d598a4b231256d08074044235 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 27 Oct 2010 07:42:28 -0300 Subject: [media] gspca_ov519: generate release button event on stream stop if needed Generate a release button event when the button is still pressed when the stream stops. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 6cf6855..19f943e 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -3912,7 +3912,6 @@ static int sd_start(struct gspca_dev *gspca_dev) pressed while we weren't streaming */ sd->snapshot_needs_reset = 1; sd_reset_snapshot(gspca_dev); - sd->snapshot_pressed = 0; sd->first_frame = 3; @@ -3940,6 +3939,15 @@ static void sd_stop0(struct gspca_dev *gspca_dev) if (sd->bridge == BRIDGE_W9968CF) w9968cf_stop0(sd); + +#ifdef CONFIG_INPUT + /* If the last button state is pressed, release it now! */ + if (sd->snapshot_pressed) { + input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); + input_sync(gspca_dev->input_dev); + sd->snapshot_pressed = 0; + } +#endif } static void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state) -- cgit v0.10.2 From 0b8851b6c3934a56eb1a4ff284ab5133065e0cb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Fri, 29 Oct 2010 07:56:06 -0300 Subject: [media] gspca - main: Version change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index a089fca..fe2c8ec 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -55,7 +55,7 @@ MODULE_AUTHOR("Jean-François Moine "); MODULE_DESCRIPTION("GSPCA USB Camera Driver"); MODULE_LICENSE("GPL"); -#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 10, 0) +#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 11, 0) #ifdef GSPCA_DEBUG int gspca_debug = D_ERR | D_PROBE; -- cgit v0.10.2 From a23c1947f4da31d9aac9bfc05ef22d8148b2f106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Fri, 29 Oct 2010 07:57:03 -0300 Subject: [media] gspca - main: Fix a small code error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index fe2c8ec..0a7af73 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -757,7 +757,7 @@ static int create_urbs(struct gspca_dev *gspca_dev, } } else { /* bulk */ urb->pipe = usb_rcvbulkpipe(gspca_dev->dev, - ep->desc.bEndpointAddress), + ep->desc.bEndpointAddress); urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; urb->complete = bulk_irq; } -- cgit v0.10.2 From d581bcd78be567af7026e3d13b54ec7df8db8b82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Fri, 29 Oct 2010 08:01:01 -0300 Subject: [media] gspca - zc3xx: Bad clocksetting for mt9v111_3 with 640x480 resolution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bad value prevented the autogain to work correctly and some images were truncated. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index c7e1970..042dc80 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -4499,7 +4499,7 @@ static const struct usb_action mt9v111_3_Initial[] = { {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, + {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, -- cgit v0.10.2 From a79cc7b9182abb2e3936a26064dec414b417f1d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Fri, 29 Oct 2010 08:10:37 -0300 Subject: [media] gspca - sonixj: Simplify and clarify the hv7131r probe function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index e23de57..901ca81 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1598,22 +1598,22 @@ static void i2c_w_seq(struct gspca_dev *gspca_dev, } } +/* check the ID of the hv7131 sensor */ +/* this sequence is needed because it activates the sensor */ static void hv7131r_probe(struct gspca_dev *gspca_dev) { - i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */ + i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */ msleep(10); - reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */ + reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */ msleep(10); - i2c_r(gspca_dev, 0, 5); /* read sensor id */ - if (gspca_dev->usb_buf[0] == 0x02 + i2c_r(gspca_dev, 0, 5); /* read sensor id */ + if (gspca_dev->usb_buf[0] == 0x02 /* chip ID (02 is R) */ && gspca_dev->usb_buf[1] == 0x09 - && gspca_dev->usb_buf[2] == 0x01 - && gspca_dev->usb_buf[3] == 0x00 - && gspca_dev->usb_buf[4] == 0x00) { - PDEBUG(D_PROBE, "Sensor sn9c102P HV7131R found"); + && gspca_dev->usb_buf[2] == 0x01) { + PDEBUG(D_PROBE, "Sensor HV7131R found"); return; } - PDEBUG(D_PROBE, "Sensor 0x%02x 0x%02x 0x%02x - sn9c102P not found", + warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x", gspca_dev->usb_buf[0], gspca_dev->usb_buf[1], gspca_dev->usb_buf[2]); } -- cgit v0.10.2 From 1d00d6c1ff13607974fcd9469aa9466fcd253c3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Fri, 29 Oct 2010 13:58:22 -0300 Subject: [media] gspca: Convert some uppercase hexadecimal values to lowercase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c index 9b12168..80b8dae 100644 --- a/drivers/media/video/gspca/cpia1.c +++ b/drivers/media/video/gspca/cpia1.c @@ -37,7 +37,7 @@ MODULE_LICENSE("GPL"); /* constant value's */ #define MAGIC_0 0x19 #define MAGIC_1 0x68 -#define DATA_IN 0xC0 +#define DATA_IN 0xc0 #define DATA_OUT 0x40 #define VIDEOSIZE_QCIF 0 /* 176x144 */ #define VIDEOSIZE_CIF 1 /* 352x288 */ @@ -660,9 +660,9 @@ static int do_command(struct gspca_dev *gspca_dev, u16 command, if (sd->params.qx3.button) { /* button pressed - unlock the latch */ do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, - 3, 0xDF, 0xDF, 0); + 3, 0xdf, 0xdf, 0); do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, - 3, 0xFF, 0xFF, 0); + 3, 0xff, 0xff, 0); } /* test whether microscope is cradled */ @@ -1110,12 +1110,12 @@ static int command_setlights(struct gspca_dev *gspca_dev) p2 = (sd->params.qx3.toplight == 0) << 3; ret = do_command(gspca_dev, CPIA_COMMAND_WriteVCReg, - 0x90, 0x8F, 0x50, 0); + 0x90, 0x8f, 0x50, 0); if (ret) return ret; return do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 2, 0, - p1 | p2 | 0xE0, 0); + p1 | p2 | 0xe0, 0); } static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply) diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c index 8ded8b1..703d486 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -624,7 +624,7 @@ static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) /* Mask away all uninteresting bits */ i2c_data = ((val & 0x0300) >> 2) | - (i2c_data & 0x3F); + (i2c_data & 0x3f); err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1); if (err < 0) return err; diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 15e97fa..96f9986 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -162,7 +162,7 @@ static const __u8 pac207_sensor_init[][8] = { {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0x84}, {0x49, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30}, {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00}, - {0x32, 0x00, 0x96, 0x00, 0xA2, 0x02, 0xaf, 0x00}, + {0x32, 0x00, 0x96, 0x00, 0xa2, 0x02, 0xaf, 0x00}, }; static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index, @@ -228,7 +228,7 @@ static int sd_config(struct gspca_dev *gspca_dev, idreg[0] = pac207_read_reg(gspca_dev, 0x0000); idreg[1] = pac207_read_reg(gspca_dev, 0x0001); - idreg[0] = ((idreg[0] & 0x0F) << 4) | ((idreg[1] & 0xf0) >> 4); + idreg[0] = ((idreg[0] & 0x0f) << 4) | ((idreg[1] & 0xf0) >> 4); idreg[1] = idreg[1] & 0x0f; PDEBUG(D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X", idreg[0], idreg[1]); diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 706f96f..11b1972 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -340,7 +340,7 @@ static const __u8 ov6650_sensor_init[][8] = { * but blue wont be there. Avoid this data ... */ {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */ {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, - {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10}, + {0xa0, 0x60, 0x30, 0x3d, 0x0a, 0xd8, 0xa4, 0x10}, /* Enable rgb brightness control */ {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10}, /* HDG: Note windows uses the line below, which sets both register 0x60 @@ -505,7 +505,7 @@ static const __u8 pas202_sensor_init[][8] = { {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10}, {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10}, {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10}, - {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x01, 0x32, 0x10}, + {0xd0, 0x40, 0x0c, 0x00, 0x0c, 0x01, 0x32, 0x10}, {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10}, {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10}, {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10}, diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index ad73f48..3a162c6 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -597,7 +597,7 @@ static void setgain(struct gspca_dev *gspca_dev) else if (sd->gain < 128) gspca_dev->usb_buf[0] = (sd->gain / 2) | 0x40; else - gspca_dev->usb_buf[0] = (sd->gain / 4) | 0xC0; + gspca_dev->usb_buf[0] = (sd->gain / 4) | 0xc0; gspca_dev->usb_buf[1] = 0; reg_w_buf(gspca_dev, 0x8335, 2); diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c index 086de44..544d5f7 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx.c @@ -349,7 +349,7 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, } /* First byte seem to be 02=data 2nd byte is unknown??? */ - if (sd->bridge == BRIDGE_ST6422 && (id & 0xFF00) == 0x0200) + if (sd->bridge == BRIDGE_ST6422 && (id & 0xff00) == 0x0200) goto frame_data; switch (id) { diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c index 3af5326..ea677b5 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c @@ -151,11 +151,11 @@ static int st6422_init(struct sd *sd) { STV_ISO_ENABLE, 0x00 }, /* disable capture */ { 0x1436, 0x00 }, { 0x1432, 0x03 }, /* 0x00-0x1F brightness */ - { 0x143a, 0xF9 }, /* 0x00-0x0F contrast */ + { 0x143a, 0xf9 }, /* 0x00-0x0F contrast */ { 0x0509, 0x38 }, /* R */ { 0x050a, 0x38 }, /* G */ { 0x050b, 0x38 }, /* B */ - { 0x050c, 0x2A }, + { 0x050c, 0x2a }, { 0x050d, 0x01 }, diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index b45f4d0..8f0c331 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -487,7 +487,7 @@ static const u8 gamma_table[GAMMA_MAX][17] = { {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f, /* 3 */ 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6, 0xff}, - {0x00, 0x04, 0x0B, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */ + {0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */ 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9, 0xff}, {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58, /* 5 */ diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index d9e3c60..38c22f0 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c @@ -132,7 +132,7 @@ static const struct v4l2_pix_format sif_mode[] = { #define R36_PID 0x36 #define R37_PIDH 0x37 #define R39_Test1 0x39 /* GPIO */ -#define R3B_Test3 0x3B /* GPIO */ +#define R3B_Test3 0x3b /* GPIO */ #define R83_AD_IDH 0x83 #define R91_AD_SLOPEREG 0x91 #define R94_AD_BITCONTROL 0x94 -- cgit v0.10.2 From 88464106f97fe1c143bda2b4019b07c3069d454c Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 13 Jun 2010 17:31:22 -0300 Subject: [media] au8522: Properly set default brightness The chip's default value for the brightness didn't match what we were sending back in the queryctrl ioctl(), so if the application actually set the brightness to the "default", it would actually end up being way too bright. This work was sponsored by GetWellNetwork Inc. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c index 6d9c594..b36d128 100644 --- a/drivers/media/dvb/frontends/au8522_decoder.c +++ b/drivers/media/dvb/frontends/au8522_decoder.c @@ -622,7 +622,7 @@ static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) return v4l2_ctrl_query_fill(qc, 0, 255, 1, AU8522_TVDEC_CONTRAST_REG00BH_CVBS); case V4L2_CID_BRIGHTNESS: - return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 109); case V4L2_CID_SATURATION: return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); case V4L2_CID_HUE: -- cgit v0.10.2 From 83f859c5a6d6e01d671f002c0ade3498b4a4b245 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 25 Jun 2010 01:33:39 -0300 Subject: [media] au0828: set max packets per URB to match Windows driver We had the max packets per URB set to an incredibly low "10" as opposed to the Windows driver which has it as 128. Set the value to match the Windows driver, which will reduce interrupts considerably. This work was sponsored by GetWellNetwork Inc. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 9905bc4..4dd8ce7 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -53,7 +53,7 @@ /* Defination for AU0828 USB transfer */ #define AU0828_MAX_ISO_BUFS 12 /* maybe resize this value in the future */ -#define AU0828_ISO_PACKETS_PER_URB 10 +#define AU0828_ISO_PACKETS_PER_URB 128 #define AU0828_MIN_BUF 4 #define AU0828_DEF_BUF 8 -- cgit v0.10.2 From bde3bb9a67d2cd260df6be9726c9c360a0e3cee9 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 5 Jul 2010 13:05:16 -0300 Subject: [media] au0828: Fix field alignment for video frames delivered by driver Fix the alignment of fields being delivered by the driver, which was resulting in jerky video when there was horizontal motion (since the bottom field of the frame was being sent with the top field of the previous frame) This work was sponsored by GetWellNetwork Inc. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 162fd5f..20ba591 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -576,7 +576,7 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) p += 4; au0828_isocdbg("Video frame %s\n", (fbyte & 0x40) ? "odd" : "even"); - if (!(fbyte & 0x40)) { + if (fbyte & 0x40) { /* VBI */ if (vbi_buf != NULL) vbi_buffer_filled(dev, -- cgit v0.10.2 From 2428a2ed6a7cbc7be6db5c70c3838a4bf0de9f48 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 27 Jun 2010 17:40:42 -0300 Subject: [media] au8522: cleanup code which disables audio decoder Cleanup the routine which disables the audio decoder. In particular, the i2s output was being shut off but the audio processor itself was not, resulting in more power being consumed than needed. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c index b36d128..55b12ce 100644 --- a/drivers/media/dvb/frontends/au8522_decoder.c +++ b/drivers/media/dvb/frontends/au8522_decoder.c @@ -410,29 +410,15 @@ static void au8522_setup_svideo_mode(struct au8522_state *state) static void disable_audio_input(struct au8522_state *state) { - /* This can probably be optimized */ au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00); au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00); au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00); - au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80); - au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84); - - au8522_writereg(state, AU8522_ENA_USB_REG101H, 0x00); - au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F); - au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F); - au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO); - au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x40); - - au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x11); - msleep(5); - au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x00); au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x04); - au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03); au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0x02); au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, - AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS); + AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_SVIDEO); } /* 0=disable, 1=SIF */ -- cgit v0.10.2 From d2c194ce4781d62bf671aa6b65a2fccb39feb50e Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 27 Jun 2010 18:01:40 -0300 Subject: [media] au8522: fix clamp control for different video modes Straighten out the clamp control configurations for the various video modes, based off of register diffs done against the Hauppauge Windows driver. This work was sponsored by GetWellNetwork Inc. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c index 55b12ce..5ec8697 100644 --- a/drivers/media/dvb/frontends/au8522_decoder.c +++ b/drivers/media/dvb/frontends/au8522_decoder.c @@ -347,9 +347,11 @@ static void au8522_setup_cvbs_mode(struct au8522_state *state) au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H, AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS); + /* PGA in automatic mode */ au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00); - au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e); - au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10); + + /* Enable clamping control */ + au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00); au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1); @@ -366,14 +368,14 @@ static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state) au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H, AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS); - /* It's not clear why they turn off the PGA before enabling the clamp - control, but the Windows trace does it so we will too... */ + /* It's not clear why we have to have the PGA in automatic mode while + enabling clamp control, but it's what Windows does */ au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00); /* Enable clamping control */ au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e); - /* Turn on the PGA */ + /* Disable automatic PGA (since the CVBS is coming from the tuner) */ au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10); /* Set input mode to CVBS on channel 4 with SIF audio input enabled */ @@ -396,7 +398,10 @@ static void au8522_setup_svideo_mode(struct au8522_state *state) au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13); - /* Disable clamping control (required for S-video) */ + /* PGA in automatic mode */ + au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00); + + /* Enable clamping control */ au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00); setup_decoder_defaults(state, -- cgit v0.10.2 From 301c9f26d7ded6e274a99c3a447a9a36790a3f3e Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 27 Jun 2010 18:12:42 -0300 Subject: [media] au8522: Handle differences in comb filter config for s-video input Tweak the comb filter config when in s-video mode to match the Hauppauge Windows driver values (based on register dumps). This work was sponsored by GetWellNetwork Inc. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c index 5ec8697..b537891 100644 --- a/drivers/media/dvb/frontends/au8522_decoder.c +++ b/drivers/media/dvb/frontends/au8522_decoder.c @@ -278,10 +278,18 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode) AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS); au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS); - au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH, - AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS); - au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH, - AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS); + if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 || + input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) { + au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH, + AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_SVIDEO); + au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH, + AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_SVIDEO); + } else { + au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH, + AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH, + AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS); + } au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH, AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS); au8522_writereg(state, AU8522_TVDEC_UV_SEP_THR_REG06FH, diff --git a/drivers/media/dvb/frontends/au8522_priv.h b/drivers/media/dvb/frontends/au8522_priv.h index 609cf04..751e17d 100644 --- a/drivers/media/dvb/frontends/au8522_priv.h +++ b/drivers/media/dvb/frontends/au8522_priv.h @@ -397,7 +397,9 @@ void au8522_release_state(struct au8522_state *state); #define AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS 0x0A #define AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS 0x32 #define AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS 0x34 +#define AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_SVIDEO 0x2a #define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS 0x05 +#define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_SVIDEO 0x15 #define AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS 0x6E #define AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS 0x0F #define AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS 0x80 -- cgit v0.10.2 From 6e04b7b95a5bd2da0aa5df05fc09a1f0d6615666 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 1 Sep 2010 22:03:43 -0300 Subject: [media] au0828: continue video streaming even when no ITU-656 coming in We need the au0828 to continue delivering frames even when the device is not delivering video, or else applications such as tvtime will block indefinitely. Unfortunately, the au8522 doesn't have any sort of free-running mode or "blue screen on no video" like some other decoders. This work was sponsored by GetWellNetwork Inc. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 20ba591..8d11e54 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -312,6 +312,9 @@ static inline void buffer_filled(struct au0828_dev *dev, list_del(&buf->vb.queue); wake_up(&buf->vb.done); + + /* Reset the timer for "no video condition" */ + mod_timer(&dev->vid_timeout, jiffies + (HZ / 10)); } static inline void vbi_buffer_filled(struct au0828_dev *dev, @@ -329,6 +332,9 @@ static inline void vbi_buffer_filled(struct au0828_dev *dev, list_del(&buf->vb.queue); wake_up(&buf->vb.done); + + /* Reset the timer for "no video condition" */ + mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); } /* @@ -907,6 +913,50 @@ static int get_ressource(struct au0828_fh *fh) } } +/* This function ensures that video frames continue to be delivered even if + the ITU-656 input isn't receiving any data (thereby preventing applications + such as tvtime from hanging) */ +void au0828_vid_buffer_timeout(unsigned long data) +{ + struct au0828_dev *dev = (struct au0828_dev *) data; + struct au0828_dmaqueue *dma_q = &dev->vidq; + struct au0828_buffer *buf; + unsigned char *vid_data; + + spin_lock(&dev->slock); + + buf = dev->isoc_ctl.buf; + if (buf != NULL) { + vid_data = videobuf_to_vmalloc(&buf->vb); + memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */ + buffer_filled(dev, dma_q, buf); + get_next_buf(dma_q, &buf); + } + + spin_unlock(&dev->slock); +} + +void au0828_vbi_buffer_timeout(unsigned long data) +{ + struct au0828_dev *dev = (struct au0828_dev *) data; + struct au0828_dmaqueue *dma_q = &dev->vbiq; + struct au0828_buffer *buf; + unsigned char *vbi_data; + + spin_lock(&dev->slock); + + buf = dev->isoc_ctl.vbi_buf; + if (buf != NULL) { + vbi_data = videobuf_to_vmalloc(&buf->vb); + memset(vbi_data, 0x00, buf->vb.size); + vbi_buffer_filled(dev, dma_q, buf); + vbi_get_next_buf(dma_q, &buf); + } + + spin_unlock(&dev->slock); +} + + static int au0828_v4l2_open(struct file *filp) { int ret = 0; @@ -976,6 +1026,15 @@ static int au0828_v4l2_open(struct file *filp) V4L2_FIELD_SEQ_TB, sizeof(struct au0828_buffer), fh, NULL); + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + dev->vid_timeout.function = au0828_vid_buffer_timeout; + dev->vid_timeout.data = (unsigned long) dev; + init_timer(&dev->vid_timeout); + } else { + dev->vbi_timeout.function = au0828_vbi_buffer_timeout; + dev->vbi_timeout.data = (unsigned long) dev; + init_timer(&dev->vbi_timeout); + } return ret; } @@ -987,11 +1046,13 @@ static int au0828_v4l2_close(struct file *filp) struct au0828_dev *dev = fh->dev; if (res_check(fh, AU0828_RESOURCE_VIDEO)) { + del_timer(&dev->vid_timeout); videobuf_stop(&fh->vb_vidq); res_free(fh, AU0828_RESOURCE_VIDEO); } if (res_check(fh, AU0828_RESOURCE_VBI)) { + del_timer(&dev->vbi_timeout); videobuf_stop(&fh->vb_vbiq); res_free(fh, AU0828_RESOURCE_VBI); } diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 4dd8ce7..ef46a88 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -204,6 +204,8 @@ struct au0828_dev { unsigned int resources; /* resources in use */ struct video_device *vdev; struct video_device *vbi_dev; + struct timer_list vid_timeout; + struct timer_list vbi_timeout; int width; int height; int vbi_width; -- cgit v0.10.2 From 78ca500559b5a4f16a95c198b3e7bdfac8455bf8 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sat, 9 Oct 2010 14:43:53 -0300 Subject: [media] au0828: fixes for timeout on no video The first pass of fixes to cause the driver to continue streaming even when there is no video arriving over the ITU656 bus were not adequate. Continue the work from the previous patch. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 8d11e54..cf8fc62 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -122,6 +122,7 @@ static void au0828_irq_callback(struct urb *urb) { struct au0828_dmaqueue *dma_q = urb->context; struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq); + unsigned long flags = 0; int rc, i; switch (urb->status) { @@ -139,9 +140,9 @@ static void au0828_irq_callback(struct urb *urb) } /* Copy data from URB */ - spin_lock(&dev->slock); + spin_lock_irqsave(&dev->slock, flags); rc = dev->isoc_ctl.isoc_copy(dev, urb); - spin_unlock(&dev->slock); + spin_unlock_irqrestore(&dev->slock, flags); /* Reset urb buffers */ for (i = 0; i < urb->number_of_packets; i++) { @@ -312,9 +313,6 @@ static inline void buffer_filled(struct au0828_dev *dev, list_del(&buf->vb.queue); wake_up(&buf->vb.done); - - /* Reset the timer for "no video condition" */ - mod_timer(&dev->vid_timeout, jiffies + (HZ / 10)); } static inline void vbi_buffer_filled(struct au0828_dev *dev, @@ -332,9 +330,6 @@ static inline void vbi_buffer_filled(struct au0828_dev *dev, list_del(&buf->vb.queue); wake_up(&buf->vb.done); - - /* Reset the timer for "no video condition" */ - mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); } /* @@ -603,6 +598,15 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) outp = NULL; else outp = videobuf_to_vmalloc(&buf->vb); + + /* As long as isoc traffic is arriving, keep + resetting the timer */ + if (dev->vid_timeout_running) + mod_timer(&dev->vid_timeout, + jiffies + (HZ / 10)); + if (dev->vbi_timeout_running) + mod_timer(&dev->vbi_timeout, + jiffies + (HZ / 10)); } if (buf != NULL) { @@ -922,18 +926,22 @@ void au0828_vid_buffer_timeout(unsigned long data) struct au0828_dmaqueue *dma_q = &dev->vidq; struct au0828_buffer *buf; unsigned char *vid_data; + unsigned long flags = 0; - spin_lock(&dev->slock); + spin_lock_irqsave(&dev->slock, flags); buf = dev->isoc_ctl.buf; if (buf != NULL) { vid_data = videobuf_to_vmalloc(&buf->vb); memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */ buffer_filled(dev, dma_q, buf); - get_next_buf(dma_q, &buf); } + get_next_buf(dma_q, &buf); + + if (dev->vid_timeout_running == 1) + mod_timer(&dev->vid_timeout, jiffies + (HZ / 10)); - spin_unlock(&dev->slock); + spin_unlock_irqrestore(&dev->slock, flags); } void au0828_vbi_buffer_timeout(unsigned long data) @@ -942,18 +950,21 @@ void au0828_vbi_buffer_timeout(unsigned long data) struct au0828_dmaqueue *dma_q = &dev->vbiq; struct au0828_buffer *buf; unsigned char *vbi_data; + unsigned long flags = 0; - spin_lock(&dev->slock); + spin_lock_irqsave(&dev->slock, flags); buf = dev->isoc_ctl.vbi_buf; if (buf != NULL) { vbi_data = videobuf_to_vmalloc(&buf->vb); memset(vbi_data, 0x00, buf->vb.size); vbi_buffer_filled(dev, dma_q, buf); - vbi_get_next_buf(dma_q, &buf); } + vbi_get_next_buf(dma_q, &buf); - spin_unlock(&dev->slock); + if (dev->vbi_timeout_running == 1) + mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); + spin_unlock_irqrestore(&dev->slock, flags); } @@ -1026,16 +1037,6 @@ static int au0828_v4l2_open(struct file *filp) V4L2_FIELD_SEQ_TB, sizeof(struct au0828_buffer), fh, NULL); - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - dev->vid_timeout.function = au0828_vid_buffer_timeout; - dev->vid_timeout.data = (unsigned long) dev; - init_timer(&dev->vid_timeout); - } else { - dev->vbi_timeout.function = au0828_vbi_buffer_timeout; - dev->vbi_timeout.data = (unsigned long) dev; - init_timer(&dev->vbi_timeout); - } - return ret; } @@ -1046,13 +1047,19 @@ static int au0828_v4l2_close(struct file *filp) struct au0828_dev *dev = fh->dev; if (res_check(fh, AU0828_RESOURCE_VIDEO)) { - del_timer(&dev->vid_timeout); + /* Cancel timeout thread in case they didn't call streamoff */ + dev->vid_timeout_running = 0; + del_timer_sync(&dev->vid_timeout); + videobuf_stop(&fh->vb_vidq); res_free(fh, AU0828_RESOURCE_VIDEO); } if (res_check(fh, AU0828_RESOURCE_VBI)) { - del_timer(&dev->vbi_timeout); + /* Cancel timeout thread in case they didn't call streamoff */ + dev->vbi_timeout_running = 0; + del_timer_sync(&dev->vbi_timeout); + videobuf_stop(&fh->vb_vbiq); res_free(fh, AU0828_RESOURCE_VBI); } @@ -1638,10 +1645,15 @@ static int vidioc_streamon(struct file *file, void *priv, v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); } - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { rc = videobuf_streamon(&fh->vb_vidq); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + dev->vid_timeout_running = 1; + mod_timer(&dev->vid_timeout, jiffies + (HZ / 10)); + } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { rc = videobuf_streamon(&fh->vb_vbiq); + dev->vbi_timeout_running = 1; + mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); + } return rc; } @@ -1668,6 +1680,9 @@ static int vidioc_streamoff(struct file *file, void *priv, fh, type, fh->resources, dev->resources); if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + dev->vid_timeout_running = 0; + del_timer_sync(&dev->vid_timeout); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); rc = au0828_stream_interrupt(dev); if (rc != 0) @@ -1682,6 +1697,9 @@ static int vidioc_streamoff(struct file *file, void *priv, videobuf_streamoff(&fh->vb_vidq); res_free(fh, AU0828_RESOURCE_VIDEO); } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + dev->vbi_timeout_running = 0; + del_timer_sync(&dev->vbi_timeout); + videobuf_streamoff(&fh->vb_vbiq); res_free(fh, AU0828_RESOURCE_VBI); } @@ -1901,6 +1919,14 @@ int au0828_analog_register(struct au0828_dev *dev, INIT_LIST_HEAD(&dev->vbiq.active); INIT_LIST_HEAD(&dev->vbiq.queued); + dev->vid_timeout.function = au0828_vid_buffer_timeout; + dev->vid_timeout.data = (unsigned long) dev; + init_timer(&dev->vid_timeout); + + dev->vbi_timeout.function = au0828_vbi_buffer_timeout; + dev->vbi_timeout.data = (unsigned long) dev; + init_timer(&dev->vbi_timeout); + dev->width = NTSC_STD_W; dev->height = NTSC_STD_H; dev->field_size = dev->width * dev->height; diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index ef46a88..9cde353 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -205,7 +205,9 @@ struct au0828_dev { struct video_device *vdev; struct video_device *vbi_dev; struct timer_list vid_timeout; + int vid_timeout_running; struct timer_list vbi_timeout; + int vbi_timeout_running; int width; int height; int vbi_width; -- cgit v0.10.2 From bf797165f099296b622bcdcea1126a113e0aaac4 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sat, 9 Oct 2010 15:09:17 -0300 Subject: [media] au0828: enable VBI timeout when calling read() without streamon() Because some clients (e.g. tvtime) will just open the filehandle and call read() instead of explicitly calling streamon first, we need to make sure the VBI timeout routine gets enabled in this case. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index cf8fc62..48682af 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -1116,6 +1116,13 @@ static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf, if (!res_get(fh, AU0828_RESOURCE_VBI)) return -EBUSY; + if (dev->vbi_timeout_running == 0) { + /* Handle case where caller tries to read without + calling streamon first */ + dev->vbi_timeout_running = 1; + mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); + } + return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0, filp->f_flags & O_NONBLOCK); } -- cgit v0.10.2 From 00df055ae315c9c8792dc4d012e6ad9c4d527e87 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 29 Oct 2010 11:31:39 -0300 Subject: [media] radio-si4713: Add regulator framework support Convert the driver to use regulator framework instead of set_power callback. This with gpio_reset platform data provide cleaner way to manage chip VIO, VDD and reset signal inside the driver. Signed-off-by: Jarkko Nikula Cc: Eduardo Valentin Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/radio/si4713-i2c.c b/drivers/media/radio/si4713-i2c.c index a6e6f19..0fab6f8 100644 --- a/drivers/media/radio/si4713-i2c.c +++ b/drivers/media/radio/si4713-i2c.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -43,6 +45,11 @@ MODULE_AUTHOR("Eduardo Valentin "); MODULE_DESCRIPTION("I2C driver for Si4713 FM Radio Transmitter"); MODULE_VERSION("0.0.1"); +static const char *si4713_supply_names[SI4713_NUM_SUPPLIES] = { + "vio", + "vdd", +}; + #define DEFAULT_RDS_PI 0x00 #define DEFAULT_RDS_PTY 0x00 #define DEFAULT_RDS_PS_NAME "" @@ -369,7 +376,17 @@ static int si4713_powerup(struct si4713_device *sdev) if (sdev->power_state) return 0; - sdev->platform_data->set_power(1); + err = regulator_bulk_enable(ARRAY_SIZE(sdev->supplies), + sdev->supplies); + if (err) { + v4l2_err(&sdev->sd, "Failed to enable supplies: %d\n", err); + return err; + } + if (gpio_is_valid(sdev->gpio_reset)) { + udelay(50); + gpio_set_value(sdev->gpio_reset, 1); + } + err = si4713_send_command(sdev, SI4713_CMD_POWER_UP, args, ARRAY_SIZE(args), resp, ARRAY_SIZE(resp), @@ -384,7 +401,13 @@ static int si4713_powerup(struct si4713_device *sdev) err = si4713_write_property(sdev, SI4713_GPO_IEN, SI4713_STC_INT | SI4713_CTS); } else { - sdev->platform_data->set_power(0); + if (gpio_is_valid(sdev->gpio_reset)) + gpio_set_value(sdev->gpio_reset, 0); + err = regulator_bulk_disable(ARRAY_SIZE(sdev->supplies), + sdev->supplies); + if (err) + v4l2_err(&sdev->sd, + "Failed to disable supplies: %d\n", err); } return err; @@ -411,7 +434,13 @@ static int si4713_powerdown(struct si4713_device *sdev) v4l2_dbg(1, debug, &sdev->sd, "Power down response: 0x%02x\n", resp[0]); v4l2_dbg(1, debug, &sdev->sd, "Device in reset mode\n"); - sdev->platform_data->set_power(0); + if (gpio_is_valid(sdev->gpio_reset)) + gpio_set_value(sdev->gpio_reset, 0); + err = regulator_bulk_disable(ARRAY_SIZE(sdev->supplies), + sdev->supplies); + if (err) + v4l2_err(&sdev->sd, + "Failed to disable supplies: %d\n", err); sdev->power_state = POWER_OFF; } @@ -1967,7 +1996,8 @@ static int si4713_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct si4713_device *sdev; - int rval; + struct si4713_platform_data *pdata = client->dev.platform_data; + int rval, i; sdev = kzalloc(sizeof *sdev, GFP_KERNEL); if (!sdev) { @@ -1976,11 +2006,26 @@ static int si4713_probe(struct i2c_client *client, goto exit; } - sdev->platform_data = client->dev.platform_data; - if (!sdev->platform_data) { - v4l2_err(&sdev->sd, "No platform data registered.\n"); - rval = -ENODEV; - goto free_sdev; + sdev->gpio_reset = -1; + if (pdata && gpio_is_valid(pdata->gpio_reset)) { + rval = gpio_request(pdata->gpio_reset, "si4713 reset"); + if (rval) { + dev_err(&client->dev, + "Failed to request gpio: %d\n", rval); + goto free_sdev; + } + sdev->gpio_reset = pdata->gpio_reset; + gpio_direction_output(sdev->gpio_reset, 0); + } + + for (i = 0; i < ARRAY_SIZE(sdev->supplies); i++) + sdev->supplies[i].supply = si4713_supply_names[i]; + + rval = regulator_bulk_get(&client->dev, ARRAY_SIZE(sdev->supplies), + sdev->supplies); + if (rval) { + dev_err(&client->dev, "Cannot get regulators: %d\n", rval); + goto free_gpio; } v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops); @@ -1994,7 +2039,7 @@ static int si4713_probe(struct i2c_client *client, client->name, sdev); if (rval < 0) { v4l2_err(&sdev->sd, "Could not request IRQ\n"); - goto free_sdev; + goto put_reg; } v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n"); } else { @@ -2012,6 +2057,11 @@ static int si4713_probe(struct i2c_client *client, free_irq: if (client->irq) free_irq(client->irq, sdev); +put_reg: + regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies); +free_gpio: + if (gpio_is_valid(sdev->gpio_reset)) + gpio_free(sdev->gpio_reset); free_sdev: kfree(sdev); exit: @@ -2031,7 +2081,9 @@ static int si4713_remove(struct i2c_client *client) free_irq(client->irq, sdev); v4l2_device_unregister_subdev(sd); - + regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies); + if (gpio_is_valid(sdev->gpio_reset)) + gpio_free(sdev->gpio_reset); kfree(sdev); return 0; diff --git a/drivers/media/radio/si4713-i2c.h b/drivers/media/radio/si4713-i2c.h index faf8cff..c6dfa7f 100644 --- a/drivers/media/radio/si4713-i2c.h +++ b/drivers/media/radio/si4713-i2c.h @@ -211,6 +211,8 @@ struct acomp_info { u32 enabled; }; +#define SI4713_NUM_SUPPLIES 2 + /* * si4713_device - private data */ @@ -220,11 +222,12 @@ struct si4713_device { /* private data structures */ struct mutex mutex; struct completion work; - struct si4713_platform_data *platform_data; struct rds_info rds_info; struct limiter_info limiter_info; struct pilot_info pilot_info; struct acomp_info acomp_info; + struct regulator_bulk_data supplies[SI4713_NUM_SUPPLIES]; + int gpio_reset; u32 frequency; u32 preemphasis; u32 mute; diff --git a/include/media/si4713.h b/include/media/si4713.h index 99850a5..ed7353e 100644 --- a/include/media/si4713.h +++ b/include/media/si4713.h @@ -23,8 +23,7 @@ * Platform dependent definition */ struct si4713_platform_data { - /* Set power state, zero is off, non-zero is on. */ - int (*set_power)(int power); + int gpio_reset; /* < 0 if not used */ }; /* -- cgit v0.10.2 From 2997137be8eba5bf9c07a24d5fda1f4225f9ca7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Fri, 29 Oct 2010 16:08:02 -0300 Subject: [media] ir-core: convert drivers/media/video/cx88 to ir-core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch converts the cx88 driver (for sampling hw) to use the decoders provided by ir-core instead of the separate ones provided by ir-functions (and gets rid of those). The value for MO_DDS_IO had a comment saying it corresponded to a 4kHz samplerate. That comment was unfortunately misleading. The actual samplerate was something like 3250Hz. The current value has been derived by analyzing the elapsed time between interrupts for different values (knowing that each interrupt corresponds to 32 samples). Thanks to Mariusz Bialonczyk for testing my patches (about one a day for two weeks!) on actual hardware. Signed-off-by: David Härdeman Acked-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/IR/ir-functions.c b/drivers/media/IR/ir-functions.c index db591e4..f4c4115 100644 --- a/drivers/media/IR/ir-functions.c +++ b/drivers/media/IR/ir-functions.c @@ -111,140 +111,6 @@ u32 ir_extract_bits(u32 data, u32 mask) } EXPORT_SYMBOL_GPL(ir_extract_bits); -static int inline getbit(u32 *samples, int bit) -{ - return (samples[bit/32] & (1 << (31-(bit%32)))) ? 1 : 0; -} - -/* sump raw samples for visual debugging ;) */ -int ir_dump_samples(u32 *samples, int count) -{ - int i, bit, start; - - printk(KERN_DEBUG "ir samples: "); - start = 0; - for (i = 0; i < count * 32; i++) { - bit = getbit(samples,i); - if (bit) - start = 1; - if (0 == start) - continue; - printk("%s", bit ? "#" : "_"); - } - printk("\n"); - return 0; -} -EXPORT_SYMBOL_GPL(ir_dump_samples); - -/* decode raw samples, pulse distance coding used by NEC remotes */ -int ir_decode_pulsedistance(u32 *samples, int count, int low, int high) -{ - int i,last,bit,len; - u32 curBit; - u32 value; - - /* find start burst */ - for (i = len = 0; i < count * 32; i++) { - bit = getbit(samples,i); - if (bit) { - len++; - } else { - if (len >= 29) - break; - len = 0; - } - } - - /* start burst to short */ - if (len < 29) - return 0xffffffff; - - /* find start silence */ - for (len = 0; i < count * 32; i++) { - bit = getbit(samples,i); - if (bit) { - break; - } else { - len++; - } - } - - /* silence to short */ - if (len < 7) - return 0xffffffff; - - /* go decoding */ - len = 0; - last = 1; - value = 0; curBit = 1; - for (; i < count * 32; i++) { - bit = getbit(samples,i); - if (last) { - if(bit) { - continue; - } else { - len = 1; - } - } else { - if (bit) { - if (len > (low + high) /2) - value |= curBit; - curBit <<= 1; - if (curBit == 1) - break; - } else { - len++; - } - } - last = bit; - } - - return value; -} -EXPORT_SYMBOL_GPL(ir_decode_pulsedistance); - -/* decode raw samples, biphase coding, used by rc5 for example */ -int ir_decode_biphase(u32 *samples, int count, int low, int high) -{ - int i,last,bit,len,flips; - u32 value; - - /* find start bit (1) */ - for (i = 0; i < 32; i++) { - bit = getbit(samples,i); - if (bit) - break; - } - - /* go decoding */ - len = 0; - flips = 0; - value = 1; - for (; i < count * 32; i++) { - if (len > high) - break; - if (flips > 1) - break; - last = bit; - bit = getbit(samples,i); - if (last == bit) { - len++; - continue; - } - if (len < low) { - len++; - flips++; - continue; - } - value <<= 1; - value |= bit; - flips = 0; - len = 1; - } - return value; -} -EXPORT_SYMBOL_GPL(ir_decode_biphase); - /* RC5 decoding stuff, moved from bttv-input.c to share it with * saa7134 */ diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 0fa85cb..bcfd1ac 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -1,6 +1,6 @@ config VIDEO_CX88 tristate "Conexant 2388x (bt878 successor) support" - depends on VIDEO_DEV && PCI && I2C && INPUT + depends on VIDEO_DEV && PCI && I2C && INPUT && IR_CORE select I2C_ALGOBIT select VIDEO_BTCX select VIDEOBUF_DMA_SG diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index fc777bc..436ace8 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -41,7 +41,6 @@ struct cx88_IR { struct cx88_core *core; struct input_dev *input; struct ir_dev_props props; - u64 ir_type; int users; @@ -50,8 +49,6 @@ struct cx88_IR { /* sample from gpio pin 16 */ u32 sampling; - u32 samples[16]; - int scount; /* poll external decoder */ int polling; @@ -63,6 +60,10 @@ struct cx88_IR { u32 mask_keyup; }; +static unsigned ir_samplerate = 4; +module_param(ir_samplerate, uint, 0444); +MODULE_PARM_DESC(ir_samplerate, "IR samplerate in kHz, 1 - 20, default 4"); + static int ir_debug; module_param(ir_debug, int, 0644); /* debug level [IR] */ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); @@ -176,8 +177,8 @@ static int __cx88_ir_start(void *priv) } if (ir->sampling) { core->pci_irqmask |= PCI_INT_IR_SMPINT; - cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ - cx_write(MO_DDSCFG_IO, 0x5); /* enable */ + cx_write(MO_DDS_IO, 0x33F286 * ir_samplerate); /* samplerate */ + cx_write(MO_DDSCFG_IO, 0x5); /* enable */ } return 0; } @@ -264,7 +265,6 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: ir_codes = RC_MAP_CINERGY_1400; - ir_type = IR_TYPE_NEC; ir->sampling = 0xeb04; /* address */ break; case CX88_BOARD_HAUPPAUGE: @@ -279,7 +279,6 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_PCHDTV_HD5500: case CX88_BOARD_HAUPPAUGE_IRONLY: ir_codes = RC_MAP_HAUPPAUGE_NEW; - ir_type = IR_TYPE_RC5; ir->sampling = 1; break; case CX88_BOARD_WINFAST_DTV2000H: @@ -367,18 +366,15 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_PROF_7301: case CX88_BOARD_PROF_6200: ir_codes = RC_MAP_TBS_NEC; - ir_type = IR_TYPE_NEC; ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_TEVII_S460: case CX88_BOARD_TEVII_S420: ir_codes = RC_MAP_TEVII_NEC; - ir_type = IR_TYPE_NEC; ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: ir_codes = RC_MAP_DNTV_LIVE_DVBT_PRO; - ir_type = IR_TYPE_NEC; ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_NORWOOD_MICRO: @@ -396,7 +392,6 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_PINNACLE_PCTV_HD_800i: ir_codes = RC_MAP_PINNACLE_PCTV_HD; - ir_type = IR_TYPE_RC5; ir->sampling = 1; break; case CX88_BOARD_POWERCOLOR_REAL_ANGEL: @@ -412,7 +407,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; } - if (NULL == ir_codes) { + if (!ir_codes) { err = -ENODEV; goto err_out_free; } @@ -436,8 +431,6 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); - ir->ir_type = ir_type; - input_dev->name = ir->name; input_dev->phys = ir->phys; input_dev->id.bustype = BUS_PCI; @@ -454,10 +447,18 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->core = core; core->ir = ir; + if (ir->sampling) { + ir_type = IR_TYPE_ALL; + ir->props.driver_type = RC_DRIVER_IR_RAW; + ir->props.timeout = 10 * 1000 * 1000; /* 10 ms */ + } else + ir->props.driver_type = RC_DRIVER_SCANCODE; + ir->props.priv = core; ir->props.open = cx88_ir_open; ir->props.close = cx88_ir_close; ir->props.scanmask = hardware_mask; + ir->props.allowed_protos = ir_type; /* all done */ err = ir_input_register(ir->input, ir_codes, &ir->props, MODULE_NAME); @@ -494,128 +495,36 @@ int cx88_ir_fini(struct cx88_core *core) void cx88_ir_irq(struct cx88_core *core) { struct cx88_IR *ir = core->ir; - u32 samples, ircode; - int i, start, range, toggle, dev, code; + u32 samples; + unsigned todo, bits; + struct ir_raw_event ev; + struct ir_input_dev *irdev; - if (NULL == ir) - return; - if (!ir->sampling) + if (!ir || !ir->sampling) return; + /* + * Samples are stored in a 32 bit register, oldest sample in + * the msb. A set bit represents space and an unset bit + * represents a pulse. + */ samples = cx_read(MO_SAMPLE_IO); - if (0 != samples && 0xffffffff != samples) { - /* record sample data */ - if (ir->scount < ARRAY_SIZE(ir->samples)) - ir->samples[ir->scount++] = samples; - return; - } - if (!ir->scount) { - /* nothing to sample */ - return; - } - - /* have a complete sample */ - if (ir->scount < ARRAY_SIZE(ir->samples)) - ir->samples[ir->scount++] = samples; - for (i = 0; i < ir->scount; i++) - ir->samples[i] = ~ir->samples[i]; - if (ir_debug) - ir_dump_samples(ir->samples, ir->scount); - - /* decode it */ - switch (core->boardnr) { - case CX88_BOARD_TEVII_S460: - case CX88_BOARD_TEVII_S420: - case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: - case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: - case CX88_BOARD_OMICOM_SS4_PCI: - case CX88_BOARD_SATTRADE_ST4200: - case CX88_BOARD_TBS_8920: - case CX88_BOARD_TBS_8910: - case CX88_BOARD_PROF_7300: - case CX88_BOARD_PROF_7301: - case CX88_BOARD_PROF_6200: - case CX88_BOARD_TWINHAN_VP1027_DVBS: - ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4); - - if (ircode == 0xffffffff) { /* decoding error */ - ir_dprintk("pulse distance decoding error\n"); - break; - } - - ir_dprintk("pulse distance decoded: %x\n", ircode); + irdev = input_get_drvdata(ir->input); - if (ircode == 0) { /* key still pressed */ - ir_dprintk("pulse distance decoded repeat code\n"); - ir_repeat(ir->input); - break; - } - - if ((ircode & 0xffff) != (ir->sampling & 0xffff)) { /* wrong address */ - ir_dprintk("pulse distance decoded wrong address\n"); - break; - } - - if (((~ircode >> 24) & 0xff) != ((ircode >> 16) & 0xff)) { /* wrong checksum */ - ir_dprintk("pulse distance decoded wrong check sum\n"); - break; - } + if (samples == 0xff && irdev->idle) + return; - ir_dprintk("Key Code: %x\n", (ircode >> 16) & 0xff); - ir_keydown(ir->input, (ircode >> 16) & 0xff, 0); - break; - case CX88_BOARD_HAUPPAUGE: - case CX88_BOARD_HAUPPAUGE_DVB_T1: - case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: - case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: - case CX88_BOARD_HAUPPAUGE_HVR1100: - case CX88_BOARD_HAUPPAUGE_HVR3000: - case CX88_BOARD_HAUPPAUGE_HVR4000: - case CX88_BOARD_HAUPPAUGE_HVR4000LITE: - case CX88_BOARD_PCHDTV_HD3000: - case CX88_BOARD_PCHDTV_HD5500: - case CX88_BOARD_HAUPPAUGE_IRONLY: - ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); - ir_dprintk("biphase decoded: %x\n", ircode); - /* - * RC5 has an extension bit which adds a new range - * of available codes, this is detected here. Also - * hauppauge remotes (black/silver) always use - * specific device ids. If we do not filter the - * device ids then messages destined for devices - * such as TVs (id=0) will get through to the - * device causing mis-fired events. - */ - /* split rc5 data block ... */ - start = (ircode & 0x2000) >> 13; - range = (ircode & 0x1000) >> 12; - toggle= (ircode & 0x0800) >> 11; - dev = (ircode & 0x07c0) >> 6; - code = (ircode & 0x003f) | ((range << 6) ^ 0x0040); - if( start != 1) - /* no key pressed */ - break; - if ( dev != 0x1e && dev != 0x1f ) - /* not a hauppauge remote */ - break; - ir_keydown(ir->input, code, toggle); - break; - case CX88_BOARD_PINNACLE_PCTV_HD_800i: - ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); - ir_dprintk("biphase decoded: %x\n", ircode); - if ((ircode & 0xfffff000) != 0x3000) - break; - /* Note: bit 0x800 being the toggle is assumed, not checked - with real hardware */ - ir_keydown(ir->input, ircode & 0x3f, ircode & 0x0800 ? 1 : 0); - break; + init_ir_raw_event(&ev); + for (todo = 32; todo > 0; todo -= bits) { + ev.pulse = samples & 0x80000000 ? false : true; + bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples)); + ev.duration = (bits * NSEC_PER_SEC) / (1000 * ir_samplerate); + ir_raw_event_store_with_filter(ir->input, &ev); + samples <<= bits; } - - ir->scount = 0; - return; + ir_raw_event_handle(ir->input); } - void cx88_i2c_init_ir(struct cx88_core *core) { struct i2c_board_info info; diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 528050e..41524204 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -96,9 +96,6 @@ void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir); void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir, u32 ir_key); u32 ir_extract_bits(u32 data, u32 mask); -int ir_dump_samples(u32 *samples, int count); -int ir_decode_biphase(u32 *samples, int count, int low, int high); -int ir_decode_pulsedistance(u32 *samples, int count, int low, int high); u32 ir_rc5_decode(unsigned int code); void ir_rc5_timer_end(unsigned long data); -- cgit v0.10.2 From 62c6503125389763a74911408d984c5dd09eeb97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=83=C2=A4rdeman?= Date: Fri, 29 Oct 2010 16:08:07 -0300 Subject: [media] ir-core: remove remaining users of the ir-functions keyhandlers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch removes the remaining usages of the ir_input_nokey() and ir_input_keydown() functions provided by drivers/media/IR/ir-functions.c by using the corresponding functionality in ir-core instead. Signed-off-by: David Härdeman Acked-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c index bc11806..79f4f58 100644 --- a/drivers/media/IR/imon.c +++ b/drivers/media/IR/imon.c @@ -1479,17 +1479,12 @@ static void imon_incoming_packet(struct imon_context *ictx, bool norelease = false; int i; u64 scancode; - struct input_dev *rdev = NULL; - struct ir_input_dev *irdev = NULL; int press_type = 0; int msec; struct timeval t; static struct timeval prev_time = { 0, 0 }; u8 ktype; - rdev = ictx->rdev; - irdev = input_get_drvdata(rdev); - /* filter out junk data on the older 0xffdc imon devices */ if ((buf[0] == 0xff) && (buf[1] == 0xff) && (buf[2] == 0xff)) return; @@ -1570,9 +1565,9 @@ static void imon_incoming_packet(struct imon_context *ictx, if (ktype != IMON_KEY_PANEL) { if (press_type == 0) - ir_keyup(irdev); + ir_keyup(ictx->rdev); else { - ir_keydown(rdev, ictx->rc_scancode, ictx->rc_toggle); + ir_keydown(ictx->rdev, ictx->rc_scancode, ictx->rc_toggle); spin_lock_irqsave(&ictx->kc_lock, flags); ictx->last_keycode = ictx->kc; spin_unlock_irqrestore(&ictx->kc_lock, flags); diff --git a/drivers/media/IR/ir-functions.c b/drivers/media/IR/ir-functions.c index f4c4115..fca734c 100644 --- a/drivers/media/IR/ir-functions.c +++ b/drivers/media/IR/ir-functions.c @@ -1,7 +1,7 @@ /* - * - * some common structs and functions to handle infrared remotes via - * input layer ... + * some common functions to handle infrared remote protocol decoding for + * drivers which have not yet been (or can't be) converted to use the + * regular protocol decoders... * * (c) 2003 Gerd Knorr [SuSE Labs] * @@ -31,67 +31,6 @@ MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); -static int repeat = 1; -module_param(repeat, int, 0444); -MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)"); - -/* -------------------------------------------------------------------------- */ - -static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) -{ - if (KEY_RESERVED == ir->keycode) { - printk(KERN_INFO "%s: unknown key: key=0x%02x down=%d\n", - dev->name, ir->ir_key, ir->keypressed); - return; - } - IR_dprintk(1,"%s: key event code=%d down=%d\n", - dev->name,ir->keycode,ir->keypressed); - input_report_key(dev,ir->keycode,ir->keypressed); - input_sync(dev); -} - -/* -------------------------------------------------------------------------- */ - -int ir_input_init(struct input_dev *dev, struct ir_input_state *ir, - const u64 ir_type) -{ - ir->ir_type = ir_type; - - if (repeat) - set_bit(EV_REP, dev->evbit); - - return 0; -} -EXPORT_SYMBOL_GPL(ir_input_init); - - -void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir) -{ - if (ir->keypressed) { - ir->keypressed = 0; - ir_input_key_event(dev,ir); - } -} -EXPORT_SYMBOL_GPL(ir_input_nokey); - -void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir, - u32 ir_key) -{ - u32 keycode = ir_g_keycode_from_table(dev, ir_key); - - if (ir->keypressed && ir->keycode != keycode) { - ir->keypressed = 0; - ir_input_key_event(dev,ir); - } - if (!ir->keypressed) { - ir->ir_key = ir_key; - ir->keycode = keycode; - ir->keypressed = 1; - ir_input_key_event(dev,ir); - } -} -EXPORT_SYMBOL_GPL(ir_input_keydown); - /* -------------------------------------------------------------------------- */ /* extract mask bits out of data and pack them into the result */ u32 ir_extract_bits(u32 data, u32 mask) @@ -115,7 +54,7 @@ EXPORT_SYMBOL_GPL(ir_extract_bits); * saa7134 */ /* decode raw bit pattern to RC5 code */ -u32 ir_rc5_decode(unsigned int code) +static u32 ir_rc5_decode(unsigned int code) { unsigned int org_code = code; unsigned int pair; @@ -144,13 +83,12 @@ u32 ir_rc5_decode(unsigned int code) RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); return rc5; } -EXPORT_SYMBOL_GPL(ir_rc5_decode); void ir_rc5_timer_end(unsigned long data) { struct card_ir *ir = (struct card_ir *)data; struct timeval tv; - unsigned long current_jiffies, timeout; + unsigned long current_jiffies; u32 gap; u32 rc5 = 0; @@ -191,32 +129,11 @@ void ir_rc5_timer_end(unsigned long data) u32 toggle = RC5_TOGGLE(rc5); u32 instr = RC5_INSTR(rc5); - /* Good code, decide if repeat/repress */ - if (toggle != RC5_TOGGLE(ir->last_rc5) || - instr != RC5_INSTR(ir->last_rc5)) { - IR_dprintk(1, "ir-common: instruction %x, toggle %x\n", instr, - toggle); - ir_input_nokey(ir->dev, &ir->ir); - ir_input_keydown(ir->dev, &ir->ir, instr); - } - - /* Set/reset key-up timer */ - timeout = current_jiffies + - msecs_to_jiffies(ir->rc5_key_timeout); - mod_timer(&ir->timer_keyup, timeout); - - /* Save code for repeat test */ - ir->last_rc5 = rc5; + /* Good code */ + ir_keydown(ir->dev, instr, toggle); + IR_dprintk(1, "ir-common: instruction %x, toggle %x\n", + instr, toggle); } } } EXPORT_SYMBOL_GPL(ir_rc5_timer_end); - -void ir_rc5_timer_keyup(unsigned long data) -{ - struct card_ir *ir = (struct card_ir *)data; - - IR_dprintk(1, "ir-common: key released\n"); - ir_input_nokey(ir->dev, &ir->ir); -} -EXPORT_SYMBOL_GPL(ir_rc5_timer_keyup); diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index f60107c..8039110 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -431,13 +431,13 @@ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); /** - * ir_keyup() - generates input event to cleanup a key press + * ir_do_keyup() - internal function to signal the release of a keypress * @ir: the struct ir_input_dev descriptor of the device * - * This routine is used to signal that a key has been released on the - * remote control. It reports a keyup input event via input_report_key(). + * This function is used internally to release a keypress, it must be + * called with keylock held. */ -void ir_keyup(struct ir_input_dev *ir) +static void ir_do_keyup(struct ir_input_dev *ir) { if (!ir->keypressed) return; @@ -447,6 +447,23 @@ void ir_keyup(struct ir_input_dev *ir) input_sync(ir->input_dev); ir->keypressed = false; } + +/** + * ir_keyup() - generates input event to signal the release of a keypress + * @dev: the struct input_dev descriptor of the device + * + * This routine is used to signal that a key has been released on the + * remote control. + */ +void ir_keyup(struct input_dev *dev) +{ + unsigned long flags; + struct ir_input_dev *ir = input_get_drvdata(dev); + + spin_lock_irqsave(&ir->keylock, flags); + ir_do_keyup(ir); + spin_unlock_irqrestore(&ir->keylock, flags); +} EXPORT_SYMBOL_GPL(ir_keyup); /** @@ -473,7 +490,7 @@ static void ir_timer_keyup(unsigned long cookie) */ spin_lock_irqsave(&ir->keylock, flags); if (time_is_before_eq_jiffies(ir->keyup_jiffies)) - ir_keyup(ir); + ir_do_keyup(ir); spin_unlock_irqrestore(&ir->keylock, flags); } @@ -506,44 +523,37 @@ out: EXPORT_SYMBOL_GPL(ir_repeat); /** - * ir_keydown() - generates input event for a key press + * ir_do_keydown() - internal function to process a keypress * @dev: the struct input_dev descriptor of the device - * @scancode: the scancode that we're seeking - * @toggle: the toggle value (protocol dependent, if the protocol doesn't - * support toggle values, this should be set to zero) + * @scancode: the scancode of the keypress + * @keycode: the keycode of the keypress + * @toggle: the toggle value of the keypress * - * This routine is used by the input routines when a key is pressed at the - * IR. It gets the keycode for a scancode and reports an input event via - * input_report_key(). + * This function is used internally to register a keypress, it must be + * called with keylock held. */ -void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) +static void ir_do_keydown(struct input_dev *dev, int scancode, + u32 keycode, u8 toggle) { - unsigned long flags; struct ir_input_dev *ir = input_get_drvdata(dev); - u32 keycode = ir_g_keycode_from_table(dev, scancode); - - spin_lock_irqsave(&ir->keylock, flags); - input_event(dev, EV_MSC, MSC_SCAN, scancode); /* Repeat event? */ if (ir->keypressed && ir->last_scancode == scancode && ir->last_toggle == toggle) - goto set_timer; + return; /* Release old keypress */ - ir_keyup(ir); + ir_do_keyup(ir); ir->last_scancode = scancode; ir->last_toggle = toggle; ir->last_keycode = keycode; - if (keycode == KEY_RESERVED) - goto out; - + return; /* Register a keypress */ ir->keypressed = true; @@ -551,15 +561,61 @@ void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) dev->name, keycode, scancode); input_report_key(dev, ir->last_keycode, 1); input_sync(dev); +} -set_timer: - ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); - mod_timer(&ir->timer_keyup, ir->keyup_jiffies); -out: +/** + * ir_keydown() - generates input event for a key press + * @dev: the struct input_dev descriptor of the device + * @scancode: the scancode that we're seeking + * @toggle: the toggle value (protocol dependent, if the protocol doesn't + * support toggle values, this should be set to zero) + * + * This routine is used by the input routines when a key is pressed at the + * IR. It gets the keycode for a scancode and reports an input event via + * input_report_key(). + */ +void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) +{ + unsigned long flags; + struct ir_input_dev *ir = input_get_drvdata(dev); + u32 keycode = ir_g_keycode_from_table(dev, scancode); + + spin_lock_irqsave(&ir->keylock, flags); + ir_do_keydown(dev, scancode, keycode, toggle); + + if (ir->keypressed) { + ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); + mod_timer(&ir->timer_keyup, ir->keyup_jiffies); + } spin_unlock_irqrestore(&ir->keylock, flags); } EXPORT_SYMBOL_GPL(ir_keydown); +/** + * ir_keydown_notimeout() - generates input event for a key press without + * an automatic keyup event at a later time + * @dev: the struct input_dev descriptor of the device + * @scancode: the scancode that we're seeking + * @toggle: the toggle value (protocol dependent, if the protocol doesn't + * support toggle values, this should be set to zero) + * + * This routine is used by the input routines when a key is pressed at the + * IR. It gets the keycode for a scancode and reports an input event via + * input_report_key(). The driver must manually call ir_keyup() at a later + * stage. + */ +void ir_keydown_notimeout(struct input_dev *dev, int scancode, u8 toggle) +{ + unsigned long flags; + struct ir_input_dev *ir = input_get_drvdata(dev); + u32 keycode = ir_g_keycode_from_table(dev, scancode); + + spin_lock_irqsave(&ir->keylock, flags); + ir_do_keydown(dev, scancode, keycode, toggle); + spin_unlock_irqrestore(&ir->keylock, flags); +} +EXPORT_SYMBOL_GPL(ir_keydown_notimeout); + static int ir_open(struct input_dev *input_dev) { struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 6bf05a7..eb71c3a 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -38,8 +38,6 @@ module_param(repeat_period, int, 0644); static int ir_rc5_remote_gap = 885; module_param(ir_rc5_remote_gap, int, 0644); -static int ir_rc5_key_timeout = 200; -module_param(ir_rc5_key_timeout, int, 0644); #undef dprintk #define dprintk(arg...) do { \ @@ -74,18 +72,17 @@ static void ir_handle_key(struct bttv *btv) (gpio & ir->mask_keydown) ? " down" : "", (gpio & ir->mask_keyup) ? " up" : ""); - if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || - (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { - ir_input_keydown(ir->dev, &ir->ir, data); + if ((ir->mask_keydown && (gpio & ir->mask_keydown)) || + (ir->mask_keyup && !(gpio & ir->mask_keyup))) { + ir_keydown_notimeout(ir->dev, data, 0); } else { /* HACK: Probably, ir->mask_keydown is missing for this board */ if (btv->c.type == BTTV_BOARD_WINFAST2000) - ir_input_keydown(ir->dev, &ir->ir, data); + ir_keydown_notimeout(ir->dev, data, 0); - ir_input_nokey(ir->dev,&ir->ir); + ir_keyup(ir->dev); } - } static void ir_enltv_handle_key(struct bttv *btv) @@ -107,9 +104,9 @@ static void ir_enltv_handle_key(struct bttv *btv) gpio, data, (gpio & ir->mask_keyup) ? " up" : "up/down"); - ir_input_keydown(ir->dev, &ir->ir, data); + ir_keydown_notimeout(ir->dev, data, 0); if (keyup) - ir_input_nokey(ir->dev, &ir->ir); + ir_keyup(ir->dev); } else { if ((ir->last_gpio & 1 << 31) == keyup) return; @@ -119,9 +116,9 @@ static void ir_enltv_handle_key(struct bttv *btv) (gpio & ir->mask_keyup) ? " up" : "down"); if (keyup) - ir_input_nokey(ir->dev, &ir->ir); + ir_keyup(ir->dev); else - ir_input_keydown(ir->dev, &ir->ir, data); + ir_keydown_notimeout(ir->dev, data, 0); } ir->last_gpio = data | keyup; @@ -215,14 +212,9 @@ static void bttv_ir_start(struct bttv *btv, struct card_ir *ir) init_timer(&ir->timer_end); ir->timer_end.function = ir_rc5_timer_end; ir->timer_end.data = (unsigned long)ir; - - init_timer(&ir->timer_keyup); - ir->timer_keyup.function = ir_rc5_timer_keyup; - ir->timer_keyup.data = (unsigned long)ir; ir->shift_by = 1; ir->start = 3; ir->addr = 0x0; - ir->rc5_key_timeout = ir_rc5_key_timeout; ir->rc5_remote_gap = ir_rc5_remote_gap; } } @@ -290,7 +282,6 @@ void __devinit init_bttv_i2c_ir(struct bttv *btv) btv->init_data.name = "PV951"; btv->init_data.get_key = get_key_pv951; btv->init_data.ir_codes = RC_MAP_PV951; - btv->init_data.type = IR_TYPE_OTHER; info.addr = 0x4b; break; default: @@ -327,7 +318,6 @@ int bttv_input_init(struct bttv *btv) struct card_ir *ir; char *ir_codes = NULL; struct input_dev *input_dev; - u64 ir_type = IR_TYPE_OTHER; int err = -ENOMEM; if (!btv->has_remote) @@ -448,10 +438,6 @@ int bttv_input_init(struct bttv *btv) snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(btv->c.pci)); - err = ir_input_init(input_dev, &ir->ir, ir_type); - if (err < 0) - goto err_out_free; - input_dev->name = ir->name; input_dev->phys = ir->phys; input_dev->id.bustype = BUS_PCI; diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index d1e26a4..157285b 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -305,7 +305,6 @@ struct bttv_pll_info { /* for gpio-connected remote control */ struct bttv_input { struct input_dev *dev; - struct ir_input_state ir; char name[32]; char phys[32]; u32 mask_keycode; diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 436ace8..564e3cb 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -131,16 +131,21 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) } else if (ir->mask_keydown) { /* bit set on keydown */ if (gpio & ir->mask_keydown) - ir_keydown(ir->input, data, 0); + ir_keydown_notimeout(ir->input, data, 0); + else + ir_keyup(ir->input); } else if (ir->mask_keyup) { /* bit cleared on keydown */ if (0 == (gpio & ir->mask_keyup)) - ir_keydown(ir->input, data, 0); + ir_keydown_notimeout(ir->input, data, 0); + else + ir_keyup(ir->input); } else { /* can't distinguish keydown/up :-/ */ - ir_keydown(ir->input, data, 0); + ir_keydown_notimeout(ir->input, data, 0); + ir_keyup(ir->input); } } diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index ce4a753..a78883a 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -269,7 +269,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) { char *ir_codes = NULL; const char *name = NULL; - u64 ir_type = 0; + u64 ir_type = IR_TYPE_UNKNOWN; struct IR_i2c *ir; struct input_dev *input_dev; struct i2c_adapter *adap = client->adapter; @@ -383,7 +383,6 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) dev_name(&client->dev)); /* init + register input device */ - ir->ir_type = ir_type; input_dev->id.bustype = BUS_I2C; input_dev->name = ir->name; input_dev->phys = ir->phys; diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index b6c682f..3e37593 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -44,8 +44,6 @@ MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=g static int ir_rc5_remote_gap = 885; module_param(ir_rc5_remote_gap, int, 0644); -static int ir_rc5_key_timeout = 115; -module_param(ir_rc5_key_timeout, int, 0644); static int repeat_delay = 500; module_param(repeat_delay, int, 0644); @@ -70,7 +68,6 @@ static int saa7134_rc5_irq(struct saa7134_dev *dev); static int saa7134_nec_irq(struct saa7134_dev *dev); static int saa7134_raw_decode_irq(struct saa7134_dev *dev); static void nec_task(unsigned long data); -static void saa7134_nec_timer(unsigned long data); /* -------------------- GPIO generic keycode builder -------------------- */ @@ -104,25 +101,25 @@ static int build_key(struct saa7134_dev *dev) switch (dev->board) { case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: if (data == ir->mask_keycode) - ir_input_nokey(ir->dev, &ir->ir); + ir_keyup(ir->dev); else - ir_input_keydown(ir->dev, &ir->ir, data); + ir_keydown_notimeout(ir->dev, data, 0); return 0; } if (ir->polling) { if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { - ir_input_keydown(ir->dev, &ir->ir, data); + ir_keydown_notimeout(ir->dev, data, 0); } else { - ir_input_nokey(ir->dev, &ir->ir); + ir_keyup(ir->dev); } } else { /* IRQ driven mode - handle key press and release in one go */ if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { - ir_input_keydown(ir->dev, &ir->ir, data); - ir_input_nokey(ir->dev, &ir->ir); + ir_keydown_notimeout(ir->dev, data, 0); + ir_keyup(ir->dev); } } @@ -465,17 +462,11 @@ static int __saa7134_ir_start(void *priv) init_timer(&ir->timer_end); ir->timer_end.function = ir_rc5_timer_end; ir->timer_end.data = (unsigned long)ir; - init_timer(&ir->timer_keyup); - ir->timer_keyup.function = ir_rc5_timer_keyup; - ir->timer_keyup.data = (unsigned long)ir; ir->shift_by = 2; ir->start = 0x2; ir->addr = 0x17; - ir->rc5_key_timeout = ir_rc5_key_timeout; ir->rc5_remote_gap = ir_rc5_remote_gap; } else if (ir->nec_gpio) { - setup_timer(&ir->timer_keyup, saa7134_nec_timer, - (unsigned long)dev); tasklet_init(&ir->tlet, nec_task, (unsigned long)dev); } else if (ir->raw_decode) { /* set timer_end for code completion */ @@ -596,7 +587,6 @@ int saa7134_input_init1(struct saa7134_dev *dev) int nec_gpio = 0; int raw_decode = 0; int allow_protocol_change = 0; - u64 ir_type = IR_TYPE_OTHER; int err; if (dev->has_remote != SAA7134_REMOTE_GPIO) @@ -871,10 +861,6 @@ int saa7134_input_init1(struct saa7134_dev *dev) ir->props.change_protocol = saa7134_ir_change_protocol; } - err = ir_input_init(input_dev, &ir->ir, ir_type); - if (err < 0) - goto err_out_free; - input_dev->name = ir->name; input_dev->phys = ir->phys; input_dev->id.bustype = BUS_PCI; @@ -1092,20 +1078,6 @@ static int saa7134_rc5_irq(struct saa7134_dev *dev) return 1; } -/* On NEC protocol, One has 2.25 ms, and zero has 1.125 ms - The first pulse (start) has 9 + 4.5 ms - */ - -static void saa7134_nec_timer(unsigned long data) -{ - struct saa7134_dev *dev = (struct saa7134_dev *) data; - struct card_ir *ir = dev->remote; - - dprintk("Cancel key repeat\n"); - - ir_input_nokey(ir->dev, &ir->ir); -} - static void nec_task(unsigned long data) { struct saa7134_dev *dev = (struct saa7134_dev *) data; @@ -1194,12 +1166,11 @@ static void nec_task(unsigned long data) dprintk("scancode = 0x%02x (code = 0x%02x, notcode= 0x%02x)\n", ir->code, ircode, not_code); - ir_input_keydown(ir->dev, &ir->ir, ir->code); - } else + ir_keydown(ir->dev, ir->code, 0); + } else { dprintk("Repeat last key\n"); - - /* Keep repeating the last key */ - mod_timer(&ir->timer_keyup, jiffies + msecs_to_jiffies(150)); + ir_repeat(ir->dev); + } saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P); } diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/staging/tm6000/tm6000-input.c index 6022caa..3e74884 100644 --- a/drivers/staging/tm6000/tm6000-input.c +++ b/drivers/staging/tm6000/tm6000-input.c @@ -25,7 +25,6 @@ #include #include -#include #include "tm6000.h" #include "tm6000-regs.h" @@ -52,7 +51,6 @@ struct tm6000_ir_poll_result { struct tm6000_IR { struct tm6000_core *dev; struct ir_input_dev *input; - struct ir_input_state ir; char name[32]; char phys[32]; @@ -67,6 +65,7 @@ struct tm6000_IR { int (*get_key) (struct tm6000_IR *, struct tm6000_ir_poll_result *); /* IR device properties */ + u64 ir_type; struct ir_dev_props props; }; @@ -145,7 +144,7 @@ static int default_polling_getkey(struct tm6000_IR *ir, return 0; if (&dev->int_in) { - if (ir->ir.ir_type == IR_TYPE_RC5) + if (ir->ir_type == IR_TYPE_RC5) poll_result->rc_data = ir->urb_data[0]; else poll_result->rc_data = ir->urb_data[0] | ir->urb_data[1] << 8; @@ -155,7 +154,7 @@ static int default_polling_getkey(struct tm6000_IR *ir, tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1); msleep(10); - if (ir->ir.ir_type == IR_TYPE_RC5) { + if (ir->ir_type == IR_TYPE_RC5) { rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, REQ_02_GET_IR_CODE, 0, 0, buf, 1); @@ -201,10 +200,7 @@ static void tm6000_ir_handle_key(struct tm6000_IR *ir) dprintk("ir->get_key result data=%04x\n", poll_result.rc_data); if (ir->key) { - ir_input_keydown(ir->input->input_dev, &ir->ir, - (u32)poll_result.rc_data); - - ir_input_nokey(ir->input->input_dev, &ir->ir); + ir_keydown(ir->input->input_dev, poll_result.rc_data, 0); ir->key = 0; } return; @@ -291,9 +287,6 @@ int tm6000_ir_init(struct tm6000_core *dev) strlcat(ir->phys, "/input0", sizeof(ir->phys)); tm6000_ir_change_protocol(ir, IR_TYPE_UNKNOWN); - err = ir_input_init(ir_input_dev->input_dev, &ir->ir, IR_TYPE_OTHER); - if (err < 0) - goto err_out_free; ir_input_dev->input_dev->name = ir->name; ir_input_dev->input_dev->phys = ir->phys; diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 41524204..4a32e89 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -1,7 +1,7 @@ /* - * - * some common structs and functions to handle infrared remotes via - * input layer ... + * some common functions to handle infrared remote protocol decoding for + * drivers which have not yet been (or can't be) converted to use the + * regular protocol decoders... * * (c) 2003 Gerd Knorr [SuSE Labs] * @@ -33,30 +33,17 @@ #define RC5_ADDR(x) (((x)>>6)&31) #define RC5_INSTR(x) ((x)&63) -struct ir_input_state { - /* configuration */ - u64 ir_type; - - /* key info */ - u32 ir_key; /* ir scancode */ - u32 keycode; /* linux key code */ - int keypressed; /* current state */ -}; - /* this was saa7134_ir and bttv_ir, moved here for * rc5 decoding. */ struct card_ir { struct input_dev *dev; - struct ir_input_state ir; char name[32]; char phys[32]; int users; - u32 running:1; struct ir_dev_props props; /* Usual gpio signalling */ - u32 mask_keycode; u32 mask_keydown; u32 mask_keyup; @@ -65,7 +52,6 @@ struct card_ir { int shift_by; int start; // What should RC5_START() be int addr; // What RC5_ADDR() should be. - int rc5_key_timeout; int rc5_remote_gap; struct work_struct work; struct timer_list timer; @@ -73,8 +59,6 @@ struct card_ir { /* RC5 gpio */ u32 rc5_gpio; struct timer_list timer_end; /* timer_end for code completion */ - struct timer_list timer_keyup; /* timer_end for key release */ - u32 last_rc5; /* last good rc5 code */ u32 last_bit; /* last raw bit seen */ u32 code; /* raw code under construction */ struct timeval base_time; /* time of last seen code */ @@ -89,16 +73,7 @@ struct card_ir { }; /* Routines from ir-functions.c */ - -int ir_input_init(struct input_dev *dev, struct ir_input_state *ir, - const u64 ir_type); -void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir); -void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir, - u32 ir_key); u32 ir_extract_bits(u32 data, u32 mask); -u32 ir_rc5_decode(unsigned int code); - void ir_rc5_timer_end(unsigned long data); -void ir_rc5_timer_keyup(unsigned long data); #endif diff --git a/include/media/ir-core.h b/include/media/ir-core.h index 6dc37fa..bff75f2 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h @@ -159,7 +159,8 @@ void ir_input_unregister(struct input_dev *input_dev); void ir_repeat(struct input_dev *dev); void ir_keydown(struct input_dev *dev, int scancode, u8 toggle); -void ir_keyup(struct ir_input_dev *ir); +void ir_keydown_notimeout(struct input_dev *dev, int scancode, u8 toggle); +void ir_keyup(struct input_dev *dev); u32 ir_g_keycode_from_table(struct input_dev *input_dev, u32 scancode); /* From ir-raw-event.c */ diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h index 557c676..8c37b5e 100644 --- a/include/media/ir-kbd-i2c.h +++ b/include/media/ir-kbd-i2c.h @@ -12,8 +12,7 @@ struct IR_i2c { struct i2c_client *c; struct input_dev *input; - struct ir_input_state ir; - u64 ir_type; + /* Used to avoid fast repeating */ unsigned char old; @@ -41,6 +40,7 @@ struct IR_i2c_init_data { const char *name; u64 type; /* IR_TYPE_RC5, etc */ u32 polling_interval; /* 0 means DEFAULT_POLLING_INTERVAL */ + /* * Specify either a function pointer or a value indicating one of * ir_kbd_i2c's internal get_key functions -- cgit v0.10.2 From 3ffea4988be3f3fa65f2104ba31eff2b5e0e82a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=83=C2=A4rdeman?= Date: Fri, 29 Oct 2010 16:08:12 -0300 Subject: [media] ir-core: more cleanups of ir-functions.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cx88 only depends on VIDEO_IR because it needs ir_extract_bits(). Move that function to ir-core.h and make it inline. Lots of drivers had dependencies on VIDEO_IR when they really wanted IR_CORE. The only remaining drivers to depend on VIDEO_IR are bt8xx and saa7134 (ir_rc5_timer_end is the only function exported by ir-functions). Rename VIDEO_IR -> IR_LEGACY to give a hint to anyone writing or converting drivers to IR_CORE that they do not want a dependency on IR_LEGACY. Signed-off-by: David Härdeman Acked-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig index aa4163e..20e02a0 100644 --- a/drivers/media/IR/Kconfig +++ b/drivers/media/IR/Kconfig @@ -10,7 +10,7 @@ menuconfig IR_CORE if you don't need IR, as otherwise, you may not be able to compile the driver for your adapter. -config VIDEO_IR +config IR_LEGACY tristate depends on IR_CORE default IR_CORE diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index f9574ad..38873cf 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile @@ -4,7 +4,7 @@ ir-core-objs := ir-keytable.o ir-sysfs.o ir-raw-event.o rc-map.o obj-y += keymaps/ obj-$(CONFIG_IR_CORE) += ir-core.o -obj-$(CONFIG_VIDEO_IR) += ir-common.o +obj-$(CONFIG_IR_LEGACY) += ir-common.o obj-$(CONFIG_LIRC) += lirc_dev.o obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o diff --git a/drivers/media/IR/ir-functions.c b/drivers/media/IR/ir-functions.c index fca734c..ec021c9 100644 --- a/drivers/media/IR/ir-functions.c +++ b/drivers/media/IR/ir-functions.c @@ -31,25 +31,6 @@ MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); -/* -------------------------------------------------------------------------- */ -/* extract mask bits out of data and pack them into the result */ -u32 ir_extract_bits(u32 data, u32 mask) -{ - u32 vbit = 1, value = 0; - - do { - if (mask&1) { - if (data&1) - value |= vbit; - vbit<<=1; - } - data>>=1; - } while (mask>>=1); - - return value; -} -EXPORT_SYMBOL_GPL(ir_extract_bits); - /* RC5 decoding stuff, moved from bttv-input.c to share it with * saa7134 */ diff --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/dvb/dm1105/Kconfig index a6ceb08..576f3b7 100644 --- a/drivers/media/dvb/dm1105/Kconfig +++ b/drivers/media/dvb/dm1105/Kconfig @@ -1,7 +1,6 @@ config DVB_DM1105 tristate "SDMC DM1105 based PCI cards" depends on DVB_CORE && PCI && I2C - depends on INPUT select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_STV0288 if !DVB_FE_CUSTOMISE @@ -9,7 +8,7 @@ config DVB_DM1105 select DVB_CX24116 if !DVB_FE_CUSTOMISE select DVB_SI21XX if !DVB_FE_CUSTOMISE select DVB_DS3000 if !DVB_FE_CUSTOMISE - depends on VIDEO_IR + depends on IR_CORE help Support for cards based on the SDMC DM1105 PCI chip like DvbWorld 2002 diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index debea8d..0ffd694 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -89,7 +89,6 @@ config DVB_BUDGET config DVB_BUDGET_CI tristate "Budget cards with onboard CI connector" depends on DVB_BUDGET_CORE && I2C - depends on INPUT # due to IR select DVB_STV0297 if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_TDA1004X if !DVB_FE_CUSTOMISE @@ -98,7 +97,7 @@ config DVB_BUDGET_CI select DVB_LNBP21 if !DVB_FE_CUSTOMISE select DVB_TDA10023 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE - depends on VIDEO_IR + depends on IR_CORE help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 6830d28..22feac4 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -96,7 +96,7 @@ config VIDEO_HELPER_CHIPS_AUTO config VIDEO_IR_I2C tristate "I2C module for IR" if !VIDEO_HELPER_CHIPS_AUTO - depends on I2C && VIDEO_IR + depends on I2C && IR_CORE default y ---help--- Most boards have an IR chip directly connected via GPIO. However, diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig index 1a4a89f..659e448 100644 --- a/drivers/media/video/bt8xx/Kconfig +++ b/drivers/media/video/bt8xx/Kconfig @@ -1,10 +1,10 @@ config VIDEO_BT848 tristate "BT848 Video For Linux" - depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 && INPUT + depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 select I2C_ALGOBIT select VIDEO_BTCX select VIDEOBUF_DMA_SG - depends on VIDEO_IR + depends on IR_LEGACY select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig index 76c054d..f3c3ccb 100644 --- a/drivers/media/video/cx18/Kconfig +++ b/drivers/media/video/cx18/Kconfig @@ -1,9 +1,8 @@ config VIDEO_CX18 tristate "Conexant cx23418 MPEG encoder support" depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL - depends on INPUT # due to VIDEO_IR select I2C_ALGOBIT - depends on VIDEO_IR + depends on IR_CORE select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_CX2341X diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/video/cx231xx/Kconfig index c37eac1..ab7d5df 100644 --- a/drivers/media/video/cx231xx/Kconfig +++ b/drivers/media/video/cx231xx/Kconfig @@ -1,9 +1,9 @@ config VIDEO_CX231XX tristate "Conexant cx231xx USB video capture support" - depends on VIDEO_DEV && I2C && INPUT + depends on VIDEO_DEV && I2C select VIDEO_TUNER select VIDEO_TVEEPROM - depends on VIDEO_IR + depends on IR_CORE select VIDEOBUF_VMALLOC select VIDEO_CX25840 select VIDEO_CX2341X diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index bcfd1ac..dbae629 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -1,12 +1,11 @@ config VIDEO_CX88 tristate "Conexant 2388x (bt878 successor) support" - depends on VIDEO_DEV && PCI && I2C && INPUT && IR_CORE + depends on VIDEO_DEV && PCI && I2C && IR_CORE select I2C_ALGOBIT select VIDEO_BTCX select VIDEOBUF_DMA_SG select VIDEO_TUNER select VIDEO_TVEEPROM - depends on VIDEO_IR select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO ---help--- This is a video4linux driver for Conexant 2388x based diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 564e3cb..8c41124 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -31,7 +31,6 @@ #include "cx88.h" #include -#include #define MODULE_NAME "cx88xx" diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 8d38c5f..72ea2ba 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -1,9 +1,9 @@ config VIDEO_EM28XX tristate "Empia EM28xx USB video capture support" - depends on VIDEO_DEV && I2C && INPUT + depends on VIDEO_DEV && I2C select VIDEO_TUNER select VIDEO_TVEEPROM - depends on VIDEO_IR + depends on IR_CORE select VIDEOBUF_VMALLOC select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig index be4af1f..c4f1980 100644 --- a/drivers/media/video/ivtv/Kconfig +++ b/drivers/media/video/ivtv/Kconfig @@ -1,9 +1,8 @@ config VIDEO_IVTV tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support" depends on VIDEO_V4L2 && PCI && I2C - depends on INPUT # due to VIDEO_IR select I2C_ALGOBIT - depends on VIDEO_IR + depends on IR_CORE select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_CX2341X diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index 3fe71be..32a95a2 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig @@ -26,7 +26,7 @@ config VIDEO_SAA7134_ALSA config VIDEO_SAA7134_RC bool "Philips SAA7134 Remote Controller support" - depends on VIDEO_IR + depends on IR_LEGACY depends on VIDEO_SAA7134 default y ---help--- diff --git a/drivers/media/video/tlg2300/Kconfig b/drivers/media/video/tlg2300/Kconfig index 1686ebf..580580e 100644 --- a/drivers/media/video/tlg2300/Kconfig +++ b/drivers/media/video/tlg2300/Kconfig @@ -1,9 +1,9 @@ config VIDEO_TLG2300 tristate "Telegent TLG2300 USB video capture support" - depends on VIDEO_DEV && I2C && INPUT && SND && DVB_CORE + depends on VIDEO_DEV && I2C && SND && DVB_CORE select VIDEO_TUNER select VIDEO_TVEEPROM - depends on VIDEO_IR + depends on IR_CORE select VIDEOBUF_VMALLOC select SND_PCM select VIDEOBUF_DVB diff --git a/drivers/staging/cx25821/Kconfig b/drivers/staging/cx25821/Kconfig index 1d73334..f8f2bb0 100644 --- a/drivers/staging/cx25821/Kconfig +++ b/drivers/staging/cx25821/Kconfig @@ -1,11 +1,11 @@ config VIDEO_CX25821 tristate "Conexant cx25821 support" - depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT + depends on DVB_CORE && VIDEO_DEV && PCI && I2C depends on BKL # please fix select I2C_ALGOBIT select VIDEO_BTCX select VIDEO_TVEEPROM - depends on VIDEO_IR + depends on IR_CORE select VIDEOBUF_DVB select VIDEOBUF_DMA_SG select VIDEO_CX25840 diff --git a/drivers/staging/go7007/Kconfig b/drivers/staging/go7007/Kconfig index 3aecd30..edc9091 100644 --- a/drivers/staging/go7007/Kconfig +++ b/drivers/staging/go7007/Kconfig @@ -1,10 +1,10 @@ config VIDEO_GO7007 tristate "WIS GO7007 MPEG encoder support" - depends on VIDEO_DEV && PCI && I2C && INPUT + depends on VIDEO_DEV && PCI && I2C depends on BKL # please fix depends on SND select VIDEOBUF_DMA_SG - depends on VIDEO_IR + depends on IR_CORE select VIDEO_TUNER select VIDEO_TVEEPROM select SND_PCM diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 4a32e89..d1ae869f 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -73,7 +73,6 @@ struct card_ir { }; /* Routines from ir-functions.c */ -u32 ir_extract_bits(u32 data, u32 mask); void ir_rc5_timer_end(unsigned long data); #endif diff --git a/include/media/ir-core.h b/include/media/ir-core.h index bff75f2..53048a2 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h @@ -212,4 +212,23 @@ static inline void ir_raw_event_reset(struct input_dev *input_dev) ir_raw_event_handle(input_dev); } + +/* extract mask bits out of data and pack them into the result */ +static inline u32 ir_extract_bits(u32 data, u32 mask) +{ + u32 vbit = 1, value = 0; + + do { + if (mask & 1) { + if (data & 1) + value |= vbit; + vbit <<= 1; + } + data >>= 1; + } while (mask >>= 1); + + return value; +} + + #endif /* _IR_CORE */ -- cgit v0.10.2 From 32cf86f6d16367db5a10039c1dd938a2427d697c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 9 Nov 2010 23:00:14 -0300 Subject: [media] rename drivers/media/IR to drives/media/rc Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig deleted file mode 100644 index 20e02a0..0000000 --- a/drivers/media/IR/Kconfig +++ /dev/null @@ -1,167 +0,0 @@ -menuconfig IR_CORE - tristate "Infrared remote controller adapters" - depends on INPUT - default INPUT - ---help--- - Enable support for Remote Controllers on Linux. This is - needed in order to support several video capture adapters. - - Enable this option if you have a video capture board even - if you don't need IR, as otherwise, you may not be able to - compile the driver for your adapter. - -config IR_LEGACY - tristate - depends on IR_CORE - default IR_CORE - -if IR_CORE - -config LIRC - tristate - default y - - ---help--- - Enable this option to build the Linux Infrared Remote - Control (LIRC) core device interface driver. The LIRC - interface passes raw IR to and from userspace, where the - LIRC daemon handles protocol decoding for IR reception and - encoding for IR transmitting (aka "blasting"). - -source "drivers/media/IR/keymaps/Kconfig" - -config IR_NEC_DECODER - tristate "Enable IR raw decoder for the NEC protocol" - depends on IR_CORE - select BITREVERSE - default y - - ---help--- - Enable this option if you have IR with NEC protocol, and - if the IR is decoded in software - -config IR_RC5_DECODER - tristate "Enable IR raw decoder for the RC-5 protocol" - depends on IR_CORE - select BITREVERSE - default y - - ---help--- - Enable this option if you have IR with RC-5 protocol, and - if the IR is decoded in software - -config IR_RC6_DECODER - tristate "Enable IR raw decoder for the RC6 protocol" - depends on IR_CORE - select BITREVERSE - default y - - ---help--- - Enable this option if you have an infrared remote control which - uses the RC6 protocol, and you need software decoding support. - -config IR_JVC_DECODER - tristate "Enable IR raw decoder for the JVC protocol" - depends on IR_CORE - select BITREVERSE - default y - - ---help--- - Enable this option if you have an infrared remote control which - uses the JVC protocol, and you need software decoding support. - -config IR_SONY_DECODER - tristate "Enable IR raw decoder for the Sony protocol" - depends on IR_CORE - default y - - ---help--- - Enable this option if you have an infrared remote control which - uses the Sony protocol, and you need software decoding support. - -config IR_RC5_SZ_DECODER - tristate "Enable IR raw decoder for the RC-5 (streamzap) protocol" - depends on IR_CORE - select BITREVERSE - default y - - ---help--- - Enable this option if you have IR with RC-5 (streamzap) protocol, - and if the IR is decoded in software. (The Streamzap PC Remote - uses an IR protocol that is almost standard RC-5, but not quite, - as it uses an additional bit). - -config IR_LIRC_CODEC - tristate "Enable IR to LIRC bridge" - depends on IR_CORE - depends on LIRC - default y - - ---help--- - Enable this option to pass raw IR to and from userspace via - the LIRC interface. - -config IR_ENE - tristate "ENE eHome Receiver/Transceiver (pnp id: ENE0100/ENE02xxx)" - depends on PNP - depends on IR_CORE - ---help--- - Say Y here to enable support for integrated infrared receiver - /transceiver made by ENE. - - You can see if you have it by looking at lspnp output. - Output should include ENE0100 ENE0200 or something similar. - - To compile this driver as a module, choose M here: the - module will be called ene_ir. - -config IR_IMON - tristate "SoundGraph iMON Receiver and Display" - depends on USB_ARCH_HAS_HCD - depends on IR_CORE - select USB - ---help--- - Say Y here if you want to use a SoundGraph iMON (aka Antec Veris) - IR Receiver and/or LCD/VFD/VGA display. - - To compile this driver as a module, choose M here: the - module will be called imon. - -config IR_MCEUSB - tristate "Windows Media Center Ed. eHome Infrared Transceiver" - depends on USB_ARCH_HAS_HCD - depends on IR_CORE - select USB - ---help--- - Say Y here if you want to use a Windows Media Center Edition - eHome Infrared Transceiver. - - To compile this driver as a module, choose M here: the - module will be called mceusb. - -config IR_NUVOTON - tristate "Nuvoton w836x7hg Consumer Infrared Transceiver" - depends on PNP - depends on IR_CORE - ---help--- - Say Y here to enable support for integrated infrared receiver - /transciever made by Nuvoton (formerly Winbond). This chip is - found in the ASRock ION 330HT, as well as assorted Intel - DP55-series motherboards (and of course, possibly others). - - To compile this driver as a module, choose M here: the - module will be called nuvoton-cir. - -config IR_STREAMZAP - tristate "Streamzap PC Remote IR Receiver" - depends on USB_ARCH_HAS_HCD - depends on IR_CORE - select USB - ---help--- - Say Y here if you want to use a Streamzap PC Remote - Infrared Receiver. - - To compile this driver as a module, choose M here: the - module will be called streamzap. - -endif #IR_CORE diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile deleted file mode 100644 index 38873cf..0000000 --- a/drivers/media/IR/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -ir-common-objs := ir-functions.o -ir-core-objs := ir-keytable.o ir-sysfs.o ir-raw-event.o rc-map.o - -obj-y += keymaps/ - -obj-$(CONFIG_IR_CORE) += ir-core.o -obj-$(CONFIG_IR_LEGACY) += ir-common.o -obj-$(CONFIG_LIRC) += lirc_dev.o -obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o -obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o -obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o -obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o -obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o -obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o -obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o - -# stand-alone IR receivers/transmitters -obj-$(CONFIG_IR_IMON) += imon.o -obj-$(CONFIG_IR_MCEUSB) += mceusb.o -obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o -obj-$(CONFIG_IR_ENE) += ene_ir.o -obj-$(CONFIG_IR_STREAMZAP) += streamzap.o diff --git a/drivers/media/IR/ene_ir.c b/drivers/media/IR/ene_ir.c deleted file mode 100644 index 7637bab..0000000 --- a/drivers/media/IR/ene_ir.c +++ /dev/null @@ -1,1217 +0,0 @@ -/* - * driver for ENE KB3926 B/C/D/E/F CIR (pnp id: ENE0XXX) - * - * Copyright (C) 2010 Maxim Levitsky - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * Special thanks to: - * Sami R. for lot of help in debugging and therefore - * bringing to life support for transmission & learning mode. - * - * Charlie Andrews for lots of help in - * bringing up the support of new firmware buffer that is popular - * on latest notebooks - * - * ENE for partial device documentation - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ene_ir.h" - -static int sample_period; -static bool learning_mode_force; -static int debug; -static bool txsim; - -static void ene_set_reg_addr(struct ene_device *dev, u16 reg) -{ - outb(reg >> 8, dev->hw_io + ENE_ADDR_HI); - outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO); -} - -/* read a hardware register */ -static u8 ene_read_reg(struct ene_device *dev, u16 reg) -{ - u8 retval; - ene_set_reg_addr(dev, reg); - retval = inb(dev->hw_io + ENE_IO); - dbg_regs("reg %04x == %02x", reg, retval); - return retval; -} - -/* write a hardware register */ -static void ene_write_reg(struct ene_device *dev, u16 reg, u8 value) -{ - dbg_regs("reg %04x <- %02x", reg, value); - ene_set_reg_addr(dev, reg); - outb(value, dev->hw_io + ENE_IO); -} - -/* Set bits in hardware register */ -static void ene_set_reg_mask(struct ene_device *dev, u16 reg, u8 mask) -{ - dbg_regs("reg %04x |= %02x", reg, mask); - ene_set_reg_addr(dev, reg); - outb(inb(dev->hw_io + ENE_IO) | mask, dev->hw_io + ENE_IO); -} - -/* Clear bits in hardware register */ -static void ene_clear_reg_mask(struct ene_device *dev, u16 reg, u8 mask) -{ - dbg_regs("reg %04x &= ~%02x ", reg, mask); - ene_set_reg_addr(dev, reg); - outb(inb(dev->hw_io + ENE_IO) & ~mask, dev->hw_io + ENE_IO); -} - -/* A helper to set/clear a bit in register according to boolean variable */ -static void ene_set_clear_reg_mask(struct ene_device *dev, u16 reg, u8 mask, - bool set) -{ - if (set) - ene_set_reg_mask(dev, reg, mask); - else - ene_clear_reg_mask(dev, reg, mask); -} - -/* detect hardware features */ -static int ene_hw_detect(struct ene_device *dev) -{ - u8 chip_major, chip_minor; - u8 hw_revision, old_ver; - u8 fw_reg2, fw_reg1; - - ene_clear_reg_mask(dev, ENE_ECSTS, ENE_ECSTS_RSRVD); - chip_major = ene_read_reg(dev, ENE_ECVER_MAJOR); - chip_minor = ene_read_reg(dev, ENE_ECVER_MINOR); - ene_set_reg_mask(dev, ENE_ECSTS, ENE_ECSTS_RSRVD); - - hw_revision = ene_read_reg(dev, ENE_ECHV); - old_ver = ene_read_reg(dev, ENE_HW_VER_OLD); - - dev->pll_freq = (ene_read_reg(dev, ENE_PLLFRH) << 4) + - (ene_read_reg(dev, ENE_PLLFRL) >> 4); - - if (sample_period != ENE_DEFAULT_SAMPLE_PERIOD) - dev->rx_period_adjust = - dev->pll_freq == ENE_DEFAULT_PLL_FREQ ? 2 : 4; - - if (hw_revision == 0xFF) { - ene_warn("device seems to be disabled"); - ene_warn("send a mail to lirc-list@lists.sourceforge.net"); - ene_warn("please attach output of acpidump and dmidecode"); - return -ENODEV; - } - - ene_notice("chip is 0x%02x%02x - kbver = 0x%02x, rev = 0x%02x", - chip_major, chip_minor, old_ver, hw_revision); - - ene_notice("PLL freq = %d", dev->pll_freq); - - if (chip_major == 0x33) { - ene_warn("chips 0x33xx aren't supported"); - return -ENODEV; - } - - if (chip_major == 0x39 && chip_minor == 0x26 && hw_revision == 0xC0) { - dev->hw_revision = ENE_HW_C; - ene_notice("KB3926C detected"); - } else if (old_ver == 0x24 && hw_revision == 0xC0) { - dev->hw_revision = ENE_HW_B; - ene_notice("KB3926B detected"); - } else { - dev->hw_revision = ENE_HW_D; - ene_notice("KB3926D or higher detected"); - } - - /* detect features hardware supports */ - if (dev->hw_revision < ENE_HW_C) - return 0; - - fw_reg1 = ene_read_reg(dev, ENE_FW1); - fw_reg2 = ene_read_reg(dev, ENE_FW2); - - ene_notice("Firmware regs: %02x %02x", fw_reg1, fw_reg2); - - dev->hw_use_gpio_0a = !!(fw_reg2 & ENE_FW2_GP0A); - dev->hw_learning_and_tx_capable = !!(fw_reg2 & ENE_FW2_LEARNING); - dev->hw_extra_buffer = !!(fw_reg1 & ENE_FW1_HAS_EXTRA_BUF); - - if (dev->hw_learning_and_tx_capable) - dev->hw_fan_input = !!(fw_reg2 & ENE_FW2_FAN_INPUT); - - ene_notice("Hardware features:"); - - if (dev->hw_learning_and_tx_capable) { - ene_notice("* Supports transmitting & learning mode"); - ene_notice(" This feature is rare and therefore,"); - ene_notice(" you are welcome to test it,"); - ene_notice(" and/or contact the author via:"); - ene_notice(" lirc-list@lists.sourceforge.net"); - ene_notice(" or maximlevitsky@gmail.com"); - - ene_notice("* Uses GPIO %s for IR raw input", - dev->hw_use_gpio_0a ? "40" : "0A"); - - if (dev->hw_fan_input) - ene_notice("* Uses unused fan feedback input as source" - " of demodulated IR data"); - } - - if (!dev->hw_fan_input) - ene_notice("* Uses GPIO %s for IR demodulated input", - dev->hw_use_gpio_0a ? "0A" : "40"); - - if (dev->hw_extra_buffer) - ene_notice("* Uses new style input buffer"); - return 0; -} - -/* Read properities of hw sample buffer */ -static void ene_rx_setup_hw_buffer(struct ene_device *dev) -{ - u16 tmp; - - ene_rx_read_hw_pointer(dev); - dev->r_pointer = dev->w_pointer; - - if (!dev->hw_extra_buffer) { - dev->buffer_len = ENE_FW_PACKET_SIZE * 2; - return; - } - - tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER); - tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER+1) << 8; - dev->extra_buf1_address = tmp; - - dev->extra_buf1_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 2); - - tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 3); - tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 4) << 8; - dev->extra_buf2_address = tmp; - - dev->extra_buf2_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 5); - - dev->buffer_len = dev->extra_buf1_len + dev->extra_buf2_len + 8; - - ene_notice("Hardware uses 2 extended buffers:"); - ene_notice(" 0x%04x - len : %d", dev->extra_buf1_address, - dev->extra_buf1_len); - ene_notice(" 0x%04x - len : %d", dev->extra_buf2_address, - dev->extra_buf2_len); - - ene_notice("Total buffer len = %d", dev->buffer_len); - - if (dev->buffer_len > 64 || dev->buffer_len < 16) - goto error; - - if (dev->extra_buf1_address > 0xFBFC || - dev->extra_buf1_address < 0xEC00) - goto error; - - if (dev->extra_buf2_address > 0xFBFC || - dev->extra_buf2_address < 0xEC00) - goto error; - - if (dev->r_pointer > dev->buffer_len) - goto error; - - ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND); - return; -error: - ene_warn("Error validating extra buffers, device probably won't work"); - dev->hw_extra_buffer = false; - ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND); -} - - -/* Restore the pointers to extra buffers - to make module reload work*/ -static void ene_rx_restore_hw_buffer(struct ene_device *dev) -{ - if (!dev->hw_extra_buffer) - return; - - ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 0, - dev->extra_buf1_address & 0xFF); - ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 1, - dev->extra_buf1_address >> 8); - ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 2, dev->extra_buf1_len); - - ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 3, - dev->extra_buf2_address & 0xFF); - ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 4, - dev->extra_buf2_address >> 8); - ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 5, - dev->extra_buf2_len); - ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND); -} - -/* Read hardware write pointer */ -static void ene_rx_read_hw_pointer(struct ene_device *dev) -{ - if (dev->hw_extra_buffer) - dev->w_pointer = ene_read_reg(dev, ENE_FW_RX_POINTER); - else - dev->w_pointer = ene_read_reg(dev, ENE_FW2) - & ENE_FW2_BUF_WPTR ? 0 : ENE_FW_PACKET_SIZE; - - dbg_verbose("RB: HW write pointer: %02x, driver read pointer: %02x", - dev->w_pointer, dev->r_pointer); -} - -/* Gets address of next sample from HW ring buffer */ -static int ene_rx_get_sample_reg(struct ene_device *dev) -{ - int r_pointer; - - if (dev->r_pointer == dev->w_pointer) { - dbg_verbose("RB: hit end, try update w_pointer"); - ene_rx_read_hw_pointer(dev); - } - - if (dev->r_pointer == dev->w_pointer) { - dbg_verbose("RB: end of data at %d", dev->r_pointer); - return 0; - } - - dbg_verbose("RB: reading at offset %d", dev->r_pointer); - r_pointer = dev->r_pointer; - - dev->r_pointer++; - if (dev->r_pointer == dev->buffer_len) - dev->r_pointer = 0; - - dbg_verbose("RB: next read will be from offset %d", dev->r_pointer); - - if (r_pointer < 8) { - dbg_verbose("RB: read at main buffer at %d", r_pointer); - return ENE_FW_SAMPLE_BUFFER + r_pointer; - } - - r_pointer -= 8; - - if (r_pointer < dev->extra_buf1_len) { - dbg_verbose("RB: read at 1st extra buffer at %d", r_pointer); - return dev->extra_buf1_address + r_pointer; - } - - r_pointer -= dev->extra_buf1_len; - - if (r_pointer < dev->extra_buf2_len) { - dbg_verbose("RB: read at 2nd extra buffer at %d", r_pointer); - return dev->extra_buf2_address + r_pointer; - } - - dbg("attempt to read beyong ring bufer end"); - return 0; -} - -/* Sense current received carrier */ -void ene_rx_sense_carrier(struct ene_device *dev) -{ - DEFINE_IR_RAW_EVENT(ev); - - int carrier, duty_cycle; - int period = ene_read_reg(dev, ENE_CIRCAR_PRD); - int hperiod = ene_read_reg(dev, ENE_CIRCAR_HPRD); - - if (!(period & ENE_CIRCAR_PRD_VALID)) - return; - - period &= ~ENE_CIRCAR_PRD_VALID; - - if (!period) - return; - - dbg("RX: hardware carrier period = %02x", period); - dbg("RX: hardware carrier pulse period = %02x", hperiod); - - carrier = 2000000 / period; - duty_cycle = (hperiod * 100) / period; - dbg("RX: sensed carrier = %d Hz, duty cycle %d%%", - carrier, duty_cycle); - if (dev->carrier_detect_enabled) { - ev.carrier_report = true; - ev.carrier = carrier; - ev.duty_cycle = duty_cycle; - ir_raw_event_store(dev->idev, &ev); - } -} - -/* this enables/disables the CIR RX engine */ -static void ene_rx_enable_cir_engine(struct ene_device *dev, bool enable) -{ - ene_set_clear_reg_mask(dev, ENE_CIRCFG, - ENE_CIRCFG_RX_EN | ENE_CIRCFG_RX_IRQ, enable); -} - -/* this selects input for CIR engine. Ether GPIO 0A or GPIO40*/ -static void ene_rx_select_input(struct ene_device *dev, bool gpio_0a) -{ - ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_GPIO0A, gpio_0a); -} - -/* - * this enables alternative input via fan tachometer sensor and bypasses - * the hw CIR engine - */ -static void ene_rx_enable_fan_input(struct ene_device *dev, bool enable) -{ - if (!dev->hw_fan_input) - return; - - if (!enable) - ene_write_reg(dev, ENE_FAN_AS_IN1, 0); - else { - ene_write_reg(dev, ENE_FAN_AS_IN1, ENE_FAN_AS_IN1_EN); - ene_write_reg(dev, ENE_FAN_AS_IN2, ENE_FAN_AS_IN2_EN); - } -} - -/* setup the receiver for RX*/ -static void ene_rx_setup(struct ene_device *dev) -{ - bool learning_mode = dev->learning_mode_enabled || - dev->carrier_detect_enabled; - int sample_period_adjust = 0; - - dbg("RX: setup receiver, learning mode = %d", learning_mode); - - - /* This selects RLC input and clears CFG2 settings */ - ene_write_reg(dev, ENE_CIRCFG2, 0x00); - - /* set sample period*/ - if (sample_period == ENE_DEFAULT_SAMPLE_PERIOD) - sample_period_adjust = - dev->pll_freq == ENE_DEFAULT_PLL_FREQ ? 1 : 2; - - ene_write_reg(dev, ENE_CIRRLC_CFG, - (sample_period + sample_period_adjust) | - ENE_CIRRLC_CFG_OVERFLOW); - /* revB doesn't support inputs */ - if (dev->hw_revision < ENE_HW_C) - goto select_timeout; - - if (learning_mode) { - - WARN_ON(!dev->hw_learning_and_tx_capable); - - /* Enable the opposite of the normal input - That means that if GPIO40 is normally used, use GPIO0A - and vice versa. - This input will carry non demodulated - signal, and we will tell the hw to demodulate it itself */ - ene_rx_select_input(dev, !dev->hw_use_gpio_0a); - dev->rx_fan_input_inuse = false; - - /* Enable carrier demodulation */ - ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD); - - /* Enable carrier detection */ - ene_write_reg(dev, ENE_CIRCAR_PULS, 0x63); - ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_CARR_DETECT, - dev->carrier_detect_enabled || debug); - } else { - if (dev->hw_fan_input) - dev->rx_fan_input_inuse = true; - else - ene_rx_select_input(dev, dev->hw_use_gpio_0a); - - /* Disable carrier detection & demodulation */ - ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD); - ene_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_CARR_DETECT); - } - -select_timeout: - if (dev->rx_fan_input_inuse) { - dev->props->rx_resolution = MS_TO_NS(ENE_FW_SAMPLE_PERIOD_FAN); - - /* Fan input doesn't support timeouts, it just ends the - input with a maximum sample */ - dev->props->min_timeout = dev->props->max_timeout = - MS_TO_NS(ENE_FW_SMPL_BUF_FAN_MSK * - ENE_FW_SAMPLE_PERIOD_FAN); - } else { - dev->props->rx_resolution = MS_TO_NS(sample_period); - - /* Theoreticly timeout is unlimited, but we cap it - * because it was seen that on one device, it - * would stop sending spaces after around 250 msec. - * Besides, this is close to 2^32 anyway and timeout is u32. - */ - dev->props->min_timeout = MS_TO_NS(127 * sample_period); - dev->props->max_timeout = MS_TO_NS(200000); - } - - if (dev->hw_learning_and_tx_capable) - dev->props->tx_resolution = MS_TO_NS(sample_period); - - if (dev->props->timeout > dev->props->max_timeout) - dev->props->timeout = dev->props->max_timeout; - if (dev->props->timeout < dev->props->min_timeout) - dev->props->timeout = dev->props->min_timeout; -} - -/* Enable the device for receive */ -static void ene_rx_enable(struct ene_device *dev) -{ - u8 reg_value; - - /* Enable system interrupt */ - if (dev->hw_revision < ENE_HW_C) { - ene_write_reg(dev, ENEB_IRQ, dev->irq << 1); - ene_write_reg(dev, ENEB_IRQ_UNK1, 0x01); - } else { - reg_value = ene_read_reg(dev, ENE_IRQ) & 0xF0; - reg_value |= ENE_IRQ_UNK_EN; - reg_value &= ~ENE_IRQ_STATUS; - reg_value |= (dev->irq & ENE_IRQ_MASK); - ene_write_reg(dev, ENE_IRQ, reg_value); - } - - /* Enable inputs */ - ene_rx_enable_fan_input(dev, dev->rx_fan_input_inuse); - ene_rx_enable_cir_engine(dev, !dev->rx_fan_input_inuse); - - /* ack any pending irqs - just in case */ - ene_irq_status(dev); - - /* enable firmware bits */ - ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ); - - /* enter idle mode */ - ir_raw_event_set_idle(dev->idev, true); - dev->rx_enabled = true; -} - -/* Disable the device receiver */ -static void ene_rx_disable(struct ene_device *dev) -{ - /* disable inputs */ - ene_rx_enable_cir_engine(dev, false); - ene_rx_enable_fan_input(dev, false); - - /* disable hardware IRQ and firmware flag */ - ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ); - - ir_raw_event_set_idle(dev->idev, true); - dev->rx_enabled = false; -} - -/* This resets the receiver. Usefull to stop stream of spaces at end of - * transmission - */ -static void ene_rx_reset(struct ene_device *dev) -{ - ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN); - ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN); -} - -/* Set up the TX carrier frequency and duty cycle */ -static void ene_tx_set_carrier(struct ene_device *dev) -{ - u8 tx_puls_width; - unsigned long flags; - - spin_lock_irqsave(&dev->hw_lock, flags); - - ene_set_clear_reg_mask(dev, ENE_CIRCFG, - ENE_CIRCFG_TX_CARR, dev->tx_period > 0); - - if (!dev->tx_period) - goto unlock; - - BUG_ON(dev->tx_duty_cycle >= 100 || dev->tx_duty_cycle <= 0); - - tx_puls_width = dev->tx_period / (100 / dev->tx_duty_cycle); - - if (!tx_puls_width) - tx_puls_width = 1; - - dbg("TX: pulse distance = %d * 500 ns", dev->tx_period); - dbg("TX: pulse width = %d * 500 ns", tx_puls_width); - - ene_write_reg(dev, ENE_CIRMOD_PRD, dev->tx_period | ENE_CIRMOD_PRD_POL); - ene_write_reg(dev, ENE_CIRMOD_HPRD, tx_puls_width); -unlock: - spin_unlock_irqrestore(&dev->hw_lock, flags); -} - -/* Enable/disable transmitters */ -static void ene_tx_set_transmitters(struct ene_device *dev) -{ - unsigned long flags; - - spin_lock_irqsave(&dev->hw_lock, flags); - ene_set_clear_reg_mask(dev, ENE_GPIOFS8, ENE_GPIOFS8_GPIO41, - !!(dev->transmitter_mask & 0x01)); - ene_set_clear_reg_mask(dev, ENE_GPIOFS1, ENE_GPIOFS1_GPIO0D, - !!(dev->transmitter_mask & 0x02)); - spin_unlock_irqrestore(&dev->hw_lock, flags); -} - -/* prepare transmission */ -static void ene_tx_enable(struct ene_device *dev) -{ - u8 conf1 = ene_read_reg(dev, ENE_CIRCFG); - u8 fwreg2 = ene_read_reg(dev, ENE_FW2); - - dev->saved_conf1 = conf1; - - /* Show information about currently connected transmitter jacks */ - if (fwreg2 & ENE_FW2_EMMITER1_CONN) - dbg("TX: Transmitter #1 is connected"); - - if (fwreg2 & ENE_FW2_EMMITER2_CONN) - dbg("TX: Transmitter #2 is connected"); - - if (!(fwreg2 & (ENE_FW2_EMMITER1_CONN | ENE_FW2_EMMITER2_CONN))) - ene_warn("TX: transmitter cable isn't connected!"); - - /* disable receive on revc */ - if (dev->hw_revision == ENE_HW_C) - conf1 &= ~ENE_CIRCFG_RX_EN; - - /* Enable TX engine */ - conf1 |= ENE_CIRCFG_TX_EN | ENE_CIRCFG_TX_IRQ; - ene_write_reg(dev, ENE_CIRCFG, conf1); -} - -/* end transmission */ -static void ene_tx_disable(struct ene_device *dev) -{ - ene_write_reg(dev, ENE_CIRCFG, dev->saved_conf1); - dev->tx_buffer = NULL; -} - - -/* TX one sample - must be called with dev->hw_lock*/ -static void ene_tx_sample(struct ene_device *dev) -{ - u8 raw_tx; - u32 sample; - bool pulse = dev->tx_sample_pulse; - - if (!dev->tx_buffer) { - ene_warn("TX: BUG: attempt to transmit NULL buffer"); - return; - } - - /* Grab next TX sample */ - if (!dev->tx_sample) { - - if (dev->tx_pos == dev->tx_len) { - if (!dev->tx_done) { - dbg("TX: no more data to send"); - dev->tx_done = true; - goto exit; - } else { - dbg("TX: last sample sent by hardware"); - ene_tx_disable(dev); - complete(&dev->tx_complete); - return; - } - } - - sample = dev->tx_buffer[dev->tx_pos++]; - dev->tx_sample_pulse = !dev->tx_sample_pulse; - - dev->tx_sample = DIV_ROUND_CLOSEST(sample, sample_period); - - if (!dev->tx_sample) - dev->tx_sample = 1; - } - - raw_tx = min(dev->tx_sample , (unsigned int)ENE_CIRRLC_OUT_MASK); - dev->tx_sample -= raw_tx; - - dbg("TX: sample %8d (%s)", raw_tx * sample_period, - pulse ? "pulse" : "space"); - if (pulse) - raw_tx |= ENE_CIRRLC_OUT_PULSE; - - ene_write_reg(dev, - dev->tx_reg ? ENE_CIRRLC_OUT1 : ENE_CIRRLC_OUT0, raw_tx); - - dev->tx_reg = !dev->tx_reg; -exit: - /* simulate TX done interrupt */ - if (txsim) - mod_timer(&dev->tx_sim_timer, jiffies + HZ / 500); -} - -/* timer to simulate tx done interrupt */ -static void ene_tx_irqsim(unsigned long data) -{ - struct ene_device *dev = (struct ene_device *)data; - unsigned long flags; - - spin_lock_irqsave(&dev->hw_lock, flags); - ene_tx_sample(dev); - spin_unlock_irqrestore(&dev->hw_lock, flags); -} - - -/* read irq status and ack it */ -static int ene_irq_status(struct ene_device *dev) -{ - u8 irq_status; - u8 fw_flags1, fw_flags2; - int retval = 0; - - fw_flags2 = ene_read_reg(dev, ENE_FW2); - - if (dev->hw_revision < ENE_HW_C) { - irq_status = ene_read_reg(dev, ENEB_IRQ_STATUS); - - if (!(irq_status & ENEB_IRQ_STATUS_IR)) - return 0; - - ene_clear_reg_mask(dev, ENEB_IRQ_STATUS, ENEB_IRQ_STATUS_IR); - return ENE_IRQ_RX; - } - - irq_status = ene_read_reg(dev, ENE_IRQ); - if (!(irq_status & ENE_IRQ_STATUS)) - return 0; - - /* original driver does that twice - a workaround ? */ - ene_write_reg(dev, ENE_IRQ, irq_status & ~ENE_IRQ_STATUS); - ene_write_reg(dev, ENE_IRQ, irq_status & ~ENE_IRQ_STATUS); - - /* check RX interrupt */ - if (fw_flags2 & ENE_FW2_RXIRQ) { - retval |= ENE_IRQ_RX; - ene_write_reg(dev, ENE_FW2, fw_flags2 & ~ENE_FW2_RXIRQ); - } - - /* check TX interrupt */ - fw_flags1 = ene_read_reg(dev, ENE_FW1); - if (fw_flags1 & ENE_FW1_TXIRQ) { - ene_write_reg(dev, ENE_FW1, fw_flags1 & ~ENE_FW1_TXIRQ); - retval |= ENE_IRQ_TX; - } - - return retval; -} - -/* interrupt handler */ -static irqreturn_t ene_isr(int irq, void *data) -{ - u16 hw_value, reg; - int hw_sample, irq_status; - bool pulse; - unsigned long flags; - irqreturn_t retval = IRQ_NONE; - struct ene_device *dev = (struct ene_device *)data; - DEFINE_IR_RAW_EVENT(ev); - - spin_lock_irqsave(&dev->hw_lock, flags); - - dbg_verbose("ISR called"); - ene_rx_read_hw_pointer(dev); - irq_status = ene_irq_status(dev); - - if (!irq_status) - goto unlock; - - retval = IRQ_HANDLED; - - if (irq_status & ENE_IRQ_TX) { - dbg_verbose("TX interrupt"); - if (!dev->hw_learning_and_tx_capable) { - dbg("TX interrupt on unsupported device!"); - goto unlock; - } - ene_tx_sample(dev); - } - - if (!(irq_status & ENE_IRQ_RX)) - goto unlock; - - dbg_verbose("RX interrupt"); - - if (dev->hw_learning_and_tx_capable) - ene_rx_sense_carrier(dev); - - /* On hardware that don't support extra buffer we need to trust - the interrupt and not track the read pointer */ - if (!dev->hw_extra_buffer) - dev->r_pointer = dev->w_pointer == 0 ? ENE_FW_PACKET_SIZE : 0; - - while (1) { - - reg = ene_rx_get_sample_reg(dev); - - dbg_verbose("next sample to read at: %04x", reg); - if (!reg) - break; - - hw_value = ene_read_reg(dev, reg); - - if (dev->rx_fan_input_inuse) { - - int offset = ENE_FW_SMPL_BUF_FAN - ENE_FW_SAMPLE_BUFFER; - - /* read high part of the sample */ - hw_value |= ene_read_reg(dev, reg + offset) << 8; - pulse = hw_value & ENE_FW_SMPL_BUF_FAN_PLS; - - /* clear space bit, and other unused bits */ - hw_value &= ENE_FW_SMPL_BUF_FAN_MSK; - hw_sample = hw_value * ENE_FW_SAMPLE_PERIOD_FAN; - - } else { - pulse = !(hw_value & ENE_FW_SAMPLE_SPACE); - hw_value &= ~ENE_FW_SAMPLE_SPACE; - hw_sample = hw_value * sample_period; - - if (dev->rx_period_adjust) { - hw_sample *= 100; - hw_sample /= (100 + dev->rx_period_adjust); - } - } - - if (!dev->hw_extra_buffer && !hw_sample) { - dev->r_pointer = dev->w_pointer; - continue; - } - - dbg("RX: %d (%s)", hw_sample, pulse ? "pulse" : "space"); - - ev.duration = MS_TO_NS(hw_sample); - ev.pulse = pulse; - ir_raw_event_store_with_filter(dev->idev, &ev); - } - - ir_raw_event_handle(dev->idev); -unlock: - spin_unlock_irqrestore(&dev->hw_lock, flags); - return retval; -} - -/* Initialize default settings */ -static void ene_setup_default_settings(struct ene_device *dev) -{ - dev->tx_period = 32; - dev->tx_duty_cycle = 50; /*%*/ - dev->transmitter_mask = 0x03; - dev->learning_mode_enabled = learning_mode_force; - - /* Set reasonable default timeout */ - dev->props->timeout = MS_TO_NS(150000); -} - -/* Upload all hardware settings at once. Used at load and resume time */ -static void ene_setup_hw_settings(struct ene_device *dev) -{ - if (dev->hw_learning_and_tx_capable) { - ene_tx_set_carrier(dev); - ene_tx_set_transmitters(dev); - } - - ene_rx_setup(dev); -} - -/* outside interface: called on first open*/ -static int ene_open(void *data) -{ - struct ene_device *dev = (struct ene_device *)data; - unsigned long flags; - - spin_lock_irqsave(&dev->hw_lock, flags); - ene_rx_enable(dev); - spin_unlock_irqrestore(&dev->hw_lock, flags); - return 0; -} - -/* outside interface: called on device close*/ -static void ene_close(void *data) -{ - struct ene_device *dev = (struct ene_device *)data; - unsigned long flags; - spin_lock_irqsave(&dev->hw_lock, flags); - - ene_rx_disable(dev); - spin_unlock_irqrestore(&dev->hw_lock, flags); -} - -/* outside interface: set transmitter mask */ -static int ene_set_tx_mask(void *data, u32 tx_mask) -{ - struct ene_device *dev = (struct ene_device *)data; - dbg("TX: attempt to set transmitter mask %02x", tx_mask); - - /* invalid txmask */ - if (!tx_mask || tx_mask & ~0x03) { - dbg("TX: invalid mask"); - /* return count of transmitters */ - return 2; - } - - dev->transmitter_mask = tx_mask; - ene_tx_set_transmitters(dev); - return 0; -} - -/* outside interface : set tx carrier */ -static int ene_set_tx_carrier(void *data, u32 carrier) -{ - struct ene_device *dev = (struct ene_device *)data; - u32 period = 2000000 / carrier; - - dbg("TX: attempt to set tx carrier to %d kHz", carrier); - - if (period && (period > ENE_CIRMOD_PRD_MAX || - period < ENE_CIRMOD_PRD_MIN)) { - - dbg("TX: out of range %d-%d kHz carrier", - 2000 / ENE_CIRMOD_PRD_MIN, 2000 / ENE_CIRMOD_PRD_MAX); - return -1; - } - - dev->tx_period = period; - ene_tx_set_carrier(dev); - return 0; -} - -/*outside interface : set tx duty cycle */ -static int ene_set_tx_duty_cycle(void *data, u32 duty_cycle) -{ - struct ene_device *dev = (struct ene_device *)data; - dbg("TX: setting duty cycle to %d%%", duty_cycle); - dev->tx_duty_cycle = duty_cycle; - ene_tx_set_carrier(dev); - return 0; -} - -/* outside interface: enable learning mode */ -static int ene_set_learning_mode(void *data, int enable) -{ - struct ene_device *dev = (struct ene_device *)data; - unsigned long flags; - if (enable == dev->learning_mode_enabled) - return 0; - - spin_lock_irqsave(&dev->hw_lock, flags); - dev->learning_mode_enabled = enable; - ene_rx_disable(dev); - ene_rx_setup(dev); - ene_rx_enable(dev); - spin_unlock_irqrestore(&dev->hw_lock, flags); - return 0; -} - -static int ene_set_carrier_report(void *data, int enable) -{ - struct ene_device *dev = (struct ene_device *)data; - unsigned long flags; - - if (enable == dev->carrier_detect_enabled) - return 0; - - spin_lock_irqsave(&dev->hw_lock, flags); - dev->carrier_detect_enabled = enable; - ene_rx_disable(dev); - ene_rx_setup(dev); - ene_rx_enable(dev); - spin_unlock_irqrestore(&dev->hw_lock, flags); - return 0; -} - -/* outside interface: enable or disable idle mode */ -static void ene_set_idle(void *data, bool idle) -{ - if (idle) { - ene_rx_reset((struct ene_device *)data); - dbg("RX: end of data"); - } -} - -/* outside interface: transmit */ -static int ene_transmit(void *data, int *buf, u32 n) -{ - struct ene_device *dev = (struct ene_device *)data; - unsigned long flags; - - dev->tx_buffer = buf; - dev->tx_len = n / sizeof(int); - dev->tx_pos = 0; - dev->tx_reg = 0; - dev->tx_done = 0; - dev->tx_sample = 0; - dev->tx_sample_pulse = 0; - - dbg("TX: %d samples", dev->tx_len); - - spin_lock_irqsave(&dev->hw_lock, flags); - - ene_tx_enable(dev); - - /* Transmit first two samples */ - ene_tx_sample(dev); - ene_tx_sample(dev); - - spin_unlock_irqrestore(&dev->hw_lock, flags); - - if (wait_for_completion_timeout(&dev->tx_complete, 2 * HZ) == 0) { - dbg("TX: timeout"); - spin_lock_irqsave(&dev->hw_lock, flags); - ene_tx_disable(dev); - spin_unlock_irqrestore(&dev->hw_lock, flags); - } else - dbg("TX: done"); - return n; -} - -/* probe entry */ -static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) -{ - int error = -ENOMEM; - struct ir_dev_props *ir_props; - struct input_dev *input_dev; - struct ene_device *dev; - - /* allocate memory */ - input_dev = input_allocate_device(); - ir_props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); - dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL); - - if (!input_dev || !ir_props || !dev) - goto error1; - - /* validate resources */ - error = -ENODEV; - - if (!pnp_port_valid(pnp_dev, 0) || - pnp_port_len(pnp_dev, 0) < ENE_IO_SIZE) - goto error; - - if (!pnp_irq_valid(pnp_dev, 0)) - goto error; - - spin_lock_init(&dev->hw_lock); - - /* claim the resources */ - error = -EBUSY; - dev->hw_io = pnp_port_start(pnp_dev, 0); - if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) { - dev->hw_io = -1; - dev->irq = -1; - goto error; - } - - dev->irq = pnp_irq(pnp_dev, 0); - if (request_irq(dev->irq, ene_isr, - IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) { - dev->irq = -1; - goto error; - } - - pnp_set_drvdata(pnp_dev, dev); - dev->pnp_dev = pnp_dev; - - /* don't allow too short/long sample periods */ - if (sample_period < 5 || sample_period > 0x7F) - sample_period = ENE_DEFAULT_SAMPLE_PERIOD; - - /* detect hardware version and features */ - error = ene_hw_detect(dev); - if (error) - goto error; - - if (!dev->hw_learning_and_tx_capable && txsim) { - dev->hw_learning_and_tx_capable = true; - setup_timer(&dev->tx_sim_timer, ene_tx_irqsim, - (long unsigned int)dev); - ene_warn("Simulation of TX activated"); - } - - if (!dev->hw_learning_and_tx_capable) - learning_mode_force = false; - - ir_props->driver_type = RC_DRIVER_IR_RAW; - ir_props->allowed_protos = IR_TYPE_ALL; - ir_props->priv = dev; - ir_props->open = ene_open; - ir_props->close = ene_close; - ir_props->s_idle = ene_set_idle; - - dev->props = ir_props; - dev->idev = input_dev; - - if (dev->hw_learning_and_tx_capable) { - ir_props->s_learning_mode = ene_set_learning_mode; - init_completion(&dev->tx_complete); - ir_props->tx_ir = ene_transmit; - ir_props->s_tx_mask = ene_set_tx_mask; - ir_props->s_tx_carrier = ene_set_tx_carrier; - ir_props->s_tx_duty_cycle = ene_set_tx_duty_cycle; - ir_props->s_carrier_report = ene_set_carrier_report; - } - - ene_rx_setup_hw_buffer(dev); - ene_setup_default_settings(dev); - ene_setup_hw_settings(dev); - - device_set_wakeup_capable(&pnp_dev->dev, true); - device_set_wakeup_enable(&pnp_dev->dev, true); - - if (dev->hw_learning_and_tx_capable) - input_dev->name = "ENE eHome Infrared Remote Transceiver"; - else - input_dev->name = "ENE eHome Infrared Remote Receiver"; - - error = -ENODEV; - if (ir_input_register(input_dev, RC_MAP_RC6_MCE, ir_props, - ENE_DRIVER_NAME)) - goto error; - - ene_notice("driver has been succesfully loaded"); - return 0; -error: - if (dev && dev->irq >= 0) - free_irq(dev->irq, dev); - if (dev && dev->hw_io >= 0) - release_region(dev->hw_io, ENE_IO_SIZE); -error1: - input_free_device(input_dev); - kfree(ir_props); - kfree(dev); - return error; -} - -/* main unload function */ -static void ene_remove(struct pnp_dev *pnp_dev) -{ - struct ene_device *dev = pnp_get_drvdata(pnp_dev); - unsigned long flags; - - spin_lock_irqsave(&dev->hw_lock, flags); - ene_rx_disable(dev); - ene_rx_restore_hw_buffer(dev); - spin_unlock_irqrestore(&dev->hw_lock, flags); - - free_irq(dev->irq, dev); - release_region(dev->hw_io, ENE_IO_SIZE); - ir_input_unregister(dev->idev); - kfree(dev->props); - kfree(dev); -} - -/* enable wake on IR (wakes on specific button on original remote) */ -static void ene_enable_wake(struct ene_device *dev, int enable) -{ - enable = enable && device_may_wakeup(&dev->pnp_dev->dev); - dbg("wake on IR %s", enable ? "enabled" : "disabled"); - ene_set_clear_reg_mask(dev, ENE_FW1, ENE_FW1_WAKE, enable); -} - -#ifdef CONFIG_PM -static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state) -{ - struct ene_device *dev = pnp_get_drvdata(pnp_dev); - ene_enable_wake(dev, true); - - /* TODO: add support for wake pattern */ - return 0; -} - -static int ene_resume(struct pnp_dev *pnp_dev) -{ - struct ene_device *dev = pnp_get_drvdata(pnp_dev); - ene_setup_hw_settings(dev); - - if (dev->rx_enabled) - ene_rx_enable(dev); - - ene_enable_wake(dev, false); - return 0; -} -#endif - -static void ene_shutdown(struct pnp_dev *pnp_dev) -{ - struct ene_device *dev = pnp_get_drvdata(pnp_dev); - ene_enable_wake(dev, true); -} - -static const struct pnp_device_id ene_ids[] = { - {.id = "ENE0100",}, - {.id = "ENE0200",}, - {.id = "ENE0201",}, - {.id = "ENE0202",}, - {}, -}; - -static struct pnp_driver ene_driver = { - .name = ENE_DRIVER_NAME, - .id_table = ene_ids, - .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, - - .probe = ene_probe, - .remove = __devexit_p(ene_remove), -#ifdef CONFIG_PM - .suspend = ene_suspend, - .resume = ene_resume, -#endif - .shutdown = ene_shutdown, -}; - -static int __init ene_init(void) -{ - return pnp_register_driver(&ene_driver); -} - -static void ene_exit(void) -{ - pnp_unregister_driver(&ene_driver); -} - -module_param(sample_period, int, S_IRUGO); -MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)"); - -module_param(learning_mode_force, bool, S_IRUGO); -MODULE_PARM_DESC(learning_mode_force, "Enable learning mode by default"); - -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug level"); - -module_param(txsim, bool, S_IRUGO); -MODULE_PARM_DESC(txsim, - "Simulate TX features on unsupported hardware (dangerous)"); - -MODULE_DEVICE_TABLE(pnp, ene_ids); -MODULE_DESCRIPTION - ("Infrared input driver for KB3926B/C/D/E/F " - "(aka ENE0100/ENE0200/ENE0201/ENE0202) CIR port"); - -MODULE_AUTHOR("Maxim Levitsky"); -MODULE_LICENSE("GPL"); - -module_init(ene_init); -module_exit(ene_exit); diff --git a/drivers/media/IR/ene_ir.h b/drivers/media/IR/ene_ir.h deleted file mode 100644 index f587066..0000000 --- a/drivers/media/IR/ene_ir.h +++ /dev/null @@ -1,262 +0,0 @@ -/* - * driver for ENE KB3926 B/C/D/E/F CIR (also known as ENE0XXX) - * - * Copyright (C) 2010 Maxim Levitsky - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ -#include - - -/* hardware address */ -#define ENE_STATUS 0 /* hardware status - unused */ -#define ENE_ADDR_HI 1 /* hi byte of register address */ -#define ENE_ADDR_LO 2 /* low byte of register address */ -#define ENE_IO 3 /* read/write window */ -#define ENE_IO_SIZE 4 - -/* 8 bytes of samples, divided in 2 packets*/ -#define ENE_FW_SAMPLE_BUFFER 0xF8F0 /* sample buffer */ -#define ENE_FW_SAMPLE_SPACE 0x80 /* sample is space */ -#define ENE_FW_PACKET_SIZE 4 - -/* first firmware flag register */ -#define ENE_FW1 0xF8F8 /* flagr */ -#define ENE_FW1_ENABLE 0x01 /* enable fw processing */ -#define ENE_FW1_TXIRQ 0x02 /* TX interrupt pending */ -#define ENE_FW1_HAS_EXTRA_BUF 0x04 /* fw uses extra buffer*/ -#define ENE_FW1_EXTRA_BUF_HND 0x08 /* extra buffer handshake bit*/ -#define ENE_FW1_LED_ON 0x10 /* turn on a led */ - -#define ENE_FW1_WPATTERN 0x20 /* enable wake pattern */ -#define ENE_FW1_WAKE 0x40 /* enable wake from S3 */ -#define ENE_FW1_IRQ 0x80 /* enable interrupt */ - -/* second firmware flag register */ -#define ENE_FW2 0xF8F9 /* flagw */ -#define ENE_FW2_BUF_WPTR 0x01 /* which half of the buffer to read */ -#define ENE_FW2_RXIRQ 0x04 /* RX IRQ pending*/ -#define ENE_FW2_GP0A 0x08 /* Use GPIO0A for demodulated input */ -#define ENE_FW2_EMMITER1_CONN 0x10 /* TX emmiter 1 connected */ -#define ENE_FW2_EMMITER2_CONN 0x20 /* TX emmiter 2 connected */ - -#define ENE_FW2_FAN_INPUT 0x40 /* fan input used for demodulated data*/ -#define ENE_FW2_LEARNING 0x80 /* hardware supports learning and TX */ - -/* firmware RX pointer for new style buffer */ -#define ENE_FW_RX_POINTER 0xF8FA - -/* high parts of samples for fan input (8 samples)*/ -#define ENE_FW_SMPL_BUF_FAN 0xF8FB -#define ENE_FW_SMPL_BUF_FAN_PLS 0x8000 /* combined sample is pulse */ -#define ENE_FW_SMPL_BUF_FAN_MSK 0x0FFF /* combined sample maximum value */ -#define ENE_FW_SAMPLE_PERIOD_FAN 61 /* fan input has fixed sample period */ - -/* transmitter ports */ -#define ENE_GPIOFS1 0xFC01 -#define ENE_GPIOFS1_GPIO0D 0x20 /* enable tx output on GPIO0D */ -#define ENE_GPIOFS8 0xFC08 -#define ENE_GPIOFS8_GPIO41 0x02 /* enable tx output on GPIO40 */ - -/* IRQ registers block (for revision B) */ -#define ENEB_IRQ 0xFD09 /* IRQ number */ -#define ENEB_IRQ_UNK1 0xFD17 /* unknown setting = 1 */ -#define ENEB_IRQ_STATUS 0xFD80 /* irq status */ -#define ENEB_IRQ_STATUS_IR 0x20 /* IR irq */ - -/* fan as input settings */ -#define ENE_FAN_AS_IN1 0xFE30 /* fan init reg 1 */ -#define ENE_FAN_AS_IN1_EN 0xCD -#define ENE_FAN_AS_IN2 0xFE31 /* fan init reg 2 */ -#define ENE_FAN_AS_IN2_EN 0x03 - -/* IRQ registers block (for revision C,D) */ -#define ENE_IRQ 0xFE9B /* new irq settings register */ -#define ENE_IRQ_MASK 0x0F /* irq number mask */ -#define ENE_IRQ_UNK_EN 0x10 /* always enabled */ -#define ENE_IRQ_STATUS 0x20 /* irq status and ACK */ - -/* CIR Config register #1 */ -#define ENE_CIRCFG 0xFEC0 -#define ENE_CIRCFG_RX_EN 0x01 /* RX enable */ -#define ENE_CIRCFG_RX_IRQ 0x02 /* Enable hardware interrupt */ -#define ENE_CIRCFG_REV_POL 0x04 /* Input polarity reversed */ -#define ENE_CIRCFG_CARR_DEMOD 0x08 /* Enable carrier demodulator */ - -#define ENE_CIRCFG_TX_EN 0x10 /* TX enable */ -#define ENE_CIRCFG_TX_IRQ 0x20 /* Send interrupt on TX done */ -#define ENE_CIRCFG_TX_POL_REV 0x40 /* TX polarity reversed */ -#define ENE_CIRCFG_TX_CARR 0x80 /* send TX carrier or not */ - -/* CIR config register #2 */ -#define ENE_CIRCFG2 0xFEC1 -#define ENE_CIRCFG2_RLC 0x00 -#define ENE_CIRCFG2_RC5 0x01 -#define ENE_CIRCFG2_RC6 0x02 -#define ENE_CIRCFG2_NEC 0x03 -#define ENE_CIRCFG2_CARR_DETECT 0x10 /* Enable carrier detection */ -#define ENE_CIRCFG2_GPIO0A 0x20 /* Use GPIO0A instead of GPIO40 for input */ -#define ENE_CIRCFG2_FAST_SAMPL1 0x40 /* Fast leading pulse detection for RC6 */ -#define ENE_CIRCFG2_FAST_SAMPL2 0x80 /* Fast data detection for RC6 */ - -/* Knobs for protocol decoding - will document when/if will use them */ -#define ENE_CIRPF 0xFEC2 -#define ENE_CIRHIGH 0xFEC3 -#define ENE_CIRBIT 0xFEC4 -#define ENE_CIRSTART 0xFEC5 -#define ENE_CIRSTART2 0xFEC6 - -/* Actual register which contains RLC RX data - read by firmware */ -#define ENE_CIRDAT_IN 0xFEC7 - - -/* RLC configuration - sample period (1us resulution) + idle mode */ -#define ENE_CIRRLC_CFG 0xFEC8 -#define ENE_CIRRLC_CFG_OVERFLOW 0x80 /* interrupt on overflows if set */ -#define ENE_DEFAULT_SAMPLE_PERIOD 50 - -/* Two byte RLC TX buffer */ -#define ENE_CIRRLC_OUT0 0xFEC9 -#define ENE_CIRRLC_OUT1 0xFECA -#define ENE_CIRRLC_OUT_PULSE 0x80 /* Transmitted sample is pulse */ -#define ENE_CIRRLC_OUT_MASK 0x7F - - -/* Carrier detect setting - * Low nibble - number of carrier pulses to average - * High nibble - number of initial carrier pulses to discard - */ -#define ENE_CIRCAR_PULS 0xFECB - -/* detected RX carrier period (resolution: 500 ns) */ -#define ENE_CIRCAR_PRD 0xFECC -#define ENE_CIRCAR_PRD_VALID 0x80 /* data valid content valid */ - -/* detected RX carrier pulse width (resolution: 500 ns) */ -#define ENE_CIRCAR_HPRD 0xFECD - -/* TX period (resolution: 500 ns, minimum 2)*/ -#define ENE_CIRMOD_PRD 0xFECE -#define ENE_CIRMOD_PRD_POL 0x80 /* TX carrier polarity*/ - -#define ENE_CIRMOD_PRD_MAX 0x7F /* 15.87 kHz */ -#define ENE_CIRMOD_PRD_MIN 0x02 /* 1 Mhz */ - -/* TX pulse width (resolution: 500 ns)*/ -#define ENE_CIRMOD_HPRD 0xFECF - -/* Hardware versions */ -#define ENE_ECHV 0xFF00 /* hardware revision */ -#define ENE_PLLFRH 0xFF16 -#define ENE_PLLFRL 0xFF17 -#define ENE_DEFAULT_PLL_FREQ 1000 - -#define ENE_ECSTS 0xFF1D -#define ENE_ECSTS_RSRVD 0x04 - -#define ENE_ECVER_MAJOR 0xFF1E /* chip version */ -#define ENE_ECVER_MINOR 0xFF1F -#define ENE_HW_VER_OLD 0xFD00 - -/******************************************************************************/ - -#define ENE_DRIVER_NAME "ene_ir" - -#define ENE_IRQ_RX 1 -#define ENE_IRQ_TX 2 - -#define ENE_HW_B 1 /* 3926B */ -#define ENE_HW_C 2 /* 3926C */ -#define ENE_HW_D 3 /* 3926D or later */ - -#define ene_printk(level, text, ...) \ - printk(level ENE_DRIVER_NAME ": " text "\n", ## __VA_ARGS__) - -#define ene_notice(text, ...) ene_printk(KERN_NOTICE, text, ## __VA_ARGS__) -#define ene_warn(text, ...) ene_printk(KERN_WARNING, text, ## __VA_ARGS__) - - -#define __dbg(level, format, ...) \ - do { \ - if (debug >= level) \ - printk(KERN_DEBUG ENE_DRIVER_NAME \ - ": " format "\n", ## __VA_ARGS__); \ - } while (0) - - -#define dbg(format, ...) __dbg(1, format, ## __VA_ARGS__) -#define dbg_verbose(format, ...) __dbg(2, format, ## __VA_ARGS__) -#define dbg_regs(format, ...) __dbg(3, format, ## __VA_ARGS__) - -#define MS_TO_NS(msec) ((msec) * 1000) - -struct ene_device { - struct pnp_dev *pnp_dev; - struct input_dev *idev; - struct ir_dev_props *props; - - /* hw IO settings */ - long hw_io; - int irq; - spinlock_t hw_lock; - - /* HW features */ - int hw_revision; /* hardware revision */ - bool hw_use_gpio_0a; /* gpio0a is demodulated input*/ - bool hw_extra_buffer; /* hardware has 'extra buffer' */ - bool hw_fan_input; /* fan input is IR data source */ - bool hw_learning_and_tx_capable; /* learning & tx capable */ - int pll_freq; - int buffer_len; - - /* Extra RX buffer location */ - int extra_buf1_address; - int extra_buf1_len; - int extra_buf2_address; - int extra_buf2_len; - - /* HW state*/ - int r_pointer; /* pointer to next sample to read */ - int w_pointer; /* pointer to next sample hw will write */ - bool rx_fan_input_inuse; /* is fan input in use for rx*/ - int tx_reg; /* current reg used for TX */ - u8 saved_conf1; /* saved FEC0 reg */ - unsigned int tx_sample; /* current sample for TX */ - bool tx_sample_pulse; /* current sample is pulse */ - - /* TX buffer */ - int *tx_buffer; /* input samples buffer*/ - int tx_pos; /* position in that bufer */ - int tx_len; /* current len of tx buffer */ - int tx_done; /* done transmitting */ - /* one more sample pending*/ - struct completion tx_complete; /* TX completion */ - struct timer_list tx_sim_timer; - - /* TX settings */ - int tx_period; - int tx_duty_cycle; - int transmitter_mask; - - /* RX settings */ - bool learning_mode_enabled; /* learning input enabled */ - bool carrier_detect_enabled; /* carrier detect enabled */ - int rx_period_adjust; - bool rx_enabled; -}; - -static int ene_irq_status(struct ene_device *dev); -static void ene_rx_read_hw_pointer(struct ene_device *dev); diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c deleted file mode 100644 index 79f4f58..0000000 --- a/drivers/media/IR/imon.c +++ /dev/null @@ -1,2465 +0,0 @@ -/* - * imon.c: input and display driver for SoundGraph iMON IR/VFD/LCD - * - * Copyright(C) 2010 Jarod Wilson - * Portions based on the original lirc_imon driver, - * Copyright(C) 2004 Venky Raju(dev@venky.ws) - * - * Huge thanks to R. Geoff Newbury for invaluable debugging on the - * 0xffdc iMON devices, and for sending me one to hack on, without - * which the support for them wouldn't be nearly as good. Thanks - * also to the numerous 0xffdc device owners that tested auto-config - * support for me and provided debug dumps from their devices. - * - * imon is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#define MOD_AUTHOR "Jarod Wilson " -#define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display" -#define MOD_NAME "imon" -#define MOD_VERSION "0.9.2" - -#define DISPLAY_MINOR_BASE 144 -#define DEVICE_NAME "lcd%d" - -#define BUF_CHUNK_SIZE 8 -#define BUF_SIZE 128 - -#define BIT_DURATION 250 /* each bit received is 250us */ - -#define IMON_CLOCK_ENABLE_PACKETS 2 - -/*** P R O T O T Y P E S ***/ - -/* USB Callback prototypes */ -static int imon_probe(struct usb_interface *interface, - const struct usb_device_id *id); -static void imon_disconnect(struct usb_interface *interface); -static void usb_rx_callback_intf0(struct urb *urb); -static void usb_rx_callback_intf1(struct urb *urb); -static void usb_tx_callback(struct urb *urb); - -/* suspend/resume support */ -static int imon_resume(struct usb_interface *intf); -static int imon_suspend(struct usb_interface *intf, pm_message_t message); - -/* Display file_operations function prototypes */ -static int display_open(struct inode *inode, struct file *file); -static int display_close(struct inode *inode, struct file *file); - -/* VFD write operation */ -static ssize_t vfd_write(struct file *file, const char *buf, - size_t n_bytes, loff_t *pos); - -/* LCD file_operations override function prototypes */ -static ssize_t lcd_write(struct file *file, const char *buf, - size_t n_bytes, loff_t *pos); - -/*** G L O B A L S ***/ - -struct imon_context { - struct device *dev; - struct ir_dev_props *props; - /* Newer devices have two interfaces */ - struct usb_device *usbdev_intf0; - struct usb_device *usbdev_intf1; - - bool display_supported; /* not all controllers do */ - bool display_isopen; /* display port has been opened */ - bool rf_device; /* true if iMON 2.4G LT/DT RF device */ - bool rf_isassociating; /* RF remote associating */ - bool dev_present_intf0; /* USB device presence, interface 0 */ - bool dev_present_intf1; /* USB device presence, interface 1 */ - - struct mutex lock; /* to lock this object */ - wait_queue_head_t remove_ok; /* For unexpected USB disconnects */ - - struct usb_endpoint_descriptor *rx_endpoint_intf0; - struct usb_endpoint_descriptor *rx_endpoint_intf1; - struct usb_endpoint_descriptor *tx_endpoint; - struct urb *rx_urb_intf0; - struct urb *rx_urb_intf1; - struct urb *tx_urb; - bool tx_control; - unsigned char usb_rx_buf[8]; - unsigned char usb_tx_buf[8]; - - struct tx_t { - unsigned char data_buf[35]; /* user data buffer */ - struct completion finished; /* wait for write to finish */ - bool busy; /* write in progress */ - int status; /* status of tx completion */ - } tx; - - u16 vendor; /* usb vendor ID */ - u16 product; /* usb product ID */ - - struct input_dev *rdev; /* input device for remote */ - struct input_dev *idev; /* input device for panel & IR mouse */ - struct input_dev *touch; /* input device for touchscreen */ - - spinlock_t kc_lock; /* make sure we get keycodes right */ - u32 kc; /* current input keycode */ - u32 last_keycode; /* last reported input keycode */ - u32 rc_scancode; /* the computed remote scancode */ - u8 rc_toggle; /* the computed remote toggle bit */ - u64 ir_type; /* iMON or MCE (RC6) IR protocol? */ - bool release_code; /* some keys send a release code */ - - u8 display_type; /* store the display type */ - bool pad_mouse; /* toggle kbd(0)/mouse(1) mode */ - - char name_rdev[128]; /* rc input device name */ - char phys_rdev[64]; /* rc input device phys path */ - - char name_idev[128]; /* input device name */ - char phys_idev[64]; /* input device phys path */ - - char name_touch[128]; /* touch screen name */ - char phys_touch[64]; /* touch screen phys path */ - struct timer_list ttimer; /* touch screen timer */ - int touch_x; /* x coordinate on touchscreen */ - int touch_y; /* y coordinate on touchscreen */ -}; - -#define TOUCH_TIMEOUT (HZ/30) - -/* vfd character device file operations */ -static const struct file_operations vfd_fops = { - .owner = THIS_MODULE, - .open = &display_open, - .write = &vfd_write, - .release = &display_close, - .llseek = noop_llseek, -}; - -/* lcd character device file operations */ -static const struct file_operations lcd_fops = { - .owner = THIS_MODULE, - .open = &display_open, - .write = &lcd_write, - .release = &display_close, - .llseek = noop_llseek, -}; - -enum { - IMON_DISPLAY_TYPE_AUTO = 0, - IMON_DISPLAY_TYPE_VFD = 1, - IMON_DISPLAY_TYPE_LCD = 2, - IMON_DISPLAY_TYPE_VGA = 3, - IMON_DISPLAY_TYPE_NONE = 4, -}; - -enum { - IMON_KEY_IMON = 0, - IMON_KEY_MCE = 1, - IMON_KEY_PANEL = 2, -}; - -/* - * USB Device ID for iMON USB Control Boards - * - * The Windows drivers contain 6 different inf files, more or less one for - * each new device until the 0x0034-0x0046 devices, which all use the same - * driver. Some of the devices in the 34-46 range haven't been definitively - * identified yet. Early devices have either a TriGem Computer, Inc. or a - * Samsung vendor ID (0x0aa8 and 0x04e8 respectively), while all later - * devices use the SoundGraph vendor ID (0x15c2). This driver only supports - * the ffdc and later devices, which do onboard decoding. - */ -static struct usb_device_id imon_usb_id_table[] = { - /* - * Several devices with this same device ID, all use iMON_PAD.inf - * SoundGraph iMON PAD (IR & VFD) - * SoundGraph iMON PAD (IR & LCD) - * SoundGraph iMON Knob (IR only) - */ - { USB_DEVICE(0x15c2, 0xffdc) }, - - /* - * Newer devices, all driven by the latest iMON Windows driver, full - * list of device IDs extracted via 'strings Setup/data1.hdr |grep 15c2' - * Need user input to fill in details on unknown devices. - */ - /* SoundGraph iMON OEM Touch LCD (IR & 7" VGA LCD) */ - { USB_DEVICE(0x15c2, 0x0034) }, - /* SoundGraph iMON OEM Touch LCD (IR & 4.3" VGA LCD) */ - { USB_DEVICE(0x15c2, 0x0035) }, - /* SoundGraph iMON OEM VFD (IR & VFD) */ - { USB_DEVICE(0x15c2, 0x0036) }, - /* device specifics unknown */ - { USB_DEVICE(0x15c2, 0x0037) }, - /* SoundGraph iMON OEM LCD (IR & LCD) */ - { USB_DEVICE(0x15c2, 0x0038) }, - /* SoundGraph iMON UltraBay (IR & LCD) */ - { USB_DEVICE(0x15c2, 0x0039) }, - /* device specifics unknown */ - { USB_DEVICE(0x15c2, 0x003a) }, - /* device specifics unknown */ - { USB_DEVICE(0x15c2, 0x003b) }, - /* SoundGraph iMON OEM Inside (IR only) */ - { USB_DEVICE(0x15c2, 0x003c) }, - /* device specifics unknown */ - { USB_DEVICE(0x15c2, 0x003d) }, - /* device specifics unknown */ - { USB_DEVICE(0x15c2, 0x003e) }, - /* device specifics unknown */ - { USB_DEVICE(0x15c2, 0x003f) }, - /* device specifics unknown */ - { USB_DEVICE(0x15c2, 0x0040) }, - /* SoundGraph iMON MINI (IR only) */ - { USB_DEVICE(0x15c2, 0x0041) }, - /* Antec Veris Multimedia Station EZ External (IR only) */ - { USB_DEVICE(0x15c2, 0x0042) }, - /* Antec Veris Multimedia Station Basic Internal (IR only) */ - { USB_DEVICE(0x15c2, 0x0043) }, - /* Antec Veris Multimedia Station Elite (IR & VFD) */ - { USB_DEVICE(0x15c2, 0x0044) }, - /* Antec Veris Multimedia Station Premiere (IR & LCD) */ - { USB_DEVICE(0x15c2, 0x0045) }, - /* device specifics unknown */ - { USB_DEVICE(0x15c2, 0x0046) }, - {} -}; - -/* USB Device data */ -static struct usb_driver imon_driver = { - .name = MOD_NAME, - .probe = imon_probe, - .disconnect = imon_disconnect, - .suspend = imon_suspend, - .resume = imon_resume, - .id_table = imon_usb_id_table, -}; - -static struct usb_class_driver imon_vfd_class = { - .name = DEVICE_NAME, - .fops = &vfd_fops, - .minor_base = DISPLAY_MINOR_BASE, -}; - -static struct usb_class_driver imon_lcd_class = { - .name = DEVICE_NAME, - .fops = &lcd_fops, - .minor_base = DISPLAY_MINOR_BASE, -}; - -/* imon receiver front panel/knob key table */ -static const struct { - u64 hw_code; - u32 keycode; -} imon_panel_key_table[] = { - { 0x000000000f00ffeell, KEY_PROG1 }, /* Go */ - { 0x000000001f00ffeell, KEY_AUDIO }, - { 0x000000002000ffeell, KEY_VIDEO }, - { 0x000000002100ffeell, KEY_CAMERA }, - { 0x000000002700ffeell, KEY_DVD }, - { 0x000000002300ffeell, KEY_TV }, - { 0x000000000500ffeell, KEY_PREVIOUS }, - { 0x000000000700ffeell, KEY_REWIND }, - { 0x000000000400ffeell, KEY_STOP }, - { 0x000000003c00ffeell, KEY_PLAYPAUSE }, - { 0x000000000800ffeell, KEY_FASTFORWARD }, - { 0x000000000600ffeell, KEY_NEXT }, - { 0x000000010000ffeell, KEY_RIGHT }, - { 0x000001000000ffeell, KEY_LEFT }, - { 0x000000003d00ffeell, KEY_SELECT }, - { 0x000100000000ffeell, KEY_VOLUMEUP }, - { 0x010000000000ffeell, KEY_VOLUMEDOWN }, - { 0x000000000100ffeell, KEY_MUTE }, - /* 0xffdc iMON MCE VFD */ - { 0x00010000ffffffeell, KEY_VOLUMEUP }, - { 0x01000000ffffffeell, KEY_VOLUMEDOWN }, - /* iMON Knob values */ - { 0x000100ffffffffeell, KEY_VOLUMEUP }, - { 0x010000ffffffffeell, KEY_VOLUMEDOWN }, - { 0x000008ffffffffeell, KEY_MUTE }, -}; - -/* to prevent races between open() and disconnect(), probing, etc */ -static DEFINE_MUTEX(driver_lock); - -/* Module bookkeeping bits */ -MODULE_AUTHOR(MOD_AUTHOR); -MODULE_DESCRIPTION(MOD_DESC); -MODULE_VERSION(MOD_VERSION); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(usb, imon_usb_id_table); - -static bool debug; -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes (default: no)"); - -/* lcd, vfd, vga or none? should be auto-detected, but can be overridden... */ -static int display_type; -module_param(display_type, int, S_IRUGO); -MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, " - "1=vfd, 2=lcd, 3=vga, 4=none (default: autodetect)"); - -static int pad_stabilize = 1; -module_param(pad_stabilize, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(pad_stabilize, "Apply stabilization algorithm to iMON PAD " - "presses in arrow key mode. 0=disable, 1=enable (default)."); - -/* - * In certain use cases, mouse mode isn't really helpful, and could actually - * cause confusion, so allow disabling it when the IR device is open. - */ -static bool nomouse; -module_param(nomouse, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(nomouse, "Disable mouse input device mode when IR device is " - "open. 0=don't disable, 1=disable. (default: don't disable)"); - -/* threshold at which a pad push registers as an arrow key in kbd mode */ -static int pad_thresh; -module_param(pad_thresh, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(pad_thresh, "Threshold at which a pad push registers as an " - "arrow key in kbd mode (default: 28)"); - - -static void free_imon_context(struct imon_context *ictx) -{ - struct device *dev = ictx->dev; - - usb_free_urb(ictx->tx_urb); - usb_free_urb(ictx->rx_urb_intf0); - usb_free_urb(ictx->rx_urb_intf1); - kfree(ictx); - - dev_dbg(dev, "%s: iMON context freed\n", __func__); -} - -/** - * Called when the Display device (e.g. /dev/lcd0) - * is opened by the application. - */ -static int display_open(struct inode *inode, struct file *file) -{ - struct usb_interface *interface; - struct imon_context *ictx = NULL; - int subminor; - int retval = 0; - - /* prevent races with disconnect */ - mutex_lock(&driver_lock); - - subminor = iminor(inode); - interface = usb_find_interface(&imon_driver, subminor); - if (!interface) { - pr_err("could not find interface for minor %d\n", subminor); - retval = -ENODEV; - goto exit; - } - ictx = usb_get_intfdata(interface); - - if (!ictx) { - pr_err("no context found for minor %d\n", subminor); - retval = -ENODEV; - goto exit; - } - - mutex_lock(&ictx->lock); - - if (!ictx->display_supported) { - pr_err("display not supported by device\n"); - retval = -ENODEV; - } else if (ictx->display_isopen) { - pr_err("display port is already open\n"); - retval = -EBUSY; - } else { - ictx->display_isopen = true; - file->private_data = ictx; - dev_dbg(ictx->dev, "display port opened\n"); - } - - mutex_unlock(&ictx->lock); - -exit: - mutex_unlock(&driver_lock); - return retval; -} - -/** - * Called when the display device (e.g. /dev/lcd0) - * is closed by the application. - */ -static int display_close(struct inode *inode, struct file *file) -{ - struct imon_context *ictx = NULL; - int retval = 0; - - ictx = file->private_data; - - if (!ictx) { - pr_err("no context for device\n"); - return -ENODEV; - } - - mutex_lock(&ictx->lock); - - if (!ictx->display_supported) { - pr_err("display not supported by device\n"); - retval = -ENODEV; - } else if (!ictx->display_isopen) { - pr_err("display is not open\n"); - retval = -EIO; - } else { - ictx->display_isopen = false; - dev_dbg(ictx->dev, "display port closed\n"); - if (!ictx->dev_present_intf0) { - /* - * Device disconnected before close and IR port is not - * open. If IR port is open, context will be deleted by - * ir_close. - */ - mutex_unlock(&ictx->lock); - free_imon_context(ictx); - return retval; - } - } - - mutex_unlock(&ictx->lock); - return retval; -} - -/** - * Sends a packet to the device -- this function must be called - * with ictx->lock held. - */ -static int send_packet(struct imon_context *ictx) -{ - unsigned int pipe; - unsigned long timeout; - int interval = 0; - int retval = 0; - struct usb_ctrlrequest *control_req = NULL; - - /* Check if we need to use control or interrupt urb */ - if (!ictx->tx_control) { - pipe = usb_sndintpipe(ictx->usbdev_intf0, - ictx->tx_endpoint->bEndpointAddress); - interval = ictx->tx_endpoint->bInterval; - - usb_fill_int_urb(ictx->tx_urb, ictx->usbdev_intf0, pipe, - ictx->usb_tx_buf, - sizeof(ictx->usb_tx_buf), - usb_tx_callback, ictx, interval); - - ictx->tx_urb->actual_length = 0; - } else { - /* fill request into kmalloc'ed space: */ - control_req = kmalloc(sizeof(struct usb_ctrlrequest), - GFP_KERNEL); - if (control_req == NULL) - return -ENOMEM; - - /* setup packet is '21 09 0200 0001 0008' */ - control_req->bRequestType = 0x21; - control_req->bRequest = 0x09; - control_req->wValue = cpu_to_le16(0x0200); - control_req->wIndex = cpu_to_le16(0x0001); - control_req->wLength = cpu_to_le16(0x0008); - - /* control pipe is endpoint 0x00 */ - pipe = usb_sndctrlpipe(ictx->usbdev_intf0, 0); - - /* build the control urb */ - usb_fill_control_urb(ictx->tx_urb, ictx->usbdev_intf0, - pipe, (unsigned char *)control_req, - ictx->usb_tx_buf, - sizeof(ictx->usb_tx_buf), - usb_tx_callback, ictx); - ictx->tx_urb->actual_length = 0; - } - - init_completion(&ictx->tx.finished); - ictx->tx.busy = true; - smp_rmb(); /* ensure later readers know we're busy */ - - retval = usb_submit_urb(ictx->tx_urb, GFP_KERNEL); - if (retval) { - ictx->tx.busy = false; - smp_rmb(); /* ensure later readers know we're not busy */ - pr_err("error submitting urb(%d)\n", retval); - } else { - /* Wait for transmission to complete (or abort) */ - mutex_unlock(&ictx->lock); - retval = wait_for_completion_interruptible( - &ictx->tx.finished); - if (retval) - pr_err("task interrupted\n"); - mutex_lock(&ictx->lock); - - retval = ictx->tx.status; - if (retval) - pr_err("packet tx failed (%d)\n", retval); - } - - kfree(control_req); - - /* - * Induce a mandatory 5ms delay before returning, as otherwise, - * send_packet can get called so rapidly as to overwhelm the device, - * particularly on faster systems and/or those with quirky usb. - */ - timeout = msecs_to_jiffies(5); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(timeout); - - return retval; -} - -/** - * Sends an associate packet to the iMON 2.4G. - * - * This might not be such a good idea, since it has an id collision with - * some versions of the "IR & VFD" combo. The only way to determine if it - * is an RF version is to look at the product description string. (Which - * we currently do not fetch). - */ -static int send_associate_24g(struct imon_context *ictx) -{ - int retval; - const unsigned char packet[8] = { 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x20 }; - - if (!ictx) { - pr_err("no context for device\n"); - return -ENODEV; - } - - if (!ictx->dev_present_intf0) { - pr_err("no iMON device present\n"); - return -ENODEV; - } - - memcpy(ictx->usb_tx_buf, packet, sizeof(packet)); - retval = send_packet(ictx); - - return retval; -} - -/** - * Sends packets to setup and show clock on iMON display - * - * Arguments: year - last 2 digits of year, month - 1..12, - * day - 1..31, dow - day of the week (0-Sun...6-Sat), - * hour - 0..23, minute - 0..59, second - 0..59 - */ -static int send_set_imon_clock(struct imon_context *ictx, - unsigned int year, unsigned int month, - unsigned int day, unsigned int dow, - unsigned int hour, unsigned int minute, - unsigned int second) -{ - unsigned char clock_enable_pkt[IMON_CLOCK_ENABLE_PACKETS][8]; - int retval = 0; - int i; - - if (!ictx) { - pr_err("no context for device\n"); - return -ENODEV; - } - - switch (ictx->display_type) { - case IMON_DISPLAY_TYPE_LCD: - clock_enable_pkt[0][0] = 0x80; - clock_enable_pkt[0][1] = year; - clock_enable_pkt[0][2] = month-1; - clock_enable_pkt[0][3] = day; - clock_enable_pkt[0][4] = hour; - clock_enable_pkt[0][5] = minute; - clock_enable_pkt[0][6] = second; - - clock_enable_pkt[1][0] = 0x80; - clock_enable_pkt[1][1] = 0; - clock_enable_pkt[1][2] = 0; - clock_enable_pkt[1][3] = 0; - clock_enable_pkt[1][4] = 0; - clock_enable_pkt[1][5] = 0; - clock_enable_pkt[1][6] = 0; - - if (ictx->product == 0xffdc) { - clock_enable_pkt[0][7] = 0x50; - clock_enable_pkt[1][7] = 0x51; - } else { - clock_enable_pkt[0][7] = 0x88; - clock_enable_pkt[1][7] = 0x8a; - } - - break; - - case IMON_DISPLAY_TYPE_VFD: - clock_enable_pkt[0][0] = year; - clock_enable_pkt[0][1] = month-1; - clock_enable_pkt[0][2] = day; - clock_enable_pkt[0][3] = dow; - clock_enable_pkt[0][4] = hour; - clock_enable_pkt[0][5] = minute; - clock_enable_pkt[0][6] = second; - clock_enable_pkt[0][7] = 0x40; - - clock_enable_pkt[1][0] = 0; - clock_enable_pkt[1][1] = 0; - clock_enable_pkt[1][2] = 1; - clock_enable_pkt[1][3] = 0; - clock_enable_pkt[1][4] = 0; - clock_enable_pkt[1][5] = 0; - clock_enable_pkt[1][6] = 0; - clock_enable_pkt[1][7] = 0x42; - - break; - - default: - return -ENODEV; - } - - for (i = 0; i < IMON_CLOCK_ENABLE_PACKETS; i++) { - memcpy(ictx->usb_tx_buf, clock_enable_pkt[i], 8); - retval = send_packet(ictx); - if (retval) { - pr_err("send_packet failed for packet %d\n", i); - break; - } - } - - return retval; -} - -/** - * These are the sysfs functions to handle the association on the iMON 2.4G LT. - */ -static ssize_t show_associate_remote(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct imon_context *ictx = dev_get_drvdata(d); - - if (!ictx) - return -ENODEV; - - mutex_lock(&ictx->lock); - if (ictx->rf_isassociating) - strcpy(buf, "associating\n"); - else - strcpy(buf, "closed\n"); - - dev_info(d, "Visit http://www.lirc.org/html/imon-24g.html for " - "instructions on how to associate your iMON 2.4G DT/LT " - "remote\n"); - mutex_unlock(&ictx->lock); - return strlen(buf); -} - -static ssize_t store_associate_remote(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct imon_context *ictx; - - ictx = dev_get_drvdata(d); - - if (!ictx) - return -ENODEV; - - mutex_lock(&ictx->lock); - ictx->rf_isassociating = true; - send_associate_24g(ictx); - mutex_unlock(&ictx->lock); - - return count; -} - -/** - * sysfs functions to control internal imon clock - */ -static ssize_t show_imon_clock(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct imon_context *ictx = dev_get_drvdata(d); - size_t len; - - if (!ictx) - return -ENODEV; - - mutex_lock(&ictx->lock); - - if (!ictx->display_supported) { - len = snprintf(buf, PAGE_SIZE, "Not supported."); - } else { - len = snprintf(buf, PAGE_SIZE, - "To set the clock on your iMON display:\n" - "# date \"+%%y %%m %%d %%w %%H %%M %%S\" > imon_clock\n" - "%s", ictx->display_isopen ? - "\nNOTE: imon device must be closed\n" : ""); - } - - mutex_unlock(&ictx->lock); - - return len; -} - -static ssize_t store_imon_clock(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct imon_context *ictx = dev_get_drvdata(d); - ssize_t retval; - unsigned int year, month, day, dow, hour, minute, second; - - if (!ictx) - return -ENODEV; - - mutex_lock(&ictx->lock); - - if (!ictx->display_supported) { - retval = -ENODEV; - goto exit; - } else if (ictx->display_isopen) { - retval = -EBUSY; - goto exit; - } - - if (sscanf(buf, "%u %u %u %u %u %u %u", &year, &month, &day, &dow, - &hour, &minute, &second) != 7) { - retval = -EINVAL; - goto exit; - } - - if ((month < 1 || month > 12) || - (day < 1 || day > 31) || (dow > 6) || - (hour > 23) || (minute > 59) || (second > 59)) { - retval = -EINVAL; - goto exit; - } - - retval = send_set_imon_clock(ictx, year, month, day, dow, - hour, minute, second); - if (retval) - goto exit; - - retval = count; -exit: - mutex_unlock(&ictx->lock); - - return retval; -} - - -static DEVICE_ATTR(imon_clock, S_IWUSR | S_IRUGO, show_imon_clock, - store_imon_clock); - -static DEVICE_ATTR(associate_remote, S_IWUSR | S_IRUGO, show_associate_remote, - store_associate_remote); - -static struct attribute *imon_display_sysfs_entries[] = { - &dev_attr_imon_clock.attr, - NULL -}; - -static struct attribute_group imon_display_attr_group = { - .attrs = imon_display_sysfs_entries -}; - -static struct attribute *imon_rf_sysfs_entries[] = { - &dev_attr_associate_remote.attr, - NULL -}; - -static struct attribute_group imon_rf_attr_group = { - .attrs = imon_rf_sysfs_entries -}; - -/** - * Writes data to the VFD. The iMON VFD is 2x16 characters - * and requires data in 5 consecutive USB interrupt packets, - * each packet but the last carrying 7 bytes. - * - * I don't know if the VFD board supports features such as - * scrolling, clearing rows, blanking, etc. so at - * the caller must provide a full screen of data. If fewer - * than 32 bytes are provided spaces will be appended to - * generate a full screen. - */ -static ssize_t vfd_write(struct file *file, const char *buf, - size_t n_bytes, loff_t *pos) -{ - int i; - int offset; - int seq; - int retval = 0; - struct imon_context *ictx; - const unsigned char vfd_packet6[] = { - 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF }; - - ictx = file->private_data; - if (!ictx) { - pr_err("no context for device\n"); - return -ENODEV; - } - - mutex_lock(&ictx->lock); - - if (!ictx->dev_present_intf0) { - pr_err("no iMON device present\n"); - retval = -ENODEV; - goto exit; - } - - if (n_bytes <= 0 || n_bytes > 32) { - pr_err("invalid payload size\n"); - retval = -EINVAL; - goto exit; - } - - if (copy_from_user(ictx->tx.data_buf, buf, n_bytes)) { - retval = -EFAULT; - goto exit; - } - - /* Pad with spaces */ - for (i = n_bytes; i < 32; ++i) - ictx->tx.data_buf[i] = ' '; - - for (i = 32; i < 35; ++i) - ictx->tx.data_buf[i] = 0xFF; - - offset = 0; - seq = 0; - - do { - memcpy(ictx->usb_tx_buf, ictx->tx.data_buf + offset, 7); - ictx->usb_tx_buf[7] = (unsigned char) seq; - - retval = send_packet(ictx); - if (retval) { - pr_err("send packet failed for packet #%d\n", seq / 2); - goto exit; - } else { - seq += 2; - offset += 7; - } - - } while (offset < 35); - - /* Send packet #6 */ - memcpy(ictx->usb_tx_buf, &vfd_packet6, sizeof(vfd_packet6)); - ictx->usb_tx_buf[7] = (unsigned char) seq; - retval = send_packet(ictx); - if (retval) - pr_err("send packet failed for packet #%d\n", seq / 2); - -exit: - mutex_unlock(&ictx->lock); - - return (!retval) ? n_bytes : retval; -} - -/** - * Writes data to the LCD. The iMON OEM LCD screen expects 8-byte - * packets. We accept data as 16 hexadecimal digits, followed by a - * newline (to make it easy to drive the device from a command-line - * -- even though the actual binary data is a bit complicated). - * - * The device itself is not a "traditional" text-mode display. It's - * actually a 16x96 pixel bitmap display. That means if you want to - * display text, you've got to have your own "font" and translate the - * text into bitmaps for display. This is really flexible (you can - * display whatever diacritics you need, and so on), but it's also - * a lot more complicated than most LCDs... - */ -static ssize_t lcd_write(struct file *file, const char *buf, - size_t n_bytes, loff_t *pos) -{ - int retval = 0; - struct imon_context *ictx; - - ictx = file->private_data; - if (!ictx) { - pr_err("no context for device\n"); - return -ENODEV; - } - - mutex_lock(&ictx->lock); - - if (!ictx->display_supported) { - pr_err("no iMON display present\n"); - retval = -ENODEV; - goto exit; - } - - if (n_bytes != 8) { - pr_err("invalid payload size: %d (expected 8)\n", (int)n_bytes); - retval = -EINVAL; - goto exit; - } - - if (copy_from_user(ictx->usb_tx_buf, buf, 8)) { - retval = -EFAULT; - goto exit; - } - - retval = send_packet(ictx); - if (retval) { - pr_err("send packet failed!\n"); - goto exit; - } else { - dev_dbg(ictx->dev, "%s: write %d bytes to LCD\n", - __func__, (int) n_bytes); - } -exit: - mutex_unlock(&ictx->lock); - return (!retval) ? n_bytes : retval; -} - -/** - * Callback function for USB core API: transmit data - */ -static void usb_tx_callback(struct urb *urb) -{ - struct imon_context *ictx; - - if (!urb) - return; - ictx = (struct imon_context *)urb->context; - if (!ictx) - return; - - ictx->tx.status = urb->status; - - /* notify waiters that write has finished */ - ictx->tx.busy = false; - smp_rmb(); /* ensure later readers know we're not busy */ - complete(&ictx->tx.finished); -} - -/** - * report touchscreen input - */ -static void imon_touch_display_timeout(unsigned long data) -{ - struct imon_context *ictx = (struct imon_context *)data; - - if (ictx->display_type != IMON_DISPLAY_TYPE_VGA) - return; - - input_report_abs(ictx->touch, ABS_X, ictx->touch_x); - input_report_abs(ictx->touch, ABS_Y, ictx->touch_y); - input_report_key(ictx->touch, BTN_TOUCH, 0x00); - input_sync(ictx->touch); -} - -/** - * iMON IR receivers support two different signal sets -- those used by - * the iMON remotes, and those used by the Windows MCE remotes (which is - * really just RC-6), but only one or the other at a time, as the signals - * are decoded onboard the receiver. - */ -int imon_ir_change_protocol(void *priv, u64 ir_type) -{ - int retval; - struct imon_context *ictx = priv; - struct device *dev = ictx->dev; - bool pad_mouse; - unsigned char ir_proto_packet[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 }; - - if (ir_type && !(ir_type & ictx->props->allowed_protos)) - dev_warn(dev, "Looks like you're trying to use an IR protocol " - "this device does not support\n"); - - switch (ir_type) { - case IR_TYPE_RC6: - dev_dbg(dev, "Configuring IR receiver for MCE protocol\n"); - ir_proto_packet[0] = 0x01; - pad_mouse = false; - break; - case IR_TYPE_UNKNOWN: - case IR_TYPE_OTHER: - dev_dbg(dev, "Configuring IR receiver for iMON protocol\n"); - if (pad_stabilize && !nomouse) - pad_mouse = true; - else { - dev_dbg(dev, "PAD stabilize functionality disabled\n"); - pad_mouse = false; - } - /* ir_proto_packet[0] = 0x00; // already the default */ - ir_type = IR_TYPE_OTHER; - break; - default: - dev_warn(dev, "Unsupported IR protocol specified, overriding " - "to iMON IR protocol\n"); - if (pad_stabilize && !nomouse) - pad_mouse = true; - else { - dev_dbg(dev, "PAD stabilize functionality disabled\n"); - pad_mouse = false; - } - /* ir_proto_packet[0] = 0x00; // already the default */ - ir_type = IR_TYPE_OTHER; - break; - } - - memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet)); - - retval = send_packet(ictx); - if (retval) - goto out; - - ictx->ir_type = ir_type; - ictx->pad_mouse = pad_mouse; - -out: - return retval; -} - -static inline int tv2int(const struct timeval *a, const struct timeval *b) -{ - int usecs = 0; - int sec = 0; - - if (b->tv_usec > a->tv_usec) { - usecs = 1000000; - sec--; - } - - usecs += a->tv_usec - b->tv_usec; - - sec += a->tv_sec - b->tv_sec; - sec *= 1000; - usecs /= 1000; - sec += usecs; - - if (sec < 0) - sec = 1000; - - return sec; -} - -/** - * The directional pad behaves a bit differently, depending on whether this is - * one of the older ffdc devices or a newer device. Newer devices appear to - * have a higher resolution matrix for more precise mouse movement, but it - * makes things overly sensitive in keyboard mode, so we do some interesting - * contortions to make it less touchy. Older devices run through the same - * routine with shorter timeout and a smaller threshold. - */ -static int stabilize(int a, int b, u16 timeout, u16 threshold) -{ - struct timeval ct; - static struct timeval prev_time = {0, 0}; - static struct timeval hit_time = {0, 0}; - static int x, y, prev_result, hits; - int result = 0; - int msec, msec_hit; - - do_gettimeofday(&ct); - msec = tv2int(&ct, &prev_time); - msec_hit = tv2int(&ct, &hit_time); - - if (msec > 100) { - x = 0; - y = 0; - hits = 0; - } - - x += a; - y += b; - - prev_time = ct; - - if (abs(x) > threshold || abs(y) > threshold) { - if (abs(y) > abs(x)) - result = (y > 0) ? 0x7F : 0x80; - else - result = (x > 0) ? 0x7F00 : 0x8000; - - x = 0; - y = 0; - - if (result == prev_result) { - hits++; - - if (hits > 3) { - switch (result) { - case 0x7F: - y = 17 * threshold / 30; - break; - case 0x80: - y -= 17 * threshold / 30; - break; - case 0x7F00: - x = 17 * threshold / 30; - break; - case 0x8000: - x -= 17 * threshold / 30; - break; - } - } - - if (hits == 2 && msec_hit < timeout) { - result = 0; - hits = 1; - } - } else { - prev_result = result; - hits = 1; - hit_time = ct; - } - } - - return result; -} - -static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 scancode) -{ - u32 keycode; - u32 release; - bool is_release_code = false; - - /* Look for the initial press of a button */ - keycode = ir_g_keycode_from_table(ictx->rdev, scancode); - ictx->rc_toggle = 0x0; - ictx->rc_scancode = scancode; - - /* Look for the release of a button */ - if (keycode == KEY_RESERVED) { - release = scancode & ~0x4000; - keycode = ir_g_keycode_from_table(ictx->rdev, release); - if (keycode != KEY_RESERVED) - is_release_code = true; - } - - ictx->release_code = is_release_code; - - return keycode; -} - -static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 scancode) -{ - u32 keycode; - -#define MCE_KEY_MASK 0x7000 -#define MCE_TOGGLE_BIT 0x8000 - - /* - * On some receivers, mce keys decode to 0x8000f04xx and 0x8000f84xx - * (the toggle bit flipping between alternating key presses), while - * on other receivers, we see 0x8000f74xx and 0x8000ff4xx. To keep - * the table trim, we always or in the bits to look up 0x8000ff4xx, - * but we can't or them into all codes, as some keys are decoded in - * a different way w/o the same use of the toggle bit... - */ - if (scancode & 0x80000000) - scancode = scancode | MCE_KEY_MASK | MCE_TOGGLE_BIT; - - ictx->rc_scancode = scancode; - keycode = ir_g_keycode_from_table(ictx->rdev, scancode); - - /* not used in mce mode, but make sure we know its false */ - ictx->release_code = false; - - return keycode; -} - -static u32 imon_panel_key_lookup(u64 code) -{ - int i; - u32 keycode = KEY_RESERVED; - - for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) { - if (imon_panel_key_table[i].hw_code == (code | 0xffee)) { - keycode = imon_panel_key_table[i].keycode; - break; - } - } - - return keycode; -} - -static bool imon_mouse_event(struct imon_context *ictx, - unsigned char *buf, int len) -{ - char rel_x = 0x00, rel_y = 0x00; - u8 right_shift = 1; - bool mouse_input = true; - int dir = 0; - unsigned long flags; - - spin_lock_irqsave(&ictx->kc_lock, flags); - - /* newer iMON device PAD or mouse button */ - if (ictx->product != 0xffdc && (buf[0] & 0x01) && len == 5) { - rel_x = buf[2]; - rel_y = buf[3]; - right_shift = 1; - /* 0xffdc iMON PAD or mouse button input */ - } else if (ictx->product == 0xffdc && (buf[0] & 0x40) && - !((buf[1] & 0x01) || ((buf[1] >> 2) & 0x01))) { - rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 | - (buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6; - if (buf[0] & 0x02) - rel_x |= ~0x0f; - rel_x = rel_x + rel_x / 2; - rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 | - (buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6; - if (buf[0] & 0x01) - rel_y |= ~0x0f; - rel_y = rel_y + rel_y / 2; - right_shift = 2; - /* some ffdc devices decode mouse buttons differently... */ - } else if (ictx->product == 0xffdc && (buf[0] == 0x68)) { - right_shift = 2; - /* ch+/- buttons, which we use for an emulated scroll wheel */ - } else if (ictx->kc == KEY_CHANNELUP && (buf[2] & 0x40) != 0x40) { - dir = 1; - } else if (ictx->kc == KEY_CHANNELDOWN && (buf[2] & 0x40) != 0x40) { - dir = -1; - } else - mouse_input = false; - - spin_unlock_irqrestore(&ictx->kc_lock, flags); - - if (mouse_input) { - dev_dbg(ictx->dev, "sending mouse data via input subsystem\n"); - - if (dir) { - input_report_rel(ictx->idev, REL_WHEEL, dir); - } else if (rel_x || rel_y) { - input_report_rel(ictx->idev, REL_X, rel_x); - input_report_rel(ictx->idev, REL_Y, rel_y); - } else { - input_report_key(ictx->idev, BTN_LEFT, buf[1] & 0x1); - input_report_key(ictx->idev, BTN_RIGHT, - buf[1] >> right_shift & 0x1); - } - input_sync(ictx->idev); - spin_lock_irqsave(&ictx->kc_lock, flags); - ictx->last_keycode = ictx->kc; - spin_unlock_irqrestore(&ictx->kc_lock, flags); - } - - return mouse_input; -} - -static void imon_touch_event(struct imon_context *ictx, unsigned char *buf) -{ - mod_timer(&ictx->ttimer, jiffies + TOUCH_TIMEOUT); - ictx->touch_x = (buf[0] << 4) | (buf[1] >> 4); - ictx->touch_y = 0xfff - ((buf[2] << 4) | (buf[1] & 0xf)); - input_report_abs(ictx->touch, ABS_X, ictx->touch_x); - input_report_abs(ictx->touch, ABS_Y, ictx->touch_y); - input_report_key(ictx->touch, BTN_TOUCH, 0x01); - input_sync(ictx->touch); -} - -static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) -{ - int dir = 0; - char rel_x = 0x00, rel_y = 0x00; - u16 timeout, threshold; - u32 scancode = KEY_RESERVED; - unsigned long flags; - - /* - * The imon directional pad functions more like a touchpad. Bytes 3 & 4 - * contain a position coordinate (x,y), with each component ranging - * from -14 to 14. We want to down-sample this to only 4 discrete values - * for up/down/left/right arrow keys. Also, when you get too close to - * diagonals, it has a tendancy to jump back and forth, so lets try to - * ignore when they get too close. - */ - if (ictx->product != 0xffdc) { - /* first, pad to 8 bytes so it conforms with everything else */ - buf[5] = buf[6] = buf[7] = 0; - timeout = 500; /* in msecs */ - /* (2*threshold) x (2*threshold) square */ - threshold = pad_thresh ? pad_thresh : 28; - rel_x = buf[2]; - rel_y = buf[3]; - - if (ictx->ir_type == IR_TYPE_OTHER && pad_stabilize) { - if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) { - dir = stabilize((int)rel_x, (int)rel_y, - timeout, threshold); - if (!dir) { - spin_lock_irqsave(&ictx->kc_lock, - flags); - ictx->kc = KEY_UNKNOWN; - spin_unlock_irqrestore(&ictx->kc_lock, - flags); - return; - } - buf[2] = dir & 0xFF; - buf[3] = (dir >> 8) & 0xFF; - scancode = be32_to_cpu(*((u32 *)buf)); - } - } else { - /* - * Hack alert: instead of using keycodes, we have - * to use hard-coded scancodes here... - */ - if (abs(rel_y) > abs(rel_x)) { - buf[2] = (rel_y > 0) ? 0x7F : 0x80; - buf[3] = 0; - if (rel_y > 0) - scancode = 0x01007f00; /* KEY_DOWN */ - else - scancode = 0x01008000; /* KEY_UP */ - } else { - buf[2] = 0; - buf[3] = (rel_x > 0) ? 0x7F : 0x80; - if (rel_x > 0) - scancode = 0x0100007f; /* KEY_RIGHT */ - else - scancode = 0x01000080; /* KEY_LEFT */ - } - } - - /* - * Handle on-board decoded pad events for e.g. older VFD/iMON-Pad - * device (15c2:ffdc). The remote generates various codes from - * 0x68nnnnB7 to 0x6AnnnnB7, the left mouse button generates - * 0x688301b7 and the right one 0x688481b7. All other keys generate - * 0x2nnnnnnn. Position coordinate is encoded in buf[1] and buf[2] with - * reversed endianess. Extract direction from buffer, rotate endianess, - * adjust sign and feed the values into stabilize(). The resulting codes - * will be 0x01008000, 0x01007F00, which match the newer devices. - */ - } else { - timeout = 10; /* in msecs */ - /* (2*threshold) x (2*threshold) square */ - threshold = pad_thresh ? pad_thresh : 15; - - /* buf[1] is x */ - rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 | - (buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6; - if (buf[0] & 0x02) - rel_x |= ~0x10+1; - /* buf[2] is y */ - rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 | - (buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6; - if (buf[0] & 0x01) - rel_y |= ~0x10+1; - - buf[0] = 0x01; - buf[1] = buf[4] = buf[5] = buf[6] = buf[7] = 0; - - if (ictx->ir_type == IR_TYPE_OTHER && pad_stabilize) { - dir = stabilize((int)rel_x, (int)rel_y, - timeout, threshold); - if (!dir) { - spin_lock_irqsave(&ictx->kc_lock, flags); - ictx->kc = KEY_UNKNOWN; - spin_unlock_irqrestore(&ictx->kc_lock, flags); - return; - } - buf[2] = dir & 0xFF; - buf[3] = (dir >> 8) & 0xFF; - scancode = be32_to_cpu(*((u32 *)buf)); - } else { - /* - * Hack alert: instead of using keycodes, we have - * to use hard-coded scancodes here... - */ - if (abs(rel_y) > abs(rel_x)) { - buf[2] = (rel_y > 0) ? 0x7F : 0x80; - buf[3] = 0; - if (rel_y > 0) - scancode = 0x01007f00; /* KEY_DOWN */ - else - scancode = 0x01008000; /* KEY_UP */ - } else { - buf[2] = 0; - buf[3] = (rel_x > 0) ? 0x7F : 0x80; - if (rel_x > 0) - scancode = 0x0100007f; /* KEY_RIGHT */ - else - scancode = 0x01000080; /* KEY_LEFT */ - } - } - } - - if (scancode) { - spin_lock_irqsave(&ictx->kc_lock, flags); - ictx->kc = imon_remote_key_lookup(ictx, scancode); - spin_unlock_irqrestore(&ictx->kc_lock, flags); - } -} - -/** - * figure out if these is a press or a release. We don't actually - * care about repeats, as those will be auto-generated within the IR - * subsystem for repeating scancodes. - */ -static int imon_parse_press_type(struct imon_context *ictx, - unsigned char *buf, u8 ktype) -{ - int press_type = 0; - unsigned long flags; - - spin_lock_irqsave(&ictx->kc_lock, flags); - - /* key release of 0x02XXXXXX key */ - if (ictx->kc == KEY_RESERVED && buf[0] == 0x02 && buf[3] == 0x00) - ictx->kc = ictx->last_keycode; - - /* mouse button release on (some) 0xffdc devices */ - else if (ictx->kc == KEY_RESERVED && buf[0] == 0x68 && buf[1] == 0x82 && - buf[2] == 0x81 && buf[3] == 0xb7) - ictx->kc = ictx->last_keycode; - - /* mouse button release on (some other) 0xffdc devices */ - else if (ictx->kc == KEY_RESERVED && buf[0] == 0x01 && buf[1] == 0x00 && - buf[2] == 0x81 && buf[3] == 0xb7) - ictx->kc = ictx->last_keycode; - - /* mce-specific button handling, no keyup events */ - else if (ktype == IMON_KEY_MCE) { - ictx->rc_toggle = buf[2]; - press_type = 1; - - /* incoherent or irrelevant data */ - } else if (ictx->kc == KEY_RESERVED) - press_type = -EINVAL; - - /* key release of 0xXXXXXXb7 key */ - else if (ictx->release_code) - press_type = 0; - - /* this is a button press */ - else - press_type = 1; - - spin_unlock_irqrestore(&ictx->kc_lock, flags); - - return press_type; -} - -/** - * Process the incoming packet - */ -static void imon_incoming_packet(struct imon_context *ictx, - struct urb *urb, int intf) -{ - int len = urb->actual_length; - unsigned char *buf = urb->transfer_buffer; - struct device *dev = ictx->dev; - unsigned long flags; - u32 kc; - bool norelease = false; - int i; - u64 scancode; - int press_type = 0; - int msec; - struct timeval t; - static struct timeval prev_time = { 0, 0 }; - u8 ktype; - - /* filter out junk data on the older 0xffdc imon devices */ - if ((buf[0] == 0xff) && (buf[1] == 0xff) && (buf[2] == 0xff)) - return; - - /* Figure out what key was pressed */ - if (len == 8 && buf[7] == 0xee) { - scancode = be64_to_cpu(*((u64 *)buf)); - ktype = IMON_KEY_PANEL; - kc = imon_panel_key_lookup(scancode); - } else { - scancode = be32_to_cpu(*((u32 *)buf)); - if (ictx->ir_type == IR_TYPE_RC6) { - ktype = IMON_KEY_IMON; - if (buf[0] == 0x80) - ktype = IMON_KEY_MCE; - kc = imon_mce_key_lookup(ictx, scancode); - } else { - ktype = IMON_KEY_IMON; - kc = imon_remote_key_lookup(ictx, scancode); - } - } - - spin_lock_irqsave(&ictx->kc_lock, flags); - /* keyboard/mouse mode toggle button */ - if (kc == KEY_KEYBOARD && !ictx->release_code) { - ictx->last_keycode = kc; - if (!nomouse) { - ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1; - dev_dbg(dev, "toggling to %s mode\n", - ictx->pad_mouse ? "mouse" : "keyboard"); - spin_unlock_irqrestore(&ictx->kc_lock, flags); - return; - } else { - ictx->pad_mouse = 0; - dev_dbg(dev, "mouse mode disabled, passing key value\n"); - } - } - - ictx->kc = kc; - spin_unlock_irqrestore(&ictx->kc_lock, flags); - - /* send touchscreen events through input subsystem if touchpad data */ - if (ictx->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 && - buf[7] == 0x86) { - imon_touch_event(ictx, buf); - return; - - /* look for mouse events with pad in mouse mode */ - } else if (ictx->pad_mouse) { - if (imon_mouse_event(ictx, buf, len)) - return; - } - - /* Now for some special handling to convert pad input to arrow keys */ - if (((len == 5) && (buf[0] == 0x01) && (buf[4] == 0x00)) || - ((len == 8) && (buf[0] & 0x40) && - !(buf[1] & 0x1 || buf[1] >> 2 & 0x1))) { - len = 8; - imon_pad_to_keys(ictx, buf); - norelease = true; - } - - if (debug) { - printk(KERN_INFO "intf%d decoded packet: ", intf); - for (i = 0; i < len; ++i) - printk("%02x ", buf[i]); - printk("\n"); - } - - press_type = imon_parse_press_type(ictx, buf, ktype); - if (press_type < 0) - goto not_input_data; - - spin_lock_irqsave(&ictx->kc_lock, flags); - if (ictx->kc == KEY_UNKNOWN) - goto unknown_key; - spin_unlock_irqrestore(&ictx->kc_lock, flags); - - if (ktype != IMON_KEY_PANEL) { - if (press_type == 0) - ir_keyup(ictx->rdev); - else { - ir_keydown(ictx->rdev, ictx->rc_scancode, ictx->rc_toggle); - spin_lock_irqsave(&ictx->kc_lock, flags); - ictx->last_keycode = ictx->kc; - spin_unlock_irqrestore(&ictx->kc_lock, flags); - } - return; - } - - /* Only panel type events left to process now */ - spin_lock_irqsave(&ictx->kc_lock, flags); - - /* KEY_MUTE repeats from knob need to be suppressed */ - if (ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) { - do_gettimeofday(&t); - msec = tv2int(&t, &prev_time); - prev_time = t; - if (msec < ictx->idev->rep[REP_DELAY]) { - spin_unlock_irqrestore(&ictx->kc_lock, flags); - return; - } - } - kc = ictx->kc; - - spin_unlock_irqrestore(&ictx->kc_lock, flags); - - input_report_key(ictx->idev, kc, press_type); - input_sync(ictx->idev); - - /* panel keys don't generate a release */ - input_report_key(ictx->idev, kc, 0); - input_sync(ictx->idev); - - ictx->last_keycode = kc; - - return; - -unknown_key: - spin_unlock_irqrestore(&ictx->kc_lock, flags); - dev_info(dev, "%s: unknown keypress, code 0x%llx\n", __func__, - (long long)scancode); - return; - -not_input_data: - if (len != 8) { - dev_warn(dev, "imon %s: invalid incoming packet " - "size (len = %d, intf%d)\n", __func__, len, intf); - return; - } - - /* iMON 2.4G associate frame */ - if (buf[0] == 0x00 && - buf[2] == 0xFF && /* REFID */ - buf[3] == 0xFF && - buf[4] == 0xFF && - buf[5] == 0xFF && /* iMON 2.4G */ - ((buf[6] == 0x4E && buf[7] == 0xDF) || /* LT */ - (buf[6] == 0x5E && buf[7] == 0xDF))) { /* DT */ - dev_warn(dev, "%s: remote associated refid=%02X\n", - __func__, buf[1]); - ictx->rf_isassociating = false; - } -} - -/** - * Callback function for USB core API: receive data - */ -static void usb_rx_callback_intf0(struct urb *urb) -{ - struct imon_context *ictx; - int intfnum = 0; - - if (!urb) - return; - - ictx = (struct imon_context *)urb->context; - if (!ictx) - return; - - switch (urb->status) { - case -ENOENT: /* usbcore unlink successful! */ - return; - - case -ESHUTDOWN: /* transport endpoint was shut down */ - break; - - case 0: - imon_incoming_packet(ictx, urb, intfnum); - break; - - default: - dev_warn(ictx->dev, "imon %s: status(%d): ignored\n", - __func__, urb->status); - break; - } - - usb_submit_urb(ictx->rx_urb_intf0, GFP_ATOMIC); -} - -static void usb_rx_callback_intf1(struct urb *urb) -{ - struct imon_context *ictx; - int intfnum = 1; - - if (!urb) - return; - - ictx = (struct imon_context *)urb->context; - if (!ictx) - return; - - switch (urb->status) { - case -ENOENT: /* usbcore unlink successful! */ - return; - - case -ESHUTDOWN: /* transport endpoint was shut down */ - break; - - case 0: - imon_incoming_packet(ictx, urb, intfnum); - break; - - default: - dev_warn(ictx->dev, "imon %s: status(%d): ignored\n", - __func__, urb->status); - break; - } - - usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC); -} - -/* - * The 0x15c2:0xffdc device ID was used for umpteen different imon - * devices, and all of them constantly spew interrupts, even when there - * is no actual data to report. However, byte 6 of this buffer looks like - * its unique across device variants, so we're trying to key off that to - * figure out which display type (if any) and what IR protocol the device - * actually supports. These devices have their IR protocol hard-coded into - * their firmware, they can't be changed on the fly like the newer hardware. - */ -static void imon_get_ffdc_type(struct imon_context *ictx) -{ - u8 ffdc_cfg_byte = ictx->usb_rx_buf[6]; - u8 detected_display_type = IMON_DISPLAY_TYPE_NONE; - u64 allowed_protos = IR_TYPE_OTHER; - - switch (ffdc_cfg_byte) { - /* iMON Knob, no display, iMON IR + vol knob */ - case 0x21: - dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR"); - ictx->display_supported = false; - break; - /* iMON 2.4G LT (usb stick), no display, iMON RF */ - case 0x4e: - dev_info(ictx->dev, "0xffdc iMON 2.4G LT, iMON RF"); - ictx->display_supported = false; - ictx->rf_device = true; - break; - /* iMON VFD, no IR (does have vol knob tho) */ - case 0x35: - dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR"); - detected_display_type = IMON_DISPLAY_TYPE_VFD; - break; - /* iMON VFD, iMON IR */ - case 0x24: - case 0x85: - dev_info(ictx->dev, "0xffdc iMON VFD, iMON IR"); - detected_display_type = IMON_DISPLAY_TYPE_VFD; - break; - /* iMON VFD, MCE IR */ - case 0x9e: - dev_info(ictx->dev, "0xffdc iMON VFD, MCE IR"); - detected_display_type = IMON_DISPLAY_TYPE_VFD; - allowed_protos = IR_TYPE_RC6; - break; - /* iMON LCD, MCE IR */ - case 0x9f: - dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR"); - detected_display_type = IMON_DISPLAY_TYPE_LCD; - allowed_protos = IR_TYPE_RC6; - break; - default: - dev_info(ictx->dev, "Unknown 0xffdc device, " - "defaulting to VFD and iMON IR"); - detected_display_type = IMON_DISPLAY_TYPE_VFD; - break; - } - - printk(KERN_CONT " (id 0x%02x)\n", ffdc_cfg_byte); - - ictx->display_type = detected_display_type; - ictx->props->allowed_protos = allowed_protos; - ictx->ir_type = allowed_protos; -} - -static void imon_set_display_type(struct imon_context *ictx) -{ - u8 configured_display_type = IMON_DISPLAY_TYPE_VFD; - - /* - * Try to auto-detect the type of display if the user hasn't set - * it by hand via the display_type modparam. Default is VFD. - */ - - if (display_type == IMON_DISPLAY_TYPE_AUTO) { - switch (ictx->product) { - case 0xffdc: - /* set in imon_get_ffdc_type() */ - configured_display_type = ictx->display_type; - break; - case 0x0034: - case 0x0035: - configured_display_type = IMON_DISPLAY_TYPE_VGA; - break; - case 0x0038: - case 0x0039: - case 0x0045: - configured_display_type = IMON_DISPLAY_TYPE_LCD; - break; - case 0x003c: - case 0x0041: - case 0x0042: - case 0x0043: - configured_display_type = IMON_DISPLAY_TYPE_NONE; - ictx->display_supported = false; - break; - case 0x0036: - case 0x0044: - default: - configured_display_type = IMON_DISPLAY_TYPE_VFD; - break; - } - } else { - configured_display_type = display_type; - if (display_type == IMON_DISPLAY_TYPE_NONE) - ictx->display_supported = false; - else - ictx->display_supported = true; - dev_info(ictx->dev, "%s: overriding display type to %d via " - "modparam\n", __func__, display_type); - } - - ictx->display_type = configured_display_type; -} - -static struct input_dev *imon_init_rdev(struct imon_context *ictx) -{ - struct input_dev *rdev; - struct ir_dev_props *props; - int ret; - char *ir_codes = NULL; - const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x88 }; - - rdev = input_allocate_device(); - props = kzalloc(sizeof(*props), GFP_KERNEL); - if (!rdev || !props) { - dev_err(ictx->dev, "remote control dev allocation failed\n"); - goto out; - } - - snprintf(ictx->name_rdev, sizeof(ictx->name_rdev), - "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product); - usb_make_path(ictx->usbdev_intf0, ictx->phys_rdev, - sizeof(ictx->phys_rdev)); - strlcat(ictx->phys_rdev, "/input0", sizeof(ictx->phys_rdev)); - - rdev->name = ictx->name_rdev; - rdev->phys = ictx->phys_rdev; - usb_to_input_id(ictx->usbdev_intf0, &rdev->id); - rdev->dev.parent = ictx->dev; - rdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); - input_set_drvdata(rdev, ictx); - - props->priv = ictx; - props->driver_type = RC_DRIVER_SCANCODE; - props->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6; /* iMON PAD or MCE */ - props->change_protocol = imon_ir_change_protocol; - ictx->props = props; - - /* Enable front-panel buttons and/or knobs */ - memcpy(ictx->usb_tx_buf, &fp_packet, sizeof(fp_packet)); - ret = send_packet(ictx); - /* Not fatal, but warn about it */ - if (ret) - dev_info(ictx->dev, "panel buttons/knobs setup failed\n"); - - if (ictx->product == 0xffdc) - imon_get_ffdc_type(ictx); - - imon_set_display_type(ictx); - - if (ictx->ir_type == IR_TYPE_RC6) - ir_codes = RC_MAP_IMON_MCE; - else - ir_codes = RC_MAP_IMON_PAD; - - ret = ir_input_register(rdev, ir_codes, props, MOD_NAME); - if (ret < 0) { - dev_err(ictx->dev, "remote input dev register failed\n"); - goto out; - } - - return rdev; - -out: - kfree(props); - input_free_device(rdev); - return NULL; -} - -static struct input_dev *imon_init_idev(struct imon_context *ictx) -{ - struct input_dev *idev; - int ret, i; - - idev = input_allocate_device(); - if (!idev) { - dev_err(ictx->dev, "input dev allocation failed\n"); - goto out; - } - - snprintf(ictx->name_idev, sizeof(ictx->name_idev), - "iMON Panel, Knob and Mouse(%04x:%04x)", - ictx->vendor, ictx->product); - idev->name = ictx->name_idev; - - usb_make_path(ictx->usbdev_intf0, ictx->phys_idev, - sizeof(ictx->phys_idev)); - strlcat(ictx->phys_idev, "/input1", sizeof(ictx->phys_idev)); - idev->phys = ictx->phys_idev; - - idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | BIT_MASK(EV_REL); - - idev->keybit[BIT_WORD(BTN_MOUSE)] = - BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); - idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) | - BIT_MASK(REL_WHEEL); - - /* panel and/or knob code support */ - for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) { - u32 kc = imon_panel_key_table[i].keycode; - __set_bit(kc, idev->keybit); - } - - usb_to_input_id(ictx->usbdev_intf0, &idev->id); - idev->dev.parent = ictx->dev; - input_set_drvdata(idev, ictx); - - ret = input_register_device(idev); - if (ret < 0) { - dev_err(ictx->dev, "input dev register failed\n"); - goto out; - } - - return idev; - -out: - input_free_device(idev); - return NULL; -} - -static struct input_dev *imon_init_touch(struct imon_context *ictx) -{ - struct input_dev *touch; - int ret; - - touch = input_allocate_device(); - if (!touch) { - dev_err(ictx->dev, "touchscreen input dev allocation failed\n"); - goto touch_alloc_failed; - } - - snprintf(ictx->name_touch, sizeof(ictx->name_touch), - "iMON USB Touchscreen (%04x:%04x)", - ictx->vendor, ictx->product); - touch->name = ictx->name_touch; - - usb_make_path(ictx->usbdev_intf1, ictx->phys_touch, - sizeof(ictx->phys_touch)); - strlcat(ictx->phys_touch, "/input2", sizeof(ictx->phys_touch)); - touch->phys = ictx->phys_touch; - - touch->evbit[0] = - BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - touch->keybit[BIT_WORD(BTN_TOUCH)] = - BIT_MASK(BTN_TOUCH); - input_set_abs_params(touch, ABS_X, - 0x00, 0xfff, 0, 0); - input_set_abs_params(touch, ABS_Y, - 0x00, 0xfff, 0, 0); - - input_set_drvdata(touch, ictx); - - usb_to_input_id(ictx->usbdev_intf1, &touch->id); - touch->dev.parent = ictx->dev; - ret = input_register_device(touch); - if (ret < 0) { - dev_info(ictx->dev, "touchscreen input dev register failed\n"); - goto touch_register_failed; - } - - return touch; - -touch_register_failed: - input_free_device(ictx->touch); - -touch_alloc_failed: - return NULL; -} - -static bool imon_find_endpoints(struct imon_context *ictx, - struct usb_host_interface *iface_desc) -{ - struct usb_endpoint_descriptor *ep; - struct usb_endpoint_descriptor *rx_endpoint = NULL; - struct usb_endpoint_descriptor *tx_endpoint = NULL; - int ifnum = iface_desc->desc.bInterfaceNumber; - int num_endpts = iface_desc->desc.bNumEndpoints; - int i, ep_dir, ep_type; - bool ir_ep_found = false; - bool display_ep_found = false; - bool tx_control = false; - - /* - * Scan the endpoint list and set: - * first input endpoint = IR endpoint - * first output endpoint = display endpoint - */ - for (i = 0; i < num_endpts && !(ir_ep_found && display_ep_found); ++i) { - ep = &iface_desc->endpoint[i].desc; - ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK; - ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - - if (!ir_ep_found && ep_dir == USB_DIR_IN && - ep_type == USB_ENDPOINT_XFER_INT) { - - rx_endpoint = ep; - ir_ep_found = true; - dev_dbg(ictx->dev, "%s: found IR endpoint\n", __func__); - - } else if (!display_ep_found && ep_dir == USB_DIR_OUT && - ep_type == USB_ENDPOINT_XFER_INT) { - tx_endpoint = ep; - display_ep_found = true; - dev_dbg(ictx->dev, "%s: found display endpoint\n", __func__); - } - } - - if (ifnum == 0) { - ictx->rx_endpoint_intf0 = rx_endpoint; - /* - * tx is used to send characters to lcd/vfd, associate RF - * remotes, set IR protocol, and maybe more... - */ - ictx->tx_endpoint = tx_endpoint; - } else { - ictx->rx_endpoint_intf1 = rx_endpoint; - } - - /* - * If we didn't find a display endpoint, this is probably one of the - * newer iMON devices that use control urb instead of interrupt - */ - if (!display_ep_found) { - tx_control = true; - display_ep_found = true; - dev_dbg(ictx->dev, "%s: device uses control endpoint, not " - "interface OUT endpoint\n", __func__); - } - - /* - * Some iMON receivers have no display. Unfortunately, it seems - * that SoundGraph recycles device IDs between devices both with - * and without... :\ - */ - if (ictx->display_type == IMON_DISPLAY_TYPE_NONE) { - display_ep_found = false; - dev_dbg(ictx->dev, "%s: device has no display\n", __func__); - } - - /* - * iMON Touch devices have a VGA touchscreen, but no "display", as - * that refers to e.g. /dev/lcd0 (a character device LCD or VFD). - */ - if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { - display_ep_found = false; - dev_dbg(ictx->dev, "%s: iMON Touch device found\n", __func__); - } - - /* Input endpoint is mandatory */ - if (!ir_ep_found) - pr_err("no valid input (IR) endpoint found\n"); - - ictx->tx_control = tx_control; - - if (display_ep_found) - ictx->display_supported = true; - - return ir_ep_found; - -} - -static struct imon_context *imon_init_intf0(struct usb_interface *intf) -{ - struct imon_context *ictx; - struct urb *rx_urb; - struct urb *tx_urb; - struct device *dev = &intf->dev; - struct usb_host_interface *iface_desc; - int ret = -ENOMEM; - - ictx = kzalloc(sizeof(struct imon_context), GFP_KERNEL); - if (!ictx) { - dev_err(dev, "%s: kzalloc failed for context", __func__); - goto exit; - } - rx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!rx_urb) { - dev_err(dev, "%s: usb_alloc_urb failed for IR urb", __func__); - goto rx_urb_alloc_failed; - } - tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!tx_urb) { - dev_err(dev, "%s: usb_alloc_urb failed for display urb", - __func__); - goto tx_urb_alloc_failed; - } - - mutex_init(&ictx->lock); - spin_lock_init(&ictx->kc_lock); - - mutex_lock(&ictx->lock); - - ictx->dev = dev; - ictx->usbdev_intf0 = usb_get_dev(interface_to_usbdev(intf)); - ictx->dev_present_intf0 = true; - ictx->rx_urb_intf0 = rx_urb; - ictx->tx_urb = tx_urb; - ictx->rf_device = false; - - ictx->vendor = le16_to_cpu(ictx->usbdev_intf0->descriptor.idVendor); - ictx->product = le16_to_cpu(ictx->usbdev_intf0->descriptor.idProduct); - - ret = -ENODEV; - iface_desc = intf->cur_altsetting; - if (!imon_find_endpoints(ictx, iface_desc)) { - goto find_endpoint_failed; - } - - ictx->idev = imon_init_idev(ictx); - if (!ictx->idev) { - dev_err(dev, "%s: input device setup failed\n", __func__); - goto idev_setup_failed; - } - - ictx->rdev = imon_init_rdev(ictx); - if (!ictx->rdev) { - dev_err(dev, "%s: rc device setup failed\n", __func__); - goto rdev_setup_failed; - } - - usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0, - usb_rcvintpipe(ictx->usbdev_intf0, - ictx->rx_endpoint_intf0->bEndpointAddress), - ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf), - usb_rx_callback_intf0, ictx, - ictx->rx_endpoint_intf0->bInterval); - - ret = usb_submit_urb(ictx->rx_urb_intf0, GFP_KERNEL); - if (ret) { - pr_err("usb_submit_urb failed for intf0 (%d)\n", ret); - goto urb_submit_failed; - } - - return ictx; - -urb_submit_failed: - ir_input_unregister(ictx->rdev); -rdev_setup_failed: - input_unregister_device(ictx->idev); -idev_setup_failed: -find_endpoint_failed: - mutex_unlock(&ictx->lock); - usb_free_urb(tx_urb); -tx_urb_alloc_failed: - usb_free_urb(rx_urb); -rx_urb_alloc_failed: - kfree(ictx); -exit: - dev_err(dev, "unable to initialize intf0, err %d\n", ret); - - return NULL; -} - -static struct imon_context *imon_init_intf1(struct usb_interface *intf, - struct imon_context *ictx) -{ - struct urb *rx_urb; - struct usb_host_interface *iface_desc; - int ret = -ENOMEM; - - rx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!rx_urb) { - pr_err("usb_alloc_urb failed for IR urb\n"); - goto rx_urb_alloc_failed; - } - - mutex_lock(&ictx->lock); - - if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { - init_timer(&ictx->ttimer); - ictx->ttimer.data = (unsigned long)ictx; - ictx->ttimer.function = imon_touch_display_timeout; - } - - ictx->usbdev_intf1 = usb_get_dev(interface_to_usbdev(intf)); - ictx->dev_present_intf1 = true; - ictx->rx_urb_intf1 = rx_urb; - - ret = -ENODEV; - iface_desc = intf->cur_altsetting; - if (!imon_find_endpoints(ictx, iface_desc)) - goto find_endpoint_failed; - - if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { - ictx->touch = imon_init_touch(ictx); - if (!ictx->touch) - goto touch_setup_failed; - } else - ictx->touch = NULL; - - usb_fill_int_urb(ictx->rx_urb_intf1, ictx->usbdev_intf1, - usb_rcvintpipe(ictx->usbdev_intf1, - ictx->rx_endpoint_intf1->bEndpointAddress), - ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf), - usb_rx_callback_intf1, ictx, - ictx->rx_endpoint_intf1->bInterval); - - ret = usb_submit_urb(ictx->rx_urb_intf1, GFP_KERNEL); - - if (ret) { - pr_err("usb_submit_urb failed for intf1 (%d)\n", ret); - goto urb_submit_failed; - } - - return ictx; - -urb_submit_failed: - if (ictx->touch) - input_unregister_device(ictx->touch); -touch_setup_failed: -find_endpoint_failed: - mutex_unlock(&ictx->lock); - usb_free_urb(rx_urb); -rx_urb_alloc_failed: - dev_err(ictx->dev, "unable to initialize intf0, err %d\n", ret); - - return NULL; -} - -static void imon_init_display(struct imon_context *ictx, - struct usb_interface *intf) -{ - int ret; - - dev_dbg(ictx->dev, "Registering iMON display with sysfs\n"); - - /* set up sysfs entry for built-in clock */ - ret = sysfs_create_group(&intf->dev.kobj, &imon_display_attr_group); - if (ret) - dev_err(ictx->dev, "Could not create display sysfs " - "entries(%d)", ret); - - if (ictx->display_type == IMON_DISPLAY_TYPE_LCD) - ret = usb_register_dev(intf, &imon_lcd_class); - else - ret = usb_register_dev(intf, &imon_vfd_class); - if (ret) - /* Not a fatal error, so ignore */ - dev_info(ictx->dev, "could not get a minor number for " - "display\n"); - -} - -/** - * Callback function for USB core API: Probe - */ -static int __devinit imon_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usb_device *usbdev = NULL; - struct usb_host_interface *iface_desc = NULL; - struct usb_interface *first_if; - struct device *dev = &interface->dev; - int ifnum, code_length, sysfs_err; - int ret = 0; - struct imon_context *ictx = NULL; - struct imon_context *first_if_ctx = NULL; - u16 vendor, product; - - code_length = BUF_CHUNK_SIZE * 8; - - usbdev = usb_get_dev(interface_to_usbdev(interface)); - iface_desc = interface->cur_altsetting; - ifnum = iface_desc->desc.bInterfaceNumber; - vendor = le16_to_cpu(usbdev->descriptor.idVendor); - product = le16_to_cpu(usbdev->descriptor.idProduct); - - dev_dbg(dev, "%s: found iMON device (%04x:%04x, intf%d)\n", - __func__, vendor, product, ifnum); - - /* prevent races probing devices w/multiple interfaces */ - mutex_lock(&driver_lock); - - first_if = usb_ifnum_to_if(usbdev, 0); - first_if_ctx = (struct imon_context *)usb_get_intfdata(first_if); - - if (ifnum == 0) { - ictx = imon_init_intf0(interface); - if (!ictx) { - pr_err("failed to initialize context!\n"); - ret = -ENODEV; - goto fail; - } - - } else { - /* this is the secondary interface on the device */ - ictx = imon_init_intf1(interface, first_if_ctx); - if (!ictx) { - pr_err("failed to attach to context!\n"); - ret = -ENODEV; - goto fail; - } - - } - - usb_set_intfdata(interface, ictx); - - if (ifnum == 0) { - if (product == 0xffdc && ictx->rf_device) { - sysfs_err = sysfs_create_group(&interface->dev.kobj, - &imon_rf_attr_group); - if (sysfs_err) - pr_err("Could not create RF sysfs entries(%d)\n", - sysfs_err); - } - - if (ictx->display_supported) - imon_init_display(ictx, interface); - } - - dev_info(dev, "iMON device (%04x:%04x, intf%d) on " - "usb<%d:%d> initialized\n", vendor, product, ifnum, - usbdev->bus->busnum, usbdev->devnum); - - mutex_unlock(&ictx->lock); - mutex_unlock(&driver_lock); - - return 0; - -fail: - mutex_unlock(&driver_lock); - dev_err(dev, "unable to register, err %d\n", ret); - - return ret; -} - -/** - * Callback function for USB core API: disconnect - */ -static void __devexit imon_disconnect(struct usb_interface *interface) -{ - struct imon_context *ictx; - struct device *dev; - int ifnum; - - /* prevent races with multi-interface device probing and display_open */ - mutex_lock(&driver_lock); - - ictx = usb_get_intfdata(interface); - dev = ictx->dev; - ifnum = interface->cur_altsetting->desc.bInterfaceNumber; - - mutex_lock(&ictx->lock); - - /* - * sysfs_remove_group is safe to call even if sysfs_create_group - * hasn't been called - */ - sysfs_remove_group(&interface->dev.kobj, &imon_display_attr_group); - sysfs_remove_group(&interface->dev.kobj, &imon_rf_attr_group); - - usb_set_intfdata(interface, NULL); - - /* Abort ongoing write */ - if (ictx->tx.busy) { - usb_kill_urb(ictx->tx_urb); - complete_all(&ictx->tx.finished); - } - - if (ifnum == 0) { - ictx->dev_present_intf0 = false; - usb_kill_urb(ictx->rx_urb_intf0); - input_unregister_device(ictx->idev); - ir_input_unregister(ictx->rdev); - if (ictx->display_supported) { - if (ictx->display_type == IMON_DISPLAY_TYPE_LCD) - usb_deregister_dev(interface, &imon_lcd_class); - else - usb_deregister_dev(interface, &imon_vfd_class); - } - } else { - ictx->dev_present_intf1 = false; - usb_kill_urb(ictx->rx_urb_intf1); - if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) - input_unregister_device(ictx->touch); - } - - if (!ictx->dev_present_intf0 && !ictx->dev_present_intf1) { - if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) - del_timer_sync(&ictx->ttimer); - mutex_unlock(&ictx->lock); - if (!ictx->display_isopen) - free_imon_context(ictx); - } else - mutex_unlock(&ictx->lock); - - mutex_unlock(&driver_lock); - - dev_dbg(dev, "%s: iMON device (intf%d) disconnected\n", - __func__, ifnum); -} - -static int imon_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct imon_context *ictx = usb_get_intfdata(intf); - int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; - - if (ifnum == 0) - usb_kill_urb(ictx->rx_urb_intf0); - else - usb_kill_urb(ictx->rx_urb_intf1); - - return 0; -} - -static int imon_resume(struct usb_interface *intf) -{ - int rc = 0; - struct imon_context *ictx = usb_get_intfdata(intf); - int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; - - if (ifnum == 0) { - usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0, - usb_rcvintpipe(ictx->usbdev_intf0, - ictx->rx_endpoint_intf0->bEndpointAddress), - ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf), - usb_rx_callback_intf0, ictx, - ictx->rx_endpoint_intf0->bInterval); - - rc = usb_submit_urb(ictx->rx_urb_intf0, GFP_ATOMIC); - - } else { - usb_fill_int_urb(ictx->rx_urb_intf1, ictx->usbdev_intf1, - usb_rcvintpipe(ictx->usbdev_intf1, - ictx->rx_endpoint_intf1->bEndpointAddress), - ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf), - usb_rx_callback_intf1, ictx, - ictx->rx_endpoint_intf1->bInterval); - - rc = usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC); - } - - return rc; -} - -static int __init imon_init(void) -{ - int rc; - - rc = usb_register(&imon_driver); - if (rc) { - pr_err("usb register failed(%d)\n", rc); - rc = -ENODEV; - } - - return rc; -} - -static void __exit imon_exit(void) -{ - usb_deregister(&imon_driver); -} - -module_init(imon_init); -module_exit(imon_exit); diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h deleted file mode 100644 index 81c936b..0000000 --- a/drivers/media/IR/ir-core-priv.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Remote Controller core raw events header - * - * Copyright (C) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _IR_RAW_EVENT -#define _IR_RAW_EVENT - -#include -#include -#include - -struct ir_raw_handler { - struct list_head list; - - u64 protocols; /* which are handled by this handler */ - int (*decode)(struct input_dev *input_dev, struct ir_raw_event event); - - /* These two should only be used by the lirc decoder */ - int (*raw_register)(struct input_dev *input_dev); - int (*raw_unregister)(struct input_dev *input_dev); -}; - -struct ir_raw_event_ctrl { - struct list_head list; /* to keep track of raw clients */ - struct task_struct *thread; - spinlock_t lock; - struct kfifo kfifo; /* fifo for the pulse/space durations */ - ktime_t last_event; /* when last event occurred */ - enum raw_event_type last_type; /* last event type */ - struct input_dev *input_dev; /* pointer to the parent input_dev */ - u64 enabled_protocols; /* enabled raw protocol decoders */ - - /* raw decoder state follows */ - struct ir_raw_event prev_ev; - struct ir_raw_event this_ev; - struct nec_dec { - int state; - unsigned count; - u32 bits; - bool is_nec_x; - bool necx_repeat; - } nec; - struct rc5_dec { - int state; - u32 bits; - unsigned count; - unsigned wanted_bits; - } rc5; - struct rc6_dec { - int state; - u8 header; - u32 body; - bool toggle; - unsigned count; - unsigned wanted_bits; - } rc6; - struct sony_dec { - int state; - u32 bits; - unsigned count; - } sony; - struct jvc_dec { - int state; - u16 bits; - u16 old_bits; - unsigned count; - bool first; - bool toggle; - } jvc; - struct rc5_sz_dec { - int state; - u32 bits; - unsigned count; - unsigned wanted_bits; - } rc5_sz; - struct lirc_codec { - struct ir_input_dev *ir_dev; - struct lirc_driver *drv; - int carrier_low; - - ktime_t gap_start; - u64 gap_duration; - bool gap; - bool send_timeout_reports; - - } lirc; -}; - -/* macros for IR decoders */ -static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin) -{ - return d1 > (d2 - margin); -} - -static inline bool eq_margin(unsigned d1, unsigned d2, unsigned margin) -{ - return ((d1 > (d2 - margin)) && (d1 < (d2 + margin))); -} - -static inline bool is_transition(struct ir_raw_event *x, struct ir_raw_event *y) -{ - return x->pulse != y->pulse; -} - -static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration) -{ - if (duration > ev->duration) - ev->duration = 0; - else - ev->duration -= duration; -} - -/* Returns true if event is normal pulse/space event */ -static inline bool is_timing_event(struct ir_raw_event ev) -{ - return !ev.carrier_report && !ev.reset; -} - -#define TO_US(duration) DIV_ROUND_CLOSEST((duration), 1000) -#define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space") -/* - * Routines from ir-sysfs.c - Meant to be called only internally inside - * ir-core - */ -int ir_register_input(struct input_dev *input_dev); - -int ir_register_class(struct input_dev *input_dev); -void ir_unregister_class(struct input_dev *input_dev); - -/* - * Routines from ir-raw-event.c to be used internally and by decoders - */ -u64 ir_raw_get_allowed_protocols(void); -int ir_raw_event_register(struct input_dev *input_dev); -void ir_raw_event_unregister(struct input_dev *input_dev); -int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); -void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); -void ir_raw_init(void); - -int ir_rcmap_init(void); -void ir_rcmap_cleanup(void); -/* - * Decoder initialization code - * - * Those load logic are called during ir-core init, and automatically - * loads the compiled decoders for their usage with IR raw events - */ - -/* from ir-nec-decoder.c */ -#ifdef CONFIG_IR_NEC_DECODER_MODULE -#define load_nec_decode() request_module("ir-nec-decoder") -#else -#define load_nec_decode() 0 -#endif - -/* from ir-rc5-decoder.c */ -#ifdef CONFIG_IR_RC5_DECODER_MODULE -#define load_rc5_decode() request_module("ir-rc5-decoder") -#else -#define load_rc5_decode() 0 -#endif - -/* from ir-rc6-decoder.c */ -#ifdef CONFIG_IR_RC6_DECODER_MODULE -#define load_rc6_decode() request_module("ir-rc6-decoder") -#else -#define load_rc6_decode() 0 -#endif - -/* from ir-jvc-decoder.c */ -#ifdef CONFIG_IR_JVC_DECODER_MODULE -#define load_jvc_decode() request_module("ir-jvc-decoder") -#else -#define load_jvc_decode() 0 -#endif - -/* from ir-sony-decoder.c */ -#ifdef CONFIG_IR_SONY_DECODER_MODULE -#define load_sony_decode() request_module("ir-sony-decoder") -#else -#define load_sony_decode() 0 -#endif - -/* from ir-lirc-codec.c */ -#ifdef CONFIG_IR_LIRC_CODEC_MODULE -#define load_lirc_codec() request_module("ir-lirc-codec") -#else -#define load_lirc_codec() 0 -#endif - - -#endif /* _IR_RAW_EVENT */ diff --git a/drivers/media/IR/ir-functions.c b/drivers/media/IR/ir-functions.c deleted file mode 100644 index ec021c9..0000000 --- a/drivers/media/IR/ir-functions.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * some common functions to handle infrared remote protocol decoding for - * drivers which have not yet been (or can't be) converted to use the - * regular protocol decoders... - * - * (c) 2003 Gerd Knorr [SuSE Labs] - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include "ir-core-priv.h" - -/* -------------------------------------------------------------------------- */ - -MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); -MODULE_LICENSE("GPL"); - -/* RC5 decoding stuff, moved from bttv-input.c to share it with - * saa7134 */ - -/* decode raw bit pattern to RC5 code */ -static u32 ir_rc5_decode(unsigned int code) -{ - unsigned int org_code = code; - unsigned int pair; - unsigned int rc5 = 0; - int i; - - for (i = 0; i < 14; ++i) { - pair = code & 0x3; - code >>= 2; - - rc5 <<= 1; - switch (pair) { - case 0: - case 2: - break; - case 1: - rc5 |= 1; - break; - case 3: - IR_dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code); - return 0; - } - } - IR_dprintk(1, "ir-common: code=%x, rc5=%x, start=%x, toggle=%x, address=%x, " - "instr=%x\n", rc5, org_code, RC5_START(rc5), - RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); - return rc5; -} - -void ir_rc5_timer_end(unsigned long data) -{ - struct card_ir *ir = (struct card_ir *)data; - struct timeval tv; - unsigned long current_jiffies; - u32 gap; - u32 rc5 = 0; - - /* get time */ - current_jiffies = jiffies; - do_gettimeofday(&tv); - - /* avoid overflow with gap >1s */ - if (tv.tv_sec - ir->base_time.tv_sec > 1) { - gap = 200000; - } else { - gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + - tv.tv_usec - ir->base_time.tv_usec; - } - - /* signal we're ready to start a new code */ - ir->active = 0; - - /* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */ - if (gap < 28000) { - IR_dprintk(1, "ir-common: spurious timer_end\n"); - return; - } - - if (ir->last_bit < 20) { - /* ignore spurious codes (caused by light/other remotes) */ - IR_dprintk(1, "ir-common: short code: %x\n", ir->code); - } else { - ir->code = (ir->code << ir->shift_by) | 1; - rc5 = ir_rc5_decode(ir->code); - - /* two start bits? */ - if (RC5_START(rc5) != ir->start) { - IR_dprintk(1, "ir-common: rc5 start bits invalid: %u\n", RC5_START(rc5)); - - /* right address? */ - } else if (RC5_ADDR(rc5) == ir->addr) { - u32 toggle = RC5_TOGGLE(rc5); - u32 instr = RC5_INSTR(rc5); - - /* Good code */ - ir_keydown(ir->dev, instr, toggle); - IR_dprintk(1, "ir-common: instruction %x, toggle %x\n", - instr, toggle); - } - } -} -EXPORT_SYMBOL_GPL(ir_rc5_timer_end); diff --git a/drivers/media/IR/ir-jvc-decoder.c b/drivers/media/IR/ir-jvc-decoder.c deleted file mode 100644 index 63dca6e..0000000 --- a/drivers/media/IR/ir-jvc-decoder.c +++ /dev/null @@ -1,199 +0,0 @@ -/* ir-jvc-decoder.c - handle JVC IR Pulse/Space protocol - * - * Copyright (C) 2010 by David Härdeman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include "ir-core-priv.h" - -#define JVC_NBITS 16 /* dev(8) + func(8) */ -#define JVC_UNIT 525000 /* ns */ -#define JVC_HEADER_PULSE (16 * JVC_UNIT) /* lack of header -> repeat */ -#define JVC_HEADER_SPACE (8 * JVC_UNIT) -#define JVC_BIT_PULSE (1 * JVC_UNIT) -#define JVC_BIT_0_SPACE (1 * JVC_UNIT) -#define JVC_BIT_1_SPACE (3 * JVC_UNIT) -#define JVC_TRAILER_PULSE (1 * JVC_UNIT) -#define JVC_TRAILER_SPACE (35 * JVC_UNIT) - -enum jvc_state { - STATE_INACTIVE, - STATE_HEADER_SPACE, - STATE_BIT_PULSE, - STATE_BIT_SPACE, - STATE_TRAILER_PULSE, - STATE_TRAILER_SPACE, - STATE_CHECK_REPEAT, -}; - -/** - * ir_jvc_decode() - Decode one JVC pulse or space - * @input_dev: the struct input_dev descriptor of the device - * @duration: the struct ir_raw_event descriptor of the pulse/space - * - * This function returns -EINVAL if the pulse violates the state machine - */ -static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct jvc_dec *data = &ir_dev->raw->jvc; - - if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC)) - return 0; - - if (!is_timing_event(ev)) { - if (ev.reset) - data->state = STATE_INACTIVE; - return 0; - } - - if (!geq_margin(ev.duration, JVC_UNIT, JVC_UNIT / 2)) - goto out; - - IR_dprintk(2, "JVC decode started at state %d (%uus %s)\n", - data->state, TO_US(ev.duration), TO_STR(ev.pulse)); - -again: - switch (data->state) { - - case STATE_INACTIVE: - if (!ev.pulse) - break; - - if (!eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2)) - break; - - data->count = 0; - data->first = true; - data->toggle = !data->toggle; - data->state = STATE_HEADER_SPACE; - return 0; - - case STATE_HEADER_SPACE: - if (ev.pulse) - break; - - if (!eq_margin(ev.duration, JVC_HEADER_SPACE, JVC_UNIT / 2)) - break; - - data->state = STATE_BIT_PULSE; - return 0; - - case STATE_BIT_PULSE: - if (!ev.pulse) - break; - - if (!eq_margin(ev.duration, JVC_BIT_PULSE, JVC_UNIT / 2)) - break; - - data->state = STATE_BIT_SPACE; - return 0; - - case STATE_BIT_SPACE: - if (ev.pulse) - break; - - data->bits <<= 1; - if (eq_margin(ev.duration, JVC_BIT_1_SPACE, JVC_UNIT / 2)) { - data->bits |= 1; - decrease_duration(&ev, JVC_BIT_1_SPACE); - } else if (eq_margin(ev.duration, JVC_BIT_0_SPACE, JVC_UNIT / 2)) - decrease_duration(&ev, JVC_BIT_0_SPACE); - else - break; - data->count++; - - if (data->count == JVC_NBITS) - data->state = STATE_TRAILER_PULSE; - else - data->state = STATE_BIT_PULSE; - return 0; - - case STATE_TRAILER_PULSE: - if (!ev.pulse) - break; - - if (!eq_margin(ev.duration, JVC_TRAILER_PULSE, JVC_UNIT / 2)) - break; - - data->state = STATE_TRAILER_SPACE; - return 0; - - case STATE_TRAILER_SPACE: - if (ev.pulse) - break; - - if (!geq_margin(ev.duration, JVC_TRAILER_SPACE, JVC_UNIT / 2)) - break; - - if (data->first) { - u32 scancode; - scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) | - (bitrev8((data->bits >> 0) & 0xff) << 0); - IR_dprintk(1, "JVC scancode 0x%04x\n", scancode); - ir_keydown(input_dev, scancode, data->toggle); - data->first = false; - data->old_bits = data->bits; - } else if (data->bits == data->old_bits) { - IR_dprintk(1, "JVC repeat\n"); - ir_repeat(input_dev); - } else { - IR_dprintk(1, "JVC invalid repeat msg\n"); - break; - } - - data->count = 0; - data->state = STATE_CHECK_REPEAT; - return 0; - - case STATE_CHECK_REPEAT: - if (!ev.pulse) - break; - - if (eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2)) - data->state = STATE_INACTIVE; - else - data->state = STATE_BIT_PULSE; - goto again; - } - -out: - IR_dprintk(1, "JVC decode failed at state %d (%uus %s)\n", - data->state, TO_US(ev.duration), TO_STR(ev.pulse)); - data->state = STATE_INACTIVE; - return -EINVAL; -} - -static struct ir_raw_handler jvc_handler = { - .protocols = IR_TYPE_JVC, - .decode = ir_jvc_decode, -}; - -static int __init ir_jvc_decode_init(void) -{ - ir_raw_handler_register(&jvc_handler); - - printk(KERN_INFO "IR JVC protocol handler initialized\n"); - return 0; -} - -static void __exit ir_jvc_decode_exit(void) -{ - ir_raw_handler_unregister(&jvc_handler); -} - -module_init(ir_jvc_decode_init); -module_exit(ir_jvc_decode_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("David Härdeman "); -MODULE_DESCRIPTION("JVC IR protocol decoder"); diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c deleted file mode 100644 index 8039110..0000000 --- a/drivers/media/IR/ir-keytable.c +++ /dev/null @@ -1,766 +0,0 @@ -/* ir-keytable.c - handle IR scancode->keycode tables - * - * Copyright (C) 2009 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - - -#include -#include -#include "ir-core-priv.h" - -/* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */ -#define IR_TAB_MIN_SIZE 256 -#define IR_TAB_MAX_SIZE 8192 - -/* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */ -#define IR_KEYPRESS_TIMEOUT 250 - -/** - * ir_create_table() - initializes a scancode table - * @rc_tab: the ir_scancode_table to initialize - * @name: name to assign to the table - * @ir_type: ir type to assign to the new table - * @size: initial size of the table - * @return: zero on success or a negative error code - * - * This routine will initialize the ir_scancode_table and will allocate - * memory to hold at least the specified number elements. - */ -static int ir_create_table(struct ir_scancode_table *rc_tab, - const char *name, u64 ir_type, size_t size) -{ - rc_tab->name = name; - rc_tab->ir_type = ir_type; - rc_tab->alloc = roundup_pow_of_two(size * sizeof(struct ir_scancode)); - rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode); - rc_tab->scan = kmalloc(rc_tab->alloc, GFP_KERNEL); - if (!rc_tab->scan) - return -ENOMEM; - - IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", - rc_tab->size, rc_tab->alloc); - return 0; -} - -/** - * ir_free_table() - frees memory allocated by a scancode table - * @rc_tab: the table whose mappings need to be freed - * - * This routine will free memory alloctaed for key mappings used by given - * scancode table. - */ -static void ir_free_table(struct ir_scancode_table *rc_tab) -{ - rc_tab->size = 0; - kfree(rc_tab->scan); - rc_tab->scan = NULL; -} - -/** - * ir_resize_table() - resizes a scancode table if necessary - * @rc_tab: the ir_scancode_table to resize - * @gfp_flags: gfp flags to use when allocating memory - * @return: zero on success or a negative error code - * - * This routine will shrink the ir_scancode_table if it has lots of - * unused entries and grow it if it is full. - */ -static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags) -{ - unsigned int oldalloc = rc_tab->alloc; - unsigned int newalloc = oldalloc; - struct ir_scancode *oldscan = rc_tab->scan; - struct ir_scancode *newscan; - - if (rc_tab->size == rc_tab->len) { - /* All entries in use -> grow keytable */ - if (rc_tab->alloc >= IR_TAB_MAX_SIZE) - return -ENOMEM; - - newalloc *= 2; - IR_dprintk(1, "Growing table to %u bytes\n", newalloc); - } - - if ((rc_tab->len * 3 < rc_tab->size) && (oldalloc > IR_TAB_MIN_SIZE)) { - /* Less than 1/3 of entries in use -> shrink keytable */ - newalloc /= 2; - IR_dprintk(1, "Shrinking table to %u bytes\n", newalloc); - } - - if (newalloc == oldalloc) - return 0; - - newscan = kmalloc(newalloc, gfp_flags); - if (!newscan) { - IR_dprintk(1, "Failed to kmalloc %u bytes\n", newalloc); - return -ENOMEM; - } - - memcpy(newscan, rc_tab->scan, rc_tab->len * sizeof(struct ir_scancode)); - rc_tab->scan = newscan; - rc_tab->alloc = newalloc; - rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode); - kfree(oldscan); - return 0; -} - -/** - * ir_update_mapping() - set a keycode in the scancode->keycode table - * @dev: the struct input_dev device descriptor - * @rc_tab: scancode table to be adjusted - * @index: index of the mapping that needs to be updated - * @keycode: the desired keycode - * @return: previous keycode assigned to the mapping - * - * This routine is used to update scancode->keycopde mapping at given - * position. - */ -static unsigned int ir_update_mapping(struct input_dev *dev, - struct ir_scancode_table *rc_tab, - unsigned int index, - unsigned int new_keycode) -{ - int old_keycode = rc_tab->scan[index].keycode; - int i; - - /* Did the user wish to remove the mapping? */ - if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) { - IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", - index, rc_tab->scan[index].scancode); - rc_tab->len--; - memmove(&rc_tab->scan[index], &rc_tab->scan[index+ 1], - (rc_tab->len - index) * sizeof(struct ir_scancode)); - } else { - IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n", - index, - old_keycode == KEY_RESERVED ? "New" : "Replacing", - rc_tab->scan[index].scancode, new_keycode); - rc_tab->scan[index].keycode = new_keycode; - __set_bit(new_keycode, dev->keybit); - } - - if (old_keycode != KEY_RESERVED) { - /* A previous mapping was updated... */ - __clear_bit(old_keycode, dev->keybit); - /* ... but another scancode might use the same keycode */ - for (i = 0; i < rc_tab->len; i++) { - if (rc_tab->scan[i].keycode == old_keycode) { - __set_bit(old_keycode, dev->keybit); - break; - } - } - - /* Possibly shrink the keytable, failure is not a problem */ - ir_resize_table(rc_tab, GFP_ATOMIC); - } - - return old_keycode; -} - -/** - * ir_locate_scancode() - set a keycode in the scancode->keycode table - * @ir_dev: the struct ir_input_dev device descriptor - * @rc_tab: scancode table to be searched - * @scancode: the desired scancode - * @resize: controls whether we allowed to resize the table to - * accomodate not yet present scancodes - * @return: index of the mapping containing scancode in question - * or -1U in case of failure. - * - * This routine is used to locate given scancode in ir_scancode_table. - * If scancode is not yet present the routine will allocate a new slot - * for it. - */ -static unsigned int ir_establish_scancode(struct ir_input_dev *ir_dev, - struct ir_scancode_table *rc_tab, - unsigned int scancode, - bool resize) -{ - unsigned int i; - - /* - * Unfortunately, some hardware-based IR decoders don't provide - * all bits for the complete IR code. In general, they provide only - * the command part of the IR code. Yet, as it is possible to replace - * the provided IR with another one, it is needed to allow loading - * IR tables from other remotes. So, - */ - if (ir_dev->props && ir_dev->props->scanmask) - scancode &= ir_dev->props->scanmask; - - /* First check if we already have a mapping for this ir command */ - for (i = 0; i < rc_tab->len; i++) { - if (rc_tab->scan[i].scancode == scancode) - return i; - - /* Keytable is sorted from lowest to highest scancode */ - if (rc_tab->scan[i].scancode >= scancode) - break; - } - - /* No previous mapping found, we might need to grow the table */ - if (rc_tab->size == rc_tab->len) { - if (!resize || ir_resize_table(rc_tab, GFP_ATOMIC)) - return -1U; - } - - /* i is the proper index to insert our new keycode */ - if (i < rc_tab->len) - memmove(&rc_tab->scan[i + 1], &rc_tab->scan[i], - (rc_tab->len - i) * sizeof(struct ir_scancode)); - rc_tab->scan[i].scancode = scancode; - rc_tab->scan[i].keycode = KEY_RESERVED; - rc_tab->len++; - - return i; -} - -/** - * ir_setkeycode() - set a keycode in the scancode->keycode table - * @dev: the struct input_dev device descriptor - * @scancode: the desired scancode - * @keycode: result - * @return: -EINVAL if the keycode could not be inserted, otherwise zero. - * - * This routine is used to handle evdev EVIOCSKEY ioctl. - */ -static int ir_setkeycode(struct input_dev *dev, - const struct input_keymap_entry *ke, - unsigned int *old_keycode) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(dev); - struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; - unsigned int index; - unsigned int scancode; - int retval; - unsigned long flags; - - spin_lock_irqsave(&rc_tab->lock, flags); - - if (ke->flags & INPUT_KEYMAP_BY_INDEX) { - index = ke->index; - if (index >= rc_tab->len) { - retval = -EINVAL; - goto out; - } - } else { - retval = input_scancode_to_scalar(ke, &scancode); - if (retval) - goto out; - - index = ir_establish_scancode(ir_dev, rc_tab, scancode, true); - if (index >= rc_tab->len) { - retval = -ENOMEM; - goto out; - } - } - - *old_keycode = ir_update_mapping(dev, rc_tab, index, ke->keycode); - -out: - spin_unlock_irqrestore(&rc_tab->lock, flags); - return retval; -} - -/** - * ir_setkeytable() - sets several entries in the scancode->keycode table - * @dev: the struct input_dev device descriptor - * @to: the struct ir_scancode_table to copy entries to - * @from: the struct ir_scancode_table to copy entries from - * @return: -ENOMEM if all keycodes could not be inserted, otherwise zero. - * - * This routine is used to handle table initialization. - */ -static int ir_setkeytable(struct ir_input_dev *ir_dev, - const struct ir_scancode_table *from) -{ - struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; - unsigned int i, index; - int rc; - - rc = ir_create_table(&ir_dev->rc_tab, - from->name, from->ir_type, from->size); - if (rc) - return rc; - - IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", - rc_tab->size, rc_tab->alloc); - - for (i = 0; i < from->size; i++) { - index = ir_establish_scancode(ir_dev, rc_tab, - from->scan[i].scancode, false); - if (index >= rc_tab->len) { - rc = -ENOMEM; - break; - } - - ir_update_mapping(ir_dev->input_dev, rc_tab, index, - from->scan[i].keycode); - } - - if (rc) - ir_free_table(rc_tab); - - return rc; -} - -/** - * ir_lookup_by_scancode() - locate mapping by scancode - * @rc_tab: the &struct ir_scancode_table to search - * @scancode: scancode to look for in the table - * @return: index in the table, -1U if not found - * - * This routine performs binary search in RC keykeymap table for - * given scancode. - */ -static unsigned int ir_lookup_by_scancode(const struct ir_scancode_table *rc_tab, - unsigned int scancode) -{ - int start = 0; - int end = rc_tab->len - 1; - int mid; - - while (start <= end) { - mid = (start + end) / 2; - if (rc_tab->scan[mid].scancode < scancode) - start = mid + 1; - else if (rc_tab->scan[mid].scancode > scancode) - end = mid - 1; - else - return mid; - } - - return -1U; -} - -/** - * ir_getkeycode() - get a keycode from the scancode->keycode table - * @dev: the struct input_dev device descriptor - * @scancode: the desired scancode - * @keycode: used to return the keycode, if found, or KEY_RESERVED - * @return: always returns zero. - * - * This routine is used to handle evdev EVIOCGKEY ioctl. - */ -static int ir_getkeycode(struct input_dev *dev, - struct input_keymap_entry *ke) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(dev); - struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; - struct ir_scancode *entry; - unsigned long flags; - unsigned int index; - unsigned int scancode; - int retval; - - spin_lock_irqsave(&rc_tab->lock, flags); - - if (ke->flags & INPUT_KEYMAP_BY_INDEX) { - index = ke->index; - } else { - retval = input_scancode_to_scalar(ke, &scancode); - if (retval) - goto out; - - index = ir_lookup_by_scancode(rc_tab, scancode); - } - - if (index >= rc_tab->len) { - if (!(ke->flags & INPUT_KEYMAP_BY_INDEX)) - IR_dprintk(1, "unknown key for scancode 0x%04x\n", - scancode); - retval = -EINVAL; - goto out; - } - - entry = &rc_tab->scan[index]; - - ke->index = index; - ke->keycode = entry->keycode; - ke->len = sizeof(entry->scancode); - memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode)); - - retval = 0; - -out: - spin_unlock_irqrestore(&rc_tab->lock, flags); - return retval; -} - -/** - * ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode - * @input_dev: the struct input_dev descriptor of the device - * @scancode: the scancode that we're seeking - * - * This routine is used by the input routines when a key is pressed at the - * IR. The scancode is received and needs to be converted into a keycode. - * If the key is not found, it returns KEY_RESERVED. Otherwise, returns the - * corresponding keycode from the table. - */ -u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(dev); - struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; - unsigned int keycode; - unsigned int index; - unsigned long flags; - - spin_lock_irqsave(&rc_tab->lock, flags); - - index = ir_lookup_by_scancode(rc_tab, scancode); - keycode = index < rc_tab->len ? - rc_tab->scan[index].keycode : KEY_RESERVED; - - spin_unlock_irqrestore(&rc_tab->lock, flags); - - if (keycode != KEY_RESERVED) - IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", - dev->name, scancode, keycode); - - return keycode; -} -EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); - -/** - * ir_do_keyup() - internal function to signal the release of a keypress - * @ir: the struct ir_input_dev descriptor of the device - * - * This function is used internally to release a keypress, it must be - * called with keylock held. - */ -static void ir_do_keyup(struct ir_input_dev *ir) -{ - if (!ir->keypressed) - return; - - IR_dprintk(1, "keyup key 0x%04x\n", ir->last_keycode); - input_report_key(ir->input_dev, ir->last_keycode, 0); - input_sync(ir->input_dev); - ir->keypressed = false; -} - -/** - * ir_keyup() - generates input event to signal the release of a keypress - * @dev: the struct input_dev descriptor of the device - * - * This routine is used to signal that a key has been released on the - * remote control. - */ -void ir_keyup(struct input_dev *dev) -{ - unsigned long flags; - struct ir_input_dev *ir = input_get_drvdata(dev); - - spin_lock_irqsave(&ir->keylock, flags); - ir_do_keyup(ir); - spin_unlock_irqrestore(&ir->keylock, flags); -} -EXPORT_SYMBOL_GPL(ir_keyup); - -/** - * ir_timer_keyup() - generates a keyup event after a timeout - * @cookie: a pointer to struct ir_input_dev passed to setup_timer() - * - * This routine will generate a keyup event some time after a keydown event - * is generated when no further activity has been detected. - */ -static void ir_timer_keyup(unsigned long cookie) -{ - struct ir_input_dev *ir = (struct ir_input_dev *)cookie; - unsigned long flags; - - /* - * ir->keyup_jiffies is used to prevent a race condition if a - * hardware interrupt occurs at this point and the keyup timer - * event is moved further into the future as a result. - * - * The timer will then be reactivated and this function called - * again in the future. We need to exit gracefully in that case - * to allow the input subsystem to do its auto-repeat magic or - * a keyup event might follow immediately after the keydown. - */ - spin_lock_irqsave(&ir->keylock, flags); - if (time_is_before_eq_jiffies(ir->keyup_jiffies)) - ir_do_keyup(ir); - spin_unlock_irqrestore(&ir->keylock, flags); -} - -/** - * ir_repeat() - notifies the IR core that a key is still pressed - * @dev: the struct input_dev descriptor of the device - * - * This routine is used by IR decoders when a repeat message which does - * not include the necessary bits to reproduce the scancode has been - * received. - */ -void ir_repeat(struct input_dev *dev) -{ - unsigned long flags; - struct ir_input_dev *ir = input_get_drvdata(dev); - - spin_lock_irqsave(&ir->keylock, flags); - - input_event(dev, EV_MSC, MSC_SCAN, ir->last_scancode); - - if (!ir->keypressed) - goto out; - - ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); - mod_timer(&ir->timer_keyup, ir->keyup_jiffies); - -out: - spin_unlock_irqrestore(&ir->keylock, flags); -} -EXPORT_SYMBOL_GPL(ir_repeat); - -/** - * ir_do_keydown() - internal function to process a keypress - * @dev: the struct input_dev descriptor of the device - * @scancode: the scancode of the keypress - * @keycode: the keycode of the keypress - * @toggle: the toggle value of the keypress - * - * This function is used internally to register a keypress, it must be - * called with keylock held. - */ -static void ir_do_keydown(struct input_dev *dev, int scancode, - u32 keycode, u8 toggle) -{ - struct ir_input_dev *ir = input_get_drvdata(dev); - - input_event(dev, EV_MSC, MSC_SCAN, scancode); - - /* Repeat event? */ - if (ir->keypressed && - ir->last_scancode == scancode && - ir->last_toggle == toggle) - return; - - /* Release old keypress */ - ir_do_keyup(ir); - - ir->last_scancode = scancode; - ir->last_toggle = toggle; - ir->last_keycode = keycode; - - if (keycode == KEY_RESERVED) - return; - - /* Register a keypress */ - ir->keypressed = true; - IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", - dev->name, keycode, scancode); - input_report_key(dev, ir->last_keycode, 1); - input_sync(dev); -} - -/** - * ir_keydown() - generates input event for a key press - * @dev: the struct input_dev descriptor of the device - * @scancode: the scancode that we're seeking - * @toggle: the toggle value (protocol dependent, if the protocol doesn't - * support toggle values, this should be set to zero) - * - * This routine is used by the input routines when a key is pressed at the - * IR. It gets the keycode for a scancode and reports an input event via - * input_report_key(). - */ -void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) -{ - unsigned long flags; - struct ir_input_dev *ir = input_get_drvdata(dev); - u32 keycode = ir_g_keycode_from_table(dev, scancode); - - spin_lock_irqsave(&ir->keylock, flags); - ir_do_keydown(dev, scancode, keycode, toggle); - - if (ir->keypressed) { - ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); - mod_timer(&ir->timer_keyup, ir->keyup_jiffies); - } - spin_unlock_irqrestore(&ir->keylock, flags); -} -EXPORT_SYMBOL_GPL(ir_keydown); - -/** - * ir_keydown_notimeout() - generates input event for a key press without - * an automatic keyup event at a later time - * @dev: the struct input_dev descriptor of the device - * @scancode: the scancode that we're seeking - * @toggle: the toggle value (protocol dependent, if the protocol doesn't - * support toggle values, this should be set to zero) - * - * This routine is used by the input routines when a key is pressed at the - * IR. It gets the keycode for a scancode and reports an input event via - * input_report_key(). The driver must manually call ir_keyup() at a later - * stage. - */ -void ir_keydown_notimeout(struct input_dev *dev, int scancode, u8 toggle) -{ - unsigned long flags; - struct ir_input_dev *ir = input_get_drvdata(dev); - u32 keycode = ir_g_keycode_from_table(dev, scancode); - - spin_lock_irqsave(&ir->keylock, flags); - ir_do_keydown(dev, scancode, keycode, toggle); - spin_unlock_irqrestore(&ir->keylock, flags); -} -EXPORT_SYMBOL_GPL(ir_keydown_notimeout); - -static int ir_open(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - - return ir_dev->props->open(ir_dev->props->priv); -} - -static void ir_close(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - - ir_dev->props->close(ir_dev->props->priv); -} - -/** - * __ir_input_register() - sets the IR keycode table and add the handlers - * for keymap table get/set - * @input_dev: the struct input_dev descriptor of the device - * @rc_tab: the struct ir_scancode_table table of scancode/keymap - * - * This routine is used to initialize the input infrastructure - * to work with an IR. - * It will register the input/evdev interface for the device and - * register the syfs code for IR class - */ -int __ir_input_register(struct input_dev *input_dev, - const struct ir_scancode_table *rc_tab, - struct ir_dev_props *props, - const char *driver_name) -{ - struct ir_input_dev *ir_dev; - int rc; - - if (rc_tab->scan == NULL || !rc_tab->size) - return -EINVAL; - - ir_dev = kzalloc(sizeof(*ir_dev), GFP_KERNEL); - if (!ir_dev) - return -ENOMEM; - - ir_dev->driver_name = kasprintf(GFP_KERNEL, "%s", driver_name); - if (!ir_dev->driver_name) { - rc = -ENOMEM; - goto out_dev; - } - - input_dev->getkeycode_new = ir_getkeycode; - input_dev->setkeycode_new = ir_setkeycode; - input_set_drvdata(input_dev, ir_dev); - ir_dev->input_dev = input_dev; - - spin_lock_init(&ir_dev->rc_tab.lock); - spin_lock_init(&ir_dev->keylock); - setup_timer(&ir_dev->timer_keyup, ir_timer_keyup, (unsigned long)ir_dev); - - if (props) { - ir_dev->props = props; - if (props->open) - input_dev->open = ir_open; - if (props->close) - input_dev->close = ir_close; - } - - set_bit(EV_KEY, input_dev->evbit); - set_bit(EV_REP, input_dev->evbit); - set_bit(EV_MSC, input_dev->evbit); - set_bit(MSC_SCAN, input_dev->mscbit); - - rc = ir_setkeytable(ir_dev, rc_tab); - if (rc) - goto out_name; - - rc = ir_register_class(input_dev); - if (rc < 0) - goto out_table; - - if (ir_dev->props) - if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) { - rc = ir_raw_event_register(input_dev); - if (rc < 0) - goto out_event; - } - - rc = ir_register_input(input_dev); - if (rc < 0) - goto out_event; - - IR_dprintk(1, "Registered input device on %s for %s remote%s.\n", - driver_name, rc_tab->name, - (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ? - " in raw mode" : ""); - - /* - * Default delay of 250ms is too short for some protocols, expecially - * since the timeout is currently set to 250ms. Increase it to 500ms, - * to avoid wrong repetition of the keycodes. - */ - input_dev->rep[REP_DELAY] = 500; - - return 0; - -out_event: - ir_unregister_class(input_dev); -out_table: - ir_free_table(&ir_dev->rc_tab); -out_name: - kfree(ir_dev->driver_name); -out_dev: - kfree(ir_dev); - return rc; -} -EXPORT_SYMBOL_GPL(__ir_input_register); - -/** - * ir_input_unregister() - unregisters IR and frees resources - * @input_dev: the struct input_dev descriptor of the device - - * This routine is used to free memory and de-register interfaces. - */ -void ir_input_unregister(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - - if (!ir_dev) - return; - - IR_dprintk(1, "Freed keycode table\n"); - - del_timer_sync(&ir_dev->timer_keyup); - if (ir_dev->props) - if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) - ir_raw_event_unregister(input_dev); - - ir_free_table(&ir_dev->rc_tab); - - ir_unregister_class(input_dev); - - kfree(ir_dev->driver_name); - kfree(ir_dev); -} -EXPORT_SYMBOL_GPL(ir_input_unregister); - -int ir_core_debug; /* ir_debug level (0,1,2) */ -EXPORT_SYMBOL_GPL(ir_core_debug); -module_param_named(debug, ir_core_debug, int, 0644); - -MODULE_AUTHOR("Mauro Carvalho Chehab "); -MODULE_LICENSE("GPL"); diff --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c deleted file mode 100644 index 9fc0db9..0000000 --- a/drivers/media/IR/ir-lirc-codec.c +++ /dev/null @@ -1,410 +0,0 @@ -/* ir-lirc-codec.c - ir-core to classic lirc interface bridge - * - * Copyright (C) 2010 by Jarod Wilson - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include "ir-core-priv.h" - -#define LIRCBUF_SIZE 256 - -/** - * ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the - * lircd userspace daemon for decoding. - * @input_dev: the struct input_dev descriptor of the device - * @duration: the struct ir_raw_event descriptor of the pulse/space - * - * This function returns -EINVAL if the lirc interfaces aren't wired up. - */ -static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct lirc_codec *lirc = &ir_dev->raw->lirc; - int sample; - - if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC)) - return 0; - - if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf) - return -EINVAL; - - /* Packet start */ - if (ev.reset) - return 0; - - /* Carrier reports */ - if (ev.carrier_report) { - sample = LIRC_FREQUENCY(ev.carrier); - - /* Packet end */ - } else if (ev.timeout) { - - if (lirc->gap) - return 0; - - lirc->gap_start = ktime_get(); - lirc->gap = true; - lirc->gap_duration = ev.duration; - - if (!lirc->send_timeout_reports) - return 0; - - sample = LIRC_TIMEOUT(ev.duration / 1000); - - /* Normal sample */ - } else { - - if (lirc->gap) { - int gap_sample; - - lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(), - lirc->gap_start)); - - /* Convert to ms and cap by LIRC_VALUE_MASK */ - do_div(lirc->gap_duration, 1000); - lirc->gap_duration = min(lirc->gap_duration, - (u64)LIRC_VALUE_MASK); - - gap_sample = LIRC_SPACE(lirc->gap_duration); - lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, - (unsigned char *) &gap_sample); - lirc->gap = false; - } - - sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) : - LIRC_SPACE(ev.duration / 1000); - } - - lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, - (unsigned char *) &sample); - wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll); - - return 0; -} - -static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf, - size_t n, loff_t *ppos) -{ - struct lirc_codec *lirc; - struct ir_input_dev *ir_dev; - int *txbuf; /* buffer with values to transmit */ - int ret = 0, count; - - lirc = lirc_get_pdata(file); - if (!lirc) - return -EFAULT; - - if (n % sizeof(int)) - return -EINVAL; - - count = n / sizeof(int); - if (count > LIRCBUF_SIZE || count % 2 == 0) - return -EINVAL; - - txbuf = memdup_user(buf, n); - if (IS_ERR(txbuf)) - return PTR_ERR(txbuf); - - ir_dev = lirc->ir_dev; - if (!ir_dev) { - ret = -EFAULT; - goto out; - } - - if (ir_dev->props && ir_dev->props->tx_ir) - ret = ir_dev->props->tx_ir(ir_dev->props->priv, txbuf, (u32)n); - -out: - kfree(txbuf); - return ret; -} - -static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, - unsigned long __user arg) -{ - struct lirc_codec *lirc; - struct ir_input_dev *ir_dev; - int ret = 0; - void *drv_data; - __u32 val = 0, tmp; - - lirc = lirc_get_pdata(filep); - if (!lirc) - return -EFAULT; - - ir_dev = lirc->ir_dev; - if (!ir_dev || !ir_dev->props || !ir_dev->props->priv) - return -EFAULT; - - drv_data = ir_dev->props->priv; - - if (_IOC_DIR(cmd) & _IOC_WRITE) { - ret = get_user(val, (__u32 *)arg); - if (ret) - return ret; - } - - switch (cmd) { - - /* legacy support */ - case LIRC_GET_SEND_MODE: - val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK; - break; - - case LIRC_SET_SEND_MODE: - if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK)) - return -EINVAL; - return 0; - - /* TX settings */ - case LIRC_SET_TRANSMITTER_MASK: - if (!ir_dev->props->s_tx_mask) - return -EINVAL; - - return ir_dev->props->s_tx_mask(drv_data, val); - - case LIRC_SET_SEND_CARRIER: - if (!ir_dev->props->s_tx_carrier) - return -EINVAL; - - return ir_dev->props->s_tx_carrier(drv_data, val); - - case LIRC_SET_SEND_DUTY_CYCLE: - if (!ir_dev->props->s_tx_duty_cycle) - return -ENOSYS; - - if (val <= 0 || val >= 100) - return -EINVAL; - - return ir_dev->props->s_tx_duty_cycle(drv_data, val); - - /* RX settings */ - case LIRC_SET_REC_CARRIER: - if (!ir_dev->props->s_rx_carrier_range) - return -ENOSYS; - - if (val <= 0) - return -EINVAL; - - return ir_dev->props->s_rx_carrier_range(drv_data, - ir_dev->raw->lirc.carrier_low, val); - - case LIRC_SET_REC_CARRIER_RANGE: - if (val <= 0) - return -EINVAL; - - ir_dev->raw->lirc.carrier_low = val; - return 0; - - case LIRC_GET_REC_RESOLUTION: - val = ir_dev->props->rx_resolution; - break; - - case LIRC_SET_WIDEBAND_RECEIVER: - if (!ir_dev->props->s_learning_mode) - return -ENOSYS; - - return ir_dev->props->s_learning_mode(drv_data, !!val); - - case LIRC_SET_MEASURE_CARRIER_MODE: - if (!ir_dev->props->s_carrier_report) - return -ENOSYS; - - return ir_dev->props->s_carrier_report(drv_data, !!val); - - /* Generic timeout support */ - case LIRC_GET_MIN_TIMEOUT: - if (!ir_dev->props->max_timeout) - return -ENOSYS; - val = ir_dev->props->min_timeout / 1000; - break; - - case LIRC_GET_MAX_TIMEOUT: - if (!ir_dev->props->max_timeout) - return -ENOSYS; - val = ir_dev->props->max_timeout / 1000; - break; - - case LIRC_SET_REC_TIMEOUT: - if (!ir_dev->props->max_timeout) - return -ENOSYS; - - tmp = val * 1000; - - if (tmp < ir_dev->props->min_timeout || - tmp > ir_dev->props->max_timeout) - return -EINVAL; - - ir_dev->props->timeout = tmp; - break; - - case LIRC_SET_REC_TIMEOUT_REPORTS: - lirc->send_timeout_reports = !!val; - break; - - default: - return lirc_dev_fop_ioctl(filep, cmd, arg); - } - - if (_IOC_DIR(cmd) & _IOC_READ) - ret = put_user(val, (__u32 *)arg); - - return ret; -} - -static int ir_lirc_open(void *data) -{ - return 0; -} - -static void ir_lirc_close(void *data) -{ - return; -} - -static struct file_operations lirc_fops = { - .owner = THIS_MODULE, - .write = ir_lirc_transmit_ir, - .unlocked_ioctl = ir_lirc_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = ir_lirc_ioctl, -#endif - .read = lirc_dev_fop_read, - .poll = lirc_dev_fop_poll, - .open = lirc_dev_fop_open, - .release = lirc_dev_fop_close, - .llseek = no_llseek, -}; - -static int ir_lirc_register(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct lirc_driver *drv; - struct lirc_buffer *rbuf; - int rc = -ENOMEM; - unsigned long features; - - drv = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); - if (!drv) - return rc; - - rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL); - if (!rbuf) - goto rbuf_alloc_failed; - - rc = lirc_buffer_init(rbuf, sizeof(int), LIRCBUF_SIZE); - if (rc) - goto rbuf_init_failed; - - features = LIRC_CAN_REC_MODE2; - if (ir_dev->props->tx_ir) { - - features |= LIRC_CAN_SEND_PULSE; - if (ir_dev->props->s_tx_mask) - features |= LIRC_CAN_SET_TRANSMITTER_MASK; - if (ir_dev->props->s_tx_carrier) - features |= LIRC_CAN_SET_SEND_CARRIER; - - if (ir_dev->props->s_tx_duty_cycle) - features |= LIRC_CAN_SET_SEND_DUTY_CYCLE; - } - - if (ir_dev->props->s_rx_carrier_range) - features |= LIRC_CAN_SET_REC_CARRIER | - LIRC_CAN_SET_REC_CARRIER_RANGE; - - if (ir_dev->props->s_learning_mode) - features |= LIRC_CAN_USE_WIDEBAND_RECEIVER; - - if (ir_dev->props->s_carrier_report) - features |= LIRC_CAN_MEASURE_CARRIER; - - - if (ir_dev->props->max_timeout) - features |= LIRC_CAN_SET_REC_TIMEOUT; - - - snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", - ir_dev->driver_name); - drv->minor = -1; - drv->features = features; - drv->data = &ir_dev->raw->lirc; - drv->rbuf = rbuf; - drv->set_use_inc = &ir_lirc_open; - drv->set_use_dec = &ir_lirc_close; - drv->code_length = sizeof(struct ir_raw_event) * 8; - drv->fops = &lirc_fops; - drv->dev = &ir_dev->dev; - drv->owner = THIS_MODULE; - - drv->minor = lirc_register_driver(drv); - if (drv->minor < 0) { - rc = -ENODEV; - goto lirc_register_failed; - } - - ir_dev->raw->lirc.drv = drv; - ir_dev->raw->lirc.ir_dev = ir_dev; - return 0; - -lirc_register_failed: -rbuf_init_failed: - kfree(rbuf); -rbuf_alloc_failed: - kfree(drv); - - return rc; -} - -static int ir_lirc_unregister(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct lirc_codec *lirc = &ir_dev->raw->lirc; - - lirc_unregister_driver(lirc->drv->minor); - lirc_buffer_free(lirc->drv->rbuf); - kfree(lirc->drv); - - return 0; -} - -static struct ir_raw_handler lirc_handler = { - .protocols = IR_TYPE_LIRC, - .decode = ir_lirc_decode, - .raw_register = ir_lirc_register, - .raw_unregister = ir_lirc_unregister, -}; - -static int __init ir_lirc_codec_init(void) -{ - ir_raw_handler_register(&lirc_handler); - - printk(KERN_INFO "IR LIRC bridge handler initialized\n"); - return 0; -} - -static void __exit ir_lirc_codec_exit(void) -{ - ir_raw_handler_unregister(&lirc_handler); -} - -module_init(ir_lirc_codec_init); -module_exit(ir_lirc_codec_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jarod Wilson "); -MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); -MODULE_DESCRIPTION("LIRC IR handler bridge"); diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c deleted file mode 100644 index 70993f7..0000000 --- a/drivers/media/IR/ir-nec-decoder.c +++ /dev/null @@ -1,217 +0,0 @@ -/* ir-nec-decoder.c - handle NEC IR Pulse/Space protocol - * - * Copyright (C) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include "ir-core-priv.h" - -#define NEC_NBITS 32 -#define NEC_UNIT 562500 /* ns */ -#define NEC_HEADER_PULSE (16 * NEC_UNIT) -#define NECX_HEADER_PULSE (8 * NEC_UNIT) /* Less common NEC variant */ -#define NEC_HEADER_SPACE (8 * NEC_UNIT) -#define NEC_REPEAT_SPACE (4 * NEC_UNIT) -#define NEC_BIT_PULSE (1 * NEC_UNIT) -#define NEC_BIT_0_SPACE (1 * NEC_UNIT) -#define NEC_BIT_1_SPACE (3 * NEC_UNIT) -#define NEC_TRAILER_PULSE (1 * NEC_UNIT) -#define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */ -#define NECX_REPEAT_BITS 1 - -enum nec_state { - STATE_INACTIVE, - STATE_HEADER_SPACE, - STATE_BIT_PULSE, - STATE_BIT_SPACE, - STATE_TRAILER_PULSE, - STATE_TRAILER_SPACE, -}; - -/** - * ir_nec_decode() - Decode one NEC pulse or space - * @input_dev: the struct input_dev descriptor of the device - * @duration: the struct ir_raw_event descriptor of the pulse/space - * - * This function returns -EINVAL if the pulse violates the state machine - */ -static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct nec_dec *data = &ir_dev->raw->nec; - u32 scancode; - u8 address, not_address, command, not_command; - - if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC)) - return 0; - - if (!is_timing_event(ev)) { - if (ev.reset) - data->state = STATE_INACTIVE; - return 0; - } - - IR_dprintk(2, "NEC decode started at state %d (%uus %s)\n", - data->state, TO_US(ev.duration), TO_STR(ev.pulse)); - - switch (data->state) { - - case STATE_INACTIVE: - if (!ev.pulse) - break; - - if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2)) { - data->is_nec_x = false; - data->necx_repeat = false; - } else if (eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2)) - data->is_nec_x = true; - else - break; - - data->count = 0; - data->state = STATE_HEADER_SPACE; - return 0; - - case STATE_HEADER_SPACE: - if (ev.pulse) - break; - - if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT / 2)) { - data->state = STATE_BIT_PULSE; - return 0; - } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) { - ir_repeat(input_dev); - IR_dprintk(1, "Repeat last key\n"); - data->state = STATE_TRAILER_PULSE; - return 0; - } - - break; - - case STATE_BIT_PULSE: - if (!ev.pulse) - break; - - if (!eq_margin(ev.duration, NEC_BIT_PULSE, NEC_UNIT / 2)) - break; - - data->state = STATE_BIT_SPACE; - return 0; - - case STATE_BIT_SPACE: - if (ev.pulse) - break; - - if (data->necx_repeat && data->count == NECX_REPEAT_BITS && - geq_margin(ev.duration, - NEC_TRAILER_SPACE, NEC_UNIT / 2)) { - IR_dprintk(1, "Repeat last key\n"); - ir_repeat(input_dev); - data->state = STATE_INACTIVE; - return 0; - - } else if (data->count > NECX_REPEAT_BITS) - data->necx_repeat = false; - - data->bits <<= 1; - if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2)) - data->bits |= 1; - else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2)) - break; - data->count++; - - if (data->count == NEC_NBITS) - data->state = STATE_TRAILER_PULSE; - else - data->state = STATE_BIT_PULSE; - - return 0; - - case STATE_TRAILER_PULSE: - if (!ev.pulse) - break; - - if (!eq_margin(ev.duration, NEC_TRAILER_PULSE, NEC_UNIT / 2)) - break; - - data->state = STATE_TRAILER_SPACE; - return 0; - - case STATE_TRAILER_SPACE: - if (ev.pulse) - break; - - if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2)) - break; - - address = bitrev8((data->bits >> 24) & 0xff); - not_address = bitrev8((data->bits >> 16) & 0xff); - command = bitrev8((data->bits >> 8) & 0xff); - not_command = bitrev8((data->bits >> 0) & 0xff); - - if ((command ^ not_command) != 0xff) { - IR_dprintk(1, "NEC checksum error: received 0x%08x\n", - data->bits); - break; - } - - if ((address ^ not_address) != 0xff) { - /* Extended NEC */ - scancode = address << 16 | - not_address << 8 | - command; - IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode); - } else { - /* Normal NEC */ - scancode = address << 8 | command; - IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); - } - - if (data->is_nec_x) - data->necx_repeat = true; - - ir_keydown(input_dev, scancode, 0); - data->state = STATE_INACTIVE; - return 0; - } - - IR_dprintk(1, "NEC decode failed at state %d (%uus %s)\n", - data->state, TO_US(ev.duration), TO_STR(ev.pulse)); - data->state = STATE_INACTIVE; - return -EINVAL; -} - -static struct ir_raw_handler nec_handler = { - .protocols = IR_TYPE_NEC, - .decode = ir_nec_decode, -}; - -static int __init ir_nec_decode_init(void) -{ - ir_raw_handler_register(&nec_handler); - - printk(KERN_INFO "IR NEC protocol handler initialized\n"); - return 0; -} - -static void __exit ir_nec_decode_exit(void) -{ - ir_raw_handler_unregister(&nec_handler); -} - -module_init(ir_nec_decode_init); -module_exit(ir_nec_decode_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); -MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); -MODULE_DESCRIPTION("NEC IR protocol decoder"); diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c deleted file mode 100644 index a06a07e..0000000 --- a/drivers/media/IR/ir-raw-event.c +++ /dev/null @@ -1,382 +0,0 @@ -/* ir-raw-event.c - handle IR Pulse/Space event - * - * Copyright (C) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include "ir-core-priv.h" - -/* Define the max number of pulse/space transitions to buffer */ -#define MAX_IR_EVENT_SIZE 512 - -/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */ -static LIST_HEAD(ir_raw_client_list); - -/* Used to handle IR raw handler extensions */ -static DEFINE_MUTEX(ir_raw_handler_lock); -static LIST_HEAD(ir_raw_handler_list); -static u64 available_protocols; - -#ifdef MODULE -/* Used to load the decoders */ -static struct work_struct wq_load; -#endif - -static int ir_raw_event_thread(void *data) -{ - struct ir_raw_event ev; - struct ir_raw_handler *handler; - struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data; - int retval; - - while (!kthread_should_stop()) { - - spin_lock_irq(&raw->lock); - retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev)); - - if (!retval) { - set_current_state(TASK_INTERRUPTIBLE); - - if (kthread_should_stop()) - set_current_state(TASK_RUNNING); - - spin_unlock_irq(&raw->lock); - schedule(); - continue; - } - - spin_unlock_irq(&raw->lock); - - - BUG_ON(retval != sizeof(ev)); - - mutex_lock(&ir_raw_handler_lock); - list_for_each_entry(handler, &ir_raw_handler_list, list) - handler->decode(raw->input_dev, ev); - raw->prev_ev = ev; - mutex_unlock(&ir_raw_handler_lock); - } - - return 0; -} - -/** - * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders - * @input_dev: the struct input_dev device descriptor - * @ev: the struct ir_raw_event descriptor of the pulse/space - * - * This routine (which may be called from an interrupt context) stores a - * pulse/space duration for the raw ir decoding state machines. Pulses are - * signalled as positive values and spaces as negative values. A zero value - * will reset the decoding state machines. - */ -int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev) -{ - struct ir_input_dev *ir = input_get_drvdata(input_dev); - - if (!ir->raw) - return -EINVAL; - - IR_dprintk(2, "sample: (%05dus %s)\n", - TO_US(ev->duration), TO_STR(ev->pulse)); - - if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) - return -ENOMEM; - - return 0; -} -EXPORT_SYMBOL_GPL(ir_raw_event_store); - -/** - * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space - * @input_dev: the struct input_dev device descriptor - * @type: the type of the event that has occurred - * - * This routine (which may be called from an interrupt context) is used to - * store the beginning of an ir pulse or space (or the start/end of ir - * reception) for the raw ir decoding state machines. This is used by - * hardware which does not provide durations directly but only interrupts - * (or similar events) on state change. - */ -int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type) -{ - struct ir_input_dev *ir = input_get_drvdata(input_dev); - ktime_t now; - s64 delta; /* ns */ - struct ir_raw_event ev; - int rc = 0; - - if (!ir->raw) - return -EINVAL; - - now = ktime_get(); - delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event)); - - /* Check for a long duration since last event or if we're - * being called for the first time, note that delta can't - * possibly be negative. - */ - ev.duration = 0; - if (delta > IR_MAX_DURATION || !ir->raw->last_type) - type |= IR_START_EVENT; - else - ev.duration = delta; - - if (type & IR_START_EVENT) - ir_raw_event_reset(input_dev); - else if (ir->raw->last_type & IR_SPACE) { - ev.pulse = false; - rc = ir_raw_event_store(input_dev, &ev); - } else if (ir->raw->last_type & IR_PULSE) { - ev.pulse = true; - rc = ir_raw_event_store(input_dev, &ev); - } else - return 0; - - ir->raw->last_event = now; - ir->raw->last_type = type; - return rc; -} -EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); - -/** - * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing - * @input_dev: the struct input_dev device descriptor - * @type: the type of the event that has occurred - * - * This routine (which may be called from an interrupt context) works - * in similiar manner to ir_raw_event_store_edge. - * This routine is intended for devices with limited internal buffer - * It automerges samples of same type, and handles timeouts - */ -int ir_raw_event_store_with_filter(struct input_dev *input_dev, - struct ir_raw_event *ev) -{ - struct ir_input_dev *ir = input_get_drvdata(input_dev); - struct ir_raw_event_ctrl *raw = ir->raw; - - if (!raw || !ir->props) - return -EINVAL; - - /* Ignore spaces in idle mode */ - if (ir->idle && !ev->pulse) - return 0; - else if (ir->idle) - ir_raw_event_set_idle(input_dev, false); - - if (!raw->this_ev.duration) { - raw->this_ev = *ev; - } else if (ev->pulse == raw->this_ev.pulse) { - raw->this_ev.duration += ev->duration; - } else { - ir_raw_event_store(input_dev, &raw->this_ev); - raw->this_ev = *ev; - } - - /* Enter idle mode if nessesary */ - if (!ev->pulse && ir->props->timeout && - raw->this_ev.duration >= ir->props->timeout) { - ir_raw_event_set_idle(input_dev, true); - } - return 0; -} -EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter); - -/** - * ir_raw_event_set_idle() - hint the ir core if device is receiving - * IR data or not - * @input_dev: the struct input_dev device descriptor - * @idle: the hint value - */ -void ir_raw_event_set_idle(struct input_dev *input_dev, bool idle) -{ - struct ir_input_dev *ir = input_get_drvdata(input_dev); - struct ir_raw_event_ctrl *raw = ir->raw; - - if (!ir->props || !ir->raw) - return; - - IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave"); - - if (idle) { - raw->this_ev.timeout = true; - ir_raw_event_store(input_dev, &raw->this_ev); - init_ir_raw_event(&raw->this_ev); - } - - if (ir->props->s_idle) - ir->props->s_idle(ir->props->priv, idle); - ir->idle = idle; -} -EXPORT_SYMBOL_GPL(ir_raw_event_set_idle); - -/** - * ir_raw_event_handle() - schedules the decoding of stored ir data - * @input_dev: the struct input_dev device descriptor - * - * This routine will signal the workqueue to start decoding stored ir data. - */ -void ir_raw_event_handle(struct input_dev *input_dev) -{ - struct ir_input_dev *ir = input_get_drvdata(input_dev); - unsigned long flags; - - if (!ir->raw) - return; - - spin_lock_irqsave(&ir->raw->lock, flags); - wake_up_process(ir->raw->thread); - spin_unlock_irqrestore(&ir->raw->lock, flags); -} -EXPORT_SYMBOL_GPL(ir_raw_event_handle); - -/* used internally by the sysfs interface */ -u64 -ir_raw_get_allowed_protocols() -{ - u64 protocols; - mutex_lock(&ir_raw_handler_lock); - protocols = available_protocols; - mutex_unlock(&ir_raw_handler_lock); - return protocols; -} - -/* - * Used to (un)register raw event clients - */ -int ir_raw_event_register(struct input_dev *input_dev) -{ - struct ir_input_dev *ir = input_get_drvdata(input_dev); - int rc; - struct ir_raw_handler *handler; - - ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); - if (!ir->raw) - return -ENOMEM; - - ir->raw->input_dev = input_dev; - - ir->raw->enabled_protocols = ~0; - rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, - GFP_KERNEL); - if (rc < 0) { - kfree(ir->raw); - ir->raw = NULL; - return rc; - } - - spin_lock_init(&ir->raw->lock); - ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw, - "rc%u", (unsigned int)ir->devno); - - if (IS_ERR(ir->raw->thread)) { - int ret = PTR_ERR(ir->raw->thread); - - kfree(ir->raw); - ir->raw = NULL; - return ret; - } - - mutex_lock(&ir_raw_handler_lock); - list_add_tail(&ir->raw->list, &ir_raw_client_list); - list_for_each_entry(handler, &ir_raw_handler_list, list) - if (handler->raw_register) - handler->raw_register(ir->raw->input_dev); - mutex_unlock(&ir_raw_handler_lock); - - return 0; -} - -void ir_raw_event_unregister(struct input_dev *input_dev) -{ - struct ir_input_dev *ir = input_get_drvdata(input_dev); - struct ir_raw_handler *handler; - - if (!ir->raw) - return; - - kthread_stop(ir->raw->thread); - - mutex_lock(&ir_raw_handler_lock); - list_del(&ir->raw->list); - list_for_each_entry(handler, &ir_raw_handler_list, list) - if (handler->raw_unregister) - handler->raw_unregister(ir->raw->input_dev); - mutex_unlock(&ir_raw_handler_lock); - - kfifo_free(&ir->raw->kfifo); - kfree(ir->raw); - ir->raw = NULL; -} - -/* - * Extension interface - used to register the IR decoders - */ - -int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) -{ - struct ir_raw_event_ctrl *raw; - - mutex_lock(&ir_raw_handler_lock); - list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); - if (ir_raw_handler->raw_register) - list_for_each_entry(raw, &ir_raw_client_list, list) - ir_raw_handler->raw_register(raw->input_dev); - available_protocols |= ir_raw_handler->protocols; - mutex_unlock(&ir_raw_handler_lock); - - return 0; -} -EXPORT_SYMBOL(ir_raw_handler_register); - -void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) -{ - struct ir_raw_event_ctrl *raw; - - mutex_lock(&ir_raw_handler_lock); - list_del(&ir_raw_handler->list); - if (ir_raw_handler->raw_unregister) - list_for_each_entry(raw, &ir_raw_client_list, list) - ir_raw_handler->raw_unregister(raw->input_dev); - available_protocols &= ~ir_raw_handler->protocols; - mutex_unlock(&ir_raw_handler_lock); -} -EXPORT_SYMBOL(ir_raw_handler_unregister); - -#ifdef MODULE -static void init_decoders(struct work_struct *work) -{ - /* Load the decoder modules */ - - load_nec_decode(); - load_rc5_decode(); - load_rc6_decode(); - load_jvc_decode(); - load_sony_decode(); - load_lirc_codec(); - - /* If needed, we may later add some init code. In this case, - it is needed to change the CONFIG_MODULE test at ir-core.h - */ -} -#endif - -void ir_raw_init(void) -{ -#ifdef MODULE - INIT_WORK(&wq_load, init_decoders); - schedule_work(&wq_load); -#endif -} diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c deleted file mode 100644 index 572ed4c..0000000 --- a/drivers/media/IR/ir-rc5-decoder.c +++ /dev/null @@ -1,190 +0,0 @@ -/* ir-rc5-decoder.c - handle RC5(x) IR Pulse/Space protocol - * - * Copyright (C) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -/* - * This code handles 14 bits RC5 protocols and 20 bits RC5x protocols. - * There are other variants that use a different number of bits. - * This is currently unsupported. - * It considers a carrier of 36 kHz, with a total of 14/20 bits, where - * the first two bits are start bits, and a third one is a filing bit - */ - -#include "ir-core-priv.h" - -#define RC5_NBITS 14 -#define RC5X_NBITS 20 -#define CHECK_RC5X_NBITS 8 -#define RC5_UNIT 888888 /* ns */ -#define RC5_BIT_START (1 * RC5_UNIT) -#define RC5_BIT_END (1 * RC5_UNIT) -#define RC5X_SPACE (4 * RC5_UNIT) - -enum rc5_state { - STATE_INACTIVE, - STATE_BIT_START, - STATE_BIT_END, - STATE_CHECK_RC5X, - STATE_FINISHED, -}; - -/** - * ir_rc5_decode() - Decode one RC-5 pulse or space - * @input_dev: the struct input_dev descriptor of the device - * @ev: the struct ir_raw_event descriptor of the pulse/space - * - * This function returns -EINVAL if the pulse violates the state machine - */ -static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct rc5_dec *data = &ir_dev->raw->rc5; - u8 toggle; - u32 scancode; - - if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5)) - return 0; - - if (!is_timing_event(ev)) { - if (ev.reset) - data->state = STATE_INACTIVE; - return 0; - } - - if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2)) - goto out; - -again: - IR_dprintk(2, "RC5(x) decode started at state %i (%uus %s)\n", - data->state, TO_US(ev.duration), TO_STR(ev.pulse)); - - if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2)) - return 0; - - switch (data->state) { - - case STATE_INACTIVE: - if (!ev.pulse) - break; - - data->state = STATE_BIT_START; - data->count = 1; - /* We just need enough bits to get to STATE_CHECK_RC5X */ - data->wanted_bits = RC5X_NBITS; - decrease_duration(&ev, RC5_BIT_START); - goto again; - - case STATE_BIT_START: - if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2)) - break; - - data->bits <<= 1; - if (!ev.pulse) - data->bits |= 1; - data->count++; - data->state = STATE_BIT_END; - return 0; - - case STATE_BIT_END: - if (!is_transition(&ev, &ir_dev->raw->prev_ev)) - break; - - if (data->count == data->wanted_bits) - data->state = STATE_FINISHED; - else if (data->count == CHECK_RC5X_NBITS) - data->state = STATE_CHECK_RC5X; - else - data->state = STATE_BIT_START; - - decrease_duration(&ev, RC5_BIT_END); - goto again; - - case STATE_CHECK_RC5X: - if (!ev.pulse && geq_margin(ev.duration, RC5X_SPACE, RC5_UNIT / 2)) { - /* RC5X */ - data->wanted_bits = RC5X_NBITS; - decrease_duration(&ev, RC5X_SPACE); - } else { - /* RC5 */ - data->wanted_bits = RC5_NBITS; - } - data->state = STATE_BIT_START; - goto again; - - case STATE_FINISHED: - if (ev.pulse) - break; - - if (data->wanted_bits == RC5X_NBITS) { - /* RC5X */ - u8 xdata, command, system; - xdata = (data->bits & 0x0003F) >> 0; - command = (data->bits & 0x00FC0) >> 6; - system = (data->bits & 0x1F000) >> 12; - toggle = (data->bits & 0x20000) ? 1 : 0; - command += (data->bits & 0x01000) ? 0 : 0x40; - scancode = system << 16 | command << 8 | xdata; - - IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n", - scancode, toggle); - - } else { - /* RC5 */ - u8 command, system; - command = (data->bits & 0x0003F) >> 0; - system = (data->bits & 0x007C0) >> 6; - toggle = (data->bits & 0x00800) ? 1 : 0; - command += (data->bits & 0x01000) ? 0 : 0x40; - scancode = system << 8 | command; - - IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n", - scancode, toggle); - } - - ir_keydown(input_dev, scancode, toggle); - data->state = STATE_INACTIVE; - return 0; - } - -out: - IR_dprintk(1, "RC5(x) decode failed at state %i (%uus %s)\n", - data->state, TO_US(ev.duration), TO_STR(ev.pulse)); - data->state = STATE_INACTIVE; - return -EINVAL; -} - -static struct ir_raw_handler rc5_handler = { - .protocols = IR_TYPE_RC5, - .decode = ir_rc5_decode, -}; - -static int __init ir_rc5_decode_init(void) -{ - ir_raw_handler_register(&rc5_handler); - - printk(KERN_INFO "IR RC5(x) protocol handler initialized\n"); - return 0; -} - -static void __exit ir_rc5_decode_exit(void) -{ - ir_raw_handler_unregister(&rc5_handler); -} - -module_init(ir_rc5_decode_init); -module_exit(ir_rc5_decode_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); -MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); -MODULE_DESCRIPTION("RC5(x) IR protocol decoder"); diff --git a/drivers/media/IR/ir-rc5-sz-decoder.c b/drivers/media/IR/ir-rc5-sz-decoder.c deleted file mode 100644 index 7c41350..0000000 --- a/drivers/media/IR/ir-rc5-sz-decoder.c +++ /dev/null @@ -1,154 +0,0 @@ -/* ir-rc5-sz-decoder.c - handle RC5 Streamzap IR Pulse/Space protocol - * - * Copyright (C) 2010 by Mauro Carvalho Chehab - * Copyright (C) 2010 by Jarod Wilson - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -/* - * This code handles the 15 bit RC5-ish protocol used by the Streamzap - * PC Remote. - * It considers a carrier of 36 kHz, with a total of 15 bits, where - * the first two bits are start bits, and a third one is a filing bit - */ - -#include "ir-core-priv.h" - -#define RC5_SZ_NBITS 15 -#define RC5_UNIT 888888 /* ns */ -#define RC5_BIT_START (1 * RC5_UNIT) -#define RC5_BIT_END (1 * RC5_UNIT) - -enum rc5_sz_state { - STATE_INACTIVE, - STATE_BIT_START, - STATE_BIT_END, - STATE_FINISHED, -}; - -/** - * ir_rc5_sz_decode() - Decode one RC-5 Streamzap pulse or space - * @input_dev: the struct input_dev descriptor of the device - * @ev: the struct ir_raw_event descriptor of the pulse/space - * - * This function returns -EINVAL if the pulse violates the state machine - */ -static int ir_rc5_sz_decode(struct input_dev *input_dev, struct ir_raw_event ev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct rc5_sz_dec *data = &ir_dev->raw->rc5_sz; - u8 toggle, command, system; - u32 scancode; - - if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5_SZ)) - return 0; - - if (!is_timing_event(ev)) { - if (ev.reset) - data->state = STATE_INACTIVE; - return 0; - } - - if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2)) - goto out; - -again: - IR_dprintk(2, "RC5-sz decode started at state %i (%uus %s)\n", - data->state, TO_US(ev.duration), TO_STR(ev.pulse)); - - if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2)) - return 0; - - switch (data->state) { - - case STATE_INACTIVE: - if (!ev.pulse) - break; - - data->state = STATE_BIT_START; - data->count = 1; - data->wanted_bits = RC5_SZ_NBITS; - decrease_duration(&ev, RC5_BIT_START); - goto again; - - case STATE_BIT_START: - if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2)) - break; - - data->bits <<= 1; - if (!ev.pulse) - data->bits |= 1; - data->count++; - data->state = STATE_BIT_END; - return 0; - - case STATE_BIT_END: - if (!is_transition(&ev, &ir_dev->raw->prev_ev)) - break; - - if (data->count == data->wanted_bits) - data->state = STATE_FINISHED; - else - data->state = STATE_BIT_START; - - decrease_duration(&ev, RC5_BIT_END); - goto again; - - case STATE_FINISHED: - if (ev.pulse) - break; - - /* RC5-sz */ - command = (data->bits & 0x0003F) >> 0; - system = (data->bits & 0x02FC0) >> 6; - toggle = (data->bits & 0x01000) ? 1 : 0; - scancode = system << 6 | command; - - IR_dprintk(1, "RC5-sz scancode 0x%04x (toggle: %u)\n", - scancode, toggle); - - ir_keydown(input_dev, scancode, toggle); - data->state = STATE_INACTIVE; - return 0; - } - -out: - IR_dprintk(1, "RC5-sz decode failed at state %i (%uus %s)\n", - data->state, TO_US(ev.duration), TO_STR(ev.pulse)); - data->state = STATE_INACTIVE; - return -EINVAL; -} - -static struct ir_raw_handler rc5_sz_handler = { - .protocols = IR_TYPE_RC5_SZ, - .decode = ir_rc5_sz_decode, -}; - -static int __init ir_rc5_sz_decode_init(void) -{ - ir_raw_handler_register(&rc5_sz_handler); - - printk(KERN_INFO "IR RC5 (streamzap) protocol handler initialized\n"); - return 0; -} - -static void __exit ir_rc5_sz_decode_exit(void) -{ - ir_raw_handler_unregister(&rc5_sz_handler); -} - -module_init(ir_rc5_sz_decode_init); -module_exit(ir_rc5_sz_decode_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jarod Wilson "); -MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); -MODULE_DESCRIPTION("RC5 (streamzap) IR protocol decoder"); diff --git a/drivers/media/IR/ir-rc6-decoder.c b/drivers/media/IR/ir-rc6-decoder.c deleted file mode 100644 index d25da91..0000000 --- a/drivers/media/IR/ir-rc6-decoder.c +++ /dev/null @@ -1,281 +0,0 @@ -/* ir-rc6-decoder.c - A decoder for the RC6 IR protocol - * - * Copyright (C) 2010 by David Härdeman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "ir-core-priv.h" - -/* - * This decoder currently supports: - * RC6-0-16 (standard toggle bit in header) - * RC6-6A-24 (no toggle bit) - * RC6-6A-32 (MCE version with toggle bit in body) - */ - -#define RC6_UNIT 444444 /* us */ -#define RC6_HEADER_NBITS 4 /* not including toggle bit */ -#define RC6_0_NBITS 16 -#define RC6_6A_SMALL_NBITS 24 -#define RC6_6A_LARGE_NBITS 32 -#define RC6_PREFIX_PULSE (6 * RC6_UNIT) -#define RC6_PREFIX_SPACE (2 * RC6_UNIT) -#define RC6_BIT_START (1 * RC6_UNIT) -#define RC6_BIT_END (1 * RC6_UNIT) -#define RC6_TOGGLE_START (2 * RC6_UNIT) -#define RC6_TOGGLE_END (2 * RC6_UNIT) -#define RC6_MODE_MASK 0x07 /* for the header bits */ -#define RC6_STARTBIT_MASK 0x08 /* for the header bits */ -#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ - -enum rc6_mode { - RC6_MODE_0, - RC6_MODE_6A, - RC6_MODE_UNKNOWN, -}; - -enum rc6_state { - STATE_INACTIVE, - STATE_PREFIX_SPACE, - STATE_HEADER_BIT_START, - STATE_HEADER_BIT_END, - STATE_TOGGLE_START, - STATE_TOGGLE_END, - STATE_BODY_BIT_START, - STATE_BODY_BIT_END, - STATE_FINISHED, -}; - -static enum rc6_mode rc6_mode(struct rc6_dec *data) -{ - switch (data->header & RC6_MODE_MASK) { - case 0: - return RC6_MODE_0; - case 6: - if (!data->toggle) - return RC6_MODE_6A; - /* fall through */ - default: - return RC6_MODE_UNKNOWN; - } -} - -/** - * ir_rc6_decode() - Decode one RC6 pulse or space - * @input_dev: the struct input_dev descriptor of the device - * @ev: the struct ir_raw_event descriptor of the pulse/space - * - * This function returns -EINVAL if the pulse violates the state machine - */ -static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct rc6_dec *data = &ir_dev->raw->rc6; - u32 scancode; - u8 toggle; - - if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6)) - return 0; - - if (!is_timing_event(ev)) { - if (ev.reset) - data->state = STATE_INACTIVE; - return 0; - } - - if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) - goto out; - -again: - IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n", - data->state, TO_US(ev.duration), TO_STR(ev.pulse)); - - if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) - return 0; - - switch (data->state) { - - case STATE_INACTIVE: - if (!ev.pulse) - break; - - /* Note: larger margin on first pulse since each RC6_UNIT - is quite short and some hardware takes some time to - adjust to the signal */ - if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT)) - break; - - data->state = STATE_PREFIX_SPACE; - data->count = 0; - return 0; - - case STATE_PREFIX_SPACE: - if (ev.pulse) - break; - - if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2)) - break; - - data->state = STATE_HEADER_BIT_START; - return 0; - - case STATE_HEADER_BIT_START: - if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) - break; - - data->header <<= 1; - if (ev.pulse) - data->header |= 1; - data->count++; - data->state = STATE_HEADER_BIT_END; - return 0; - - case STATE_HEADER_BIT_END: - if (!is_transition(&ev, &ir_dev->raw->prev_ev)) - break; - - if (data->count == RC6_HEADER_NBITS) - data->state = STATE_TOGGLE_START; - else - data->state = STATE_HEADER_BIT_START; - - decrease_duration(&ev, RC6_BIT_END); - goto again; - - case STATE_TOGGLE_START: - if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2)) - break; - - data->toggle = ev.pulse; - data->state = STATE_TOGGLE_END; - return 0; - - case STATE_TOGGLE_END: - if (!is_transition(&ev, &ir_dev->raw->prev_ev) || - !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2)) - break; - - if (!(data->header & RC6_STARTBIT_MASK)) { - IR_dprintk(1, "RC6 invalid start bit\n"); - break; - } - - data->state = STATE_BODY_BIT_START; - decrease_duration(&ev, RC6_TOGGLE_END); - data->count = 0; - - switch (rc6_mode(data)) { - case RC6_MODE_0: - data->wanted_bits = RC6_0_NBITS; - break; - case RC6_MODE_6A: - /* This might look weird, but we basically - check the value of the first body bit to - determine the number of bits in mode 6A */ - if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) || - geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) - data->wanted_bits = RC6_6A_LARGE_NBITS; - else - data->wanted_bits = RC6_6A_SMALL_NBITS; - break; - default: - IR_dprintk(1, "RC6 unknown mode\n"); - goto out; - } - goto again; - - case STATE_BODY_BIT_START: - if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) - break; - - data->body <<= 1; - if (ev.pulse) - data->body |= 1; - data->count++; - data->state = STATE_BODY_BIT_END; - return 0; - - case STATE_BODY_BIT_END: - if (!is_transition(&ev, &ir_dev->raw->prev_ev)) - break; - - if (data->count == data->wanted_bits) - data->state = STATE_FINISHED; - else - data->state = STATE_BODY_BIT_START; - - decrease_duration(&ev, RC6_BIT_END); - goto again; - - case STATE_FINISHED: - if (ev.pulse) - break; - - switch (rc6_mode(data)) { - case RC6_MODE_0: - scancode = data->body & 0xffff; - toggle = data->toggle; - IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n", - scancode, toggle); - break; - case RC6_MODE_6A: - if (data->wanted_bits == RC6_6A_LARGE_NBITS) { - toggle = data->body & RC6_6A_MCE_TOGGLE_MASK ? 1 : 0; - scancode = data->body & ~RC6_6A_MCE_TOGGLE_MASK; - } else { - toggle = 0; - scancode = data->body & 0xffffff; - } - - IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n", - scancode, toggle); - break; - default: - IR_dprintk(1, "RC6 unknown mode\n"); - goto out; - } - - ir_keydown(input_dev, scancode, toggle); - data->state = STATE_INACTIVE; - return 0; - } - -out: - IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n", - data->state, TO_US(ev.duration), TO_STR(ev.pulse)); - data->state = STATE_INACTIVE; - return -EINVAL; -} - -static struct ir_raw_handler rc6_handler = { - .protocols = IR_TYPE_RC6, - .decode = ir_rc6_decode, -}; - -static int __init ir_rc6_decode_init(void) -{ - ir_raw_handler_register(&rc6_handler); - - printk(KERN_INFO "IR RC6 protocol handler initialized\n"); - return 0; -} - -static void __exit ir_rc6_decode_exit(void) -{ - ir_raw_handler_unregister(&rc6_handler); -} - -module_init(ir_rc6_decode_init); -module_exit(ir_rc6_decode_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("David Härdeman "); -MODULE_DESCRIPTION("RC6 IR protocol decoder"); diff --git a/drivers/media/IR/ir-sony-decoder.c b/drivers/media/IR/ir-sony-decoder.c deleted file mode 100644 index 2d15730..0000000 --- a/drivers/media/IR/ir-sony-decoder.c +++ /dev/null @@ -1,182 +0,0 @@ -/* ir-sony-decoder.c - handle Sony IR Pulse/Space protocol - * - * Copyright (C) 2010 by David Härdeman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include "ir-core-priv.h" - -#define SONY_UNIT 600000 /* ns */ -#define SONY_HEADER_PULSE (4 * SONY_UNIT) -#define SONY_HEADER_SPACE (1 * SONY_UNIT) -#define SONY_BIT_0_PULSE (1 * SONY_UNIT) -#define SONY_BIT_1_PULSE (2 * SONY_UNIT) -#define SONY_BIT_SPACE (1 * SONY_UNIT) -#define SONY_TRAILER_SPACE (10 * SONY_UNIT) /* minimum */ - -enum sony_state { - STATE_INACTIVE, - STATE_HEADER_SPACE, - STATE_BIT_PULSE, - STATE_BIT_SPACE, - STATE_FINISHED, -}; - -/** - * ir_sony_decode() - Decode one Sony pulse or space - * @input_dev: the struct input_dev descriptor of the device - * @ev: the struct ir_raw_event descriptor of the pulse/space - * - * This function returns -EINVAL if the pulse violates the state machine - */ -static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct sony_dec *data = &ir_dev->raw->sony; - u32 scancode; - u8 device, subdevice, function; - - if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY)) - return 0; - - if (!is_timing_event(ev)) { - if (ev.reset) - data->state = STATE_INACTIVE; - return 0; - } - - if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2)) - goto out; - - IR_dprintk(2, "Sony decode started at state %d (%uus %s)\n", - data->state, TO_US(ev.duration), TO_STR(ev.pulse)); - - switch (data->state) { - - case STATE_INACTIVE: - if (!ev.pulse) - break; - - if (!eq_margin(ev.duration, SONY_HEADER_PULSE, SONY_UNIT / 2)) - break; - - data->count = 0; - data->state = STATE_HEADER_SPACE; - return 0; - - case STATE_HEADER_SPACE: - if (ev.pulse) - break; - - if (!eq_margin(ev.duration, SONY_HEADER_SPACE, SONY_UNIT / 2)) - break; - - data->state = STATE_BIT_PULSE; - return 0; - - case STATE_BIT_PULSE: - if (!ev.pulse) - break; - - data->bits <<= 1; - if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2)) - data->bits |= 1; - else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2)) - break; - - data->count++; - data->state = STATE_BIT_SPACE; - return 0; - - case STATE_BIT_SPACE: - if (ev.pulse) - break; - - if (!geq_margin(ev.duration, SONY_BIT_SPACE, SONY_UNIT / 2)) - break; - - decrease_duration(&ev, SONY_BIT_SPACE); - - if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2)) { - data->state = STATE_BIT_PULSE; - return 0; - } - - data->state = STATE_FINISHED; - /* Fall through */ - - case STATE_FINISHED: - if (ev.pulse) - break; - - if (!geq_margin(ev.duration, SONY_TRAILER_SPACE, SONY_UNIT / 2)) - break; - - switch (data->count) { - case 12: - device = bitrev8((data->bits << 3) & 0xF8); - subdevice = 0; - function = bitrev8((data->bits >> 4) & 0xFE); - break; - case 15: - device = bitrev8((data->bits >> 0) & 0xFF); - subdevice = 0; - function = bitrev8((data->bits >> 7) & 0xFD); - break; - case 20: - device = bitrev8((data->bits >> 5) & 0xF8); - subdevice = bitrev8((data->bits >> 0) & 0xFF); - function = bitrev8((data->bits >> 12) & 0xFE); - break; - default: - IR_dprintk(1, "Sony invalid bitcount %u\n", data->count); - goto out; - } - - scancode = device << 16 | subdevice << 8 | function; - IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode); - ir_keydown(input_dev, scancode, 0); - data->state = STATE_INACTIVE; - return 0; - } - -out: - IR_dprintk(1, "Sony decode failed at state %d (%uus %s)\n", - data->state, TO_US(ev.duration), TO_STR(ev.pulse)); - data->state = STATE_INACTIVE; - return -EINVAL; -} - -static struct ir_raw_handler sony_handler = { - .protocols = IR_TYPE_SONY, - .decode = ir_sony_decode, -}; - -static int __init ir_sony_decode_init(void) -{ - ir_raw_handler_register(&sony_handler); - - printk(KERN_INFO "IR Sony protocol handler initialized\n"); - return 0; -} - -static void __exit ir_sony_decode_exit(void) -{ - ir_raw_handler_unregister(&sony_handler); -} - -module_init(ir_sony_decode_init); -module_exit(ir_sony_decode_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("David Härdeman "); -MODULE_DESCRIPTION("Sony IR protocol decoder"); diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c deleted file mode 100644 index 38423a8..0000000 --- a/drivers/media/IR/ir-sysfs.c +++ /dev/null @@ -1,362 +0,0 @@ -/* ir-sysfs.c - sysfs interface for RC devices (/sys/class/rc) - * - * Copyright (C) 2009-2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include "ir-core-priv.h" - -#define IRRCV_NUM_DEVICES 256 - -/* bit array to represent IR sysfs device number */ -static unsigned long ir_core_dev_number; - -/* class for /sys/class/rc */ -static char *ir_devnode(struct device *dev, mode_t *mode) -{ - return kasprintf(GFP_KERNEL, "rc/%s", dev_name(dev)); -} - -static struct class ir_input_class = { - .name = "rc", - .devnode = ir_devnode, -}; - -static struct { - u64 type; - char *name; -} proto_names[] = { - { IR_TYPE_UNKNOWN, "unknown" }, - { IR_TYPE_RC5, "rc-5" }, - { IR_TYPE_NEC, "nec" }, - { IR_TYPE_RC6, "rc-6" }, - { IR_TYPE_JVC, "jvc" }, - { IR_TYPE_SONY, "sony" }, - { IR_TYPE_RC5_SZ, "rc-5-sz" }, - { IR_TYPE_LIRC, "lirc" }, -}; - -#define PROTO_NONE "none" - -/** - * show_protocols() - shows the current IR protocol(s) - * @d: the device descriptor - * @mattr: the device attribute struct (unused) - * @buf: a pointer to the output buffer - * - * This routine is a callback routine for input read the IR protocol type(s). - * it is trigged by reading /sys/class/rc/rc?/protocols. - * It returns the protocol names of supported protocols. - * Enabled protocols are printed in brackets. - */ -static ssize_t show_protocols(struct device *d, - struct device_attribute *mattr, char *buf) -{ - struct ir_input_dev *ir_dev = dev_get_drvdata(d); - u64 allowed, enabled; - char *tmp = buf; - int i; - - /* Device is being removed */ - if (!ir_dev) - return -EINVAL; - - if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { - enabled = ir_dev->rc_tab.ir_type; - allowed = ir_dev->props->allowed_protos; - } else if (ir_dev->raw) { - enabled = ir_dev->raw->enabled_protocols; - allowed = ir_raw_get_allowed_protocols(); - } else - return sprintf(tmp, "[builtin]\n"); - - IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", - (long long)allowed, - (long long)enabled); - - for (i = 0; i < ARRAY_SIZE(proto_names); i++) { - if (allowed & enabled & proto_names[i].type) - tmp += sprintf(tmp, "[%s] ", proto_names[i].name); - else if (allowed & proto_names[i].type) - tmp += sprintf(tmp, "%s ", proto_names[i].name); - } - - if (tmp != buf) - tmp--; - *tmp = '\n'; - return tmp + 1 - buf; -} - -/** - * store_protocols() - changes the current IR protocol(s) - * @d: the device descriptor - * @mattr: the device attribute struct (unused) - * @buf: a pointer to the input buffer - * @len: length of the input buffer - * - * This routine is a callback routine for changing the IR protocol type. - * It is trigged by writing to /sys/class/rc/rc?/protocols. - * Writing "+proto" will add a protocol to the list of enabled protocols. - * Writing "-proto" will remove a protocol from the list of enabled protocols. - * Writing "proto" will enable only "proto". - * Writing "none" will disable all protocols. - * Returns -EINVAL if an invalid protocol combination or unknown protocol name - * is used, otherwise @len. - */ -static ssize_t store_protocols(struct device *d, - struct device_attribute *mattr, - const char *data, - size_t len) -{ - struct ir_input_dev *ir_dev = dev_get_drvdata(d); - bool enable, disable; - const char *tmp; - u64 type; - u64 mask; - int rc, i, count = 0; - unsigned long flags; - - /* Device is being removed */ - if (!ir_dev) - return -EINVAL; - - if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) - type = ir_dev->rc_tab.ir_type; - else if (ir_dev->raw) - type = ir_dev->raw->enabled_protocols; - else { - IR_dprintk(1, "Protocol switching not supported\n"); - return -EINVAL; - } - - while ((tmp = strsep((char **) &data, " \n")) != NULL) { - if (!*tmp) - break; - - if (*tmp == '+') { - enable = true; - disable = false; - tmp++; - } else if (*tmp == '-') { - enable = false; - disable = true; - tmp++; - } else { - enable = false; - disable = false; - } - - if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) { - tmp += sizeof(PROTO_NONE); - mask = 0; - count++; - } else { - for (i = 0; i < ARRAY_SIZE(proto_names); i++) { - if (!strncasecmp(tmp, proto_names[i].name, strlen(proto_names[i].name))) { - tmp += strlen(proto_names[i].name); - mask = proto_names[i].type; - break; - } - } - if (i == ARRAY_SIZE(proto_names)) { - IR_dprintk(1, "Unknown protocol: '%s'\n", tmp); - return -EINVAL; - } - count++; - } - - if (enable) - type |= mask; - else if (disable) - type &= ~mask; - else - type = mask; - } - - if (!count) { - IR_dprintk(1, "Protocol not specified\n"); - return -EINVAL; - } - - if (ir_dev->props && ir_dev->props->change_protocol) { - rc = ir_dev->props->change_protocol(ir_dev->props->priv, - type); - if (rc < 0) { - IR_dprintk(1, "Error setting protocols to 0x%llx\n", - (long long)type); - return -EINVAL; - } - } - - if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { - spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); - ir_dev->rc_tab.ir_type = type; - spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); - } else { - ir_dev->raw->enabled_protocols = type; - } - - IR_dprintk(1, "Current protocol(s): 0x%llx\n", - (long long)type); - - return len; -} - -#define ADD_HOTPLUG_VAR(fmt, val...) \ - do { \ - int err = add_uevent_var(env, fmt, val); \ - if (err) \ - return err; \ - } while (0) - -static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) -{ - struct ir_input_dev *ir_dev = dev_get_drvdata(device); - - if (ir_dev->rc_tab.name) - ADD_HOTPLUG_VAR("NAME=%s", ir_dev->rc_tab.name); - if (ir_dev->driver_name) - ADD_HOTPLUG_VAR("DRV_NAME=%s", ir_dev->driver_name); - - return 0; -} - -/* - * Static device attribute struct with the sysfs attributes for IR's - */ -static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR, - show_protocols, store_protocols); - -static struct attribute *rc_dev_attrs[] = { - &dev_attr_protocols.attr, - NULL, -}; - -static struct attribute_group rc_dev_attr_grp = { - .attrs = rc_dev_attrs, -}; - -static const struct attribute_group *rc_dev_attr_groups[] = { - &rc_dev_attr_grp, - NULL -}; - -static struct device_type rc_dev_type = { - .groups = rc_dev_attr_groups, - .uevent = rc_dev_uevent, -}; - -/** - * ir_register_class() - creates the sysfs for /sys/class/rc/rc? - * @input_dev: the struct input_dev descriptor of the device - * - * This routine is used to register the syfs code for IR class - */ -int ir_register_class(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - int devno = find_first_zero_bit(&ir_core_dev_number, - IRRCV_NUM_DEVICES); - - if (unlikely(devno < 0)) - return devno; - - ir_dev->dev.type = &rc_dev_type; - ir_dev->devno = devno; - - ir_dev->dev.class = &ir_input_class; - ir_dev->dev.parent = input_dev->dev.parent; - input_dev->dev.parent = &ir_dev->dev; - dev_set_name(&ir_dev->dev, "rc%d", devno); - dev_set_drvdata(&ir_dev->dev, ir_dev); - return device_register(&ir_dev->dev); -}; - -/** - * ir_register_input - registers ir input device with input subsystem - * @input_dev: the struct input_dev descriptor of the device - */ - -int ir_register_input(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - int rc; - const char *path; - - - rc = input_register_device(input_dev); - if (rc < 0) { - device_del(&ir_dev->dev); - return rc; - } - - __module_get(THIS_MODULE); - - path = kobject_get_path(&ir_dev->dev.kobj, GFP_KERNEL); - printk(KERN_INFO "%s: %s as %s\n", - dev_name(&ir_dev->dev), - input_dev->name ? input_dev->name : "Unspecified device", - path ? path : "N/A"); - kfree(path); - - set_bit(ir_dev->devno, &ir_core_dev_number); - return 0; -} - -/** - * ir_unregister_class() - removes the sysfs for sysfs for - * /sys/class/rc/rc? - * @input_dev: the struct input_dev descriptor of the device - * - * This routine is used to unregister the syfs code for IR class - */ -void ir_unregister_class(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - - input_set_drvdata(input_dev, NULL); - clear_bit(ir_dev->devno, &ir_core_dev_number); - input_unregister_device(input_dev); - device_del(&ir_dev->dev); - - module_put(THIS_MODULE); -} - -/* - * Init/exit code for the module. Basically, creates/removes /sys/class/rc - */ - -static int __init ir_core_init(void) -{ - int rc = class_register(&ir_input_class); - if (rc) { - printk(KERN_ERR "ir_core: unable to register rc class\n"); - return rc; - } - - /* Initialize/load the decoders/keymap code that will be used */ - ir_raw_init(); - ir_rcmap_init(); - - return 0; -} - -static void __exit ir_core_exit(void) -{ - class_unregister(&ir_input_class); - ir_rcmap_cleanup(); -} - -module_init(ir_core_init); -module_exit(ir_core_exit); diff --git a/drivers/media/IR/keymaps/Kconfig b/drivers/media/IR/keymaps/Kconfig deleted file mode 100644 index 14b22f5..0000000 --- a/drivers/media/IR/keymaps/Kconfig +++ /dev/null @@ -1,15 +0,0 @@ -config RC_MAP - tristate "Compile Remote Controller keymap modules" - depends on IR_CORE - default y - - ---help--- - This option enables the compilation of lots of Remote - Controller tables. They are short tables, but if you - don't use a remote controller, or prefer to load the - tables on userspace, you should disable it. - - The ir-keytable program, available at v4l-utils package - provide the tool and the same RC maps for load from - userspace. Its available at - http://git.linuxtv.org/v4l-utils diff --git a/drivers/media/IR/keymaps/Makefile b/drivers/media/IR/keymaps/Makefile deleted file mode 100644 index 3194d39..0000000 --- a/drivers/media/IR/keymaps/Makefile +++ /dev/null @@ -1,86 +0,0 @@ -obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ - rc-alink-dtu-m.o \ - rc-anysee.o \ - rc-apac-viewcomp.o \ - rc-asus-pc39.o \ - rc-ati-tv-wonder-hd-600.o \ - rc-avermedia-a16d.o \ - rc-avermedia.o \ - rc-avermedia-cardbus.o \ - rc-avermedia-dvbt.o \ - rc-avermedia-m135a.o \ - rc-avermedia-m733a-rm-k6.o \ - rc-avermedia-rm-ks.o \ - rc-avertv-303.o \ - rc-azurewave-ad-tu700.o \ - rc-behold.o \ - rc-behold-columbus.o \ - rc-budget-ci-old.o \ - rc-cinergy-1400.o \ - rc-cinergy.o \ - rc-dib0700-nec.o \ - rc-dib0700-rc5.o \ - rc-digitalnow-tinytwin.o \ - rc-digittrade.o \ - rc-dm1105-nec.o \ - rc-dntv-live-dvb-t.o \ - rc-dntv-live-dvbt-pro.o \ - rc-em-terratec.o \ - rc-encore-enltv2.o \ - rc-encore-enltv.o \ - rc-encore-enltv-fm53.o \ - rc-evga-indtube.o \ - rc-eztv.o \ - rc-flydvb.o \ - rc-flyvideo.o \ - rc-fusionhdtv-mce.o \ - rc-gadmei-rm008z.o \ - rc-genius-tvgo-a11mce.o \ - rc-gotview7135.o \ - rc-hauppauge-new.o \ - rc-imon-mce.o \ - rc-imon-pad.o \ - rc-iodata-bctv7e.o \ - rc-kaiomy.o \ - rc-kworld-315u.o \ - rc-kworld-plus-tv-analog.o \ - rc-leadtek-y04g0051.o \ - rc-lirc.o \ - rc-lme2510.o \ - rc-manli.o \ - rc-msi-digivox-ii.o \ - rc-msi-digivox-iii.o \ - rc-msi-tvanywhere.o \ - rc-msi-tvanywhere-plus.o \ - rc-nebula.o \ - rc-nec-terratec-cinergy-xs.o \ - rc-norwood.o \ - rc-npgtech.o \ - rc-pctv-sedna.o \ - rc-pinnacle-color.o \ - rc-pinnacle-grey.o \ - rc-pinnacle-pctv-hd.o \ - rc-pixelview.o \ - rc-pixelview-mk12.o \ - rc-pixelview-new.o \ - rc-powercolor-real-angel.o \ - rc-proteus-2309.o \ - rc-purpletv.o \ - rc-pv951.o \ - rc-rc5-hauppauge-new.o \ - rc-rc5-tv.o \ - rc-rc6-mce.o \ - rc-real-audio-220-32-keys.o \ - rc-streamzap.o \ - rc-tbs-nec.o \ - rc-terratec-cinergy-xs.o \ - rc-terratec-slim.o \ - rc-tevii-nec.o \ - rc-total-media-in-hand.o \ - rc-trekstor.o \ - rc-tt-1500.o \ - rc-twinhan1027.o \ - rc-videomate-s350.o \ - rc-videomate-tv-pvr.o \ - rc-winfast.o \ - rc-winfast-usbii-deluxe.o diff --git a/drivers/media/IR/keymaps/rc-adstech-dvb-t-pci.c b/drivers/media/IR/keymaps/rc-adstech-dvb-t-pci.c deleted file mode 100644 index b172831..0000000 --- a/drivers/media/IR/keymaps/rc-adstech-dvb-t-pci.c +++ /dev/null @@ -1,89 +0,0 @@ -/* adstech-dvb-t-pci.h - Keytable for adstech_dvb_t_pci Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* ADS Tech Instant TV DVB-T PCI Remote */ - -static struct ir_scancode adstech_dvb_t_pci[] = { - /* Keys 0 to 9 */ - { 0x4d, KEY_0 }, - { 0x57, KEY_1 }, - { 0x4f, KEY_2 }, - { 0x53, KEY_3 }, - { 0x56, KEY_4 }, - { 0x4e, KEY_5 }, - { 0x5e, KEY_6 }, - { 0x54, KEY_7 }, - { 0x4c, KEY_8 }, - { 0x5c, KEY_9 }, - - { 0x5b, KEY_POWER }, - { 0x5f, KEY_MUTE }, - { 0x55, KEY_GOTO }, - { 0x5d, KEY_SEARCH }, - { 0x17, KEY_EPG }, /* Guide */ - { 0x1f, KEY_MENU }, - { 0x0f, KEY_UP }, - { 0x46, KEY_DOWN }, - { 0x16, KEY_LEFT }, - { 0x1e, KEY_RIGHT }, - { 0x0e, KEY_SELECT }, /* Enter */ - { 0x5a, KEY_INFO }, - { 0x52, KEY_EXIT }, - { 0x59, KEY_PREVIOUS }, - { 0x51, KEY_NEXT }, - { 0x58, KEY_REWIND }, - { 0x50, KEY_FORWARD }, - { 0x44, KEY_PLAYPAUSE }, - { 0x07, KEY_STOP }, - { 0x1b, KEY_RECORD }, - { 0x13, KEY_TUNER }, /* Live */ - { 0x0a, KEY_A }, - { 0x12, KEY_B }, - { 0x03, KEY_PROG1 }, /* 1 */ - { 0x01, KEY_PROG2 }, /* 2 */ - { 0x00, KEY_PROG3 }, /* 3 */ - { 0x06, KEY_DVD }, - { 0x48, KEY_AUX }, /* Photo */ - { 0x40, KEY_VIDEO }, - { 0x19, KEY_AUDIO }, /* Music */ - { 0x0b, KEY_CHANNELUP }, - { 0x08, KEY_CHANNELDOWN }, - { 0x15, KEY_VOLUMEUP }, - { 0x1c, KEY_VOLUMEDOWN }, -}; - -static struct rc_keymap adstech_dvb_t_pci_map = { - .map = { - .scan = adstech_dvb_t_pci, - .size = ARRAY_SIZE(adstech_dvb_t_pci), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_ADSTECH_DVB_T_PCI, - } -}; - -static int __init init_rc_map_adstech_dvb_t_pci(void) -{ - return ir_register_map(&adstech_dvb_t_pci_map); -} - -static void __exit exit_rc_map_adstech_dvb_t_pci(void) -{ - ir_unregister_map(&adstech_dvb_t_pci_map); -} - -module_init(init_rc_map_adstech_dvb_t_pci) -module_exit(exit_rc_map_adstech_dvb_t_pci) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-alink-dtu-m.c b/drivers/media/IR/keymaps/rc-alink-dtu-m.c deleted file mode 100644 index ddfee7f..0000000 --- a/drivers/media/IR/keymaps/rc-alink-dtu-m.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * A-Link DTU(m) remote controller keytable - * - * Copyright (C) 2010 Antti Palosaari - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -/* A-Link DTU(m) slim remote, 6 rows, 3 columns. */ -static struct ir_scancode alink_dtu_m[] = { - { 0x0800, KEY_VOLUMEUP }, - { 0x0801, KEY_1 }, - { 0x0802, KEY_3 }, - { 0x0803, KEY_7 }, - { 0x0804, KEY_9 }, - { 0x0805, KEY_NEW }, /* symbol: PIP */ - { 0x0806, KEY_0 }, - { 0x0807, KEY_CHANNEL }, /* JUMP */ - { 0x080d, KEY_5 }, - { 0x080f, KEY_2 }, - { 0x0812, KEY_POWER2 }, - { 0x0814, KEY_CHANNELUP }, - { 0x0816, KEY_VOLUMEDOWN }, - { 0x0818, KEY_6 }, - { 0x081a, KEY_MUTE }, - { 0x081b, KEY_8 }, - { 0x081c, KEY_4 }, - { 0x081d, KEY_CHANNELDOWN }, -}; - -static struct rc_keymap alink_dtu_m_map = { - .map = { - .scan = alink_dtu_m, - .size = ARRAY_SIZE(alink_dtu_m), - .ir_type = IR_TYPE_NEC, - .name = RC_MAP_ALINK_DTU_M, - } -}; - -static int __init init_rc_map_alink_dtu_m(void) -{ - return ir_register_map(&alink_dtu_m_map); -} - -static void __exit exit_rc_map_alink_dtu_m(void) -{ - ir_unregister_map(&alink_dtu_m_map); -} - -module_init(init_rc_map_alink_dtu_m) -module_exit(exit_rc_map_alink_dtu_m) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/IR/keymaps/rc-anysee.c b/drivers/media/IR/keymaps/rc-anysee.c deleted file mode 100644 index 30d7049..0000000 --- a/drivers/media/IR/keymaps/rc-anysee.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Anysee remote controller keytable - * - * Copyright (C) 2010 Antti Palosaari - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -static struct ir_scancode anysee[] = { - { 0x0800, KEY_0 }, - { 0x0801, KEY_1 }, - { 0x0802, KEY_2 }, - { 0x0803, KEY_3 }, - { 0x0804, KEY_4 }, - { 0x0805, KEY_5 }, - { 0x0806, KEY_6 }, - { 0x0807, KEY_7 }, - { 0x0808, KEY_8 }, - { 0x0809, KEY_9 }, - { 0x080a, KEY_POWER2 }, /* [red power button] */ - { 0x080b, KEY_VIDEO }, /* [*] MODE */ - { 0x080c, KEY_CHANNEL }, /* [symbol counterclockwise arrow] */ - { 0x080d, KEY_NEXT }, /* [>>|] */ - { 0x080e, KEY_MENU }, /* MENU */ - { 0x080f, KEY_EPG }, /* [EPG] */ - { 0x0810, KEY_CLEAR }, /* EXIT */ - { 0x0811, KEY_CHANNELUP }, - { 0x0812, KEY_VOLUMEDOWN }, - { 0x0813, KEY_VOLUMEUP }, - { 0x0814, KEY_CHANNELDOWN }, - { 0x0815, KEY_OK }, - { 0x0816, KEY_RADIO }, /* [symbol TV/radio] */ - { 0x0817, KEY_INFO }, /* [i] */ - { 0x0818, KEY_PREVIOUS }, /* [|<<] */ - { 0x0819, KEY_FAVORITES }, /* FAV. */ - { 0x081a, KEY_SUBTITLE }, /* Subtitle */ - { 0x081b, KEY_CAMERA }, /* [symbol camera] */ - { 0x081c, KEY_YELLOW }, - { 0x081d, KEY_RED }, - { 0x081e, KEY_LANGUAGE }, /* [symbol Second Audio Program] */ - { 0x081f, KEY_GREEN }, - { 0x0820, KEY_SLEEP }, /* Sleep */ - { 0x0821, KEY_SCREEN }, /* 16:9 / 4:3 */ - { 0x0822, KEY_ZOOM }, /* SIZE */ - { 0x0824, KEY_FN }, /* [F1] */ - { 0x0825, KEY_FN }, /* [F2] */ - { 0x0842, KEY_MUTE }, /* symbol mute */ - { 0x0844, KEY_BLUE }, - { 0x0847, KEY_TEXT }, /* TEXT */ - { 0x0848, KEY_STOP }, - { 0x0849, KEY_RECORD }, - { 0x0850, KEY_PLAY }, - { 0x0851, KEY_PAUSE }, -}; - -static struct rc_keymap anysee_map = { - .map = { - .scan = anysee, - .size = ARRAY_SIZE(anysee), - .ir_type = IR_TYPE_NEC, - .name = RC_MAP_ANYSEE, - } -}; - -static int __init init_rc_map_anysee(void) -{ - return ir_register_map(&anysee_map); -} - -static void __exit exit_rc_map_anysee(void) -{ - ir_unregister_map(&anysee_map); -} - -module_init(init_rc_map_anysee) -module_exit(exit_rc_map_anysee) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/IR/keymaps/rc-apac-viewcomp.c b/drivers/media/IR/keymaps/rc-apac-viewcomp.c deleted file mode 100644 index 0ef2b56..0000000 --- a/drivers/media/IR/keymaps/rc-apac-viewcomp.c +++ /dev/null @@ -1,80 +0,0 @@ -/* apac-viewcomp.h - Keytable for apac_viewcomp Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Attila Kondoros */ - -static struct ir_scancode apac_viewcomp[] = { - - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - { 0x00, KEY_0 }, - { 0x17, KEY_LAST }, /* +100 */ - { 0x0a, KEY_LIST }, /* recall */ - - - { 0x1c, KEY_TUNER }, /* TV/FM */ - { 0x15, KEY_SEARCH }, /* scan */ - { 0x12, KEY_POWER }, /* power */ - { 0x1f, KEY_VOLUMEDOWN }, /* vol up */ - { 0x1b, KEY_VOLUMEUP }, /* vol down */ - { 0x1e, KEY_CHANNELDOWN }, /* chn up */ - { 0x1a, KEY_CHANNELUP }, /* chn down */ - - { 0x11, KEY_VIDEO }, /* video */ - { 0x0f, KEY_ZOOM }, /* full screen */ - { 0x13, KEY_MUTE }, /* mute/unmute */ - { 0x10, KEY_TEXT }, /* min */ - - { 0x0d, KEY_STOP }, /* freeze */ - { 0x0e, KEY_RECORD }, /* record */ - { 0x1d, KEY_PLAYPAUSE }, /* stop */ - { 0x19, KEY_PLAY }, /* play */ - - { 0x16, KEY_GOTO }, /* osd */ - { 0x14, KEY_REFRESH }, /* default */ - { 0x0c, KEY_KPPLUS }, /* fine tune >>>> */ - { 0x18, KEY_KPMINUS }, /* fine tune <<<< */ -}; - -static struct rc_keymap apac_viewcomp_map = { - .map = { - .scan = apac_viewcomp, - .size = ARRAY_SIZE(apac_viewcomp), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_APAC_VIEWCOMP, - } -}; - -static int __init init_rc_map_apac_viewcomp(void) -{ - return ir_register_map(&apac_viewcomp_map); -} - -static void __exit exit_rc_map_apac_viewcomp(void) -{ - ir_unregister_map(&apac_viewcomp_map); -} - -module_init(init_rc_map_apac_viewcomp) -module_exit(exit_rc_map_apac_viewcomp) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-asus-pc39.c b/drivers/media/IR/keymaps/rc-asus-pc39.c deleted file mode 100644 index 2996e0a..0000000 --- a/drivers/media/IR/keymaps/rc-asus-pc39.c +++ /dev/null @@ -1,91 +0,0 @@ -/* asus-pc39.h - Keytable for asus_pc39 Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* - * Marc Fargas - * this is the remote control that comes with the asus p7131 - * which has a label saying is "Model PC-39" - */ - -static struct ir_scancode asus_pc39[] = { - /* Keys 0 to 9 */ - { 0x082a, KEY_0 }, - { 0x0816, KEY_1 }, - { 0x0812, KEY_2 }, - { 0x0814, KEY_3 }, - { 0x0836, KEY_4 }, - { 0x0832, KEY_5 }, - { 0x0834, KEY_6 }, - { 0x080e, KEY_7 }, - { 0x080a, KEY_8 }, - { 0x080c, KEY_9 }, - - { 0x0801, KEY_RADIO }, /* radio */ - { 0x083c, KEY_MENU }, /* dvd/menu */ - { 0x0815, KEY_VOLUMEUP }, - { 0x0826, KEY_VOLUMEDOWN }, - { 0x0808, KEY_UP }, - { 0x0804, KEY_DOWN }, - { 0x0818, KEY_LEFT }, - { 0x0810, KEY_RIGHT }, - { 0x081a, KEY_VIDEO }, /* video */ - { 0x0806, KEY_AUDIO }, /* music */ - - { 0x081e, KEY_TV }, /* tv */ - { 0x0822, KEY_EXIT }, /* back */ - { 0x0835, KEY_CHANNELUP }, /* channel / program + */ - { 0x0824, KEY_CHANNELDOWN }, /* channel / program - */ - { 0x0825, KEY_ENTER }, /* enter */ - - { 0x0839, KEY_PAUSE }, /* play/pause */ - { 0x0821, KEY_PREVIOUS }, /* rew */ - { 0x0819, KEY_NEXT }, /* forward */ - { 0x0831, KEY_REWIND }, /* backward << */ - { 0x0805, KEY_FASTFORWARD }, /* forward >> */ - { 0x0809, KEY_STOP }, - { 0x0811, KEY_RECORD }, /* recording */ - { 0x0829, KEY_POWER }, /* the button that reads "close" */ - - { 0x082e, KEY_ZOOM }, /* full screen */ - { 0x082c, KEY_MACRO }, /* recall */ - { 0x081c, KEY_HOME }, /* home */ - { 0x083a, KEY_PVR }, /* picture */ - { 0x0802, KEY_MUTE }, /* mute */ - { 0x083e, KEY_DVD }, /* dvd */ -}; - -static struct rc_keymap asus_pc39_map = { - .map = { - .scan = asus_pc39, - .size = ARRAY_SIZE(asus_pc39), - .ir_type = IR_TYPE_RC5, - .name = RC_MAP_ASUS_PC39, - } -}; - -static int __init init_rc_map_asus_pc39(void) -{ - return ir_register_map(&asus_pc39_map); -} - -static void __exit exit_rc_map_asus_pc39(void) -{ - ir_unregister_map(&asus_pc39_map); -} - -module_init(init_rc_map_asus_pc39) -module_exit(exit_rc_map_asus_pc39) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-ati-tv-wonder-hd-600.c b/drivers/media/IR/keymaps/rc-ati-tv-wonder-hd-600.c deleted file mode 100644 index 8edfd29..0000000 --- a/drivers/media/IR/keymaps/rc-ati-tv-wonder-hd-600.c +++ /dev/null @@ -1,69 +0,0 @@ -/* ati-tv-wonder-hd-600.h - Keytable for ati_tv_wonder_hd_600 Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* ATI TV Wonder HD 600 USB - Devin Heitmueller - */ - -static struct ir_scancode ati_tv_wonder_hd_600[] = { - { 0x00, KEY_RECORD}, /* Row 1 */ - { 0x01, KEY_PLAYPAUSE}, - { 0x02, KEY_STOP}, - { 0x03, KEY_POWER}, - { 0x04, KEY_PREVIOUS}, /* Row 2 */ - { 0x05, KEY_REWIND}, - { 0x06, KEY_FORWARD}, - { 0x07, KEY_NEXT}, - { 0x08, KEY_EPG}, /* Row 3 */ - { 0x09, KEY_HOME}, - { 0x0a, KEY_MENU}, - { 0x0b, KEY_CHANNELUP}, - { 0x0c, KEY_BACK}, /* Row 4 */ - { 0x0d, KEY_UP}, - { 0x0e, KEY_INFO}, - { 0x0f, KEY_CHANNELDOWN}, - { 0x10, KEY_LEFT}, /* Row 5 */ - { 0x11, KEY_SELECT}, - { 0x12, KEY_RIGHT}, - { 0x13, KEY_VOLUMEUP}, - { 0x14, KEY_LAST}, /* Row 6 */ - { 0x15, KEY_DOWN}, - { 0x16, KEY_MUTE}, - { 0x17, KEY_VOLUMEDOWN}, -}; - -static struct rc_keymap ati_tv_wonder_hd_600_map = { - .map = { - .scan = ati_tv_wonder_hd_600, - .size = ARRAY_SIZE(ati_tv_wonder_hd_600), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_ATI_TV_WONDER_HD_600, - } -}; - -static int __init init_rc_map_ati_tv_wonder_hd_600(void) -{ - return ir_register_map(&ati_tv_wonder_hd_600_map); -} - -static void __exit exit_rc_map_ati_tv_wonder_hd_600(void) -{ - ir_unregister_map(&ati_tv_wonder_hd_600_map); -} - -module_init(init_rc_map_ati_tv_wonder_hd_600) -module_exit(exit_rc_map_ati_tv_wonder_hd_600) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-avermedia-a16d.c b/drivers/media/IR/keymaps/rc-avermedia-a16d.c deleted file mode 100644 index 12f0435..0000000 --- a/drivers/media/IR/keymaps/rc-avermedia-a16d.c +++ /dev/null @@ -1,75 +0,0 @@ -/* avermedia-a16d.h - Keytable for avermedia_a16d Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode avermedia_a16d[] = { - { 0x20, KEY_LIST}, - { 0x00, KEY_POWER}, - { 0x28, KEY_1}, - { 0x18, KEY_2}, - { 0x38, KEY_3}, - { 0x24, KEY_4}, - { 0x14, KEY_5}, - { 0x34, KEY_6}, - { 0x2c, KEY_7}, - { 0x1c, KEY_8}, - { 0x3c, KEY_9}, - { 0x12, KEY_SUBTITLE}, - { 0x22, KEY_0}, - { 0x32, KEY_REWIND}, - { 0x3a, KEY_SHUFFLE}, - { 0x02, KEY_PRINT}, - { 0x11, KEY_CHANNELDOWN}, - { 0x31, KEY_CHANNELUP}, - { 0x0c, KEY_ZOOM}, - { 0x1e, KEY_VOLUMEDOWN}, - { 0x3e, KEY_VOLUMEUP}, - { 0x0a, KEY_MUTE}, - { 0x04, KEY_AUDIO}, - { 0x26, KEY_RECORD}, - { 0x06, KEY_PLAY}, - { 0x36, KEY_STOP}, - { 0x16, KEY_PAUSE}, - { 0x2e, KEY_REWIND}, - { 0x0e, KEY_FASTFORWARD}, - { 0x30, KEY_TEXT}, - { 0x21, KEY_GREEN}, - { 0x01, KEY_BLUE}, - { 0x08, KEY_EPG}, - { 0x2a, KEY_MENU}, -}; - -static struct rc_keymap avermedia_a16d_map = { - .map = { - .scan = avermedia_a16d, - .size = ARRAY_SIZE(avermedia_a16d), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_AVERMEDIA_A16D, - } -}; - -static int __init init_rc_map_avermedia_a16d(void) -{ - return ir_register_map(&avermedia_a16d_map); -} - -static void __exit exit_rc_map_avermedia_a16d(void) -{ - ir_unregister_map(&avermedia_a16d_map); -} - -module_init(init_rc_map_avermedia_a16d) -module_exit(exit_rc_map_avermedia_a16d) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-avermedia-cardbus.c b/drivers/media/IR/keymaps/rc-avermedia-cardbus.c deleted file mode 100644 index 2a945b0..0000000 --- a/drivers/media/IR/keymaps/rc-avermedia-cardbus.c +++ /dev/null @@ -1,97 +0,0 @@ -/* avermedia-cardbus.h - Keytable for avermedia_cardbus Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Oldrich Jedlicka */ - -static struct ir_scancode avermedia_cardbus[] = { - { 0x00, KEY_POWER }, - { 0x01, KEY_TUNER }, /* TV/FM */ - { 0x03, KEY_TEXT }, /* Teletext */ - { 0x04, KEY_EPG }, - { 0x05, KEY_1 }, - { 0x06, KEY_2 }, - { 0x07, KEY_3 }, - { 0x08, KEY_AUDIO }, - { 0x09, KEY_4 }, - { 0x0a, KEY_5 }, - { 0x0b, KEY_6 }, - { 0x0c, KEY_ZOOM }, /* Full screen */ - { 0x0d, KEY_7 }, - { 0x0e, KEY_8 }, - { 0x0f, KEY_9 }, - { 0x10, KEY_PAGEUP }, /* 16-CH PREV */ - { 0x11, KEY_0 }, - { 0x12, KEY_INFO }, - { 0x13, KEY_AGAIN }, /* CH RTN - channel return */ - { 0x14, KEY_MUTE }, - { 0x15, KEY_EDIT }, /* Autoscan */ - { 0x17, KEY_SAVE }, /* Screenshot */ - { 0x18, KEY_PLAYPAUSE }, - { 0x19, KEY_RECORD }, - { 0x1a, KEY_PLAY }, - { 0x1b, KEY_STOP }, - { 0x1c, KEY_FASTFORWARD }, - { 0x1d, KEY_REWIND }, - { 0x1e, KEY_VOLUMEDOWN }, - { 0x1f, KEY_VOLUMEUP }, - { 0x22, KEY_SLEEP }, /* Sleep */ - { 0x23, KEY_ZOOM }, /* Aspect */ - { 0x26, KEY_SCREEN }, /* Pos */ - { 0x27, KEY_ANGLE }, /* Size */ - { 0x28, KEY_SELECT }, /* Select */ - { 0x29, KEY_BLUE }, /* Blue/Picture */ - { 0x2a, KEY_BACKSPACE }, /* Back */ - { 0x2b, KEY_MEDIA }, /* PIP (Picture-in-picture) */ - { 0x2c, KEY_DOWN }, - { 0x2e, KEY_DOT }, - { 0x2f, KEY_TV }, /* Live TV */ - { 0x32, KEY_LEFT }, - { 0x33, KEY_CLEAR }, /* Clear */ - { 0x35, KEY_RED }, /* Red/TV */ - { 0x36, KEY_UP }, - { 0x37, KEY_HOME }, /* Home */ - { 0x39, KEY_GREEN }, /* Green/Video */ - { 0x3d, KEY_YELLOW }, /* Yellow/Music */ - { 0x3e, KEY_OK }, /* Ok */ - { 0x3f, KEY_RIGHT }, - { 0x40, KEY_NEXT }, /* Next */ - { 0x41, KEY_PREVIOUS }, /* Previous */ - { 0x42, KEY_CHANNELDOWN }, /* Channel down */ - { 0x43, KEY_CHANNELUP }, /* Channel up */ -}; - -static struct rc_keymap avermedia_cardbus_map = { - .map = { - .scan = avermedia_cardbus, - .size = ARRAY_SIZE(avermedia_cardbus), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_AVERMEDIA_CARDBUS, - } -}; - -static int __init init_rc_map_avermedia_cardbus(void) -{ - return ir_register_map(&avermedia_cardbus_map); -} - -static void __exit exit_rc_map_avermedia_cardbus(void) -{ - ir_unregister_map(&avermedia_cardbus_map); -} - -module_init(init_rc_map_avermedia_cardbus) -module_exit(exit_rc_map_avermedia_cardbus) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-avermedia-dvbt.c b/drivers/media/IR/keymaps/rc-avermedia-dvbt.c deleted file mode 100644 index 39dde62..0000000 --- a/drivers/media/IR/keymaps/rc-avermedia-dvbt.c +++ /dev/null @@ -1,78 +0,0 @@ -/* avermedia-dvbt.h - Keytable for avermedia_dvbt Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Matt Jesson >' */ - { 0x3a, KEY_RECORD }, /* 'capture' */ - { 0x0a, KEY_MUTE }, /* 'mute' */ - { 0x2c, KEY_RECORD }, /* 'record' */ - { 0x1c, KEY_PAUSE }, /* 'pause' */ - { 0x3c, KEY_STOP }, /* 'stop' */ - { 0x0c, KEY_PLAY }, /* 'play' */ - { 0x2e, KEY_RED }, /* 'red' */ - { 0x01, KEY_BLUE }, /* 'blue' / 'cancel' */ - { 0x0e, KEY_YELLOW }, /* 'yellow' / 'ok' */ - { 0x21, KEY_GREEN }, /* 'green' */ - { 0x11, KEY_CHANNELDOWN }, /* 'channel -' */ - { 0x31, KEY_CHANNELUP }, /* 'channel +' */ - { 0x1e, KEY_VOLUMEDOWN }, /* 'volume -' */ - { 0x3e, KEY_VOLUMEUP }, /* 'volume +' */ -}; - -static struct rc_keymap avermedia_dvbt_map = { - .map = { - .scan = avermedia_dvbt, - .size = ARRAY_SIZE(avermedia_dvbt), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_AVERMEDIA_DVBT, - } -}; - -static int __init init_rc_map_avermedia_dvbt(void) -{ - return ir_register_map(&avermedia_dvbt_map); -} - -static void __exit exit_rc_map_avermedia_dvbt(void) -{ - ir_unregister_map(&avermedia_dvbt_map); -} - -module_init(init_rc_map_avermedia_dvbt) -module_exit(exit_rc_map_avermedia_dvbt) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-avermedia-m135a.c b/drivers/media/IR/keymaps/rc-avermedia-m135a.c deleted file mode 100644 index e4471fb..0000000 --- a/drivers/media/IR/keymaps/rc-avermedia-m135a.c +++ /dev/null @@ -1,147 +0,0 @@ -/* avermedia-m135a.c - Keytable for Avermedia M135A Remote Controllers - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * Copyright (c) 2010 by Herton Ronaldo Krzesinski - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* - * Avermedia M135A with RM-JX and RM-K6 remote controls - * - * On Avermedia M135A with IR model RM-JX, the same codes exist on both - * Positivo (BR) and original IR, initial version and remote control codes - * added by Mauro Carvalho Chehab - * - * Positivo also ships Avermedia M135A with model RM-K6, extra control - * codes added by Herton Ronaldo Krzesinski - */ - -static struct ir_scancode avermedia_m135a[] = { - /* RM-JX */ - { 0x0200, KEY_POWER2 }, - { 0x022e, KEY_DOT }, /* '.' */ - { 0x0201, KEY_MODE }, /* TV/FM or SOURCE */ - - { 0x0205, KEY_1 }, - { 0x0206, KEY_2 }, - { 0x0207, KEY_3 }, - { 0x0209, KEY_4 }, - { 0x020a, KEY_5 }, - { 0x020b, KEY_6 }, - { 0x020d, KEY_7 }, - { 0x020e, KEY_8 }, - { 0x020f, KEY_9 }, - { 0x0211, KEY_0 }, - - { 0x0213, KEY_RIGHT }, /* -> or L */ - { 0x0212, KEY_LEFT }, /* <- or R */ - - { 0x0217, KEY_SLEEP }, /* Capturar Imagem or Snapshot */ - { 0x0210, KEY_SHUFFLE }, /* Amostra or 16 chan prev */ - - { 0x0303, KEY_CHANNELUP }, - { 0x0302, KEY_CHANNELDOWN }, - { 0x021f, KEY_VOLUMEUP }, - { 0x021e, KEY_VOLUMEDOWN }, - { 0x020c, KEY_ENTER }, /* Full Screen */ - - { 0x0214, KEY_MUTE }, - { 0x0208, KEY_AUDIO }, - - { 0x0203, KEY_TEXT }, /* Teletext */ - { 0x0204, KEY_EPG }, - { 0x022b, KEY_TV2 }, /* TV2 or PIP */ - - { 0x021d, KEY_RED }, - { 0x021c, KEY_YELLOW }, - { 0x0301, KEY_GREEN }, - { 0x0300, KEY_BLUE }, - - { 0x021a, KEY_PLAYPAUSE }, - { 0x0219, KEY_RECORD }, - { 0x0218, KEY_PLAY }, - { 0x021b, KEY_STOP }, - - /* RM-K6 */ - { 0x0401, KEY_POWER2 }, - { 0x0406, KEY_MUTE }, - { 0x0408, KEY_MODE }, /* TV/FM */ - - { 0x0409, KEY_1 }, - { 0x040a, KEY_2 }, - { 0x040b, KEY_3 }, - { 0x040c, KEY_4 }, - { 0x040d, KEY_5 }, - { 0x040e, KEY_6 }, - { 0x040f, KEY_7 }, - { 0x0410, KEY_8 }, - { 0x0411, KEY_9 }, - { 0x044c, KEY_DOT }, /* '.' */ - { 0x0412, KEY_0 }, - { 0x0407, KEY_REFRESH }, /* Refresh/Reload */ - - { 0x0413, KEY_AUDIO }, - { 0x0440, KEY_SCREEN }, /* Full Screen toggle */ - { 0x0441, KEY_HOME }, - { 0x0442, KEY_BACK }, - { 0x0447, KEY_UP }, - { 0x0448, KEY_DOWN }, - { 0x0449, KEY_LEFT }, - { 0x044a, KEY_RIGHT }, - { 0x044b, KEY_OK }, - { 0x0404, KEY_VOLUMEUP }, - { 0x0405, KEY_VOLUMEDOWN }, - { 0x0402, KEY_CHANNELUP }, - { 0x0403, KEY_CHANNELDOWN }, - - { 0x0443, KEY_RED }, - { 0x0444, KEY_GREEN }, - { 0x0445, KEY_YELLOW }, - { 0x0446, KEY_BLUE }, - - { 0x0414, KEY_TEXT }, - { 0x0415, KEY_EPG }, - { 0x041a, KEY_TV2 }, /* PIP */ - { 0x041b, KEY_MHP }, /* Snapshot */ - - { 0x0417, KEY_RECORD }, - { 0x0416, KEY_PLAYPAUSE }, - { 0x0418, KEY_STOP }, - { 0x0419, KEY_PAUSE }, - - { 0x041f, KEY_PREVIOUS }, - { 0x041c, KEY_REWIND }, - { 0x041d, KEY_FORWARD }, - { 0x041e, KEY_NEXT }, -}; - -static struct rc_keymap avermedia_m135a_map = { - .map = { - .scan = avermedia_m135a, - .size = ARRAY_SIZE(avermedia_m135a), - .ir_type = IR_TYPE_NEC, - .name = RC_MAP_AVERMEDIA_M135A, - } -}; - -static int __init init_rc_map_avermedia_m135a(void) -{ - return ir_register_map(&avermedia_m135a_map); -} - -static void __exit exit_rc_map_avermedia_m135a(void) -{ - ir_unregister_map(&avermedia_m135a_map); -} - -module_init(init_rc_map_avermedia_m135a) -module_exit(exit_rc_map_avermedia_m135a) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-avermedia-m733a-rm-k6.c b/drivers/media/IR/keymaps/rc-avermedia-m733a-rm-k6.c deleted file mode 100644 index cf8d457..0000000 --- a/drivers/media/IR/keymaps/rc-avermedia-m733a-rm-k6.c +++ /dev/null @@ -1,95 +0,0 @@ -/* avermedia-m733a-rm-k6.h - Keytable for avermedia_m733a_rm_k6 Remote Controller - * - * Copyright (c) 2010 by Herton Ronaldo Krzesinski - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* - * Avermedia M733A with IR model RM-K6 - * This is the stock remote controller used with Positivo machines with M733A - * Herton Ronaldo Krzesinski - */ - -static struct ir_scancode avermedia_m733a_rm_k6[] = { - { 0x0401, KEY_POWER2 }, - { 0x0406, KEY_MUTE }, - { 0x0408, KEY_MODE }, /* TV/FM */ - - { 0x0409, KEY_1 }, - { 0x040a, KEY_2 }, - { 0x040b, KEY_3 }, - { 0x040c, KEY_4 }, - { 0x040d, KEY_5 }, - { 0x040e, KEY_6 }, - { 0x040f, KEY_7 }, - { 0x0410, KEY_8 }, - { 0x0411, KEY_9 }, - { 0x044c, KEY_DOT }, /* '.' */ - { 0x0412, KEY_0 }, - { 0x0407, KEY_REFRESH }, /* Refresh/Reload */ - - { 0x0413, KEY_AUDIO }, - { 0x0440, KEY_SCREEN }, /* Full Screen toggle */ - { 0x0441, KEY_HOME }, - { 0x0442, KEY_BACK }, - { 0x0447, KEY_UP }, - { 0x0448, KEY_DOWN }, - { 0x0449, KEY_LEFT }, - { 0x044a, KEY_RIGHT }, - { 0x044b, KEY_OK }, - { 0x0404, KEY_VOLUMEUP }, - { 0x0405, KEY_VOLUMEDOWN }, - { 0x0402, KEY_CHANNELUP }, - { 0x0403, KEY_CHANNELDOWN }, - - { 0x0443, KEY_RED }, - { 0x0444, KEY_GREEN }, - { 0x0445, KEY_YELLOW }, - { 0x0446, KEY_BLUE }, - - { 0x0414, KEY_TEXT }, - { 0x0415, KEY_EPG }, - { 0x041a, KEY_TV2 }, /* PIP */ - { 0x041b, KEY_MHP }, /* Snapshot */ - - { 0x0417, KEY_RECORD }, - { 0x0416, KEY_PLAYPAUSE }, - { 0x0418, KEY_STOP }, - { 0x0419, KEY_PAUSE }, - - { 0x041f, KEY_PREVIOUS }, - { 0x041c, KEY_REWIND }, - { 0x041d, KEY_FORWARD }, - { 0x041e, KEY_NEXT }, -}; - -static struct rc_keymap avermedia_m733a_rm_k6_map = { - .map = { - .scan = avermedia_m733a_rm_k6, - .size = ARRAY_SIZE(avermedia_m733a_rm_k6), - .ir_type = IR_TYPE_NEC, - .name = RC_MAP_AVERMEDIA_M733A_RM_K6, - } -}; - -static int __init init_rc_map_avermedia_m733a_rm_k6(void) -{ - return ir_register_map(&avermedia_m733a_rm_k6_map); -} - -static void __exit exit_rc_map_avermedia_m733a_rm_k6(void) -{ - ir_unregister_map(&avermedia_m733a_rm_k6_map); -} - -module_init(init_rc_map_avermedia_m733a_rm_k6) -module_exit(exit_rc_map_avermedia_m733a_rm_k6) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-avermedia-rm-ks.c b/drivers/media/IR/keymaps/rc-avermedia-rm-ks.c deleted file mode 100644 index 9ee6090..0000000 --- a/drivers/media/IR/keymaps/rc-avermedia-rm-ks.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * AverMedia RM-KS remote controller keytable - * - * Copyright (C) 2010 Antti Palosaari - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -/* Initial keytable is from Jose Alberto Reguero - and Felipe Morales Moreno */ -/* FIXME: mappings are not 100% correct? */ -static struct ir_scancode avermedia_rm_ks[] = { - { 0x0501, KEY_POWER2 }, - { 0x0502, KEY_CHANNELUP }, - { 0x0503, KEY_CHANNELDOWN }, - { 0x0504, KEY_VOLUMEUP }, - { 0x0505, KEY_VOLUMEDOWN }, - { 0x0506, KEY_MUTE }, - { 0x0507, KEY_RIGHT }, - { 0x0508, KEY_PROG1 }, - { 0x0509, KEY_1 }, - { 0x050a, KEY_2 }, - { 0x050b, KEY_3 }, - { 0x050c, KEY_4 }, - { 0x050d, KEY_5 }, - { 0x050e, KEY_6 }, - { 0x050f, KEY_7 }, - { 0x0510, KEY_8 }, - { 0x0511, KEY_9 }, - { 0x0512, KEY_0 }, - { 0x0513, KEY_AUDIO }, - { 0x0515, KEY_EPG }, - { 0x0516, KEY_PLAY }, - { 0x0517, KEY_RECORD }, - { 0x0518, KEY_STOP }, - { 0x051c, KEY_BACK }, - { 0x051d, KEY_FORWARD }, - { 0x054d, KEY_LEFT }, - { 0x0556, KEY_ZOOM }, -}; - -static struct rc_keymap avermedia_rm_ks_map = { - .map = { - .scan = avermedia_rm_ks, - .size = ARRAY_SIZE(avermedia_rm_ks), - .ir_type = IR_TYPE_NEC, - .name = RC_MAP_AVERMEDIA_RM_KS, - } -}; - -static int __init init_rc_map_avermedia_rm_ks(void) -{ - return ir_register_map(&avermedia_rm_ks_map); -} - -static void __exit exit_rc_map_avermedia_rm_ks(void) -{ - ir_unregister_map(&avermedia_rm_ks_map); -} - -module_init(init_rc_map_avermedia_rm_ks) -module_exit(exit_rc_map_avermedia_rm_ks) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/IR/keymaps/rc-avermedia.c b/drivers/media/IR/keymaps/rc-avermedia.c deleted file mode 100644 index 21effd5..0000000 --- a/drivers/media/IR/keymaps/rc-avermedia.c +++ /dev/null @@ -1,86 +0,0 @@ -/* avermedia.h - Keytable for avermedia Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Alex Hermann */ - -static struct ir_scancode avermedia[] = { - { 0x28, KEY_1 }, - { 0x18, KEY_2 }, - { 0x38, KEY_3 }, - { 0x24, KEY_4 }, - { 0x14, KEY_5 }, - { 0x34, KEY_6 }, - { 0x2c, KEY_7 }, - { 0x1c, KEY_8 }, - { 0x3c, KEY_9 }, - { 0x22, KEY_0 }, - - { 0x20, KEY_TV }, /* TV/FM */ - { 0x10, KEY_CD }, /* CD */ - { 0x30, KEY_TEXT }, /* TELETEXT */ - { 0x00, KEY_POWER }, /* POWER */ - - { 0x08, KEY_VIDEO }, /* VIDEO */ - { 0x04, KEY_AUDIO }, /* AUDIO */ - { 0x0c, KEY_ZOOM }, /* FULL SCREEN */ - - { 0x12, KEY_SUBTITLE }, /* DISPLAY */ - { 0x32, KEY_REWIND }, /* LOOP */ - { 0x02, KEY_PRINT }, /* PREVIEW */ - - { 0x2a, KEY_SEARCH }, /* AUTOSCAN */ - { 0x1a, KEY_SLEEP }, /* FREEZE */ - { 0x3a, KEY_CAMERA }, /* SNAPSHOT */ - { 0x0a, KEY_MUTE }, /* MUTE */ - - { 0x26, KEY_RECORD }, /* RECORD */ - { 0x16, KEY_PAUSE }, /* PAUSE */ - { 0x36, KEY_STOP }, /* STOP */ - { 0x06, KEY_PLAY }, /* PLAY */ - - { 0x2e, KEY_RED }, /* RED */ - { 0x21, KEY_GREEN }, /* GREEN */ - { 0x0e, KEY_YELLOW }, /* YELLOW */ - { 0x01, KEY_BLUE }, /* BLUE */ - - { 0x1e, KEY_VOLUMEDOWN }, /* VOLUME- */ - { 0x3e, KEY_VOLUMEUP }, /* VOLUME+ */ - { 0x11, KEY_CHANNELDOWN }, /* CHANNEL/PAGE- */ - { 0x31, KEY_CHANNELUP } /* CHANNEL/PAGE+ */ -}; - -static struct rc_keymap avermedia_map = { - .map = { - .scan = avermedia, - .size = ARRAY_SIZE(avermedia), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_AVERMEDIA, - } -}; - -static int __init init_rc_map_avermedia(void) -{ - return ir_register_map(&avermedia_map); -} - -static void __exit exit_rc_map_avermedia(void) -{ - ir_unregister_map(&avermedia_map); -} - -module_init(init_rc_map_avermedia) -module_exit(exit_rc_map_avermedia) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-avertv-303.c b/drivers/media/IR/keymaps/rc-avertv-303.c deleted file mode 100644 index 971c59d..0000000 --- a/drivers/media/IR/keymaps/rc-avertv-303.c +++ /dev/null @@ -1,85 +0,0 @@ -/* avertv-303.h - Keytable for avertv_303 Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* AVERTV STUDIO 303 Remote */ - -static struct ir_scancode avertv_303[] = { - { 0x2a, KEY_1 }, - { 0x32, KEY_2 }, - { 0x3a, KEY_3 }, - { 0x4a, KEY_4 }, - { 0x52, KEY_5 }, - { 0x5a, KEY_6 }, - { 0x6a, KEY_7 }, - { 0x72, KEY_8 }, - { 0x7a, KEY_9 }, - { 0x0e, KEY_0 }, - - { 0x02, KEY_POWER }, - { 0x22, KEY_VIDEO }, - { 0x42, KEY_AUDIO }, - { 0x62, KEY_ZOOM }, - { 0x0a, KEY_TV }, - { 0x12, KEY_CD }, - { 0x1a, KEY_TEXT }, - - { 0x16, KEY_SUBTITLE }, - { 0x1e, KEY_REWIND }, - { 0x06, KEY_PRINT }, - - { 0x2e, KEY_SEARCH }, - { 0x36, KEY_SLEEP }, - { 0x3e, KEY_SHUFFLE }, - { 0x26, KEY_MUTE }, - - { 0x4e, KEY_RECORD }, - { 0x56, KEY_PAUSE }, - { 0x5e, KEY_STOP }, - { 0x46, KEY_PLAY }, - - { 0x6e, KEY_RED }, - { 0x0b, KEY_GREEN }, - { 0x66, KEY_YELLOW }, - { 0x03, KEY_BLUE }, - - { 0x76, KEY_LEFT }, - { 0x7e, KEY_RIGHT }, - { 0x13, KEY_DOWN }, - { 0x1b, KEY_UP }, -}; - -static struct rc_keymap avertv_303_map = { - .map = { - .scan = avertv_303, - .size = ARRAY_SIZE(avertv_303), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_AVERTV_303, - } -}; - -static int __init init_rc_map_avertv_303(void) -{ - return ir_register_map(&avertv_303_map); -} - -static void __exit exit_rc_map_avertv_303(void) -{ - ir_unregister_map(&avertv_303_map); -} - -module_init(init_rc_map_avertv_303) -module_exit(exit_rc_map_avertv_303) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-azurewave-ad-tu700.c b/drivers/media/IR/keymaps/rc-azurewave-ad-tu700.c deleted file mode 100644 index e087614..0000000 --- a/drivers/media/IR/keymaps/rc-azurewave-ad-tu700.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * TwinHan AzureWave AD-TU700(704J) remote controller keytable - * - * Copyright (C) 2010 Antti Palosaari - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -static struct ir_scancode azurewave_ad_tu700[] = { - { 0x0000, KEY_TAB }, /* Tab */ - { 0x0001, KEY_2 }, - { 0x0002, KEY_CHANNELDOWN }, - { 0x0003, KEY_1 }, - { 0x0004, KEY_MENU }, /* Record List */ - { 0x0005, KEY_CHANNELUP }, - { 0x0006, KEY_3 }, - { 0x0007, KEY_SLEEP }, /* Hibernate */ - { 0x0008, KEY_VIDEO }, /* A/V */ - { 0x0009, KEY_4 }, - { 0x000a, KEY_VOLUMEDOWN }, - { 0x000c, KEY_CANCEL }, /* Cancel */ - { 0x000d, KEY_7 }, - { 0x000e, KEY_AGAIN }, /* Recall */ - { 0x000f, KEY_TEXT }, /* Teletext */ - { 0x0010, KEY_MUTE }, - { 0x0011, KEY_RECORD }, - { 0x0012, KEY_FASTFORWARD }, /* FF >> */ - { 0x0013, KEY_BACK }, /* Back */ - { 0x0014, KEY_PLAY }, - { 0x0015, KEY_0 }, - { 0x0016, KEY_POWER2 }, /* [red power button] */ - { 0x0017, KEY_FAVORITES }, /* Favorite List */ - { 0x0018, KEY_RED }, - { 0x0019, KEY_8 }, - { 0x001a, KEY_STOP }, - { 0x001b, KEY_9 }, - { 0x001c, KEY_EPG }, /* Info/EPG */ - { 0x001d, KEY_5 }, - { 0x001e, KEY_VOLUMEUP }, - { 0x001f, KEY_6 }, - { 0x0040, KEY_REWIND }, /* FR << */ - { 0x0041, KEY_PREVIOUS }, /* Replay */ - { 0x0042, KEY_NEXT }, /* Skip */ - { 0x0043, KEY_SUBTITLE }, /* Subtitle / CC */ - { 0x0045, KEY_KPPLUS }, /* Zoom+ */ - { 0x0046, KEY_KPMINUS }, /* Zoom- */ - { 0x0047, KEY_NEW }, /* PIP */ - { 0x0048, KEY_INFO }, /* Preview */ - { 0x0049, KEY_MODE }, /* L/R */ - { 0x004a, KEY_CLEAR }, /* Clear */ - { 0x004b, KEY_UP }, /* up arrow */ - { 0x004c, KEY_PAUSE }, - { 0x004d, KEY_ZOOM }, /* Full Screen */ - { 0x004e, KEY_LEFT }, /* left arrow */ - { 0x004f, KEY_OK }, /* Enter / ok */ - { 0x0050, KEY_LANGUAGE }, /* SAP */ - { 0x0051, KEY_DOWN }, /* down arrow */ - { 0x0052, KEY_RIGHT }, /* right arrow */ - { 0x0053, KEY_GREEN }, - { 0x0054, KEY_CAMERA }, /* Capture */ - { 0x005e, KEY_YELLOW }, - { 0x005f, KEY_BLUE }, -}; - -static struct rc_keymap azurewave_ad_tu700_map = { - .map = { - .scan = azurewave_ad_tu700, - .size = ARRAY_SIZE(azurewave_ad_tu700), - .ir_type = IR_TYPE_NEC, - .name = RC_MAP_AZUREWAVE_AD_TU700, - } -}; - -static int __init init_rc_map_azurewave_ad_tu700(void) -{ - return ir_register_map(&azurewave_ad_tu700_map); -} - -static void __exit exit_rc_map_azurewave_ad_tu700(void) -{ - ir_unregister_map(&azurewave_ad_tu700_map); -} - -module_init(init_rc_map_azurewave_ad_tu700) -module_exit(exit_rc_map_azurewave_ad_tu700) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/IR/keymaps/rc-behold-columbus.c b/drivers/media/IR/keymaps/rc-behold-columbus.c deleted file mode 100644 index 9f56c98..0000000 --- a/drivers/media/IR/keymaps/rc-behold-columbus.c +++ /dev/null @@ -1,108 +0,0 @@ -/* behold-columbus.h - Keytable for behold_columbus Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Beholder Intl. Ltd. 2008 - * Dmitry Belimov d.belimov@google.com - * Keytable is used by BeholdTV Columbus - * The "ascii-art picture" below (in comments, first row - * is the keycode in hex, and subsequent row(s) shows - * the button labels (several variants when appropriate) - * helps to descide which keycodes to assign to the buttons. - */ - -static struct ir_scancode behold_columbus[] = { - - /* 0x13 0x11 0x1C 0x12 * - * Mute Source TV/FM Power * - * */ - - { 0x13, KEY_MUTE }, - { 0x11, KEY_PROPS }, - { 0x1C, KEY_TUNER }, /* KEY_TV/KEY_RADIO */ - { 0x12, KEY_POWER }, - - /* 0x01 0x02 0x03 0x0D * - * 1 2 3 Stereo * - * * - * 0x04 0x05 0x06 0x19 * - * 4 5 6 Snapshot * - * * - * 0x07 0x08 0x09 0x10 * - * 7 8 9 Zoom * - * */ - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x0D, KEY_SETUP }, /* Setup key */ - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x19, KEY_CAMERA }, /* Snapshot key */ - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - { 0x10, KEY_ZOOM }, - - /* 0x0A 0x00 0x0B 0x0C * - * RECALL 0 ChannelUp VolumeUp * - * */ - { 0x0A, KEY_AGAIN }, - { 0x00, KEY_0 }, - { 0x0B, KEY_CHANNELUP }, - { 0x0C, KEY_VOLUMEUP }, - - /* 0x1B 0x1D 0x15 0x18 * - * Timeshift Record ChannelDown VolumeDown * - * */ - - { 0x1B, KEY_TIME }, - { 0x1D, KEY_RECORD }, - { 0x15, KEY_CHANNELDOWN }, - { 0x18, KEY_VOLUMEDOWN }, - - /* 0x0E 0x1E 0x0F 0x1A * - * Stop Pause Previouse Next * - * */ - - { 0x0E, KEY_STOP }, - { 0x1E, KEY_PAUSE }, - { 0x0F, KEY_PREVIOUS }, - { 0x1A, KEY_NEXT }, - -}; - -static struct rc_keymap behold_columbus_map = { - .map = { - .scan = behold_columbus, - .size = ARRAY_SIZE(behold_columbus), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_BEHOLD_COLUMBUS, - } -}; - -static int __init init_rc_map_behold_columbus(void) -{ - return ir_register_map(&behold_columbus_map); -} - -static void __exit exit_rc_map_behold_columbus(void) -{ - ir_unregister_map(&behold_columbus_map); -} - -module_init(init_rc_map_behold_columbus) -module_exit(exit_rc_map_behold_columbus) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-behold.c b/drivers/media/IR/keymaps/rc-behold.c deleted file mode 100644 index abc140b..0000000 --- a/drivers/media/IR/keymaps/rc-behold.c +++ /dev/null @@ -1,141 +0,0 @@ -/* behold.h - Keytable for behold Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* - * Igor Kuznetsov - * Andrey J. Melnikov - * - * Keytable is used by BeholdTV 60x series, M6 series at - * least, and probably other cards too. - * The "ascii-art picture" below (in comments, first row - * is the keycode in hex, and subsequent row(s) shows - * the button labels (several variants when appropriate) - * helps to descide which keycodes to assign to the buttons. - */ - -static struct ir_scancode behold[] = { - - /* 0x1c 0x12 * - * TV/FM POWER * - * */ - { 0x1c, KEY_TUNER }, /* XXX KEY_TV / KEY_RADIO */ - { 0x12, KEY_POWER }, - - /* 0x01 0x02 0x03 * - * 1 2 3 * - * * - * 0x04 0x05 0x06 * - * 4 5 6 * - * * - * 0x07 0x08 0x09 * - * 7 8 9 * - * */ - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - /* 0x0a 0x00 0x17 * - * RECALL 0 MODE * - * */ - { 0x0a, KEY_AGAIN }, - { 0x00, KEY_0 }, - { 0x17, KEY_MODE }, - - /* 0x14 0x10 * - * ASPECT FULLSCREEN * - * */ - { 0x14, KEY_SCREEN }, - { 0x10, KEY_ZOOM }, - - /* 0x0b * - * Up * - * * - * 0x18 0x16 0x0c * - * Left Ok Right * - * * - * 0x015 * - * Down * - * */ - { 0x0b, KEY_CHANNELUP }, - { 0x18, KEY_VOLUMEDOWN }, - { 0x16, KEY_OK }, /* XXX KEY_ENTER */ - { 0x0c, KEY_VOLUMEUP }, - { 0x15, KEY_CHANNELDOWN }, - - /* 0x11 0x0d * - * MUTE INFO * - * */ - { 0x11, KEY_MUTE }, - { 0x0d, KEY_INFO }, - - /* 0x0f 0x1b 0x1a * - * RECORD PLAY/PAUSE STOP * - * * - * 0x0e 0x1f 0x1e * - *TELETEXT AUDIO SOURCE * - * RED YELLOW * - * */ - { 0x0f, KEY_RECORD }, - { 0x1b, KEY_PLAYPAUSE }, - { 0x1a, KEY_STOP }, - { 0x0e, KEY_TEXT }, - { 0x1f, KEY_RED }, /*XXX KEY_AUDIO */ - { 0x1e, KEY_YELLOW }, /*XXX KEY_SOURCE */ - - /* 0x1d 0x13 0x19 * - * SLEEP PREVIEW DVB * - * GREEN BLUE * - * */ - { 0x1d, KEY_SLEEP }, - { 0x13, KEY_GREEN }, - { 0x19, KEY_BLUE }, /* XXX KEY_SAT */ - - /* 0x58 0x5c * - * FREEZE SNAPSHOT * - * */ - { 0x58, KEY_SLOW }, - { 0x5c, KEY_CAMERA }, - -}; - -static struct rc_keymap behold_map = { - .map = { - .scan = behold, - .size = ARRAY_SIZE(behold), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_BEHOLD, - } -}; - -static int __init init_rc_map_behold(void) -{ - return ir_register_map(&behold_map); -} - -static void __exit exit_rc_map_behold(void) -{ - ir_unregister_map(&behold_map); -} - -module_init(init_rc_map_behold) -module_exit(exit_rc_map_behold) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-budget-ci-old.c b/drivers/media/IR/keymaps/rc-budget-ci-old.c deleted file mode 100644 index 64c2ac9..0000000 --- a/drivers/media/IR/keymaps/rc-budget-ci-old.c +++ /dev/null @@ -1,92 +0,0 @@ -/* budget-ci-old.h - Keytable for budget_ci_old Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* From reading the following remotes: - * Zenith Universal 7 / TV Mode 807 / VCR Mode 837 - * Hauppauge (from NOVA-CI-s box product) - * This is a "middle of the road" approach, differences are noted - */ - -static struct ir_scancode budget_ci_old[] = { - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - { 0x0a, KEY_ENTER }, - { 0x0b, KEY_RED }, - { 0x0c, KEY_POWER }, /* RADIO on Hauppauge */ - { 0x0d, KEY_MUTE }, - { 0x0f, KEY_A }, /* TV on Hauppauge */ - { 0x10, KEY_VOLUMEUP }, - { 0x11, KEY_VOLUMEDOWN }, - { 0x14, KEY_B }, - { 0x1c, KEY_UP }, - { 0x1d, KEY_DOWN }, - { 0x1e, KEY_OPTION }, /* RESERVED on Hauppauge */ - { 0x1f, KEY_BREAK }, - { 0x20, KEY_CHANNELUP }, - { 0x21, KEY_CHANNELDOWN }, - { 0x22, KEY_PREVIOUS }, /* Prev Ch on Zenith, SOURCE on Hauppauge */ - { 0x24, KEY_RESTART }, - { 0x25, KEY_OK }, - { 0x26, KEY_CYCLEWINDOWS }, /* MINIMIZE on Hauppauge */ - { 0x28, KEY_ENTER }, /* VCR mode on Zenith */ - { 0x29, KEY_PAUSE }, - { 0x2b, KEY_RIGHT }, - { 0x2c, KEY_LEFT }, - { 0x2e, KEY_MENU }, /* FULL SCREEN on Hauppauge */ - { 0x30, KEY_SLOW }, - { 0x31, KEY_PREVIOUS }, /* VCR mode on Zenith */ - { 0x32, KEY_REWIND }, - { 0x34, KEY_FASTFORWARD }, - { 0x35, KEY_PLAY }, - { 0x36, KEY_STOP }, - { 0x37, KEY_RECORD }, - { 0x38, KEY_TUNER }, /* TV/VCR on Zenith */ - { 0x3a, KEY_C }, - { 0x3c, KEY_EXIT }, - { 0x3d, KEY_POWER2 }, - { 0x3e, KEY_TUNER }, -}; - -static struct rc_keymap budget_ci_old_map = { - .map = { - .scan = budget_ci_old, - .size = ARRAY_SIZE(budget_ci_old), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_BUDGET_CI_OLD, - } -}; - -static int __init init_rc_map_budget_ci_old(void) -{ - return ir_register_map(&budget_ci_old_map); -} - -static void __exit exit_rc_map_budget_ci_old(void) -{ - ir_unregister_map(&budget_ci_old_map); -} - -module_init(init_rc_map_budget_ci_old) -module_exit(exit_rc_map_budget_ci_old) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-cinergy-1400.c b/drivers/media/IR/keymaps/rc-cinergy-1400.c deleted file mode 100644 index 074f2c2..0000000 --- a/drivers/media/IR/keymaps/rc-cinergy-1400.c +++ /dev/null @@ -1,84 +0,0 @@ -/* cinergy-1400.h - Keytable for cinergy_1400 Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Cinergy 1400 DVB-T */ - -static struct ir_scancode cinergy_1400[] = { - { 0x01, KEY_POWER }, - { 0x02, KEY_1 }, - { 0x03, KEY_2 }, - { 0x04, KEY_3 }, - { 0x05, KEY_4 }, - { 0x06, KEY_5 }, - { 0x07, KEY_6 }, - { 0x08, KEY_7 }, - { 0x09, KEY_8 }, - { 0x0a, KEY_9 }, - { 0x0c, KEY_0 }, - - { 0x0b, KEY_VIDEO }, - { 0x0d, KEY_REFRESH }, - { 0x0e, KEY_SELECT }, - { 0x0f, KEY_EPG }, - { 0x10, KEY_UP }, - { 0x11, KEY_LEFT }, - { 0x12, KEY_OK }, - { 0x13, KEY_RIGHT }, - { 0x14, KEY_DOWN }, - { 0x15, KEY_TEXT }, - { 0x16, KEY_INFO }, - - { 0x17, KEY_RED }, - { 0x18, KEY_GREEN }, - { 0x19, KEY_YELLOW }, - { 0x1a, KEY_BLUE }, - - { 0x1b, KEY_CHANNELUP }, - { 0x1c, KEY_VOLUMEUP }, - { 0x1d, KEY_MUTE }, - { 0x1e, KEY_VOLUMEDOWN }, - { 0x1f, KEY_CHANNELDOWN }, - - { 0x40, KEY_PAUSE }, - { 0x4c, KEY_PLAY }, - { 0x58, KEY_RECORD }, - { 0x54, KEY_PREVIOUS }, - { 0x48, KEY_STOP }, - { 0x5c, KEY_NEXT }, -}; - -static struct rc_keymap cinergy_1400_map = { - .map = { - .scan = cinergy_1400, - .size = ARRAY_SIZE(cinergy_1400), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_CINERGY_1400, - } -}; - -static int __init init_rc_map_cinergy_1400(void) -{ - return ir_register_map(&cinergy_1400_map); -} - -static void __exit exit_rc_map_cinergy_1400(void) -{ - ir_unregister_map(&cinergy_1400_map); -} - -module_init(init_rc_map_cinergy_1400) -module_exit(exit_rc_map_cinergy_1400) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-cinergy.c b/drivers/media/IR/keymaps/rc-cinergy.c deleted file mode 100644 index cf84c3d..0000000 --- a/drivers/media/IR/keymaps/rc-cinergy.c +++ /dev/null @@ -1,78 +0,0 @@ -/* cinergy.h - Keytable for cinergy Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode cinergy[] = { - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - { 0x0a, KEY_POWER }, - { 0x0b, KEY_PROG1 }, /* app */ - { 0x0c, KEY_ZOOM }, /* zoom/fullscreen */ - { 0x0d, KEY_CHANNELUP }, /* channel */ - { 0x0e, KEY_CHANNELDOWN }, /* channel- */ - { 0x0f, KEY_VOLUMEUP }, - { 0x10, KEY_VOLUMEDOWN }, - { 0x11, KEY_TUNER }, /* AV */ - { 0x12, KEY_NUMLOCK }, /* -/-- */ - { 0x13, KEY_AUDIO }, /* audio */ - { 0x14, KEY_MUTE }, - { 0x15, KEY_UP }, - { 0x16, KEY_DOWN }, - { 0x17, KEY_LEFT }, - { 0x18, KEY_RIGHT }, - { 0x19, BTN_LEFT, }, - { 0x1a, BTN_RIGHT, }, - { 0x1b, KEY_WWW }, /* text */ - { 0x1c, KEY_REWIND }, - { 0x1d, KEY_FORWARD }, - { 0x1e, KEY_RECORD }, - { 0x1f, KEY_PLAY }, - { 0x20, KEY_PREVIOUSSONG }, - { 0x21, KEY_NEXTSONG }, - { 0x22, KEY_PAUSE }, - { 0x23, KEY_STOP }, -}; - -static struct rc_keymap cinergy_map = { - .map = { - .scan = cinergy, - .size = ARRAY_SIZE(cinergy), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_CINERGY, - } -}; - -static int __init init_rc_map_cinergy(void) -{ - return ir_register_map(&cinergy_map); -} - -static void __exit exit_rc_map_cinergy(void) -{ - ir_unregister_map(&cinergy_map); -} - -module_init(init_rc_map_cinergy) -module_exit(exit_rc_map_cinergy) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-dib0700-nec.c b/drivers/media/IR/keymaps/rc-dib0700-nec.c deleted file mode 100644 index ae18320..0000000 --- a/drivers/media/IR/keymaps/rc-dib0700-nec.c +++ /dev/null @@ -1,124 +0,0 @@ -/* rc-dvb0700-big.c - Keytable for devices in dvb0700 - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * TODO: This table is a real mess, as it merges RC codes from several - * devices into a big table. It also has both RC-5 and NEC codes inside. - * It should be broken into small tables, and the protocols should properly - * be indentificated. - * - * The table were imported from dib0700_devices.c. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode dib0700_nec_table[] = { - /* Key codes for the Pixelview SBTVD remote */ - { 0x8613, KEY_MUTE }, - { 0x8612, KEY_POWER }, - { 0x8601, KEY_1 }, - { 0x8602, KEY_2 }, - { 0x8603, KEY_3 }, - { 0x8604, KEY_4 }, - { 0x8605, KEY_5 }, - { 0x8606, KEY_6 }, - { 0x8607, KEY_7 }, - { 0x8608, KEY_8 }, - { 0x8609, KEY_9 }, - { 0x8600, KEY_0 }, - { 0x860d, KEY_CHANNELUP }, - { 0x8619, KEY_CHANNELDOWN }, - { 0x8610, KEY_VOLUMEUP }, - { 0x860c, KEY_VOLUMEDOWN }, - - { 0x860a, KEY_CAMERA }, - { 0x860b, KEY_ZOOM }, - { 0x861b, KEY_BACKSPACE }, - { 0x8615, KEY_ENTER }, - - { 0x861d, KEY_UP }, - { 0x861e, KEY_DOWN }, - { 0x860e, KEY_LEFT }, - { 0x860f, KEY_RIGHT }, - - { 0x8618, KEY_RECORD }, - { 0x861a, KEY_STOP }, - - /* Key codes for the EvolutePC TVWay+ remote */ - { 0x7a00, KEY_MENU }, - { 0x7a01, KEY_RECORD }, - { 0x7a02, KEY_PLAY }, - { 0x7a03, KEY_STOP }, - { 0x7a10, KEY_CHANNELUP }, - { 0x7a11, KEY_CHANNELDOWN }, - { 0x7a12, KEY_VOLUMEUP }, - { 0x7a13, KEY_VOLUMEDOWN }, - { 0x7a40, KEY_POWER }, - { 0x7a41, KEY_MUTE }, - - /* Key codes for the Elgato EyeTV Diversity silver remote */ - { 0x4501, KEY_POWER }, - { 0x4502, KEY_MUTE }, - { 0x4503, KEY_1 }, - { 0x4504, KEY_2 }, - { 0x4505, KEY_3 }, - { 0x4506, KEY_4 }, - { 0x4507, KEY_5 }, - { 0x4508, KEY_6 }, - { 0x4509, KEY_7 }, - { 0x450a, KEY_8 }, - { 0x450b, KEY_9 }, - { 0x450c, KEY_LAST }, - { 0x450d, KEY_0 }, - { 0x450e, KEY_ENTER }, - { 0x450f, KEY_RED }, - { 0x4510, KEY_CHANNELUP }, - { 0x4511, KEY_GREEN }, - { 0x4512, KEY_VOLUMEDOWN }, - { 0x4513, KEY_OK }, - { 0x4514, KEY_VOLUMEUP }, - { 0x4515, KEY_YELLOW }, - { 0x4516, KEY_CHANNELDOWN }, - { 0x4517, KEY_BLUE }, - { 0x4518, KEY_LEFT }, /* Skip backwards */ - { 0x4519, KEY_PLAYPAUSE }, - { 0x451a, KEY_RIGHT }, /* Skip forward */ - { 0x451b, KEY_REWIND }, - { 0x451c, KEY_L }, /* Live */ - { 0x451d, KEY_FASTFORWARD }, - { 0x451e, KEY_STOP }, /* 'Reveal' for Teletext */ - { 0x451f, KEY_MENU }, /* KEY_TEXT for Teletext */ - { 0x4540, KEY_RECORD }, /* Font 'Size' for Teletext */ - { 0x4541, KEY_SCREEN }, /* Full screen toggle, 'Hold' for Teletext */ - { 0x4542, KEY_SELECT }, /* Select video input, 'Select' for Teletext */ -}; - -static struct rc_keymap dib0700_nec_map = { - .map = { - .scan = dib0700_nec_table, - .size = ARRAY_SIZE(dib0700_nec_table), - .ir_type = IR_TYPE_NEC, - .name = RC_MAP_DIB0700_NEC_TABLE, - } -}; - -static int __init init_rc_map(void) -{ - return ir_register_map(&dib0700_nec_map); -} - -static void __exit exit_rc_map(void) -{ - ir_unregister_map(&dib0700_nec_map); -} - -module_init(init_rc_map) -module_exit(exit_rc_map) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-dib0700-rc5.c b/drivers/media/IR/keymaps/rc-dib0700-rc5.c deleted file mode 100644 index 4a4797c..0000000 --- a/drivers/media/IR/keymaps/rc-dib0700-rc5.c +++ /dev/null @@ -1,235 +0,0 @@ -/* rc-dvb0700-big.c - Keytable for devices in dvb0700 - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * TODO: This table is a real mess, as it merges RC codes from several - * devices into a big table. It also has both RC-5 and NEC codes inside. - * It should be broken into small tables, and the protocols should properly - * be indentificated. - * - * The table were imported from dib0700_devices.c. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode dib0700_rc5_table[] = { - /* Key codes for the tiny Pinnacle remote*/ - { 0x0700, KEY_MUTE }, - { 0x0701, KEY_MENU }, /* Pinnacle logo */ - { 0x0739, KEY_POWER }, - { 0x0703, KEY_VOLUMEUP }, - { 0x0709, KEY_VOLUMEDOWN }, - { 0x0706, KEY_CHANNELUP }, - { 0x070c, KEY_CHANNELDOWN }, - { 0x070f, KEY_1 }, - { 0x0715, KEY_2 }, - { 0x0710, KEY_3 }, - { 0x0718, KEY_4 }, - { 0x071b, KEY_5 }, - { 0x071e, KEY_6 }, - { 0x0711, KEY_7 }, - { 0x0721, KEY_8 }, - { 0x0712, KEY_9 }, - { 0x0727, KEY_0 }, - { 0x0724, KEY_SCREEN }, /* 'Square' key */ - { 0x072a, KEY_TEXT }, /* 'T' key */ - { 0x072d, KEY_REWIND }, - { 0x0730, KEY_PLAY }, - { 0x0733, KEY_FASTFORWARD }, - { 0x0736, KEY_RECORD }, - { 0x073c, KEY_STOP }, - { 0x073f, KEY_CANCEL }, /* '?' key */ - - /* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */ - { 0xeb01, KEY_POWER }, - { 0xeb02, KEY_1 }, - { 0xeb03, KEY_2 }, - { 0xeb04, KEY_3 }, - { 0xeb05, KEY_4 }, - { 0xeb06, KEY_5 }, - { 0xeb07, KEY_6 }, - { 0xeb08, KEY_7 }, - { 0xeb09, KEY_8 }, - { 0xeb0a, KEY_9 }, - { 0xeb0b, KEY_VIDEO }, - { 0xeb0c, KEY_0 }, - { 0xeb0d, KEY_REFRESH }, - { 0xeb0f, KEY_EPG }, - { 0xeb10, KEY_UP }, - { 0xeb11, KEY_LEFT }, - { 0xeb12, KEY_OK }, - { 0xeb13, KEY_RIGHT }, - { 0xeb14, KEY_DOWN }, - { 0xeb16, KEY_INFO }, - { 0xeb17, KEY_RED }, - { 0xeb18, KEY_GREEN }, - { 0xeb19, KEY_YELLOW }, - { 0xeb1a, KEY_BLUE }, - { 0xeb1b, KEY_CHANNELUP }, - { 0xeb1c, KEY_VOLUMEUP }, - { 0xeb1d, KEY_MUTE }, - { 0xeb1e, KEY_VOLUMEDOWN }, - { 0xeb1f, KEY_CHANNELDOWN }, - { 0xeb40, KEY_PAUSE }, - { 0xeb41, KEY_HOME }, - { 0xeb42, KEY_MENU }, /* DVD Menu */ - { 0xeb43, KEY_SUBTITLE }, - { 0xeb44, KEY_TEXT }, /* Teletext */ - { 0xeb45, KEY_DELETE }, - { 0xeb46, KEY_TV }, - { 0xeb47, KEY_DVD }, - { 0xeb48, KEY_STOP }, - { 0xeb49, KEY_VIDEO }, - { 0xeb4a, KEY_AUDIO }, /* Music */ - { 0xeb4b, KEY_SCREEN }, /* Pic */ - { 0xeb4c, KEY_PLAY }, - { 0xeb4d, KEY_BACK }, - { 0xeb4e, KEY_REWIND }, - { 0xeb4f, KEY_FASTFORWARD }, - { 0xeb54, KEY_PREVIOUS }, - { 0xeb58, KEY_RECORD }, - { 0xeb5c, KEY_NEXT }, - - /* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */ - { 0x1e00, KEY_0 }, - { 0x1e01, KEY_1 }, - { 0x1e02, KEY_2 }, - { 0x1e03, KEY_3 }, - { 0x1e04, KEY_4 }, - { 0x1e05, KEY_5 }, - { 0x1e06, KEY_6 }, - { 0x1e07, KEY_7 }, - { 0x1e08, KEY_8 }, - { 0x1e09, KEY_9 }, - { 0x1e0a, KEY_KPASTERISK }, - { 0x1e0b, KEY_RED }, - { 0x1e0c, KEY_RADIO }, - { 0x1e0d, KEY_MENU }, - { 0x1e0e, KEY_GRAVE }, /* # */ - { 0x1e0f, KEY_MUTE }, - { 0x1e10, KEY_VOLUMEUP }, - { 0x1e11, KEY_VOLUMEDOWN }, - { 0x1e12, KEY_CHANNEL }, - { 0x1e14, KEY_UP }, - { 0x1e15, KEY_DOWN }, - { 0x1e16, KEY_LEFT }, - { 0x1e17, KEY_RIGHT }, - { 0x1e18, KEY_VIDEO }, - { 0x1e19, KEY_AUDIO }, - { 0x1e1a, KEY_MEDIA }, - { 0x1e1b, KEY_EPG }, - { 0x1e1c, KEY_TV }, - { 0x1e1e, KEY_NEXT }, - { 0x1e1f, KEY_BACK }, - { 0x1e20, KEY_CHANNELUP }, - { 0x1e21, KEY_CHANNELDOWN }, - { 0x1e24, KEY_LAST }, /* Skip backwards */ - { 0x1e25, KEY_OK }, - { 0x1e29, KEY_BLUE}, - { 0x1e2e, KEY_GREEN }, - { 0x1e30, KEY_PAUSE }, - { 0x1e32, KEY_REWIND }, - { 0x1e34, KEY_FASTFORWARD }, - { 0x1e35, KEY_PLAY }, - { 0x1e36, KEY_STOP }, - { 0x1e37, KEY_RECORD }, - { 0x1e38, KEY_YELLOW }, - { 0x1e3b, KEY_GOTO }, - { 0x1e3d, KEY_POWER }, - - /* Key codes for the Leadtek Winfast DTV Dongle */ - { 0x0042, KEY_POWER }, - { 0x077c, KEY_TUNER }, - { 0x0f4e, KEY_PRINT }, /* PREVIEW */ - { 0x0840, KEY_SCREEN }, /* full screen toggle*/ - { 0x0f71, KEY_DOT }, /* frequency */ - { 0x0743, KEY_0 }, - { 0x0c41, KEY_1 }, - { 0x0443, KEY_2 }, - { 0x0b7f, KEY_3 }, - { 0x0e41, KEY_4 }, - { 0x0643, KEY_5 }, - { 0x097f, KEY_6 }, - { 0x0d7e, KEY_7 }, - { 0x057c, KEY_8 }, - { 0x0a40, KEY_9 }, - { 0x0e4e, KEY_CLEAR }, - { 0x047c, KEY_CHANNEL }, /* show channel number */ - { 0x0f41, KEY_LAST }, /* recall */ - { 0x0342, KEY_MUTE }, - { 0x064c, KEY_RESERVED }, /* PIP button*/ - { 0x0172, KEY_SHUFFLE }, /* SNAPSHOT */ - { 0x0c4e, KEY_PLAYPAUSE }, /* TIMESHIFT */ - { 0x0b70, KEY_RECORD }, - { 0x037d, KEY_VOLUMEUP }, - { 0x017d, KEY_VOLUMEDOWN }, - { 0x0242, KEY_CHANNELUP }, - { 0x007d, KEY_CHANNELDOWN }, - - /* Key codes for Nova-TD "credit card" remote control. */ - { 0x1d00, KEY_0 }, - { 0x1d01, KEY_1 }, - { 0x1d02, KEY_2 }, - { 0x1d03, KEY_3 }, - { 0x1d04, KEY_4 }, - { 0x1d05, KEY_5 }, - { 0x1d06, KEY_6 }, - { 0x1d07, KEY_7 }, - { 0x1d08, KEY_8 }, - { 0x1d09, KEY_9 }, - { 0x1d0a, KEY_TEXT }, - { 0x1d0d, KEY_MENU }, - { 0x1d0f, KEY_MUTE }, - { 0x1d10, KEY_VOLUMEUP }, - { 0x1d11, KEY_VOLUMEDOWN }, - { 0x1d12, KEY_CHANNEL }, - { 0x1d14, KEY_UP }, - { 0x1d15, KEY_DOWN }, - { 0x1d16, KEY_LEFT }, - { 0x1d17, KEY_RIGHT }, - { 0x1d1c, KEY_TV }, - { 0x1d1e, KEY_NEXT }, - { 0x1d1f, KEY_BACK }, - { 0x1d20, KEY_CHANNELUP }, - { 0x1d21, KEY_CHANNELDOWN }, - { 0x1d24, KEY_LAST }, - { 0x1d25, KEY_OK }, - { 0x1d30, KEY_PAUSE }, - { 0x1d32, KEY_REWIND }, - { 0x1d34, KEY_FASTFORWARD }, - { 0x1d35, KEY_PLAY }, - { 0x1d36, KEY_STOP }, - { 0x1d37, KEY_RECORD }, - { 0x1d3b, KEY_GOTO }, - { 0x1d3d, KEY_POWER }, -}; - -static struct rc_keymap dib0700_rc5_map = { - .map = { - .scan = dib0700_rc5_table, - .size = ARRAY_SIZE(dib0700_rc5_table), - .ir_type = IR_TYPE_RC5, - .name = RC_MAP_DIB0700_RC5_TABLE, - } -}; - -static int __init init_rc_map(void) -{ - return ir_register_map(&dib0700_rc5_map); -} - -static void __exit exit_rc_map(void) -{ - ir_unregister_map(&dib0700_rc5_map); -} - -module_init(init_rc_map) -module_exit(exit_rc_map) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-digitalnow-tinytwin.c b/drivers/media/IR/keymaps/rc-digitalnow-tinytwin.c deleted file mode 100644 index 63e469e..0000000 --- a/drivers/media/IR/keymaps/rc-digitalnow-tinytwin.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * DigitalNow TinyTwin remote controller keytable - * - * Copyright (C) 2010 Antti Palosaari - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -static struct ir_scancode digitalnow_tinytwin[] = { - { 0x0000, KEY_MUTE }, /* [symbol speaker] */ - { 0x0001, KEY_VOLUMEUP }, - { 0x0002, KEY_POWER2 }, /* TV [power button] */ - { 0x0003, KEY_2 }, - { 0x0004, KEY_3 }, - { 0x0005, KEY_4 }, - { 0x0006, KEY_6 }, - { 0x0007, KEY_7 }, - { 0x0008, KEY_8 }, - { 0x0009, KEY_NUMERIC_STAR }, /* [*] */ - { 0x000a, KEY_0 }, - { 0x000b, KEY_NUMERIC_POUND }, /* [#] */ - { 0x000c, KEY_RIGHT }, /* [right arrow] */ - { 0x000d, KEY_HOMEPAGE }, /* [symbol home] Start */ - { 0x000e, KEY_RED }, /* [red] Videos */ - { 0x0010, KEY_POWER }, /* PC [power button] */ - { 0x0011, KEY_YELLOW }, /* [yellow] Pictures */ - { 0x0012, KEY_DOWN }, /* [down arrow] */ - { 0x0013, KEY_GREEN }, /* [green] Music */ - { 0x0014, KEY_CYCLEWINDOWS }, /* BACK */ - { 0x0015, KEY_FAVORITES }, /* MORE */ - { 0x0016, KEY_UP }, /* [up arrow] */ - { 0x0017, KEY_LEFT }, /* [left arrow] */ - { 0x0018, KEY_OK }, /* OK */ - { 0x0019, KEY_BLUE }, /* [blue] MyTV */ - { 0x001a, KEY_REWIND }, /* REW [<<] */ - { 0x001b, KEY_PLAY }, /* PLAY */ - { 0x001c, KEY_5 }, - { 0x001d, KEY_9 }, - { 0x001e, KEY_VOLUMEDOWN }, - { 0x001f, KEY_1 }, - { 0x0040, KEY_STOP }, /* STOP */ - { 0x0042, KEY_PAUSE }, /* PAUSE */ - { 0x0043, KEY_SCREEN }, /* Aspect */ - { 0x0044, KEY_FORWARD }, /* FWD [>>] */ - { 0x0045, KEY_NEXT }, /* SKIP */ - { 0x0048, KEY_RECORD }, /* RECORD */ - { 0x0049, KEY_VIDEO }, /* RTV */ - { 0x004a, KEY_EPG }, /* Guide */ - { 0x004b, KEY_CHANNELUP }, - { 0x004c, KEY_HELP }, /* Help */ - { 0x004d, KEY_RADIO }, /* Radio */ - { 0x004f, KEY_CHANNELDOWN }, - { 0x0050, KEY_DVD }, /* DVD */ - { 0x0051, KEY_AUDIO }, /* Audio */ - { 0x0052, KEY_TITLE }, /* Title */ - { 0x0053, KEY_NEW }, /* [symbol PIP?] */ - { 0x0057, KEY_MENU }, /* Mouse */ - { 0x005a, KEY_PREVIOUS }, /* REPLAY */ -}; - -static struct rc_keymap digitalnow_tinytwin_map = { - .map = { - .scan = digitalnow_tinytwin, - .size = ARRAY_SIZE(digitalnow_tinytwin), - .ir_type = IR_TYPE_NEC, - .name = RC_MAP_DIGITALNOW_TINYTWIN, - } -}; - -static int __init init_rc_map_digitalnow_tinytwin(void) -{ - return ir_register_map(&digitalnow_tinytwin_map); -} - -static void __exit exit_rc_map_digitalnow_tinytwin(void) -{ - ir_unregister_map(&digitalnow_tinytwin_map); -} - -module_init(init_rc_map_digitalnow_tinytwin) -module_exit(exit_rc_map_digitalnow_tinytwin) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/IR/keymaps/rc-digittrade.c b/drivers/media/IR/keymaps/rc-digittrade.c deleted file mode 100644 index 5dece78..0000000 --- a/drivers/media/IR/keymaps/rc-digittrade.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Digittrade DVB-T USB Stick remote controller keytable - * - * Copyright (C) 2010 Antti Palosaari - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -/* Digittrade DVB-T USB Stick remote controller. */ -/* Imported from af9015.h. - Initial keytable was from Alain Kalker */ - -/* Digittrade DVB-T USB Stick */ -static struct ir_scancode digittrade[] = { - { 0x0000, KEY_9 }, - { 0x0001, KEY_EPG }, /* EPG */ - { 0x0002, KEY_VOLUMEDOWN }, /* Vol Dn */ - { 0x0003, KEY_TEXT }, /* TELETEXT */ - { 0x0004, KEY_8 }, - { 0x0005, KEY_MUTE }, /* MUTE */ - { 0x0006, KEY_POWER2 }, /* POWER */ - { 0x0009, KEY_ZOOM }, /* FULLSCREEN */ - { 0x000a, KEY_RECORD }, /* RECORD */ - { 0x000d, KEY_SUBTITLE }, /* SUBTITLE */ - { 0x000e, KEY_STOP }, /* STOP */ - { 0x0010, KEY_OK }, /* RETURN */ - { 0x0011, KEY_2 }, - { 0x0012, KEY_4 }, - { 0x0015, KEY_3 }, - { 0x0016, KEY_5 }, - { 0x0017, KEY_CHANNELDOWN }, /* Ch Dn */ - { 0x0019, KEY_CHANNELUP }, /* CH Up */ - { 0x001a, KEY_PAUSE }, /* PAUSE */ - { 0x001b, KEY_1 }, - { 0x001d, KEY_AUDIO }, /* DUAL SOUND */ - { 0x001e, KEY_PLAY }, /* PLAY */ - { 0x001f, KEY_CAMERA }, /* SNAPSHOT */ - { 0x0040, KEY_VOLUMEUP }, /* Vol Up */ - { 0x0048, KEY_7 }, - { 0x004c, KEY_6 }, - { 0x004d, KEY_PLAYPAUSE }, /* TIMESHIFT */ - { 0x0054, KEY_0 }, -}; - -static struct rc_keymap digittrade_map = { - .map = { - .scan = digittrade, - .size = ARRAY_SIZE(digittrade), - .ir_type = IR_TYPE_NEC, - .name = RC_MAP_DIGITTRADE, - } -}; - -static int __init init_rc_map_digittrade(void) -{ - return ir_register_map(&digittrade_map); -} - -static void __exit exit_rc_map_digittrade(void) -{ - ir_unregister_map(&digittrade_map); -} - -module_init(init_rc_map_digittrade) -module_exit(exit_rc_map_digittrade) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/IR/keymaps/rc-dm1105-nec.c b/drivers/media/IR/keymaps/rc-dm1105-nec.c deleted file mode 100644 index 90684d0..0000000 --- a/drivers/media/IR/keymaps/rc-dm1105-nec.c +++ /dev/null @@ -1,76 +0,0 @@ -/* dm1105-nec.h - Keytable for dm1105_nec Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* DVBWorld remotes - Igor M. Liplianin - */ - -static struct ir_scancode dm1105_nec[] = { - { 0x0a, KEY_POWER2}, /* power */ - { 0x0c, KEY_MUTE}, /* mute */ - { 0x11, KEY_1}, - { 0x12, KEY_2}, - { 0x13, KEY_3}, - { 0x14, KEY_4}, - { 0x15, KEY_5}, - { 0x16, KEY_6}, - { 0x17, KEY_7}, - { 0x18, KEY_8}, - { 0x19, KEY_9}, - { 0x10, KEY_0}, - { 0x1c, KEY_CHANNELUP}, /* ch+ */ - { 0x0f, KEY_CHANNELDOWN}, /* ch- */ - { 0x1a, KEY_VOLUMEUP}, /* vol+ */ - { 0x0e, KEY_VOLUMEDOWN}, /* vol- */ - { 0x04, KEY_RECORD}, /* rec */ - { 0x09, KEY_CHANNEL}, /* fav */ - { 0x08, KEY_BACKSPACE}, /* rewind */ - { 0x07, KEY_FASTFORWARD}, /* fast */ - { 0x0b, KEY_PAUSE}, /* pause */ - { 0x02, KEY_ESC}, /* cancel */ - { 0x03, KEY_TAB}, /* tab */ - { 0x00, KEY_UP}, /* up */ - { 0x1f, KEY_ENTER}, /* ok */ - { 0x01, KEY_DOWN}, /* down */ - { 0x05, KEY_RECORD}, /* cap */ - { 0x06, KEY_STOP}, /* stop */ - { 0x40, KEY_ZOOM}, /* full */ - { 0x1e, KEY_TV}, /* tvmode */ - { 0x1b, KEY_B}, /* recall */ -}; - -static struct rc_keymap dm1105_nec_map = { - .map = { - .scan = dm1105_nec, - .size = ARRAY_SIZE(dm1105_nec), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_DM1105_NEC, - } -}; - -static int __init init_rc_map_dm1105_nec(void) -{ - return ir_register_map(&dm1105_nec_map); -} - -static void __exit exit_rc_map_dm1105_nec(void) -{ - ir_unregister_map(&dm1105_nec_map); -} - -module_init(init_rc_map_dm1105_nec) -module_exit(exit_rc_map_dm1105_nec) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-dntv-live-dvb-t.c b/drivers/media/IR/keymaps/rc-dntv-live-dvb-t.c deleted file mode 100644 index 8a4027a..0000000 --- a/drivers/media/IR/keymaps/rc-dntv-live-dvb-t.c +++ /dev/null @@ -1,78 +0,0 @@ -/* dntv-live-dvb-t.h - Keytable for dntv_live_dvb_t Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* DigitalNow DNTV Live DVB-T Remote */ - -static struct ir_scancode dntv_live_dvb_t[] = { - { 0x00, KEY_ESC }, /* 'go up a level?' */ - /* Keys 0 to 9 */ - { 0x0a, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - { 0x0b, KEY_TUNER }, /* tv/fm */ - { 0x0c, KEY_SEARCH }, /* scan */ - { 0x0d, KEY_STOP }, - { 0x0e, KEY_PAUSE }, - { 0x0f, KEY_LIST }, /* source */ - - { 0x10, KEY_MUTE }, - { 0x11, KEY_REWIND }, /* backward << */ - { 0x12, KEY_POWER }, - { 0x13, KEY_CAMERA }, /* snap */ - { 0x14, KEY_AUDIO }, /* stereo */ - { 0x15, KEY_CLEAR }, /* reset */ - { 0x16, KEY_PLAY }, - { 0x17, KEY_ENTER }, - { 0x18, KEY_ZOOM }, /* full screen */ - { 0x19, KEY_FASTFORWARD }, /* forward >> */ - { 0x1a, KEY_CHANNELUP }, - { 0x1b, KEY_VOLUMEUP }, - { 0x1c, KEY_INFO }, /* preview */ - { 0x1d, KEY_RECORD }, /* record */ - { 0x1e, KEY_CHANNELDOWN }, - { 0x1f, KEY_VOLUMEDOWN }, -}; - -static struct rc_keymap dntv_live_dvb_t_map = { - .map = { - .scan = dntv_live_dvb_t, - .size = ARRAY_SIZE(dntv_live_dvb_t), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_DNTV_LIVE_DVB_T, - } -}; - -static int __init init_rc_map_dntv_live_dvb_t(void) -{ - return ir_register_map(&dntv_live_dvb_t_map); -} - -static void __exit exit_rc_map_dntv_live_dvb_t(void) -{ - ir_unregister_map(&dntv_live_dvb_t_map); -} - -module_init(init_rc_map_dntv_live_dvb_t) -module_exit(exit_rc_map_dntv_live_dvb_t) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-dntv-live-dvbt-pro.c b/drivers/media/IR/keymaps/rc-dntv-live-dvbt-pro.c deleted file mode 100644 index 6f4d607..0000000 --- a/drivers/media/IR/keymaps/rc-dntv-live-dvbt-pro.c +++ /dev/null @@ -1,97 +0,0 @@ -/* dntv-live-dvbt-pro.h - Keytable for dntv_live_dvbt_pro Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* DigitalNow DNTV Live! DVB-T Pro Remote */ - -static struct ir_scancode dntv_live_dvbt_pro[] = { - { 0x16, KEY_POWER }, - { 0x5b, KEY_HOME }, - - { 0x55, KEY_TV }, /* live tv */ - { 0x58, KEY_TUNER }, /* digital Radio */ - { 0x5a, KEY_RADIO }, /* FM radio */ - { 0x59, KEY_DVD }, /* dvd menu */ - { 0x03, KEY_1 }, - { 0x01, KEY_2 }, - { 0x06, KEY_3 }, - { 0x09, KEY_4 }, - { 0x1d, KEY_5 }, - { 0x1f, KEY_6 }, - { 0x0d, KEY_7 }, - { 0x19, KEY_8 }, - { 0x1b, KEY_9 }, - { 0x0c, KEY_CANCEL }, - { 0x15, KEY_0 }, - { 0x4a, KEY_CLEAR }, - { 0x13, KEY_BACK }, - { 0x00, KEY_TAB }, - { 0x4b, KEY_UP }, - { 0x4e, KEY_LEFT }, - { 0x4f, KEY_OK }, - { 0x52, KEY_RIGHT }, - { 0x51, KEY_DOWN }, - { 0x1e, KEY_VOLUMEUP }, - { 0x0a, KEY_VOLUMEDOWN }, - { 0x02, KEY_CHANNELDOWN }, - { 0x05, KEY_CHANNELUP }, - { 0x11, KEY_RECORD }, - { 0x14, KEY_PLAY }, - { 0x4c, KEY_PAUSE }, - { 0x1a, KEY_STOP }, - { 0x40, KEY_REWIND }, - { 0x12, KEY_FASTFORWARD }, - { 0x41, KEY_PREVIOUSSONG }, /* replay |< */ - { 0x42, KEY_NEXTSONG }, /* skip >| */ - { 0x54, KEY_CAMERA }, /* capture */ - { 0x50, KEY_LANGUAGE }, /* sap */ - { 0x47, KEY_TV2 }, /* pip */ - { 0x4d, KEY_SCREEN }, - { 0x43, KEY_SUBTITLE }, - { 0x10, KEY_MUTE }, - { 0x49, KEY_AUDIO }, /* l/r */ - { 0x07, KEY_SLEEP }, - { 0x08, KEY_VIDEO }, /* a/v */ - { 0x0e, KEY_PREVIOUS }, /* recall */ - { 0x45, KEY_ZOOM }, /* zoom + */ - { 0x46, KEY_ANGLE }, /* zoom - */ - { 0x56, KEY_RED }, - { 0x57, KEY_GREEN }, - { 0x5c, KEY_YELLOW }, - { 0x5d, KEY_BLUE }, -}; - -static struct rc_keymap dntv_live_dvbt_pro_map = { - .map = { - .scan = dntv_live_dvbt_pro, - .size = ARRAY_SIZE(dntv_live_dvbt_pro), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_DNTV_LIVE_DVBT_PRO, - } -}; - -static int __init init_rc_map_dntv_live_dvbt_pro(void) -{ - return ir_register_map(&dntv_live_dvbt_pro_map); -} - -static void __exit exit_rc_map_dntv_live_dvbt_pro(void) -{ - ir_unregister_map(&dntv_live_dvbt_pro_map); -} - -module_init(init_rc_map_dntv_live_dvbt_pro) -module_exit(exit_rc_map_dntv_live_dvbt_pro) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-em-terratec.c b/drivers/media/IR/keymaps/rc-em-terratec.c deleted file mode 100644 index 3130c9c..0000000 --- a/drivers/media/IR/keymaps/rc-em-terratec.c +++ /dev/null @@ -1,69 +0,0 @@ -/* em-terratec.h - Keytable for em_terratec Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode em_terratec[] = { - { 0x01, KEY_CHANNEL }, - { 0x02, KEY_SELECT }, - { 0x03, KEY_MUTE }, - { 0x04, KEY_POWER }, - { 0x05, KEY_1 }, - { 0x06, KEY_2 }, - { 0x07, KEY_3 }, - { 0x08, KEY_CHANNELUP }, - { 0x09, KEY_4 }, - { 0x0a, KEY_5 }, - { 0x0b, KEY_6 }, - { 0x0c, KEY_CHANNELDOWN }, - { 0x0d, KEY_7 }, - { 0x0e, KEY_8 }, - { 0x0f, KEY_9 }, - { 0x10, KEY_VOLUMEUP }, - { 0x11, KEY_0 }, - { 0x12, KEY_MENU }, - { 0x13, KEY_PRINT }, - { 0x14, KEY_VOLUMEDOWN }, - { 0x16, KEY_PAUSE }, - { 0x18, KEY_RECORD }, - { 0x19, KEY_REWIND }, - { 0x1a, KEY_PLAY }, - { 0x1b, KEY_FORWARD }, - { 0x1c, KEY_BACKSPACE }, - { 0x1e, KEY_STOP }, - { 0x40, KEY_ZOOM }, -}; - -static struct rc_keymap em_terratec_map = { - .map = { - .scan = em_terratec, - .size = ARRAY_SIZE(em_terratec), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_EM_TERRATEC, - } -}; - -static int __init init_rc_map_em_terratec(void) -{ - return ir_register_map(&em_terratec_map); -} - -static void __exit exit_rc_map_em_terratec(void) -{ - ir_unregister_map(&em_terratec_map); -} - -module_init(init_rc_map_em_terratec) -module_exit(exit_rc_map_em_terratec) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-encore-enltv-fm53.c b/drivers/media/IR/keymaps/rc-encore-enltv-fm53.c deleted file mode 100644 index 4b81696..0000000 --- a/drivers/media/IR/keymaps/rc-encore-enltv-fm53.c +++ /dev/null @@ -1,81 +0,0 @@ -/* encore-enltv-fm53.h - Keytable for encore_enltv_fm53 Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Encore ENLTV-FM v5.3 - Mauro Carvalho Chehab - */ - -static struct ir_scancode encore_enltv_fm53[] = { - { 0x10, KEY_POWER2}, - { 0x06, KEY_MUTE}, - - { 0x09, KEY_1}, - { 0x1d, KEY_2}, - { 0x1f, KEY_3}, - { 0x19, KEY_4}, - { 0x1b, KEY_5}, - { 0x11, KEY_6}, - { 0x17, KEY_7}, - { 0x12, KEY_8}, - { 0x16, KEY_9}, - { 0x48, KEY_0}, - - { 0x04, KEY_LIST}, /* -/-- */ - { 0x40, KEY_LAST}, /* recall */ - - { 0x02, KEY_MODE}, /* TV/AV */ - { 0x05, KEY_CAMERA}, /* SNAPSHOT */ - - { 0x4c, KEY_CHANNELUP}, /* UP */ - { 0x00, KEY_CHANNELDOWN}, /* DOWN */ - { 0x0d, KEY_VOLUMEUP}, /* RIGHT */ - { 0x15, KEY_VOLUMEDOWN}, /* LEFT */ - { 0x49, KEY_ENTER}, /* OK */ - - { 0x54, KEY_RECORD}, - { 0x4d, KEY_PLAY}, /* pause */ - - { 0x1e, KEY_MENU}, /* video setting */ - { 0x0e, KEY_RIGHT}, /* <- */ - { 0x1a, KEY_LEFT}, /* -> */ - - { 0x0a, KEY_CLEAR}, /* video default */ - { 0x0c, KEY_ZOOM}, /* hide pannel */ - { 0x47, KEY_SLEEP}, /* shutdown */ -}; - -static struct rc_keymap encore_enltv_fm53_map = { - .map = { - .scan = encore_enltv_fm53, - .size = ARRAY_SIZE(encore_enltv_fm53), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_ENCORE_ENLTV_FM53, - } -}; - -static int __init init_rc_map_encore_enltv_fm53(void) -{ - return ir_register_map(&encore_enltv_fm53_map); -} - -static void __exit exit_rc_map_encore_enltv_fm53(void) -{ - ir_unregister_map(&encore_enltv_fm53_map); -} - -module_init(init_rc_map_encore_enltv_fm53) -module_exit(exit_rc_map_encore_enltv_fm53) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-encore-enltv.c b/drivers/media/IR/keymaps/rc-encore-enltv.c deleted file mode 100644 index 9fabffd..0000000 --- a/drivers/media/IR/keymaps/rc-encore-enltv.c +++ /dev/null @@ -1,112 +0,0 @@ -/* encore-enltv.h - Keytable for encore_enltv Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Encore ENLTV-FM - black plastic, white front cover with white glowing buttons - Juan Pablo Sormani */ - -static struct ir_scancode encore_enltv[] = { - - /* Power button does nothing, neither in Windows app, - although it sends data (used for BIOS wakeup?) */ - { 0x0d, KEY_MUTE }, - - { 0x1e, KEY_TV }, - { 0x00, KEY_VIDEO }, - { 0x01, KEY_AUDIO }, /* music */ - { 0x02, KEY_MHP }, /* picture */ - - { 0x1f, KEY_1 }, - { 0x03, KEY_2 }, - { 0x04, KEY_3 }, - { 0x05, KEY_4 }, - { 0x1c, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x1d, KEY_9 }, - { 0x0a, KEY_0 }, - - { 0x09, KEY_LIST }, /* -/-- */ - { 0x0b, KEY_LAST }, /* recall */ - - { 0x14, KEY_HOME }, /* win start menu */ - { 0x15, KEY_EXIT }, /* exit */ - { 0x16, KEY_CHANNELUP }, /* UP */ - { 0x12, KEY_CHANNELDOWN }, /* DOWN */ - { 0x0c, KEY_VOLUMEUP }, /* RIGHT */ - { 0x17, KEY_VOLUMEDOWN }, /* LEFT */ - - { 0x18, KEY_ENTER }, /* OK */ - - { 0x0e, KEY_ESC }, - { 0x13, KEY_CYCLEWINDOWS }, /* desktop */ - { 0x11, KEY_TAB }, - { 0x19, KEY_SWITCHVIDEOMODE }, /* switch */ - - { 0x1a, KEY_MENU }, - { 0x1b, KEY_ZOOM }, /* fullscreen */ - { 0x44, KEY_TIME }, /* time shift */ - { 0x40, KEY_MODE }, /* source */ - - { 0x5a, KEY_RECORD }, - { 0x42, KEY_PLAY }, /* play/pause */ - { 0x45, KEY_STOP }, - { 0x43, KEY_CAMERA }, /* camera icon */ - - { 0x48, KEY_REWIND }, - { 0x4a, KEY_FASTFORWARD }, - { 0x49, KEY_PREVIOUS }, - { 0x4b, KEY_NEXT }, - - { 0x4c, KEY_FAVORITES }, /* tv wall */ - { 0x4d, KEY_SOUND }, /* DVD sound */ - { 0x4e, KEY_LANGUAGE }, /* DVD lang */ - { 0x4f, KEY_TEXT }, /* DVD text */ - - { 0x50, KEY_SLEEP }, /* shutdown */ - { 0x51, KEY_MODE }, /* stereo > main */ - { 0x52, KEY_SELECT }, /* stereo > sap */ - { 0x53, KEY_PROG1 }, /* teletext */ - - - { 0x59, KEY_RED }, /* AP1 */ - { 0x41, KEY_GREEN }, /* AP2 */ - { 0x47, KEY_YELLOW }, /* AP3 */ - { 0x57, KEY_BLUE }, /* AP4 */ -}; - -static struct rc_keymap encore_enltv_map = { - .map = { - .scan = encore_enltv, - .size = ARRAY_SIZE(encore_enltv), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_ENCORE_ENLTV, - } -}; - -static int __init init_rc_map_encore_enltv(void) -{ - return ir_register_map(&encore_enltv_map); -} - -static void __exit exit_rc_map_encore_enltv(void) -{ - ir_unregister_map(&encore_enltv_map); -} - -module_init(init_rc_map_encore_enltv) -module_exit(exit_rc_map_encore_enltv) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-encore-enltv2.c b/drivers/media/IR/keymaps/rc-encore-enltv2.c deleted file mode 100644 index efefd51..0000000 --- a/drivers/media/IR/keymaps/rc-encore-enltv2.c +++ /dev/null @@ -1,90 +0,0 @@ -/* encore-enltv2.h - Keytable for encore_enltv2 Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Encore ENLTV2-FM - silver plastic - "Wand Media" written at the botton - Mauro Carvalho Chehab */ - -static struct ir_scancode encore_enltv2[] = { - { 0x4c, KEY_POWER2 }, - { 0x4a, KEY_TUNER }, - { 0x40, KEY_1 }, - { 0x60, KEY_2 }, - { 0x50, KEY_3 }, - { 0x70, KEY_4 }, - { 0x48, KEY_5 }, - { 0x68, KEY_6 }, - { 0x58, KEY_7 }, - { 0x78, KEY_8 }, - { 0x44, KEY_9 }, - { 0x54, KEY_0 }, - - { 0x64, KEY_LAST }, /* +100 */ - { 0x4e, KEY_AGAIN }, /* Recall */ - - { 0x6c, KEY_SWITCHVIDEOMODE }, /* Video Source */ - { 0x5e, KEY_MENU }, - { 0x56, KEY_SCREEN }, - { 0x7a, KEY_SETUP }, - - { 0x46, KEY_MUTE }, - { 0x5c, KEY_MODE }, /* Stereo */ - { 0x74, KEY_INFO }, - { 0x7c, KEY_CLEAR }, - - { 0x55, KEY_UP }, - { 0x49, KEY_DOWN }, - { 0x7e, KEY_LEFT }, - { 0x59, KEY_RIGHT }, - { 0x6a, KEY_ENTER }, - - { 0x42, KEY_VOLUMEUP }, - { 0x62, KEY_VOLUMEDOWN }, - { 0x52, KEY_CHANNELUP }, - { 0x72, KEY_CHANNELDOWN }, - - { 0x41, KEY_RECORD }, - { 0x51, KEY_CAMERA }, /* Snapshot */ - { 0x75, KEY_TIME }, /* Timeshift */ - { 0x71, KEY_TV2 }, /* PIP */ - - { 0x45, KEY_REWIND }, - { 0x6f, KEY_PAUSE }, - { 0x7d, KEY_FORWARD }, - { 0x79, KEY_STOP }, -}; - -static struct rc_keymap encore_enltv2_map = { - .map = { - .scan = encore_enltv2, - .size = ARRAY_SIZE(encore_enltv2), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_ENCORE_ENLTV2, - } -}; - -static int __init init_rc_map_encore_enltv2(void) -{ - return ir_register_map(&encore_enltv2_map); -} - -static void __exit exit_rc_map_encore_enltv2(void) -{ - ir_unregister_map(&encore_enltv2_map); -} - -module_init(init_rc_map_encore_enltv2) -module_exit(exit_rc_map_encore_enltv2) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-evga-indtube.c b/drivers/media/IR/keymaps/rc-evga-indtube.c deleted file mode 100644 index 3f3fb13..0000000 --- a/drivers/media/IR/keymaps/rc-evga-indtube.c +++ /dev/null @@ -1,61 +0,0 @@ -/* evga-indtube.h - Keytable for evga_indtube Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* EVGA inDtube - Devin Heitmueller - */ - -static struct ir_scancode evga_indtube[] = { - { 0x12, KEY_POWER}, - { 0x02, KEY_MODE}, /* TV */ - { 0x14, KEY_MUTE}, - { 0x1a, KEY_CHANNELUP}, - { 0x16, KEY_TV2}, /* PIP */ - { 0x1d, KEY_VOLUMEUP}, - { 0x05, KEY_CHANNELDOWN}, - { 0x0f, KEY_PLAYPAUSE}, - { 0x19, KEY_VOLUMEDOWN}, - { 0x1c, KEY_REWIND}, - { 0x0d, KEY_RECORD}, - { 0x18, KEY_FORWARD}, - { 0x1e, KEY_PREVIOUS}, - { 0x1b, KEY_STOP}, - { 0x1f, KEY_NEXT}, - { 0x13, KEY_CAMERA}, -}; - -static struct rc_keymap evga_indtube_map = { - .map = { - .scan = evga_indtube, - .size = ARRAY_SIZE(evga_indtube), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_EVGA_INDTUBE, - } -}; - -static int __init init_rc_map_evga_indtube(void) -{ - return ir_register_map(&evga_indtube_map); -} - -static void __exit exit_rc_map_evga_indtube(void) -{ - ir_unregister_map(&evga_indtube_map); -} - -module_init(init_rc_map_evga_indtube) -module_exit(exit_rc_map_evga_indtube) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-eztv.c b/drivers/media/IR/keymaps/rc-eztv.c deleted file mode 100644 index 660907a..0000000 --- a/drivers/media/IR/keymaps/rc-eztv.c +++ /dev/null @@ -1,96 +0,0 @@ -/* eztv.h - Keytable for eztv Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Alfons Geser - * updates from Job D. R. Borges */ - -static struct ir_scancode eztv[] = { - { 0x12, KEY_POWER }, - { 0x01, KEY_TV }, /* DVR */ - { 0x15, KEY_DVD }, /* DVD */ - { 0x17, KEY_AUDIO }, /* music */ - /* DVR mode / DVD mode / music mode */ - - { 0x1b, KEY_MUTE }, /* mute */ - { 0x02, KEY_LANGUAGE }, /* MTS/SAP / audio / autoseek */ - { 0x1e, KEY_SUBTITLE }, /* closed captioning / subtitle / seek */ - { 0x16, KEY_ZOOM }, /* full screen */ - { 0x1c, KEY_VIDEO }, /* video source / eject / delall */ - { 0x1d, KEY_RESTART }, /* playback / angle / del */ - { 0x2f, KEY_SEARCH }, /* scan / menu / playlist */ - { 0x30, KEY_CHANNEL }, /* CH surfing / bookmark / memo */ - - { 0x31, KEY_HELP }, /* help */ - { 0x32, KEY_MODE }, /* num/memo */ - { 0x33, KEY_ESC }, /* cancel */ - - { 0x0c, KEY_UP }, /* up */ - { 0x10, KEY_DOWN }, /* down */ - { 0x08, KEY_LEFT }, /* left */ - { 0x04, KEY_RIGHT }, /* right */ - { 0x03, KEY_SELECT }, /* select */ - - { 0x1f, KEY_REWIND }, /* rewind */ - { 0x20, KEY_PLAYPAUSE },/* play/pause */ - { 0x29, KEY_FORWARD }, /* forward */ - { 0x14, KEY_AGAIN }, /* repeat */ - { 0x2b, KEY_RECORD }, /* recording */ - { 0x2c, KEY_STOP }, /* stop */ - { 0x2d, KEY_PLAY }, /* play */ - { 0x2e, KEY_CAMERA }, /* snapshot / shuffle */ - - { 0x00, KEY_0 }, - { 0x05, KEY_1 }, - { 0x06, KEY_2 }, - { 0x07, KEY_3 }, - { 0x09, KEY_4 }, - { 0x0a, KEY_5 }, - { 0x0b, KEY_6 }, - { 0x0d, KEY_7 }, - { 0x0e, KEY_8 }, - { 0x0f, KEY_9 }, - - { 0x2a, KEY_VOLUMEUP }, - { 0x11, KEY_VOLUMEDOWN }, - { 0x18, KEY_CHANNELUP },/* CH.tracking up */ - { 0x19, KEY_CHANNELDOWN },/* CH.tracking down */ - - { 0x13, KEY_ENTER }, /* enter */ - { 0x21, KEY_DOT }, /* . (decimal dot) */ -}; - -static struct rc_keymap eztv_map = { - .map = { - .scan = eztv, - .size = ARRAY_SIZE(eztv), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_EZTV, - } -}; - -static int __init init_rc_map_eztv(void) -{ - return ir_register_map(&eztv_map); -} - -static void __exit exit_rc_map_eztv(void) -{ - ir_unregister_map(&eztv_map); -} - -module_init(init_rc_map_eztv) -module_exit(exit_rc_map_eztv) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-flydvb.c b/drivers/media/IR/keymaps/rc-flydvb.c deleted file mode 100644 index a173c81..0000000 --- a/drivers/media/IR/keymaps/rc-flydvb.c +++ /dev/null @@ -1,77 +0,0 @@ -/* flydvb.h - Keytable for flydvb Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode flydvb[] = { - { 0x01, KEY_ZOOM }, /* Full Screen */ - { 0x00, KEY_POWER }, /* Power */ - - { 0x03, KEY_1 }, - { 0x04, KEY_2 }, - { 0x05, KEY_3 }, - { 0x07, KEY_4 }, - { 0x08, KEY_5 }, - { 0x09, KEY_6 }, - { 0x0b, KEY_7 }, - { 0x0c, KEY_8 }, - { 0x0d, KEY_9 }, - { 0x06, KEY_AGAIN }, /* Recall */ - { 0x0f, KEY_0 }, - { 0x10, KEY_MUTE }, /* Mute */ - { 0x02, KEY_RADIO }, /* TV/Radio */ - { 0x1b, KEY_LANGUAGE }, /* SAP (Second Audio Program) */ - - { 0x14, KEY_VOLUMEUP }, /* VOL+ */ - { 0x17, KEY_VOLUMEDOWN }, /* VOL- */ - { 0x12, KEY_CHANNELUP }, /* CH+ */ - { 0x13, KEY_CHANNELDOWN }, /* CH- */ - { 0x1d, KEY_ENTER }, /* Enter */ - - { 0x1a, KEY_MODE }, /* PIP */ - { 0x18, KEY_TUNER }, /* Source */ - - { 0x1e, KEY_RECORD }, /* Record/Pause */ - { 0x15, KEY_ANGLE }, /* Swap (no label on key) */ - { 0x1c, KEY_PAUSE }, /* Timeshift/Pause */ - { 0x19, KEY_BACK }, /* Rewind << */ - { 0x0a, KEY_PLAYPAUSE }, /* Play/Pause */ - { 0x1f, KEY_FORWARD }, /* Forward >> */ - { 0x16, KEY_PREVIOUS }, /* Back |<< */ - { 0x11, KEY_STOP }, /* Stop */ - { 0x0e, KEY_NEXT }, /* End >>| */ -}; - -static struct rc_keymap flydvb_map = { - .map = { - .scan = flydvb, - .size = ARRAY_SIZE(flydvb), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_FLYDVB, - } -}; - -static int __init init_rc_map_flydvb(void) -{ - return ir_register_map(&flydvb_map); -} - -static void __exit exit_rc_map_flydvb(void) -{ - ir_unregister_map(&flydvb_map); -} - -module_init(init_rc_map_flydvb) -module_exit(exit_rc_map_flydvb) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-flyvideo.c b/drivers/media/IR/keymaps/rc-flyvideo.c deleted file mode 100644 index 9c73043..0000000 --- a/drivers/media/IR/keymaps/rc-flyvideo.c +++ /dev/null @@ -1,70 +0,0 @@ -/* flyvideo.h - Keytable for flyvideo Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode flyvideo[] = { - { 0x0f, KEY_0 }, - { 0x03, KEY_1 }, - { 0x04, KEY_2 }, - { 0x05, KEY_3 }, - { 0x07, KEY_4 }, - { 0x08, KEY_5 }, - { 0x09, KEY_6 }, - { 0x0b, KEY_7 }, - { 0x0c, KEY_8 }, - { 0x0d, KEY_9 }, - - { 0x0e, KEY_MODE }, /* Air/Cable */ - { 0x11, KEY_VIDEO }, /* Video */ - { 0x15, KEY_AUDIO }, /* Audio */ - { 0x00, KEY_POWER }, /* Power */ - { 0x18, KEY_TUNER }, /* AV Source */ - { 0x02, KEY_ZOOM }, /* Fullscreen */ - { 0x1a, KEY_LANGUAGE }, /* Stereo */ - { 0x1b, KEY_MUTE }, /* Mute */ - { 0x14, KEY_VOLUMEUP }, /* Volume + */ - { 0x17, KEY_VOLUMEDOWN },/* Volume - */ - { 0x12, KEY_CHANNELUP },/* Channel + */ - { 0x13, KEY_CHANNELDOWN },/* Channel - */ - { 0x06, KEY_AGAIN }, /* Recall */ - { 0x10, KEY_ENTER }, /* Enter */ - - { 0x19, KEY_BACK }, /* Rewind ( <<< ) */ - { 0x1f, KEY_FORWARD }, /* Forward ( >>> ) */ - { 0x0a, KEY_ANGLE }, /* no label, may be used as the PAUSE button */ -}; - -static struct rc_keymap flyvideo_map = { - .map = { - .scan = flyvideo, - .size = ARRAY_SIZE(flyvideo), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_FLYVIDEO, - } -}; - -static int __init init_rc_map_flyvideo(void) -{ - return ir_register_map(&flyvideo_map); -} - -static void __exit exit_rc_map_flyvideo(void) -{ - ir_unregister_map(&flyvideo_map); -} - -module_init(init_rc_map_flyvideo) -module_exit(exit_rc_map_flyvideo) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-fusionhdtv-mce.c b/drivers/media/IR/keymaps/rc-fusionhdtv-mce.c deleted file mode 100644 index cdb1038..0000000 --- a/drivers/media/IR/keymaps/rc-fusionhdtv-mce.c +++ /dev/null @@ -1,98 +0,0 @@ -/* fusionhdtv-mce.h - Keytable for fusionhdtv_mce Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* DViCO FUSION HDTV MCE remote */ - -static struct ir_scancode fusionhdtv_mce[] = { - - { 0x0b, KEY_1 }, - { 0x17, KEY_2 }, - { 0x1b, KEY_3 }, - { 0x07, KEY_4 }, - { 0x50, KEY_5 }, - { 0x54, KEY_6 }, - { 0x48, KEY_7 }, - { 0x4c, KEY_8 }, - { 0x58, KEY_9 }, - { 0x03, KEY_0 }, - - { 0x5e, KEY_OK }, - { 0x51, KEY_UP }, - { 0x53, KEY_DOWN }, - { 0x5b, KEY_LEFT }, - { 0x5f, KEY_RIGHT }, - - { 0x02, KEY_TV }, /* Labeled DTV on remote */ - { 0x0e, KEY_MP3 }, - { 0x1a, KEY_DVD }, - { 0x1e, KEY_FAVORITES }, /* Labeled CPF on remote */ - { 0x16, KEY_SETUP }, - { 0x46, KEY_POWER2 }, /* TV On/Off button on remote */ - { 0x0a, KEY_EPG }, /* Labeled Guide on remote */ - - { 0x49, KEY_BACK }, - { 0x59, KEY_INFO }, /* Labeled MORE on remote */ - { 0x4d, KEY_MENU }, /* Labeled DVDMENU on remote */ - { 0x55, KEY_CYCLEWINDOWS }, /* Labeled ALT-TAB on remote */ - - { 0x0f, KEY_PREVIOUSSONG }, /* Labeled |<< REPLAY on remote */ - { 0x12, KEY_NEXTSONG }, /* Labeled >>| SKIP on remote */ - { 0x42, KEY_ENTER }, /* Labeled START with a green - MS windows logo on remote */ - - { 0x15, KEY_VOLUMEUP }, - { 0x05, KEY_VOLUMEDOWN }, - { 0x11, KEY_CHANNELUP }, - { 0x09, KEY_CHANNELDOWN }, - - { 0x52, KEY_CAMERA }, - { 0x5a, KEY_TUNER }, - { 0x19, KEY_OPEN }, - - { 0x13, KEY_MODE }, /* 4:3 16:9 select */ - { 0x1f, KEY_ZOOM }, - - { 0x43, KEY_REWIND }, - { 0x47, KEY_PLAYPAUSE }, - { 0x4f, KEY_FASTFORWARD }, - { 0x57, KEY_MUTE }, - { 0x0d, KEY_STOP }, - { 0x01, KEY_RECORD }, - { 0x4e, KEY_POWER }, -}; - -static struct rc_keymap fusionhdtv_mce_map = { - .map = { - .scan = fusionhdtv_mce, - .size = ARRAY_SIZE(fusionhdtv_mce), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_FUSIONHDTV_MCE, - } -}; - -static int __init init_rc_map_fusionhdtv_mce(void) -{ - return ir_register_map(&fusionhdtv_mce_map); -} - -static void __exit exit_rc_map_fusionhdtv_mce(void) -{ - ir_unregister_map(&fusionhdtv_mce_map); -} - -module_init(init_rc_map_fusionhdtv_mce) -module_exit(exit_rc_map_fusionhdtv_mce) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-gadmei-rm008z.c b/drivers/media/IR/keymaps/rc-gadmei-rm008z.c deleted file mode 100644 index c16c0d1..0000000 --- a/drivers/media/IR/keymaps/rc-gadmei-rm008z.c +++ /dev/null @@ -1,81 +0,0 @@ -/* gadmei-rm008z.h - Keytable for gadmei_rm008z Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* GADMEI UTV330+ RM008Z remote - Shine Liu - */ - -static struct ir_scancode gadmei_rm008z[] = { - { 0x14, KEY_POWER2}, /* POWER OFF */ - { 0x0c, KEY_MUTE}, /* MUTE */ - - { 0x18, KEY_TV}, /* TV */ - { 0x0e, KEY_VIDEO}, /* AV */ - { 0x0b, KEY_AUDIO}, /* SV */ - { 0x0f, KEY_RADIO}, /* FM */ - - { 0x00, KEY_1}, - { 0x01, KEY_2}, - { 0x02, KEY_3}, - { 0x03, KEY_4}, - { 0x04, KEY_5}, - { 0x05, KEY_6}, - { 0x06, KEY_7}, - { 0x07, KEY_8}, - { 0x08, KEY_9}, - { 0x09, KEY_0}, - { 0x0a, KEY_INFO}, /* OSD */ - { 0x1c, KEY_BACKSPACE}, /* LAST */ - - { 0x0d, KEY_PLAY}, /* PLAY */ - { 0x1e, KEY_CAMERA}, /* SNAPSHOT */ - { 0x1a, KEY_RECORD}, /* RECORD */ - { 0x17, KEY_STOP}, /* STOP */ - - { 0x1f, KEY_UP}, /* UP */ - { 0x44, KEY_DOWN}, /* DOWN */ - { 0x46, KEY_TAB}, /* BACK */ - { 0x4a, KEY_ZOOM}, /* FULLSECREEN */ - - { 0x10, KEY_VOLUMEUP}, /* VOLUMEUP */ - { 0x11, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */ - { 0x12, KEY_CHANNELUP}, /* CHANNELUP */ - { 0x13, KEY_CHANNELDOWN}, /* CHANNELDOWN */ - { 0x15, KEY_ENTER}, /* OK */ -}; - -static struct rc_keymap gadmei_rm008z_map = { - .map = { - .scan = gadmei_rm008z, - .size = ARRAY_SIZE(gadmei_rm008z), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_GADMEI_RM008Z, - } -}; - -static int __init init_rc_map_gadmei_rm008z(void) -{ - return ir_register_map(&gadmei_rm008z_map); -} - -static void __exit exit_rc_map_gadmei_rm008z(void) -{ - ir_unregister_map(&gadmei_rm008z_map); -} - -module_init(init_rc_map_gadmei_rm008z) -module_exit(exit_rc_map_gadmei_rm008z) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-genius-tvgo-a11mce.c b/drivers/media/IR/keymaps/rc-genius-tvgo-a11mce.c deleted file mode 100644 index 89f8e38..0000000 --- a/drivers/media/IR/keymaps/rc-genius-tvgo-a11mce.c +++ /dev/null @@ -1,84 +0,0 @@ -/* genius-tvgo-a11mce.h - Keytable for genius_tvgo_a11mce Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* - * Remote control for the Genius TVGO A11MCE - * Adrian Pardini - */ - -static struct ir_scancode genius_tvgo_a11mce[] = { - /* Keys 0 to 9 */ - { 0x48, KEY_0 }, - { 0x09, KEY_1 }, - { 0x1d, KEY_2 }, - { 0x1f, KEY_3 }, - { 0x19, KEY_4 }, - { 0x1b, KEY_5 }, - { 0x11, KEY_6 }, - { 0x17, KEY_7 }, - { 0x12, KEY_8 }, - { 0x16, KEY_9 }, - - { 0x54, KEY_RECORD }, /* recording */ - { 0x06, KEY_MUTE }, /* mute */ - { 0x10, KEY_POWER }, - { 0x40, KEY_LAST }, /* recall */ - { 0x4c, KEY_CHANNELUP }, /* channel / program + */ - { 0x00, KEY_CHANNELDOWN }, /* channel / program - */ - { 0x0d, KEY_VOLUMEUP }, - { 0x15, KEY_VOLUMEDOWN }, - { 0x4d, KEY_OK }, /* also labeled as Pause */ - { 0x1c, KEY_ZOOM }, /* full screen and Stop*/ - { 0x02, KEY_MODE }, /* AV Source or Rewind*/ - { 0x04, KEY_LIST }, /* -/-- */ - /* small arrows above numbers */ - { 0x1a, KEY_NEXT }, /* also Fast Forward */ - { 0x0e, KEY_PREVIOUS }, /* also Rewind */ - /* these are in a rather non standard layout and have - an alternate name written */ - { 0x1e, KEY_UP }, /* Video Setting */ - { 0x0a, KEY_DOWN }, /* Video Default */ - { 0x05, KEY_CAMERA }, /* Snapshot */ - { 0x0c, KEY_RIGHT }, /* Hide Panel */ - /* Four buttons without label */ - { 0x49, KEY_RED }, - { 0x0b, KEY_GREEN }, - { 0x13, KEY_YELLOW }, - { 0x50, KEY_BLUE }, -}; - -static struct rc_keymap genius_tvgo_a11mce_map = { - .map = { - .scan = genius_tvgo_a11mce, - .size = ARRAY_SIZE(genius_tvgo_a11mce), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_GENIUS_TVGO_A11MCE, - } -}; - -static int __init init_rc_map_genius_tvgo_a11mce(void) -{ - return ir_register_map(&genius_tvgo_a11mce_map); -} - -static void __exit exit_rc_map_genius_tvgo_a11mce(void) -{ - ir_unregister_map(&genius_tvgo_a11mce_map); -} - -module_init(init_rc_map_genius_tvgo_a11mce) -module_exit(exit_rc_map_genius_tvgo_a11mce) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-gotview7135.c b/drivers/media/IR/keymaps/rc-gotview7135.c deleted file mode 100644 index 52f025b..0000000 --- a/drivers/media/IR/keymaps/rc-gotview7135.c +++ /dev/null @@ -1,79 +0,0 @@ -/* gotview7135.h - Keytable for gotview7135 Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Mike Baikov */ - -static struct ir_scancode gotview7135[] = { - - { 0x11, KEY_POWER }, - { 0x35, KEY_TV }, - { 0x1b, KEY_0 }, - { 0x29, KEY_1 }, - { 0x19, KEY_2 }, - { 0x39, KEY_3 }, - { 0x1f, KEY_4 }, - { 0x2c, KEY_5 }, - { 0x21, KEY_6 }, - { 0x24, KEY_7 }, - { 0x18, KEY_8 }, - { 0x2b, KEY_9 }, - { 0x3b, KEY_AGAIN }, /* LOOP */ - { 0x06, KEY_AUDIO }, - { 0x31, KEY_PRINT }, /* PREVIEW */ - { 0x3e, KEY_VIDEO }, - { 0x10, KEY_CHANNELUP }, - { 0x20, KEY_CHANNELDOWN }, - { 0x0c, KEY_VOLUMEDOWN }, - { 0x28, KEY_VOLUMEUP }, - { 0x08, KEY_MUTE }, - { 0x26, KEY_SEARCH }, /* SCAN */ - { 0x3f, KEY_CAMERA }, /* SNAPSHOT */ - { 0x12, KEY_RECORD }, - { 0x32, KEY_STOP }, - { 0x3c, KEY_PLAY }, - { 0x1d, KEY_REWIND }, - { 0x2d, KEY_PAUSE }, - { 0x0d, KEY_FORWARD }, - { 0x05, KEY_ZOOM }, /*FULL*/ - - { 0x2a, KEY_F21 }, /* LIVE TIMESHIFT */ - { 0x0e, KEY_F22 }, /* MIN TIMESHIFT */ - { 0x1e, KEY_TIME }, /* TIMESHIFT */ - { 0x38, KEY_F24 }, /* NORMAL TIMESHIFT */ -}; - -static struct rc_keymap gotview7135_map = { - .map = { - .scan = gotview7135, - .size = ARRAY_SIZE(gotview7135), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_GOTVIEW7135, - } -}; - -static int __init init_rc_map_gotview7135(void) -{ - return ir_register_map(&gotview7135_map); -} - -static void __exit exit_rc_map_gotview7135(void) -{ - ir_unregister_map(&gotview7135_map); -} - -module_init(init_rc_map_gotview7135) -module_exit(exit_rc_map_gotview7135) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-hauppauge-new.c b/drivers/media/IR/keymaps/rc-hauppauge-new.c deleted file mode 100644 index c6f8cd7..0000000 --- a/drivers/media/IR/keymaps/rc-hauppauge-new.c +++ /dev/null @@ -1,100 +0,0 @@ -/* hauppauge-new.h - Keytable for hauppauge_new Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Hauppauge: the newer, gray remotes (seems there are multiple - * slightly different versions), shipped with cx88+ivtv cards. - * almost rc5 coding, but some non-standard keys */ - -static struct ir_scancode hauppauge_new[] = { - /* Keys 0 to 9 */ - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - { 0x0a, KEY_TEXT }, /* keypad asterisk as well */ - { 0x0b, KEY_RED }, /* red button */ - { 0x0c, KEY_RADIO }, - { 0x0d, KEY_MENU }, - { 0x0e, KEY_SUBTITLE }, /* also the # key */ - { 0x0f, KEY_MUTE }, - { 0x10, KEY_VOLUMEUP }, - { 0x11, KEY_VOLUMEDOWN }, - { 0x12, KEY_PREVIOUS }, /* previous channel */ - { 0x14, KEY_UP }, - { 0x15, KEY_DOWN }, - { 0x16, KEY_LEFT }, - { 0x17, KEY_RIGHT }, - { 0x18, KEY_VIDEO }, /* Videos */ - { 0x19, KEY_AUDIO }, /* Music */ - /* 0x1a: Pictures - presume this means - "Multimedia Home Platform" - - no "PICTURES" key in input.h - */ - { 0x1a, KEY_MHP }, - - { 0x1b, KEY_EPG }, /* Guide */ - { 0x1c, KEY_TV }, - { 0x1e, KEY_NEXTSONG }, /* skip >| */ - { 0x1f, KEY_EXIT }, /* back/exit */ - { 0x20, KEY_CHANNELUP }, /* channel / program + */ - { 0x21, KEY_CHANNELDOWN }, /* channel / program - */ - { 0x22, KEY_CHANNEL }, /* source (old black remote) */ - { 0x24, KEY_PREVIOUSSONG }, /* replay |< */ - { 0x25, KEY_ENTER }, /* OK */ - { 0x26, KEY_SLEEP }, /* minimize (old black remote) */ - { 0x29, KEY_BLUE }, /* blue key */ - { 0x2e, KEY_GREEN }, /* green button */ - { 0x30, KEY_PAUSE }, /* pause */ - { 0x32, KEY_REWIND }, /* backward << */ - { 0x34, KEY_FASTFORWARD }, /* forward >> */ - { 0x35, KEY_PLAY }, - { 0x36, KEY_STOP }, - { 0x37, KEY_RECORD }, /* recording */ - { 0x38, KEY_YELLOW }, /* yellow key */ - { 0x3b, KEY_SELECT }, /* top right button */ - { 0x3c, KEY_ZOOM }, /* full */ - { 0x3d, KEY_POWER }, /* system power (green button) */ -}; - -static struct rc_keymap hauppauge_new_map = { - .map = { - .scan = hauppauge_new, - .size = ARRAY_SIZE(hauppauge_new), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_HAUPPAUGE_NEW, - } -}; - -static int __init init_rc_map_hauppauge_new(void) -{ - return ir_register_map(&hauppauge_new_map); -} - -static void __exit exit_rc_map_hauppauge_new(void) -{ - ir_unregister_map(&hauppauge_new_map); -} - -module_init(init_rc_map_hauppauge_new) -module_exit(exit_rc_map_hauppauge_new) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-imon-mce.c b/drivers/media/IR/keymaps/rc-imon-mce.c deleted file mode 100644 index e49f350..0000000 --- a/drivers/media/IR/keymaps/rc-imon-mce.c +++ /dev/null @@ -1,142 +0,0 @@ -/* rc5-imon-mce.c - Keytable for Windows Media Center RC-6 remotes for use - * with the SoundGraph iMON/Antec Veris hardware IR decoder - * - * Copyright (c) 2010 by Jarod Wilson - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* mce-mode imon mce remote key table */ -static struct ir_scancode imon_mce[] = { - /* keys sorted mostly by frequency of use to optimize lookups */ - { 0x800ff415, KEY_REWIND }, - { 0x800ff414, KEY_FASTFORWARD }, - { 0x800ff41b, KEY_PREVIOUS }, - { 0x800ff41a, KEY_NEXT }, - - { 0x800ff416, KEY_PLAY }, - { 0x800ff418, KEY_PAUSE }, - { 0x800ff419, KEY_STOP }, - { 0x800ff417, KEY_RECORD }, - - { 0x02000052, KEY_UP }, - { 0x02000051, KEY_DOWN }, - { 0x02000050, KEY_LEFT }, - { 0x0200004f, KEY_RIGHT }, - - { 0x800ff41e, KEY_UP }, - { 0x800ff41f, KEY_DOWN }, - { 0x800ff420, KEY_LEFT }, - { 0x800ff421, KEY_RIGHT }, - - /* 0x800ff40b also KEY_NUMERIC_POUND on some receivers */ - { 0x800ff40b, KEY_ENTER }, - { 0x02000028, KEY_ENTER }, -/* the OK and Enter buttons decode to the same value on some remotes - { 0x02000028, KEY_OK }, */ - { 0x800ff422, KEY_OK }, - { 0x0200002a, KEY_EXIT }, - { 0x800ff423, KEY_EXIT }, - { 0x02000029, KEY_DELETE }, - /* 0x800ff40a also KEY_NUMERIC_STAR on some receivers */ - { 0x800ff40a, KEY_DELETE }, - - { 0x800ff40e, KEY_MUTE }, - { 0x800ff410, KEY_VOLUMEUP }, - { 0x800ff411, KEY_VOLUMEDOWN }, - { 0x800ff412, KEY_CHANNELUP }, - { 0x800ff413, KEY_CHANNELDOWN }, - - { 0x0200001e, KEY_NUMERIC_1 }, - { 0x0200001f, KEY_NUMERIC_2 }, - { 0x02000020, KEY_NUMERIC_3 }, - { 0x02000021, KEY_NUMERIC_4 }, - { 0x02000022, KEY_NUMERIC_5 }, - { 0x02000023, KEY_NUMERIC_6 }, - { 0x02000024, KEY_NUMERIC_7 }, - { 0x02000025, KEY_NUMERIC_8 }, - { 0x02000026, KEY_NUMERIC_9 }, - { 0x02000027, KEY_NUMERIC_0 }, - - { 0x800ff401, KEY_NUMERIC_1 }, - { 0x800ff402, KEY_NUMERIC_2 }, - { 0x800ff403, KEY_NUMERIC_3 }, - { 0x800ff404, KEY_NUMERIC_4 }, - { 0x800ff405, KEY_NUMERIC_5 }, - { 0x800ff406, KEY_NUMERIC_6 }, - { 0x800ff407, KEY_NUMERIC_7 }, - { 0x800ff408, KEY_NUMERIC_8 }, - { 0x800ff409, KEY_NUMERIC_9 }, - { 0x800ff400, KEY_NUMERIC_0 }, - - { 0x02200025, KEY_NUMERIC_STAR }, - { 0x02200020, KEY_NUMERIC_POUND }, - /* 0x800ff41d also KEY_BLUE on some receivers */ - { 0x800ff41d, KEY_NUMERIC_STAR }, - /* 0x800ff41c also KEY_PREVIOUS on some receivers */ - { 0x800ff41c, KEY_NUMERIC_POUND }, - - { 0x800ff446, KEY_TV }, - { 0x800ff447, KEY_AUDIO }, /* My Music */ - { 0x800ff448, KEY_PVR }, /* RecordedTV */ - { 0x800ff449, KEY_CAMERA }, - { 0x800ff44a, KEY_VIDEO }, - /* 0x800ff424 also KEY_MENU on some receivers */ - { 0x800ff424, KEY_DVD }, - /* 0x800ff425 also KEY_GREEN on some receivers */ - { 0x800ff425, KEY_TUNER }, /* LiveTV */ - { 0x800ff450, KEY_RADIO }, - - { 0x800ff44c, KEY_LANGUAGE }, - { 0x800ff427, KEY_ZOOM }, /* Aspect */ - - { 0x800ff45b, KEY_RED }, - { 0x800ff45c, KEY_GREEN }, - { 0x800ff45d, KEY_YELLOW }, - { 0x800ff45e, KEY_BLUE }, - - { 0x800ff466, KEY_RED }, - /* { 0x800ff425, KEY_GREEN }, */ - { 0x800ff468, KEY_YELLOW }, - /* { 0x800ff41d, KEY_BLUE }, */ - - { 0x800ff40f, KEY_INFO }, - { 0x800ff426, KEY_EPG }, /* Guide */ - { 0x800ff45a, KEY_SUBTITLE }, /* Caption/Teletext */ - { 0x800ff44d, KEY_TITLE }, - - { 0x800ff40c, KEY_POWER }, - { 0x800ff40d, KEY_PROG1 }, /* Windows MCE button */ - -}; - -static struct rc_keymap imon_mce_map = { - .map = { - .scan = imon_mce, - .size = ARRAY_SIZE(imon_mce), - /* its RC6, but w/a hardware decoder */ - .ir_type = IR_TYPE_RC6, - .name = RC_MAP_IMON_MCE, - } -}; - -static int __init init_rc_map_imon_mce(void) -{ - return ir_register_map(&imon_mce_map); -} - -static void __exit exit_rc_map_imon_mce(void) -{ - ir_unregister_map(&imon_mce_map); -} - -module_init(init_rc_map_imon_mce) -module_exit(exit_rc_map_imon_mce) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jarod Wilson "); diff --git a/drivers/media/IR/keymaps/rc-imon-pad.c b/drivers/media/IR/keymaps/rc-imon-pad.c deleted file mode 100644 index bc4db72..0000000 --- a/drivers/media/IR/keymaps/rc-imon-pad.c +++ /dev/null @@ -1,156 +0,0 @@ -/* rc5-imon-pad.c - Keytable for SoundGraph iMON PAD and Antec Veris - * RM-200 Remote Control - * - * Copyright (c) 2010 by Jarod Wilson - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* - * standard imon remote key table, which isn't really entirely - * "standard", as different receivers decode the same key on the - * same remote to different hex codes, and the silkscreened names - * vary a bit between the SoundGraph and Antec remotes... ugh. - */ -static struct ir_scancode imon_pad[] = { - /* keys sorted mostly by frequency of use to optimize lookups */ - { 0x2a8195b7, KEY_REWIND }, - { 0x298315b7, KEY_REWIND }, - { 0x2b8115b7, KEY_FASTFORWARD }, - { 0x2b8315b7, KEY_FASTFORWARD }, - { 0x2b9115b7, KEY_PREVIOUS }, - { 0x298195b7, KEY_NEXT }, - - { 0x2a8115b7, KEY_PLAY }, - { 0x2a8315b7, KEY_PLAY }, - { 0x2a9115b7, KEY_PAUSE }, - { 0x2b9715b7, KEY_STOP }, - { 0x298115b7, KEY_RECORD }, - - { 0x01008000, KEY_UP }, - { 0x01007f00, KEY_DOWN }, - { 0x01000080, KEY_LEFT }, - { 0x0100007f, KEY_RIGHT }, - - { 0x2aa515b7, KEY_UP }, - { 0x289515b7, KEY_DOWN }, - { 0x29a515b7, KEY_LEFT }, - { 0x2ba515b7, KEY_RIGHT }, - - { 0x0200002c, KEY_SPACE }, /* Select/Space */ - { 0x2a9315b7, KEY_SPACE }, /* Select/Space */ - { 0x02000028, KEY_ENTER }, - { 0x28a195b7, KEY_ENTER }, - { 0x288195b7, KEY_EXIT }, - { 0x02000029, KEY_ESC }, - { 0x2bb715b7, KEY_ESC }, - { 0x0200002a, KEY_BACKSPACE }, - { 0x28a115b7, KEY_BACKSPACE }, - - { 0x2b9595b7, KEY_MUTE }, - { 0x28a395b7, KEY_VOLUMEUP }, - { 0x28a595b7, KEY_VOLUMEDOWN }, - { 0x289395b7, KEY_CHANNELUP }, - { 0x288795b7, KEY_CHANNELDOWN }, - - { 0x0200001e, KEY_NUMERIC_1 }, - { 0x0200001f, KEY_NUMERIC_2 }, - { 0x02000020, KEY_NUMERIC_3 }, - { 0x02000021, KEY_NUMERIC_4 }, - { 0x02000022, KEY_NUMERIC_5 }, - { 0x02000023, KEY_NUMERIC_6 }, - { 0x02000024, KEY_NUMERIC_7 }, - { 0x02000025, KEY_NUMERIC_8 }, - { 0x02000026, KEY_NUMERIC_9 }, - { 0x02000027, KEY_NUMERIC_0 }, - - { 0x28b595b7, KEY_NUMERIC_1 }, - { 0x2bb195b7, KEY_NUMERIC_2 }, - { 0x28b195b7, KEY_NUMERIC_3 }, - { 0x2a8595b7, KEY_NUMERIC_4 }, - { 0x299595b7, KEY_NUMERIC_5 }, - { 0x2aa595b7, KEY_NUMERIC_6 }, - { 0x2b9395b7, KEY_NUMERIC_7 }, - { 0x2a8515b7, KEY_NUMERIC_8 }, - { 0x2aa115b7, KEY_NUMERIC_9 }, - { 0x2ba595b7, KEY_NUMERIC_0 }, - - { 0x02200025, KEY_NUMERIC_STAR }, - { 0x28b515b7, KEY_NUMERIC_STAR }, - { 0x02200020, KEY_NUMERIC_POUND }, - { 0x29a115b7, KEY_NUMERIC_POUND }, - - { 0x2b8515b7, KEY_VIDEO }, - { 0x299195b7, KEY_AUDIO }, - { 0x2ba115b7, KEY_CAMERA }, - { 0x28a515b7, KEY_TV }, - { 0x29a395b7, KEY_DVD }, - { 0x29a295b7, KEY_DVD }, - - /* the Menu key between DVD and Subtitle on the RM-200... */ - { 0x2ba385b7, KEY_MENU }, - { 0x2ba395b7, KEY_MENU }, - - { 0x288515b7, KEY_BOOKMARKS }, - { 0x2ab715b7, KEY_MEDIA }, /* Thumbnail */ - { 0x298595b7, KEY_SUBTITLE }, - { 0x2b8595b7, KEY_LANGUAGE }, - - { 0x29a595b7, KEY_ZOOM }, - { 0x2aa395b7, KEY_SCREEN }, /* FullScreen */ - - { 0x299115b7, KEY_KEYBOARD }, - { 0x299135b7, KEY_KEYBOARD }, - - { 0x01010000, BTN_LEFT }, - { 0x01020000, BTN_RIGHT }, - { 0x01010080, BTN_LEFT }, - { 0x01020080, BTN_RIGHT }, - { 0x688301b7, BTN_LEFT }, - { 0x688481b7, BTN_RIGHT }, - - { 0x2a9395b7, KEY_CYCLEWINDOWS }, /* TaskSwitcher */ - { 0x2b8395b7, KEY_TIME }, /* Timer */ - - { 0x289115b7, KEY_POWER }, - { 0x29b195b7, KEY_EJECTCD }, /* the one next to play */ - { 0x299395b7, KEY_EJECTCLOSECD }, /* eject (by TaskSw) */ - - { 0x02800000, KEY_CONTEXT_MENU }, /* Left Menu */ - { 0x2b8195b7, KEY_CONTEXT_MENU }, /* Left Menu*/ - { 0x02000065, KEY_COMPOSE }, /* RightMenu */ - { 0x28b715b7, KEY_COMPOSE }, /* RightMenu */ - { 0x2ab195b7, KEY_PROG1 }, /* Go or MultiMon */ - { 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */ -}; - -static struct rc_keymap imon_pad_map = { - .map = { - .scan = imon_pad, - .size = ARRAY_SIZE(imon_pad), - /* actual protocol details unknown, hardware decoder */ - .ir_type = IR_TYPE_OTHER, - .name = RC_MAP_IMON_PAD, - } -}; - -static int __init init_rc_map_imon_pad(void) -{ - return ir_register_map(&imon_pad_map); -} - -static void __exit exit_rc_map_imon_pad(void) -{ - ir_unregister_map(&imon_pad_map); -} - -module_init(init_rc_map_imon_pad) -module_exit(exit_rc_map_imon_pad) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jarod Wilson "); diff --git a/drivers/media/IR/keymaps/rc-iodata-bctv7e.c b/drivers/media/IR/keymaps/rc-iodata-bctv7e.c deleted file mode 100644 index ef66002..0000000 --- a/drivers/media/IR/keymaps/rc-iodata-bctv7e.c +++ /dev/null @@ -1,88 +0,0 @@ -/* iodata-bctv7e.h - Keytable for iodata_bctv7e Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* IO-DATA BCTV7E Remote */ - -static struct ir_scancode iodata_bctv7e[] = { - { 0x40, KEY_TV }, - { 0x20, KEY_RADIO }, /* FM */ - { 0x60, KEY_EPG }, - { 0x00, KEY_POWER }, - - /* Keys 0 to 9 */ - { 0x44, KEY_0 }, /* 10 */ - { 0x50, KEY_1 }, - { 0x30, KEY_2 }, - { 0x70, KEY_3 }, - { 0x48, KEY_4 }, - { 0x28, KEY_5 }, - { 0x68, KEY_6 }, - { 0x58, KEY_7 }, - { 0x38, KEY_8 }, - { 0x78, KEY_9 }, - - { 0x10, KEY_L }, /* Live */ - { 0x08, KEY_TIME }, /* Time Shift */ - - { 0x18, KEY_PLAYPAUSE }, /* Play */ - - { 0x24, KEY_ENTER }, /* 11 */ - { 0x64, KEY_ESC }, /* 12 */ - { 0x04, KEY_M }, /* Multi */ - - { 0x54, KEY_VIDEO }, - { 0x34, KEY_CHANNELUP }, - { 0x74, KEY_VOLUMEUP }, - { 0x14, KEY_MUTE }, - - { 0x4c, KEY_VCR }, /* SVIDEO */ - { 0x2c, KEY_CHANNELDOWN }, - { 0x6c, KEY_VOLUMEDOWN }, - { 0x0c, KEY_ZOOM }, - - { 0x5c, KEY_PAUSE }, - { 0x3c, KEY_RED }, /* || (red) */ - { 0x7c, KEY_RECORD }, /* recording */ - { 0x1c, KEY_STOP }, - - { 0x41, KEY_REWIND }, /* backward << */ - { 0x21, KEY_PLAY }, - { 0x61, KEY_FASTFORWARD }, /* forward >> */ - { 0x01, KEY_NEXT }, /* skip >| */ -}; - -static struct rc_keymap iodata_bctv7e_map = { - .map = { - .scan = iodata_bctv7e, - .size = ARRAY_SIZE(iodata_bctv7e), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_IODATA_BCTV7E, - } -}; - -static int __init init_rc_map_iodata_bctv7e(void) -{ - return ir_register_map(&iodata_bctv7e_map); -} - -static void __exit exit_rc_map_iodata_bctv7e(void) -{ - ir_unregister_map(&iodata_bctv7e_map); -} - -module_init(init_rc_map_iodata_bctv7e) -module_exit(exit_rc_map_iodata_bctv7e) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-kaiomy.c b/drivers/media/IR/keymaps/rc-kaiomy.c deleted file mode 100644 index 4c7883b..0000000 --- a/drivers/media/IR/keymaps/rc-kaiomy.c +++ /dev/null @@ -1,87 +0,0 @@ -/* kaiomy.h - Keytable for kaiomy Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Kaiomy TVnPC U2 - Mauro Carvalho Chehab - */ - -static struct ir_scancode kaiomy[] = { - { 0x43, KEY_POWER2}, - { 0x01, KEY_LIST}, - { 0x0b, KEY_ZOOM}, - { 0x03, KEY_POWER}, - - { 0x04, KEY_1}, - { 0x08, KEY_2}, - { 0x02, KEY_3}, - - { 0x0f, KEY_4}, - { 0x05, KEY_5}, - { 0x06, KEY_6}, - - { 0x0c, KEY_7}, - { 0x0d, KEY_8}, - { 0x0a, KEY_9}, - - { 0x11, KEY_0}, - - { 0x09, KEY_CHANNELUP}, - { 0x07, KEY_CHANNELDOWN}, - - { 0x0e, KEY_VOLUMEUP}, - { 0x13, KEY_VOLUMEDOWN}, - - { 0x10, KEY_HOME}, - { 0x12, KEY_ENTER}, - - { 0x14, KEY_RECORD}, - { 0x15, KEY_STOP}, - { 0x16, KEY_PLAY}, - { 0x17, KEY_MUTE}, - - { 0x18, KEY_UP}, - { 0x19, KEY_DOWN}, - { 0x1a, KEY_LEFT}, - { 0x1b, KEY_RIGHT}, - - { 0x1c, KEY_RED}, - { 0x1d, KEY_GREEN}, - { 0x1e, KEY_YELLOW}, - { 0x1f, KEY_BLUE}, -}; - -static struct rc_keymap kaiomy_map = { - .map = { - .scan = kaiomy, - .size = ARRAY_SIZE(kaiomy), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_KAIOMY, - } -}; - -static int __init init_rc_map_kaiomy(void) -{ - return ir_register_map(&kaiomy_map); -} - -static void __exit exit_rc_map_kaiomy(void) -{ - ir_unregister_map(&kaiomy_map); -} - -module_init(init_rc_map_kaiomy) -module_exit(exit_rc_map_kaiomy) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-kworld-315u.c b/drivers/media/IR/keymaps/rc-kworld-315u.c deleted file mode 100644 index 618c817..0000000 --- a/drivers/media/IR/keymaps/rc-kworld-315u.c +++ /dev/null @@ -1,83 +0,0 @@ -/* kworld-315u.h - Keytable for kworld_315u Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Kworld 315U - */ - -static struct ir_scancode kworld_315u[] = { - { 0x6143, KEY_POWER }, - { 0x6101, KEY_TUNER }, /* source */ - { 0x610b, KEY_ZOOM }, - { 0x6103, KEY_POWER2 }, /* shutdown */ - - { 0x6104, KEY_1 }, - { 0x6108, KEY_2 }, - { 0x6102, KEY_3 }, - { 0x6109, KEY_CHANNELUP }, - - { 0x610f, KEY_4 }, - { 0x6105, KEY_5 }, - { 0x6106, KEY_6 }, - { 0x6107, KEY_CHANNELDOWN }, - - { 0x610c, KEY_7 }, - { 0x610d, KEY_8 }, - { 0x610a, KEY_9 }, - { 0x610e, KEY_VOLUMEUP }, - - { 0x6110, KEY_LAST }, - { 0x6111, KEY_0 }, - { 0x6112, KEY_ENTER }, - { 0x6113, KEY_VOLUMEDOWN }, - - { 0x6114, KEY_RECORD }, - { 0x6115, KEY_STOP }, - { 0x6116, KEY_PLAY }, - { 0x6117, KEY_MUTE }, - - { 0x6118, KEY_UP }, - { 0x6119, KEY_DOWN }, - { 0x611a, KEY_LEFT }, - { 0x611b, KEY_RIGHT }, - - { 0x611c, KEY_RED }, - { 0x611d, KEY_GREEN }, - { 0x611e, KEY_YELLOW }, - { 0x611f, KEY_BLUE }, -}; - -static struct rc_keymap kworld_315u_map = { - .map = { - .scan = kworld_315u, - .size = ARRAY_SIZE(kworld_315u), - .ir_type = IR_TYPE_NEC, - .name = RC_MAP_KWORLD_315U, - } -}; - -static int __init init_rc_map_kworld_315u(void) -{ - return ir_register_map(&kworld_315u_map); -} - -static void __exit exit_rc_map_kworld_315u(void) -{ - ir_unregister_map(&kworld_315u_map); -} - -module_init(init_rc_map_kworld_315u) -module_exit(exit_rc_map_kworld_315u) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-kworld-plus-tv-analog.c b/drivers/media/IR/keymaps/rc-kworld-plus-tv-analog.c deleted file mode 100644 index 366732f..0000000 --- a/drivers/media/IR/keymaps/rc-kworld-plus-tv-analog.c +++ /dev/null @@ -1,99 +0,0 @@ -/* kworld-plus-tv-analog.h - Keytable for kworld_plus_tv_analog Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Kworld Plus TV Analog Lite PCI IR - Mauro Carvalho Chehab - */ - -static struct ir_scancode kworld_plus_tv_analog[] = { - { 0x0c, KEY_PROG1 }, /* Kworld key */ - { 0x16, KEY_CLOSECD }, /* -> ) */ - { 0x1d, KEY_POWER2 }, - - { 0x00, KEY_1 }, - { 0x01, KEY_2 }, - { 0x02, KEY_3 }, /* Two keys have the same code: 3 and left */ - { 0x03, KEY_4 }, /* Two keys have the same code: 3 and right */ - { 0x04, KEY_5 }, - { 0x05, KEY_6 }, - { 0x06, KEY_7 }, - { 0x07, KEY_8 }, - { 0x08, KEY_9 }, - { 0x0a, KEY_0 }, - - { 0x09, KEY_AGAIN }, - { 0x14, KEY_MUTE }, - - { 0x20, KEY_UP }, - { 0x21, KEY_DOWN }, - { 0x0b, KEY_ENTER }, - - { 0x10, KEY_CHANNELUP }, - { 0x11, KEY_CHANNELDOWN }, - - /* Couldn't map key left/key right since those - conflict with '3' and '4' scancodes - I dunno what the original driver does - */ - - { 0x13, KEY_VOLUMEUP }, - { 0x12, KEY_VOLUMEDOWN }, - - /* The lower part of the IR - There are several duplicated keycodes there. - Most of them conflict with digits. - Add mappings just to the unused scancodes. - Somehow, the original driver has a way to know, - but this doesn't seem to be on some GPIO. - Also, it is not related to the time between keyup - and keydown. - */ - { 0x19, KEY_TIME}, /* Timeshift */ - { 0x1a, KEY_STOP}, - { 0x1b, KEY_RECORD}, - - { 0x22, KEY_TEXT}, - - { 0x15, KEY_AUDIO}, /* ((*)) */ - { 0x0f, KEY_ZOOM}, - { 0x1c, KEY_CAMERA}, /* snapshot */ - - { 0x18, KEY_RED}, /* B */ - { 0x23, KEY_GREEN}, /* C */ -}; - -static struct rc_keymap kworld_plus_tv_analog_map = { - .map = { - .scan = kworld_plus_tv_analog, - .size = ARRAY_SIZE(kworld_plus_tv_analog), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_KWORLD_PLUS_TV_ANALOG, - } -}; - -static int __init init_rc_map_kworld_plus_tv_analog(void) -{ - return ir_register_map(&kworld_plus_tv_analog_map); -} - -static void __exit exit_rc_map_kworld_plus_tv_analog(void) -{ - ir_unregister_map(&kworld_plus_tv_analog_map); -} - -module_init(init_rc_map_kworld_plus_tv_analog) -module_exit(exit_rc_map_kworld_plus_tv_analog) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-leadtek-y04g0051.c b/drivers/media/IR/keymaps/rc-leadtek-y04g0051.c deleted file mode 100644 index 7521315..0000000 --- a/drivers/media/IR/keymaps/rc-leadtek-y04g0051.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * LeadTek Y04G0051 remote controller keytable - * - * Copyright (C) 2010 Antti Palosaari - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -static struct ir_scancode leadtek_y04g0051[] = { - { 0x0300, KEY_POWER2 }, - { 0x0303, KEY_SCREEN }, - { 0x0304, KEY_RIGHT }, - { 0x0305, KEY_1 }, - { 0x0306, KEY_2 }, - { 0x0307, KEY_3 }, - { 0x0308, KEY_LEFT }, - { 0x0309, KEY_4 }, - { 0x030a, KEY_5 }, - { 0x030b, KEY_6 }, - { 0x030c, KEY_UP }, - { 0x030d, KEY_7 }, - { 0x030e, KEY_8 }, - { 0x030f, KEY_9 }, - { 0x0310, KEY_DOWN }, - { 0x0311, KEY_AGAIN }, - { 0x0312, KEY_0 }, - { 0x0313, KEY_OK }, /* 1st ok */ - { 0x0314, KEY_MUTE }, - { 0x0316, KEY_OK }, /* 2nd ok */ - { 0x031e, KEY_VIDEO }, /* 2nd video */ - { 0x031b, KEY_AUDIO }, - { 0x031f, KEY_TEXT }, - { 0x0340, KEY_SLEEP }, - { 0x0341, KEY_DOT }, - { 0x0342, KEY_REWIND }, - { 0x0343, KEY_PLAY }, - { 0x0344, KEY_FASTFORWARD }, - { 0x0345, KEY_TIME }, - { 0x0346, KEY_STOP }, /* 2nd stop */ - { 0x0347, KEY_RECORD }, - { 0x0348, KEY_CAMERA }, - { 0x0349, KEY_ESC }, - { 0x034a, KEY_NEW }, - { 0x034b, KEY_RED }, - { 0x034c, KEY_GREEN }, - { 0x034d, KEY_YELLOW }, - { 0x034e, KEY_BLUE }, - { 0x034f, KEY_MENU }, - { 0x0350, KEY_STOP }, /* 1st stop */ - { 0x0351, KEY_CHANNEL }, - { 0x0352, KEY_VIDEO }, /* 1st video */ - { 0x0353, KEY_EPG }, - { 0x0354, KEY_PREVIOUS }, - { 0x0355, KEY_NEXT }, - { 0x0356, KEY_TV }, - { 0x035a, KEY_VOLUMEDOWN }, - { 0x035b, KEY_CHANNELUP }, - { 0x035e, KEY_VOLUMEUP }, - { 0x035f, KEY_CHANNELDOWN }, -}; - -static struct rc_keymap leadtek_y04g0051_map = { - .map = { - .scan = leadtek_y04g0051, - .size = ARRAY_SIZE(leadtek_y04g0051), - .ir_type = IR_TYPE_NEC, - .name = RC_MAP_LEADTEK_Y04G0051, - } -}; - -static int __init init_rc_map_leadtek_y04g0051(void) -{ - return ir_register_map(&leadtek_y04g0051_map); -} - -static void __exit exit_rc_map_leadtek_y04g0051(void) -{ - ir_unregister_map(&leadtek_y04g0051_map); -} - -module_init(init_rc_map_leadtek_y04g0051) -module_exit(exit_rc_map_leadtek_y04g0051) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/IR/keymaps/rc-lirc.c b/drivers/media/IR/keymaps/rc-lirc.c deleted file mode 100644 index 43fcf90..0000000 --- a/drivers/media/IR/keymaps/rc-lirc.c +++ /dev/null @@ -1,41 +0,0 @@ -/* rc-lirc.c - Empty dummy keytable, for use when its preferred to pass - * all raw IR data to the lirc userspace decoder. - * - * Copyright (c) 2010 by Jarod Wilson - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode lirc[] = { - { }, -}; - -static struct rc_keymap lirc_map = { - .map = { - .scan = lirc, - .size = ARRAY_SIZE(lirc), - .ir_type = IR_TYPE_LIRC, - .name = RC_MAP_LIRC, - } -}; - -static int __init init_rc_map_lirc(void) -{ - return ir_register_map(&lirc_map); -} - -static void __exit exit_rc_map_lirc(void) -{ - ir_unregister_map(&lirc_map); -} - -module_init(init_rc_map_lirc) -module_exit(exit_rc_map_lirc) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jarod Wilson "); diff --git a/drivers/media/IR/keymaps/rc-lme2510.c b/drivers/media/IR/keymaps/rc-lme2510.c deleted file mode 100644 index 40dcf0b..0000000 --- a/drivers/media/IR/keymaps/rc-lme2510.c +++ /dev/null @@ -1,68 +0,0 @@ -/* LME2510 remote control - * - * - * Copyright (C) 2010 Malcolm Priestley (tvboxspy@gmail.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - - -static struct ir_scancode lme2510_rc[] = { - { 0xba45, KEY_0 }, - { 0xa05f, KEY_1 }, - { 0xaf50, KEY_2 }, - { 0xa25d, KEY_3 }, - { 0xbe41, KEY_4 }, - { 0xf50a, KEY_5 }, - { 0xbd42, KEY_6 }, - { 0xb847, KEY_7 }, - { 0xb649, KEY_8 }, - { 0xfa05, KEY_9 }, - { 0xbc43, KEY_POWER }, - { 0xb946, KEY_SUBTITLE }, - { 0xf906, KEY_PAUSE }, - { 0xfc03, KEY_MEDIA_REPEAT}, - { 0xfd02, KEY_PAUSE }, - { 0xa15e, KEY_VOLUMEUP }, - { 0xa35c, KEY_VOLUMEDOWN }, - { 0xf609, KEY_CHANNELUP }, - { 0xe51a, KEY_CHANNELDOWN }, - { 0xe11e, KEY_PLAY }, - { 0xe41b, KEY_ZOOM }, - { 0xa659, KEY_MUTE }, - { 0xa55a, KEY_TV }, - { 0xe718, KEY_RECORD }, - { 0xf807, KEY_EPG }, - { 0xfe01, KEY_STOP }, - -}; - -static struct rc_keymap lme2510_map = { - .map = { - .scan = lme2510_rc, - .size = ARRAY_SIZE(lme2510_rc), - .ir_type = IR_TYPE_UNKNOWN, - .name = RC_MAP_LME2510, - } -}; - -static int __init init_rc_lme2510_map(void) -{ - return ir_register_map(&lme2510_map); -} - -static void __exit exit_rc_lme2510_map(void) -{ - ir_unregister_map(&lme2510_map); -} - -module_init(init_rc_lme2510_map) -module_exit(exit_rc_lme2510_map) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); diff --git a/drivers/media/IR/keymaps/rc-manli.c b/drivers/media/IR/keymaps/rc-manli.c deleted file mode 100644 index 0f590b3..0000000 --- a/drivers/media/IR/keymaps/rc-manli.c +++ /dev/null @@ -1,134 +0,0 @@ -/* manli.h - Keytable for manli Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Michael Tokarev - keytable is used by MANLI MTV00[0x0c] and BeholdTV 40[13] at - least, and probably other cards too. - The "ascii-art picture" below (in comments, first row - is the keycode in hex, and subsequent row(s) shows - the button labels (several variants when appropriate) - helps to descide which keycodes to assign to the buttons. - */ - -static struct ir_scancode manli[] = { - - /* 0x1c 0x12 * - * FUNCTION POWER * - * FM (|) * - * */ - { 0x1c, KEY_RADIO }, /*XXX*/ - { 0x12, KEY_POWER }, - - /* 0x01 0x02 0x03 * - * 1 2 3 * - * * - * 0x04 0x05 0x06 * - * 4 5 6 * - * * - * 0x07 0x08 0x09 * - * 7 8 9 * - * */ - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - /* 0x0a 0x00 0x17 * - * RECALL 0 +100 * - * PLUS * - * */ - { 0x0a, KEY_AGAIN }, /*XXX KEY_REWIND? */ - { 0x00, KEY_0 }, - { 0x17, KEY_DIGITS }, /*XXX*/ - - /* 0x14 0x10 * - * MENU INFO * - * OSD */ - { 0x14, KEY_MENU }, - { 0x10, KEY_INFO }, - - /* 0x0b * - * Up * - * * - * 0x18 0x16 0x0c * - * Left Ok Right * - * * - * 0x015 * - * Down * - * */ - { 0x0b, KEY_UP }, - { 0x18, KEY_LEFT }, - { 0x16, KEY_OK }, /*XXX KEY_SELECT? KEY_ENTER? */ - { 0x0c, KEY_RIGHT }, - { 0x15, KEY_DOWN }, - - /* 0x11 0x0d * - * TV/AV MODE * - * SOURCE STEREO * - * */ - { 0x11, KEY_TV }, /*XXX*/ - { 0x0d, KEY_MODE }, /*XXX there's no KEY_STEREO */ - - /* 0x0f 0x1b 0x1a * - * AUDIO Vol+ Chan+ * - * TIMESHIFT??? * - * * - * 0x0e 0x1f 0x1e * - * SLEEP Vol- Chan- * - * */ - { 0x0f, KEY_AUDIO }, - { 0x1b, KEY_VOLUMEUP }, - { 0x1a, KEY_CHANNELUP }, - { 0x0e, KEY_TIME }, - { 0x1f, KEY_VOLUMEDOWN }, - { 0x1e, KEY_CHANNELDOWN }, - - /* 0x13 0x19 * - * MUTE SNAPSHOT* - * */ - { 0x13, KEY_MUTE }, - { 0x19, KEY_CAMERA }, - - /* 0x1d unused ? */ -}; - -static struct rc_keymap manli_map = { - .map = { - .scan = manli, - .size = ARRAY_SIZE(manli), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_MANLI, - } -}; - -static int __init init_rc_map_manli(void) -{ - return ir_register_map(&manli_map); -} - -static void __exit exit_rc_map_manli(void) -{ - ir_unregister_map(&manli_map); -} - -module_init(init_rc_map_manli) -module_exit(exit_rc_map_manli) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-msi-digivox-ii.c b/drivers/media/IR/keymaps/rc-msi-digivox-ii.c deleted file mode 100644 index 67237fb..0000000 --- a/drivers/media/IR/keymaps/rc-msi-digivox-ii.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * MSI DIGIVOX mini II remote controller keytable - * - * Copyright (C) 2010 Antti Palosaari - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -static struct ir_scancode msi_digivox_ii[] = { - { 0x0002, KEY_2 }, - { 0x0003, KEY_UP }, /* up */ - { 0x0004, KEY_3 }, - { 0x0005, KEY_CHANNELDOWN }, - { 0x0008, KEY_5 }, - { 0x0009, KEY_0 }, - { 0x000b, KEY_8 }, - { 0x000d, KEY_DOWN }, /* down */ - { 0x0010, KEY_9 }, - { 0x0011, KEY_7 }, - { 0x0014, KEY_VOLUMEUP }, - { 0x0015, KEY_CHANNELUP }, - { 0x0016, KEY_OK }, - { 0x0017, KEY_POWER2 }, - { 0x001a, KEY_1 }, - { 0x001c, KEY_4 }, - { 0x001d, KEY_6 }, - { 0x001f, KEY_VOLUMEDOWN }, -}; - -static struct rc_keymap msi_digivox_ii_map = { - .map = { - .scan = msi_digivox_ii, - .size = ARRAY_SIZE(msi_digivox_ii), - .ir_type = IR_TYPE_NEC, - .name = RC_MAP_MSI_DIGIVOX_II, - } -}; - -static int __init init_rc_map_msi_digivox_ii(void) -{ - return ir_register_map(&msi_digivox_ii_map); -} - -static void __exit exit_rc_map_msi_digivox_ii(void) -{ - ir_unregister_map(&msi_digivox_ii_map); -} - -module_init(init_rc_map_msi_digivox_ii) -module_exit(exit_rc_map_msi_digivox_ii) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/IR/keymaps/rc-msi-digivox-iii.c b/drivers/media/IR/keymaps/rc-msi-digivox-iii.c deleted file mode 100644 index 882056e..0000000 --- a/drivers/media/IR/keymaps/rc-msi-digivox-iii.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * MSI DIGIVOX mini III remote controller keytable - * - * Copyright (C) 2010 Antti Palosaari - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -/* MSI DIGIVOX mini III */ -/* Uses NEC extended 0x61d6. */ -/* This remote seems to be same as rc-kworld-315u.c. Anyhow, add new remote - since rc-kworld-315u.c lacks NEC extended address byte. */ -static struct ir_scancode msi_digivox_iii[] = { - { 0x61d601, KEY_VIDEO }, /* Source */ - { 0x61d602, KEY_3 }, - { 0x61d603, KEY_POWER }, /* ShutDown */ - { 0x61d604, KEY_1 }, - { 0x61d605, KEY_5 }, - { 0x61d606, KEY_6 }, - { 0x61d607, KEY_CHANNELDOWN }, /* CH- */ - { 0x61d608, KEY_2 }, - { 0x61d609, KEY_CHANNELUP }, /* CH+ */ - { 0x61d60a, KEY_9 }, - { 0x61d60b, KEY_ZOOM }, /* Zoom */ - { 0x61d60c, KEY_7 }, - { 0x61d60d, KEY_8 }, - { 0x61d60e, KEY_VOLUMEUP }, /* Vol+ */ - { 0x61d60f, KEY_4 }, - { 0x61d610, KEY_ESC }, /* [back up arrow] */ - { 0x61d611, KEY_0 }, - { 0x61d612, KEY_OK }, /* [enter arrow] */ - { 0x61d613, KEY_VOLUMEDOWN }, /* Vol- */ - { 0x61d614, KEY_RECORD }, /* Rec */ - { 0x61d615, KEY_STOP }, /* Stop */ - { 0x61d616, KEY_PLAY }, /* Play */ - { 0x61d617, KEY_MUTE }, /* Mute */ - { 0x61d618, KEY_UP }, - { 0x61d619, KEY_DOWN }, - { 0x61d61a, KEY_LEFT }, - { 0x61d61b, KEY_RIGHT }, - { 0x61d61c, KEY_RED }, - { 0x61d61d, KEY_GREEN }, - { 0x61d61e, KEY_YELLOW }, - { 0x61d61f, KEY_BLUE }, - { 0x61d643, KEY_POWER2 }, /* [red power button] */ -}; - -static struct rc_keymap msi_digivox_iii_map = { - .map = { - .scan = msi_digivox_iii, - .size = ARRAY_SIZE(msi_digivox_iii), - .ir_type = IR_TYPE_NEC, - .name = RC_MAP_MSI_DIGIVOX_III, - } -}; - -static int __init init_rc_map_msi_digivox_iii(void) -{ - return ir_register_map(&msi_digivox_iii_map); -} - -static void __exit exit_rc_map_msi_digivox_iii(void) -{ - ir_unregister_map(&msi_digivox_iii_map); -} - -module_init(init_rc_map_msi_digivox_iii) -module_exit(exit_rc_map_msi_digivox_iii) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/IR/keymaps/rc-msi-tvanywhere-plus.c b/drivers/media/IR/keymaps/rc-msi-tvanywhere-plus.c deleted file mode 100644 index eb8e42c..0000000 --- a/drivers/media/IR/keymaps/rc-msi-tvanywhere-plus.c +++ /dev/null @@ -1,123 +0,0 @@ -/* msi-tvanywhere-plus.h - Keytable for msi_tvanywhere_plus Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* - Keycodes for remote on the MSI TV@nywhere Plus. The controller IC on the card - is marked "KS003". The controller is I2C at address 0x30, but does not seem - to respond to probes until a read is performed from a valid device. - I don't know why... - - Note: This remote may be of similar or identical design to the - Pixelview remote (?). The raw codes and duplicate button codes - appear to be the same. - - Henry Wong - Some changes to formatting and keycodes by Mark Schultz -*/ - -static struct ir_scancode msi_tvanywhere_plus[] = { - -/* ---- Remote Button Layout ---- - - POWER SOURCE SCAN MUTE - TV/FM 1 2 3 - |> 4 5 6 - <| 7 8 9 - ^^UP 0 + RECALL - vvDN RECORD STOP PLAY - - MINIMIZE ZOOM - - CH+ - VOL- VOL+ - CH- - - SNAPSHOT MTS - - << FUNC >> RESET -*/ - - { 0x01, KEY_1 }, /* 1 */ - { 0x0b, KEY_2 }, /* 2 */ - { 0x1b, KEY_3 }, /* 3 */ - { 0x05, KEY_4 }, /* 4 */ - { 0x09, KEY_5 }, /* 5 */ - { 0x15, KEY_6 }, /* 6 */ - { 0x06, KEY_7 }, /* 7 */ - { 0x0a, KEY_8 }, /* 8 */ - { 0x12, KEY_9 }, /* 9 */ - { 0x02, KEY_0 }, /* 0 */ - { 0x10, KEY_KPPLUS }, /* + */ - { 0x13, KEY_AGAIN }, /* Recall */ - - { 0x1e, KEY_POWER }, /* Power */ - { 0x07, KEY_TUNER }, /* Source */ - { 0x1c, KEY_SEARCH }, /* Scan */ - { 0x18, KEY_MUTE }, /* Mute */ - - { 0x03, KEY_RADIO }, /* TV/FM */ - /* The next four keys are duplicates that appear to send the - same IR code as Ch+, Ch-, >>, and << . The raw code assigned - to them is the actual code + 0x20 - they will never be - detected as such unless some way is discovered to distinguish - these buttons from those that have the same code. */ - { 0x3f, KEY_RIGHT }, /* |> and Ch+ */ - { 0x37, KEY_LEFT }, /* <| and Ch- */ - { 0x2c, KEY_UP }, /* ^^Up and >> */ - { 0x24, KEY_DOWN }, /* vvDn and << */ - - { 0x00, KEY_RECORD }, /* Record */ - { 0x08, KEY_STOP }, /* Stop */ - { 0x11, KEY_PLAY }, /* Play */ - - { 0x0f, KEY_CLOSE }, /* Minimize */ - { 0x19, KEY_ZOOM }, /* Zoom */ - { 0x1a, KEY_CAMERA }, /* Snapshot */ - { 0x0d, KEY_LANGUAGE }, /* MTS */ - - { 0x14, KEY_VOLUMEDOWN }, /* Vol- */ - { 0x16, KEY_VOLUMEUP }, /* Vol+ */ - { 0x17, KEY_CHANNELDOWN }, /* Ch- */ - { 0x1f, KEY_CHANNELUP }, /* Ch+ */ - - { 0x04, KEY_REWIND }, /* << */ - { 0x0e, KEY_MENU }, /* Function */ - { 0x0c, KEY_FASTFORWARD }, /* >> */ - { 0x1d, KEY_RESTART }, /* Reset */ -}; - -static struct rc_keymap msi_tvanywhere_plus_map = { - .map = { - .scan = msi_tvanywhere_plus, - .size = ARRAY_SIZE(msi_tvanywhere_plus), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_MSI_TVANYWHERE_PLUS, - } -}; - -static int __init init_rc_map_msi_tvanywhere_plus(void) -{ - return ir_register_map(&msi_tvanywhere_plus_map); -} - -static void __exit exit_rc_map_msi_tvanywhere_plus(void) -{ - ir_unregister_map(&msi_tvanywhere_plus_map); -} - -module_init(init_rc_map_msi_tvanywhere_plus) -module_exit(exit_rc_map_msi_tvanywhere_plus) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-msi-tvanywhere.c b/drivers/media/IR/keymaps/rc-msi-tvanywhere.c deleted file mode 100644 index ef41185..0000000 --- a/drivers/media/IR/keymaps/rc-msi-tvanywhere.c +++ /dev/null @@ -1,69 +0,0 @@ -/* msi-tvanywhere.h - Keytable for msi_tvanywhere Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* MSI TV@nywhere MASTER remote */ - -static struct ir_scancode msi_tvanywhere[] = { - /* Keys 0 to 9 */ - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - { 0x0c, KEY_MUTE }, - { 0x0f, KEY_SCREEN }, /* Full Screen */ - { 0x10, KEY_FN }, /* Funtion */ - { 0x11, KEY_TIME }, /* Time shift */ - { 0x12, KEY_POWER }, - { 0x13, KEY_MEDIA }, /* MTS */ - { 0x14, KEY_SLOW }, - { 0x16, KEY_REWIND }, /* backward << */ - { 0x17, KEY_ENTER }, /* Return */ - { 0x18, KEY_FASTFORWARD }, /* forward >> */ - { 0x1a, KEY_CHANNELUP }, - { 0x1b, KEY_VOLUMEUP }, - { 0x1e, KEY_CHANNELDOWN }, - { 0x1f, KEY_VOLUMEDOWN }, -}; - -static struct rc_keymap msi_tvanywhere_map = { - .map = { - .scan = msi_tvanywhere, - .size = ARRAY_SIZE(msi_tvanywhere), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_MSI_TVANYWHERE, - } -}; - -static int __init init_rc_map_msi_tvanywhere(void) -{ - return ir_register_map(&msi_tvanywhere_map); -} - -static void __exit exit_rc_map_msi_tvanywhere(void) -{ - ir_unregister_map(&msi_tvanywhere_map); -} - -module_init(init_rc_map_msi_tvanywhere) -module_exit(exit_rc_map_msi_tvanywhere) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-nebula.c b/drivers/media/IR/keymaps/rc-nebula.c deleted file mode 100644 index ccc50eb..0000000 --- a/drivers/media/IR/keymaps/rc-nebula.c +++ /dev/null @@ -1,96 +0,0 @@ -/* nebula.h - Keytable for nebula Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode nebula[] = { - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - { 0x0a, KEY_TV }, - { 0x0b, KEY_AUX }, - { 0x0c, KEY_DVD }, - { 0x0d, KEY_POWER }, - { 0x0e, KEY_MHP }, /* labelled 'Picture' */ - { 0x0f, KEY_AUDIO }, - { 0x10, KEY_INFO }, - { 0x11, KEY_F13 }, /* 16:9 */ - { 0x12, KEY_F14 }, /* 14:9 */ - { 0x13, KEY_EPG }, - { 0x14, KEY_EXIT }, - { 0x15, KEY_MENU }, - { 0x16, KEY_UP }, - { 0x17, KEY_DOWN }, - { 0x18, KEY_LEFT }, - { 0x19, KEY_RIGHT }, - { 0x1a, KEY_ENTER }, - { 0x1b, KEY_CHANNELUP }, - { 0x1c, KEY_CHANNELDOWN }, - { 0x1d, KEY_VOLUMEUP }, - { 0x1e, KEY_VOLUMEDOWN }, - { 0x1f, KEY_RED }, - { 0x20, KEY_GREEN }, - { 0x21, KEY_YELLOW }, - { 0x22, KEY_BLUE }, - { 0x23, KEY_SUBTITLE }, - { 0x24, KEY_F15 }, /* AD */ - { 0x25, KEY_TEXT }, - { 0x26, KEY_MUTE }, - { 0x27, KEY_REWIND }, - { 0x28, KEY_STOP }, - { 0x29, KEY_PLAY }, - { 0x2a, KEY_FASTFORWARD }, - { 0x2b, KEY_F16 }, /* chapter */ - { 0x2c, KEY_PAUSE }, - { 0x2d, KEY_PLAY }, - { 0x2e, KEY_RECORD }, - { 0x2f, KEY_F17 }, /* picture in picture */ - { 0x30, KEY_KPPLUS }, /* zoom in */ - { 0x31, KEY_KPMINUS }, /* zoom out */ - { 0x32, KEY_F18 }, /* capture */ - { 0x33, KEY_F19 }, /* web */ - { 0x34, KEY_EMAIL }, - { 0x35, KEY_PHONE }, - { 0x36, KEY_PC }, -}; - -static struct rc_keymap nebula_map = { - .map = { - .scan = nebula, - .size = ARRAY_SIZE(nebula), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_NEBULA, - } -}; - -static int __init init_rc_map_nebula(void) -{ - return ir_register_map(&nebula_map); -} - -static void __exit exit_rc_map_nebula(void) -{ - ir_unregister_map(&nebula_map); -} - -module_init(init_rc_map_nebula) -module_exit(exit_rc_map_nebula) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-nec-terratec-cinergy-xs.c b/drivers/media/IR/keymaps/rc-nec-terratec-cinergy-xs.c deleted file mode 100644 index e1b54d2..0000000 --- a/drivers/media/IR/keymaps/rc-nec-terratec-cinergy-xs.c +++ /dev/null @@ -1,105 +0,0 @@ -/* nec-terratec-cinergy-xs.h - Keytable for nec_terratec_cinergy_xs Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Terratec Cinergy Hybrid T USB XS FM - Mauro Carvalho Chehab - */ - -static struct ir_scancode nec_terratec_cinergy_xs[] = { - { 0x1441, KEY_HOME}, - { 0x1401, KEY_POWER2}, - - { 0x1442, KEY_MENU}, /* DVD menu */ - { 0x1443, KEY_SUBTITLE}, - { 0x1444, KEY_TEXT}, /* Teletext */ - { 0x1445, KEY_DELETE}, - - { 0x1402, KEY_1}, - { 0x1403, KEY_2}, - { 0x1404, KEY_3}, - { 0x1405, KEY_4}, - { 0x1406, KEY_5}, - { 0x1407, KEY_6}, - { 0x1408, KEY_7}, - { 0x1409, KEY_8}, - { 0x140a, KEY_9}, - { 0x140c, KEY_0}, - - { 0x140b, KEY_TUNER}, /* AV */ - { 0x140d, KEY_MODE}, /* A.B */ - - { 0x1446, KEY_TV}, - { 0x1447, KEY_DVD}, - { 0x1449, KEY_VIDEO}, - { 0x144a, KEY_RADIO}, /* Music */ - { 0x144b, KEY_CAMERA}, /* PIC */ - - { 0x1410, KEY_UP}, - { 0x1411, KEY_LEFT}, - { 0x1412, KEY_OK}, - { 0x1413, KEY_RIGHT}, - { 0x1414, KEY_DOWN}, - - { 0x140f, KEY_EPG}, - { 0x1416, KEY_INFO}, - { 0x144d, KEY_BACKSPACE}, - - { 0x141c, KEY_VOLUMEUP}, - { 0x141e, KEY_VOLUMEDOWN}, - - { 0x144c, KEY_PLAY}, - { 0x141d, KEY_MUTE}, - - { 0x141b, KEY_CHANNELUP}, - { 0x141f, KEY_CHANNELDOWN}, - - { 0x1417, KEY_RED}, - { 0x1418, KEY_GREEN}, - { 0x1419, KEY_YELLOW}, - { 0x141a, KEY_BLUE}, - - { 0x1458, KEY_RECORD}, - { 0x1448, KEY_STOP}, - { 0x1440, KEY_PAUSE}, - - { 0x1454, KEY_LAST}, - { 0x144e, KEY_REWIND}, - { 0x144f, KEY_FASTFORWARD}, - { 0x145c, KEY_NEXT}, -}; - -static struct rc_keymap nec_terratec_cinergy_xs_map = { - .map = { - .scan = nec_terratec_cinergy_xs, - .size = ARRAY_SIZE(nec_terratec_cinergy_xs), - .ir_type = IR_TYPE_NEC, - .name = RC_MAP_NEC_TERRATEC_CINERGY_XS, - } -}; - -static int __init init_rc_map_nec_terratec_cinergy_xs(void) -{ - return ir_register_map(&nec_terratec_cinergy_xs_map); -} - -static void __exit exit_rc_map_nec_terratec_cinergy_xs(void) -{ - ir_unregister_map(&nec_terratec_cinergy_xs_map); -} - -module_init(init_rc_map_nec_terratec_cinergy_xs) -module_exit(exit_rc_map_nec_terratec_cinergy_xs) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-norwood.c b/drivers/media/IR/keymaps/rc-norwood.c deleted file mode 100644 index e5849a6..0000000 --- a/drivers/media/IR/keymaps/rc-norwood.c +++ /dev/null @@ -1,85 +0,0 @@ -/* norwood.h - Keytable for norwood Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Norwood Micro (non-Pro) TV Tuner - By Peter Naulls - Key comments are the functions given in the manual */ - -static struct ir_scancode norwood[] = { - /* Keys 0 to 9 */ - { 0x20, KEY_0 }, - { 0x21, KEY_1 }, - { 0x22, KEY_2 }, - { 0x23, KEY_3 }, - { 0x24, KEY_4 }, - { 0x25, KEY_5 }, - { 0x26, KEY_6 }, - { 0x27, KEY_7 }, - { 0x28, KEY_8 }, - { 0x29, KEY_9 }, - - { 0x78, KEY_TUNER }, /* Video Source */ - { 0x2c, KEY_EXIT }, /* Open/Close software */ - { 0x2a, KEY_SELECT }, /* 2 Digit Select */ - { 0x69, KEY_AGAIN }, /* Recall */ - - { 0x32, KEY_BRIGHTNESSUP }, /* Brightness increase */ - { 0x33, KEY_BRIGHTNESSDOWN }, /* Brightness decrease */ - { 0x6b, KEY_KPPLUS }, /* (not named >>>>>) */ - { 0x6c, KEY_KPMINUS }, /* (not named <<<<<) */ - - { 0x2d, KEY_MUTE }, /* Mute */ - { 0x30, KEY_VOLUMEUP }, /* Volume up */ - { 0x31, KEY_VOLUMEDOWN }, /* Volume down */ - { 0x60, KEY_CHANNELUP }, /* Channel up */ - { 0x61, KEY_CHANNELDOWN }, /* Channel down */ - - { 0x3f, KEY_RECORD }, /* Record */ - { 0x37, KEY_PLAY }, /* Play */ - { 0x36, KEY_PAUSE }, /* Pause */ - { 0x2b, KEY_STOP }, /* Stop */ - { 0x67, KEY_FASTFORWARD }, /* Foward */ - { 0x66, KEY_REWIND }, /* Rewind */ - { 0x3e, KEY_SEARCH }, /* Auto Scan */ - { 0x2e, KEY_CAMERA }, /* Capture Video */ - { 0x6d, KEY_MENU }, /* Show/Hide Control */ - { 0x2f, KEY_ZOOM }, /* Full Screen */ - { 0x34, KEY_RADIO }, /* FM */ - { 0x65, KEY_POWER }, /* Computer power */ -}; - -static struct rc_keymap norwood_map = { - .map = { - .scan = norwood, - .size = ARRAY_SIZE(norwood), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_NORWOOD, - } -}; - -static int __init init_rc_map_norwood(void) -{ - return ir_register_map(&norwood_map); -} - -static void __exit exit_rc_map_norwood(void) -{ - ir_unregister_map(&norwood_map); -} - -module_init(init_rc_map_norwood) -module_exit(exit_rc_map_norwood) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-npgtech.c b/drivers/media/IR/keymaps/rc-npgtech.c deleted file mode 100644 index b9ece1e..0000000 --- a/drivers/media/IR/keymaps/rc-npgtech.c +++ /dev/null @@ -1,80 +0,0 @@ -/* npgtech.h - Keytable for npgtech Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode npgtech[] = { - { 0x1d, KEY_SWITCHVIDEOMODE }, /* switch inputs */ - { 0x2a, KEY_FRONT }, - - { 0x3e, KEY_1 }, - { 0x02, KEY_2 }, - { 0x06, KEY_3 }, - { 0x0a, KEY_4 }, - { 0x0e, KEY_5 }, - { 0x12, KEY_6 }, - { 0x16, KEY_7 }, - { 0x1a, KEY_8 }, - { 0x1e, KEY_9 }, - { 0x3a, KEY_0 }, - { 0x22, KEY_NUMLOCK }, /* -/-- */ - { 0x20, KEY_REFRESH }, - - { 0x03, KEY_BRIGHTNESSDOWN }, - { 0x28, KEY_AUDIO }, - { 0x3c, KEY_CHANNELUP }, - { 0x3f, KEY_VOLUMEDOWN }, - { 0x2e, KEY_MUTE }, - { 0x3b, KEY_VOLUMEUP }, - { 0x00, KEY_CHANNELDOWN }, - { 0x07, KEY_BRIGHTNESSUP }, - { 0x2c, KEY_TEXT }, - - { 0x37, KEY_RECORD }, - { 0x17, KEY_PLAY }, - { 0x13, KEY_PAUSE }, - { 0x26, KEY_STOP }, - { 0x18, KEY_FASTFORWARD }, - { 0x14, KEY_REWIND }, - { 0x33, KEY_ZOOM }, - { 0x32, KEY_KEYBOARD }, - { 0x30, KEY_GOTO }, /* Pointing arrow */ - { 0x36, KEY_MACRO }, /* Maximize/Minimize (yellow) */ - { 0x0b, KEY_RADIO }, - { 0x10, KEY_POWER }, - -}; - -static struct rc_keymap npgtech_map = { - .map = { - .scan = npgtech, - .size = ARRAY_SIZE(npgtech), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_NPGTECH, - } -}; - -static int __init init_rc_map_npgtech(void) -{ - return ir_register_map(&npgtech_map); -} - -static void __exit exit_rc_map_npgtech(void) -{ - ir_unregister_map(&npgtech_map); -} - -module_init(init_rc_map_npgtech) -module_exit(exit_rc_map_npgtech) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-pctv-sedna.c b/drivers/media/IR/keymaps/rc-pctv-sedna.c deleted file mode 100644 index 4129bb4..0000000 --- a/drivers/media/IR/keymaps/rc-pctv-sedna.c +++ /dev/null @@ -1,80 +0,0 @@ -/* pctv-sedna.h - Keytable for pctv_sedna Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Mapping for the 28 key remote control as seen at - http://www.sednacomputer.com/photo/cardbus-tv.jpg - Pavel Mihaylov - Also for the remote bundled with Kozumi KTV-01C card */ - -static struct ir_scancode pctv_sedna[] = { - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - { 0x0a, KEY_AGAIN }, /* Recall */ - { 0x0b, KEY_CHANNELUP }, - { 0x0c, KEY_VOLUMEUP }, - { 0x0d, KEY_MODE }, /* Stereo */ - { 0x0e, KEY_STOP }, - { 0x0f, KEY_PREVIOUSSONG }, - { 0x10, KEY_ZOOM }, - { 0x11, KEY_TUNER }, /* Source */ - { 0x12, KEY_POWER }, - { 0x13, KEY_MUTE }, - { 0x15, KEY_CHANNELDOWN }, - { 0x18, KEY_VOLUMEDOWN }, - { 0x19, KEY_CAMERA }, /* Snapshot */ - { 0x1a, KEY_NEXTSONG }, - { 0x1b, KEY_TIME }, /* Time Shift */ - { 0x1c, KEY_RADIO }, /* FM Radio */ - { 0x1d, KEY_RECORD }, - { 0x1e, KEY_PAUSE }, - /* additional codes for Kozumi's remote */ - { 0x14, KEY_INFO }, /* OSD */ - { 0x16, KEY_OK }, /* OK */ - { 0x17, KEY_DIGITS }, /* Plus */ - { 0x1f, KEY_PLAY }, /* Play */ -}; - -static struct rc_keymap pctv_sedna_map = { - .map = { - .scan = pctv_sedna, - .size = ARRAY_SIZE(pctv_sedna), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_PCTV_SEDNA, - } -}; - -static int __init init_rc_map_pctv_sedna(void) -{ - return ir_register_map(&pctv_sedna_map); -} - -static void __exit exit_rc_map_pctv_sedna(void) -{ - ir_unregister_map(&pctv_sedna_map); -} - -module_init(init_rc_map_pctv_sedna) -module_exit(exit_rc_map_pctv_sedna) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-pinnacle-color.c b/drivers/media/IR/keymaps/rc-pinnacle-color.c deleted file mode 100644 index 326e023..0000000 --- a/drivers/media/IR/keymaps/rc-pinnacle-color.c +++ /dev/null @@ -1,94 +0,0 @@ -/* pinnacle-color.h - Keytable for pinnacle_color Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode pinnacle_color[] = { - { 0x59, KEY_MUTE }, - { 0x4a, KEY_POWER }, - - { 0x18, KEY_TEXT }, - { 0x26, KEY_TV }, - { 0x3d, KEY_PRINT }, - - { 0x48, KEY_RED }, - { 0x04, KEY_GREEN }, - { 0x11, KEY_YELLOW }, - { 0x00, KEY_BLUE }, - - { 0x2d, KEY_VOLUMEUP }, - { 0x1e, KEY_VOLUMEDOWN }, - - { 0x49, KEY_MENU }, - - { 0x16, KEY_CHANNELUP }, - { 0x17, KEY_CHANNELDOWN }, - - { 0x20, KEY_UP }, - { 0x21, KEY_DOWN }, - { 0x22, KEY_LEFT }, - { 0x23, KEY_RIGHT }, - { 0x0d, KEY_SELECT }, - - { 0x08, KEY_BACK }, - { 0x07, KEY_REFRESH }, - - { 0x2f, KEY_ZOOM }, - { 0x29, KEY_RECORD }, - - { 0x4b, KEY_PAUSE }, - { 0x4d, KEY_REWIND }, - { 0x2e, KEY_PLAY }, - { 0x4e, KEY_FORWARD }, - { 0x53, KEY_PREVIOUS }, - { 0x4c, KEY_STOP }, - { 0x54, KEY_NEXT }, - - { 0x69, KEY_0 }, - { 0x6a, KEY_1 }, - { 0x6b, KEY_2 }, - { 0x6c, KEY_3 }, - { 0x6d, KEY_4 }, - { 0x6e, KEY_5 }, - { 0x6f, KEY_6 }, - { 0x70, KEY_7 }, - { 0x71, KEY_8 }, - { 0x72, KEY_9 }, - - { 0x74, KEY_CHANNEL }, - { 0x0a, KEY_BACKSPACE }, -}; - -static struct rc_keymap pinnacle_color_map = { - .map = { - .scan = pinnacle_color, - .size = ARRAY_SIZE(pinnacle_color), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_PINNACLE_COLOR, - } -}; - -static int __init init_rc_map_pinnacle_color(void) -{ - return ir_register_map(&pinnacle_color_map); -} - -static void __exit exit_rc_map_pinnacle_color(void) -{ - ir_unregister_map(&pinnacle_color_map); -} - -module_init(init_rc_map_pinnacle_color) -module_exit(exit_rc_map_pinnacle_color) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-pinnacle-grey.c b/drivers/media/IR/keymaps/rc-pinnacle-grey.c deleted file mode 100644 index 14cb772..0000000 --- a/drivers/media/IR/keymaps/rc-pinnacle-grey.c +++ /dev/null @@ -1,89 +0,0 @@ -/* pinnacle-grey.h - Keytable for pinnacle_grey Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode pinnacle_grey[] = { - { 0x3a, KEY_0 }, - { 0x31, KEY_1 }, - { 0x32, KEY_2 }, - { 0x33, KEY_3 }, - { 0x34, KEY_4 }, - { 0x35, KEY_5 }, - { 0x36, KEY_6 }, - { 0x37, KEY_7 }, - { 0x38, KEY_8 }, - { 0x39, KEY_9 }, - - { 0x2f, KEY_POWER }, - - { 0x2e, KEY_P }, - { 0x1f, KEY_L }, - { 0x2b, KEY_I }, - - { 0x2d, KEY_SCREEN }, - { 0x1e, KEY_ZOOM }, - { 0x1b, KEY_VOLUMEUP }, - { 0x0f, KEY_VOLUMEDOWN }, - { 0x17, KEY_CHANNELUP }, - { 0x1c, KEY_CHANNELDOWN }, - { 0x25, KEY_INFO }, - - { 0x3c, KEY_MUTE }, - - { 0x3d, KEY_LEFT }, - { 0x3b, KEY_RIGHT }, - - { 0x3f, KEY_UP }, - { 0x3e, KEY_DOWN }, - { 0x1a, KEY_ENTER }, - - { 0x1d, KEY_MENU }, - { 0x19, KEY_AGAIN }, - { 0x16, KEY_PREVIOUSSONG }, - { 0x13, KEY_NEXTSONG }, - { 0x15, KEY_PAUSE }, - { 0x0e, KEY_REWIND }, - { 0x0d, KEY_PLAY }, - { 0x0b, KEY_STOP }, - { 0x07, KEY_FORWARD }, - { 0x27, KEY_RECORD }, - { 0x26, KEY_TUNER }, - { 0x29, KEY_TEXT }, - { 0x2a, KEY_MEDIA }, - { 0x18, KEY_EPG }, -}; - -static struct rc_keymap pinnacle_grey_map = { - .map = { - .scan = pinnacle_grey, - .size = ARRAY_SIZE(pinnacle_grey), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_PINNACLE_GREY, - } -}; - -static int __init init_rc_map_pinnacle_grey(void) -{ - return ir_register_map(&pinnacle_grey_map); -} - -static void __exit exit_rc_map_pinnacle_grey(void) -{ - ir_unregister_map(&pinnacle_grey_map); -} - -module_init(init_rc_map_pinnacle_grey) -module_exit(exit_rc_map_pinnacle_grey) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-pinnacle-pctv-hd.c b/drivers/media/IR/keymaps/rc-pinnacle-pctv-hd.c deleted file mode 100644 index 835bf4e..0000000 --- a/drivers/media/IR/keymaps/rc-pinnacle-pctv-hd.c +++ /dev/null @@ -1,73 +0,0 @@ -/* pinnacle-pctv-hd.h - Keytable for pinnacle_pctv_hd Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Pinnacle PCTV HD 800i mini remote */ - -static struct ir_scancode pinnacle_pctv_hd[] = { - - { 0x0f, KEY_1 }, - { 0x15, KEY_2 }, - { 0x10, KEY_3 }, - { 0x18, KEY_4 }, - { 0x1b, KEY_5 }, - { 0x1e, KEY_6 }, - { 0x11, KEY_7 }, - { 0x21, KEY_8 }, - { 0x12, KEY_9 }, - { 0x27, KEY_0 }, - - { 0x24, KEY_ZOOM }, - { 0x2a, KEY_SUBTITLE }, - - { 0x00, KEY_MUTE }, - { 0x01, KEY_ENTER }, /* Pinnacle Logo */ - { 0x39, KEY_POWER }, - - { 0x03, KEY_VOLUMEUP }, - { 0x09, KEY_VOLUMEDOWN }, - { 0x06, KEY_CHANNELUP }, - { 0x0c, KEY_CHANNELDOWN }, - - { 0x2d, KEY_REWIND }, - { 0x30, KEY_PLAYPAUSE }, - { 0x33, KEY_FASTFORWARD }, - { 0x3c, KEY_STOP }, - { 0x36, KEY_RECORD }, - { 0x3f, KEY_EPG }, /* Labeled "?" */ -}; - -static struct rc_keymap pinnacle_pctv_hd_map = { - .map = { - .scan = pinnacle_pctv_hd, - .size = ARRAY_SIZE(pinnacle_pctv_hd), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_PINNACLE_PCTV_HD, - } -}; - -static int __init init_rc_map_pinnacle_pctv_hd(void) -{ - return ir_register_map(&pinnacle_pctv_hd_map); -} - -static void __exit exit_rc_map_pinnacle_pctv_hd(void) -{ - ir_unregister_map(&pinnacle_pctv_hd_map); -} - -module_init(init_rc_map_pinnacle_pctv_hd) -module_exit(exit_rc_map_pinnacle_pctv_hd) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-pixelview-mk12.c b/drivers/media/IR/keymaps/rc-pixelview-mk12.c deleted file mode 100644 index 5a735d5..0000000 --- a/drivers/media/IR/keymaps/rc-pixelview-mk12.c +++ /dev/null @@ -1,83 +0,0 @@ -/* rc-pixelview-mk12.h - Keytable for pixelview Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* - * Keytable for MK-F12 IR remote provided together with Pixelview - * Ultra Pro Remote Controller. Uses NEC extended format. - */ -static struct ir_scancode pixelview_mk12[] = { - { 0x866b03, KEY_TUNER }, /* Timeshift */ - { 0x866b1e, KEY_POWER2 }, /* power */ - - { 0x866b01, KEY_1 }, - { 0x866b0b, KEY_2 }, - { 0x866b1b, KEY_3 }, - { 0x866b05, KEY_4 }, - { 0x866b09, KEY_5 }, - { 0x866b15, KEY_6 }, - { 0x866b06, KEY_7 }, - { 0x866b0a, KEY_8 }, - { 0x866b12, KEY_9 }, - { 0x866b02, KEY_0 }, - - { 0x866b13, KEY_AGAIN }, /* loop */ - { 0x866b10, KEY_DIGITS }, /* +100 */ - - { 0x866b00, KEY_MEDIA }, /* source */ - { 0x866b18, KEY_MUTE }, /* mute */ - { 0x866b19, KEY_CAMERA }, /* snapshot */ - { 0x866b1a, KEY_SEARCH }, /* scan */ - - { 0x866b16, KEY_CHANNELUP }, /* chn + */ - { 0x866b14, KEY_CHANNELDOWN }, /* chn - */ - { 0x866b1f, KEY_VOLUMEUP }, /* vol + */ - { 0x866b17, KEY_VOLUMEDOWN }, /* vol - */ - { 0x866b1c, KEY_ZOOM }, /* zoom */ - - { 0x866b04, KEY_REWIND }, - { 0x866b0e, KEY_RECORD }, - { 0x866b0c, KEY_FORWARD }, - - { 0x866b1d, KEY_STOP }, - { 0x866b08, KEY_PLAY }, - { 0x866b0f, KEY_PAUSE }, - - { 0x866b0d, KEY_TV }, - { 0x866b07, KEY_RADIO }, /* FM */ -}; - -static struct rc_keymap pixelview_map = { - .map = { - .scan = pixelview_mk12, - .size = ARRAY_SIZE(pixelview_mk12), - .ir_type = IR_TYPE_NEC, - .name = RC_MAP_PIXELVIEW_MK12, - } -}; - -static int __init init_rc_map_pixelview(void) -{ - return ir_register_map(&pixelview_map); -} - -static void __exit exit_rc_map_pixelview(void) -{ - ir_unregister_map(&pixelview_map); -} - -module_init(init_rc_map_pixelview) -module_exit(exit_rc_map_pixelview) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-pixelview-new.c b/drivers/media/IR/keymaps/rc-pixelview-new.c deleted file mode 100644 index 7bbbbf5..0000000 --- a/drivers/media/IR/keymaps/rc-pixelview-new.c +++ /dev/null @@ -1,83 +0,0 @@ -/* pixelview-new.h - Keytable for pixelview_new Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* - Mauro Carvalho Chehab - present on PV MPEG 8000GT - */ - -static struct ir_scancode pixelview_new[] = { - { 0x3c, KEY_TIME }, /* Timeshift */ - { 0x12, KEY_POWER }, - - { 0x3d, KEY_1 }, - { 0x38, KEY_2 }, - { 0x18, KEY_3 }, - { 0x35, KEY_4 }, - { 0x39, KEY_5 }, - { 0x15, KEY_6 }, - { 0x36, KEY_7 }, - { 0x3a, KEY_8 }, - { 0x1e, KEY_9 }, - { 0x3e, KEY_0 }, - - { 0x1c, KEY_AGAIN }, /* LOOP */ - { 0x3f, KEY_MEDIA }, /* Source */ - { 0x1f, KEY_LAST }, /* +100 */ - { 0x1b, KEY_MUTE }, - - { 0x17, KEY_CHANNELDOWN }, - { 0x16, KEY_CHANNELUP }, - { 0x10, KEY_VOLUMEUP }, - { 0x14, KEY_VOLUMEDOWN }, - { 0x13, KEY_ZOOM }, - - { 0x19, KEY_CAMERA }, /* SNAPSHOT */ - { 0x1a, KEY_SEARCH }, /* scan */ - - { 0x37, KEY_REWIND }, /* << */ - { 0x32, KEY_RECORD }, /* o (red) */ - { 0x33, KEY_FORWARD }, /* >> */ - { 0x11, KEY_STOP }, /* square */ - { 0x3b, KEY_PLAY }, /* > */ - { 0x30, KEY_PLAYPAUSE }, /* || */ - - { 0x31, KEY_TV }, - { 0x34, KEY_RADIO }, -}; - -static struct rc_keymap pixelview_new_map = { - .map = { - .scan = pixelview_new, - .size = ARRAY_SIZE(pixelview_new), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_PIXELVIEW_NEW, - } -}; - -static int __init init_rc_map_pixelview_new(void) -{ - return ir_register_map(&pixelview_new_map); -} - -static void __exit exit_rc_map_pixelview_new(void) -{ - ir_unregister_map(&pixelview_new_map); -} - -module_init(init_rc_map_pixelview_new) -module_exit(exit_rc_map_pixelview_new) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-pixelview.c b/drivers/media/IR/keymaps/rc-pixelview.c deleted file mode 100644 index 82ff12e..0000000 --- a/drivers/media/IR/keymaps/rc-pixelview.c +++ /dev/null @@ -1,82 +0,0 @@ -/* pixelview.h - Keytable for pixelview Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode pixelview[] = { - - { 0x1e, KEY_POWER }, /* power */ - { 0x07, KEY_MEDIA }, /* source */ - { 0x1c, KEY_SEARCH }, /* scan */ - - - { 0x03, KEY_TUNER }, /* TV/FM */ - - { 0x00, KEY_RECORD }, - { 0x08, KEY_STOP }, - { 0x11, KEY_PLAY }, - - { 0x1a, KEY_PLAYPAUSE }, /* freeze */ - { 0x19, KEY_ZOOM }, /* zoom */ - { 0x0f, KEY_TEXT }, /* min */ - - { 0x01, KEY_1 }, - { 0x0b, KEY_2 }, - { 0x1b, KEY_3 }, - { 0x05, KEY_4 }, - { 0x09, KEY_5 }, - { 0x15, KEY_6 }, - { 0x06, KEY_7 }, - { 0x0a, KEY_8 }, - { 0x12, KEY_9 }, - { 0x02, KEY_0 }, - { 0x10, KEY_LAST }, /* +100 */ - { 0x13, KEY_LIST }, /* recall */ - - { 0x1f, KEY_CHANNELUP }, /* chn down */ - { 0x17, KEY_CHANNELDOWN }, /* chn up */ - { 0x16, KEY_VOLUMEUP }, /* vol down */ - { 0x14, KEY_VOLUMEDOWN }, /* vol up */ - - { 0x04, KEY_KPMINUS }, /* <<< */ - { 0x0e, KEY_SETUP }, /* function */ - { 0x0c, KEY_KPPLUS }, /* >>> */ - - { 0x0d, KEY_GOTO }, /* mts */ - { 0x1d, KEY_REFRESH }, /* reset */ - { 0x18, KEY_MUTE }, /* mute/unmute */ -}; - -static struct rc_keymap pixelview_map = { - .map = { - .scan = pixelview, - .size = ARRAY_SIZE(pixelview), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_PIXELVIEW, - } -}; - -static int __init init_rc_map_pixelview(void) -{ - return ir_register_map(&pixelview_map); -} - -static void __exit exit_rc_map_pixelview(void) -{ - ir_unregister_map(&pixelview_map); -} - -module_init(init_rc_map_pixelview) -module_exit(exit_rc_map_pixelview) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-powercolor-real-angel.c b/drivers/media/IR/keymaps/rc-powercolor-real-angel.c deleted file mode 100644 index 7cef819..0000000 --- a/drivers/media/IR/keymaps/rc-powercolor-real-angel.c +++ /dev/null @@ -1,81 +0,0 @@ -/* powercolor-real-angel.h - Keytable for powercolor_real_angel Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* - * Remote control for Powercolor Real Angel 330 - * Daniel Fraga - */ - -static struct ir_scancode powercolor_real_angel[] = { - { 0x38, KEY_SWITCHVIDEOMODE }, /* switch inputs */ - { 0x0c, KEY_MEDIA }, /* Turn ON/OFF App */ - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - { 0x0a, KEY_DIGITS }, /* single, double, tripple digit */ - { 0x29, KEY_PREVIOUS }, /* previous channel */ - { 0x12, KEY_BRIGHTNESSUP }, - { 0x13, KEY_BRIGHTNESSDOWN }, - { 0x2b, KEY_MODE }, /* stereo/mono */ - { 0x2c, KEY_TEXT }, /* teletext */ - { 0x20, KEY_CHANNELUP }, /* channel up */ - { 0x21, KEY_CHANNELDOWN }, /* channel down */ - { 0x10, KEY_VOLUMEUP }, /* volume up */ - { 0x11, KEY_VOLUMEDOWN }, /* volume down */ - { 0x0d, KEY_MUTE }, - { 0x1f, KEY_RECORD }, - { 0x17, KEY_PLAY }, - { 0x16, KEY_PAUSE }, - { 0x0b, KEY_STOP }, - { 0x27, KEY_FASTFORWARD }, - { 0x26, KEY_REWIND }, - { 0x1e, KEY_SEARCH }, /* autoscan */ - { 0x0e, KEY_CAMERA }, /* snapshot */ - { 0x2d, KEY_SETUP }, - { 0x0f, KEY_SCREEN }, /* full screen */ - { 0x14, KEY_RADIO }, /* FM radio */ - { 0x25, KEY_POWER }, /* power */ -}; - -static struct rc_keymap powercolor_real_angel_map = { - .map = { - .scan = powercolor_real_angel, - .size = ARRAY_SIZE(powercolor_real_angel), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_POWERCOLOR_REAL_ANGEL, - } -}; - -static int __init init_rc_map_powercolor_real_angel(void) -{ - return ir_register_map(&powercolor_real_angel_map); -} - -static void __exit exit_rc_map_powercolor_real_angel(void) -{ - ir_unregister_map(&powercolor_real_angel_map); -} - -module_init(init_rc_map_powercolor_real_angel) -module_exit(exit_rc_map_powercolor_real_angel) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-proteus-2309.c b/drivers/media/IR/keymaps/rc-proteus-2309.c deleted file mode 100644 index 22e92d3..0000000 --- a/drivers/media/IR/keymaps/rc-proteus-2309.c +++ /dev/null @@ -1,69 +0,0 @@ -/* proteus-2309.h - Keytable for proteus_2309 Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Michal Majchrowicz */ - -static struct ir_scancode proteus_2309[] = { - /* numeric */ - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - { 0x5c, KEY_POWER }, /* power */ - { 0x20, KEY_ZOOM }, /* full screen */ - { 0x0f, KEY_BACKSPACE }, /* recall */ - { 0x1b, KEY_ENTER }, /* mute */ - { 0x41, KEY_RECORD }, /* record */ - { 0x43, KEY_STOP }, /* stop */ - { 0x16, KEY_S }, - { 0x1a, KEY_POWER2 }, /* off */ - { 0x2e, KEY_RED }, - { 0x1f, KEY_CHANNELDOWN }, /* channel - */ - { 0x1c, KEY_CHANNELUP }, /* channel + */ - { 0x10, KEY_VOLUMEDOWN }, /* volume - */ - { 0x1e, KEY_VOLUMEUP }, /* volume + */ - { 0x14, KEY_F1 }, -}; - -static struct rc_keymap proteus_2309_map = { - .map = { - .scan = proteus_2309, - .size = ARRAY_SIZE(proteus_2309), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_PROTEUS_2309, - } -}; - -static int __init init_rc_map_proteus_2309(void) -{ - return ir_register_map(&proteus_2309_map); -} - -static void __exit exit_rc_map_proteus_2309(void) -{ - ir_unregister_map(&proteus_2309_map); -} - -module_init(init_rc_map_proteus_2309) -module_exit(exit_rc_map_proteus_2309) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-purpletv.c b/drivers/media/IR/keymaps/rc-purpletv.c deleted file mode 100644 index 4e20fc2..0000000 --- a/drivers/media/IR/keymaps/rc-purpletv.c +++ /dev/null @@ -1,81 +0,0 @@ -/* purpletv.h - Keytable for purpletv Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode purpletv[] = { - { 0x03, KEY_POWER }, - { 0x6f, KEY_MUTE }, - { 0x10, KEY_BACKSPACE }, /* Recall */ - - { 0x11, KEY_0 }, - { 0x04, KEY_1 }, - { 0x05, KEY_2 }, - { 0x06, KEY_3 }, - { 0x08, KEY_4 }, - { 0x09, KEY_5 }, - { 0x0a, KEY_6 }, - { 0x0c, KEY_7 }, - { 0x0d, KEY_8 }, - { 0x0e, KEY_9 }, - { 0x12, KEY_DOT }, /* 100+ */ - - { 0x07, KEY_VOLUMEUP }, - { 0x0b, KEY_VOLUMEDOWN }, - { 0x1a, KEY_KPPLUS }, - { 0x18, KEY_KPMINUS }, - { 0x15, KEY_UP }, - { 0x1d, KEY_DOWN }, - { 0x0f, KEY_CHANNELUP }, - { 0x13, KEY_CHANNELDOWN }, - { 0x48, KEY_ZOOM }, - - { 0x1b, KEY_VIDEO }, /* Video source */ - { 0x1f, KEY_CAMERA }, /* Snapshot */ - { 0x49, KEY_LANGUAGE }, /* MTS Select */ - { 0x19, KEY_SEARCH }, /* Auto Scan */ - - { 0x4b, KEY_RECORD }, - { 0x46, KEY_PLAY }, - { 0x45, KEY_PAUSE }, /* Pause */ - { 0x44, KEY_STOP }, - { 0x43, KEY_TIME }, /* Time Shift */ - { 0x17, KEY_CHANNEL }, /* SURF CH */ - { 0x40, KEY_FORWARD }, /* Forward ? */ - { 0x42, KEY_REWIND }, /* Backward ? */ - -}; - -static struct rc_keymap purpletv_map = { - .map = { - .scan = purpletv, - .size = ARRAY_SIZE(purpletv), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_PURPLETV, - } -}; - -static int __init init_rc_map_purpletv(void) -{ - return ir_register_map(&purpletv_map); -} - -static void __exit exit_rc_map_purpletv(void) -{ - ir_unregister_map(&purpletv_map); -} - -module_init(init_rc_map_purpletv) -module_exit(exit_rc_map_purpletv) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-pv951.c b/drivers/media/IR/keymaps/rc-pv951.c deleted file mode 100644 index 36679e7..0000000 --- a/drivers/media/IR/keymaps/rc-pv951.c +++ /dev/null @@ -1,78 +0,0 @@ -/* pv951.h - Keytable for pv951 Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Mark Phalan */ - -static struct ir_scancode pv951[] = { - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - { 0x12, KEY_POWER }, - { 0x10, KEY_MUTE }, - { 0x1f, KEY_VOLUMEDOWN }, - { 0x1b, KEY_VOLUMEUP }, - { 0x1a, KEY_CHANNELUP }, - { 0x1e, KEY_CHANNELDOWN }, - { 0x0e, KEY_PAGEUP }, - { 0x1d, KEY_PAGEDOWN }, - { 0x13, KEY_SOUND }, - - { 0x18, KEY_KPPLUSMINUS }, /* CH +/- */ - { 0x16, KEY_SUBTITLE }, /* CC */ - { 0x0d, KEY_TEXT }, /* TTX */ - { 0x0b, KEY_TV }, /* AIR/CBL */ - { 0x11, KEY_PC }, /* PC/TV */ - { 0x17, KEY_OK }, /* CH RTN */ - { 0x19, KEY_MODE }, /* FUNC */ - { 0x0c, KEY_SEARCH }, /* AUTOSCAN */ - - /* Not sure what to do with these ones! */ - { 0x0f, KEY_SELECT }, /* SOURCE */ - { 0x0a, KEY_KPPLUS }, /* +100 */ - { 0x14, KEY_EQUAL }, /* SYNC */ - { 0x1c, KEY_MEDIA }, /* PC/TV */ -}; - -static struct rc_keymap pv951_map = { - .map = { - .scan = pv951, - .size = ARRAY_SIZE(pv951), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_PV951, - } -}; - -static int __init init_rc_map_pv951(void) -{ - return ir_register_map(&pv951_map); -} - -static void __exit exit_rc_map_pv951(void) -{ - ir_unregister_map(&pv951_map); -} - -module_init(init_rc_map_pv951) -module_exit(exit_rc_map_pv951) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-rc5-hauppauge-new.c b/drivers/media/IR/keymaps/rc-rc5-hauppauge-new.c deleted file mode 100644 index cc6b8f5..0000000 --- a/drivers/media/IR/keymaps/rc-rc5-hauppauge-new.c +++ /dev/null @@ -1,103 +0,0 @@ -/* rc5-hauppauge-new.h - Keytable for rc5_hauppauge_new Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* - * Hauppauge:the newer, gray remotes (seems there are multiple - * slightly different versions), shipped with cx88+ivtv cards. - * - * This table contains the complete RC5 code, instead of just the data part - */ - -static struct ir_scancode rc5_hauppauge_new[] = { - /* Keys 0 to 9 */ - { 0x1e00, KEY_0 }, - { 0x1e01, KEY_1 }, - { 0x1e02, KEY_2 }, - { 0x1e03, KEY_3 }, - { 0x1e04, KEY_4 }, - { 0x1e05, KEY_5 }, - { 0x1e06, KEY_6 }, - { 0x1e07, KEY_7 }, - { 0x1e08, KEY_8 }, - { 0x1e09, KEY_9 }, - - { 0x1e0a, KEY_TEXT }, /* keypad asterisk as well */ - { 0x1e0b, KEY_RED }, /* red button */ - { 0x1e0c, KEY_RADIO }, - { 0x1e0d, KEY_MENU }, - { 0x1e0e, KEY_SUBTITLE }, /* also the # key */ - { 0x1e0f, KEY_MUTE }, - { 0x1e10, KEY_VOLUMEUP }, - { 0x1e11, KEY_VOLUMEDOWN }, - { 0x1e12, KEY_PREVIOUS }, /* previous channel */ - { 0x1e14, KEY_UP }, - { 0x1e15, KEY_DOWN }, - { 0x1e16, KEY_LEFT }, - { 0x1e17, KEY_RIGHT }, - { 0x1e18, KEY_VIDEO }, /* Videos */ - { 0x1e19, KEY_AUDIO }, /* Music */ - /* 0x1e1a: Pictures - presume this means - "Multimedia Home Platform" - - no "PICTURES" key in input.h - */ - { 0x1e1a, KEY_MHP }, - - { 0x1e1b, KEY_EPG }, /* Guide */ - { 0x1e1c, KEY_TV }, - { 0x1e1e, KEY_NEXTSONG }, /* skip >| */ - { 0x1e1f, KEY_EXIT }, /* back/exit */ - { 0x1e20, KEY_CHANNELUP }, /* channel / program + */ - { 0x1e21, KEY_CHANNELDOWN }, /* channel / program - */ - { 0x1e22, KEY_CHANNEL }, /* source (old black remote) */ - { 0x1e24, KEY_PREVIOUSSONG }, /* replay |< */ - { 0x1e25, KEY_ENTER }, /* OK */ - { 0x1e26, KEY_SLEEP }, /* minimize (old black remote) */ - { 0x1e29, KEY_BLUE }, /* blue key */ - { 0x1e2e, KEY_GREEN }, /* green button */ - { 0x1e30, KEY_PAUSE }, /* pause */ - { 0x1e32, KEY_REWIND }, /* backward << */ - { 0x1e34, KEY_FASTFORWARD }, /* forward >> */ - { 0x1e35, KEY_PLAY }, - { 0x1e36, KEY_STOP }, - { 0x1e37, KEY_RECORD }, /* recording */ - { 0x1e38, KEY_YELLOW }, /* yellow key */ - { 0x1e3b, KEY_SELECT }, /* top right button */ - { 0x1e3c, KEY_ZOOM }, /* full */ - { 0x1e3d, KEY_POWER }, /* system power (green button) */ -}; - -static struct rc_keymap rc5_hauppauge_new_map = { - .map = { - .scan = rc5_hauppauge_new, - .size = ARRAY_SIZE(rc5_hauppauge_new), - .ir_type = IR_TYPE_RC5, - .name = RC_MAP_RC5_HAUPPAUGE_NEW, - } -}; - -static int __init init_rc_map_rc5_hauppauge_new(void) -{ - return ir_register_map(&rc5_hauppauge_new_map); -} - -static void __exit exit_rc_map_rc5_hauppauge_new(void) -{ - ir_unregister_map(&rc5_hauppauge_new_map); -} - -module_init(init_rc_map_rc5_hauppauge_new) -module_exit(exit_rc_map_rc5_hauppauge_new) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-rc5-tv.c b/drivers/media/IR/keymaps/rc-rc5-tv.c deleted file mode 100644 index 73cce2f..0000000 --- a/drivers/media/IR/keymaps/rc-rc5-tv.c +++ /dev/null @@ -1,81 +0,0 @@ -/* rc5-tv.h - Keytable for rc5_tv Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* generic RC5 keytable */ -/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ -/* used by old (black) Hauppauge remotes */ - -static struct ir_scancode rc5_tv[] = { - /* Keys 0 to 9 */ - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - { 0x0b, KEY_CHANNEL }, /* channel / program (japan: 11) */ - { 0x0c, KEY_POWER }, /* standby */ - { 0x0d, KEY_MUTE }, /* mute / demute */ - { 0x0f, KEY_TV }, /* display */ - { 0x10, KEY_VOLUMEUP }, - { 0x11, KEY_VOLUMEDOWN }, - { 0x12, KEY_BRIGHTNESSUP }, - { 0x13, KEY_BRIGHTNESSDOWN }, - { 0x1e, KEY_SEARCH }, /* search + */ - { 0x20, KEY_CHANNELUP }, /* channel / program + */ - { 0x21, KEY_CHANNELDOWN }, /* channel / program - */ - { 0x22, KEY_CHANNEL }, /* alt / channel */ - { 0x23, KEY_LANGUAGE }, /* 1st / 2nd language */ - { 0x26, KEY_SLEEP }, /* sleeptimer */ - { 0x2e, KEY_MENU }, /* 2nd controls (USA: menu) */ - { 0x30, KEY_PAUSE }, - { 0x32, KEY_REWIND }, - { 0x33, KEY_GOTO }, - { 0x35, KEY_PLAY }, - { 0x36, KEY_STOP }, - { 0x37, KEY_RECORD }, /* recording */ - { 0x3c, KEY_TEXT }, /* teletext submode (Japan: 12) */ - { 0x3d, KEY_SUSPEND }, /* system standby */ - -}; - -static struct rc_keymap rc5_tv_map = { - .map = { - .scan = rc5_tv, - .size = ARRAY_SIZE(rc5_tv), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_RC5_TV, - } -}; - -static int __init init_rc_map_rc5_tv(void) -{ - return ir_register_map(&rc5_tv_map); -} - -static void __exit exit_rc_map_rc5_tv(void) -{ - ir_unregister_map(&rc5_tv_map); -} - -module_init(init_rc_map_rc5_tv) -module_exit(exit_rc_map_rc5_tv) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-rc6-mce.c b/drivers/media/IR/keymaps/rc-rc6-mce.c deleted file mode 100644 index 6da955d..0000000 --- a/drivers/media/IR/keymaps/rc-rc6-mce.c +++ /dev/null @@ -1,113 +0,0 @@ -/* rc-rc6-mce.c - Keytable for Windows Media Center RC-6 remotes for use - * with the Media Center Edition eHome Infrared Transceiver. - * - * Copyright (c) 2010 by Jarod Wilson - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode rc6_mce[] = { - - { 0x800f0400, KEY_NUMERIC_0 }, - { 0x800f0401, KEY_NUMERIC_1 }, - { 0x800f0402, KEY_NUMERIC_2 }, - { 0x800f0403, KEY_NUMERIC_3 }, - { 0x800f0404, KEY_NUMERIC_4 }, - { 0x800f0405, KEY_NUMERIC_5 }, - { 0x800f0406, KEY_NUMERIC_6 }, - { 0x800f0407, KEY_NUMERIC_7 }, - { 0x800f0408, KEY_NUMERIC_8 }, - { 0x800f0409, KEY_NUMERIC_9 }, - - { 0x800f040a, KEY_DELETE }, - { 0x800f040b, KEY_ENTER }, - { 0x800f040c, KEY_POWER }, /* PC Power */ - { 0x800f040d, KEY_PROG1 }, /* Windows MCE button */ - { 0x800f040e, KEY_MUTE }, - { 0x800f040f, KEY_INFO }, - - { 0x800f0410, KEY_VOLUMEUP }, - { 0x800f0411, KEY_VOLUMEDOWN }, - { 0x800f0412, KEY_CHANNELUP }, - { 0x800f0413, KEY_CHANNELDOWN }, - - { 0x800f0414, KEY_FASTFORWARD }, - { 0x800f0415, KEY_REWIND }, - { 0x800f0416, KEY_PLAY }, - { 0x800f0417, KEY_RECORD }, - { 0x800f0418, KEY_PAUSE }, - { 0x800f046e, KEY_PLAYPAUSE }, - { 0x800f0419, KEY_STOP }, - { 0x800f041a, KEY_NEXT }, - { 0x800f041b, KEY_PREVIOUS }, - { 0x800f041c, KEY_NUMERIC_POUND }, - { 0x800f041d, KEY_NUMERIC_STAR }, - - { 0x800f041e, KEY_UP }, - { 0x800f041f, KEY_DOWN }, - { 0x800f0420, KEY_LEFT }, - { 0x800f0421, KEY_RIGHT }, - - { 0x800f0422, KEY_OK }, - { 0x800f0423, KEY_EXIT }, - { 0x800f0424, KEY_DVD }, - { 0x800f0425, KEY_TUNER }, /* LiveTV */ - { 0x800f0426, KEY_EPG }, /* Guide */ - { 0x800f0427, KEY_ZOOM }, /* Aspect */ - - { 0x800f043a, KEY_BRIGHTNESSUP }, - - { 0x800f0446, KEY_TV }, - { 0x800f0447, KEY_AUDIO }, /* My Music */ - { 0x800f0448, KEY_PVR }, /* RecordedTV */ - { 0x800f0449, KEY_CAMERA }, - { 0x800f044a, KEY_VIDEO }, - { 0x800f044c, KEY_LANGUAGE }, - { 0x800f044d, KEY_TITLE }, - { 0x800f044e, KEY_PRINT }, /* Print - HP OEM version of remote */ - - { 0x800f0450, KEY_RADIO }, - - { 0x800f045a, KEY_SUBTITLE }, /* Caption/Teletext */ - { 0x800f045b, KEY_RED }, - { 0x800f045c, KEY_GREEN }, - { 0x800f045d, KEY_YELLOW }, - { 0x800f045e, KEY_BLUE }, - - { 0x800f0465, KEY_POWER2 }, /* TV Power */ - { 0x800f046e, KEY_PLAYPAUSE }, - { 0x800f046f, KEY_MEDIA }, /* Start media application (NEW) */ - - { 0x800f0480, KEY_BRIGHTNESSDOWN }, - { 0x800f0481, KEY_PLAYPAUSE }, -}; - -static struct rc_keymap rc6_mce_map = { - .map = { - .scan = rc6_mce, - .size = ARRAY_SIZE(rc6_mce), - .ir_type = IR_TYPE_RC6, - .name = RC_MAP_RC6_MCE, - } -}; - -static int __init init_rc_map_rc6_mce(void) -{ - return ir_register_map(&rc6_mce_map); -} - -static void __exit exit_rc_map_rc6_mce(void) -{ - ir_unregister_map(&rc6_mce_map); -} - -module_init(init_rc_map_rc6_mce) -module_exit(exit_rc_map_rc6_mce) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jarod Wilson "); diff --git a/drivers/media/IR/keymaps/rc-real-audio-220-32-keys.c b/drivers/media/IR/keymaps/rc-real-audio-220-32-keys.c deleted file mode 100644 index ab1a6d2..0000000 --- a/drivers/media/IR/keymaps/rc-real-audio-220-32-keys.c +++ /dev/null @@ -1,78 +0,0 @@ -/* real-audio-220-32-keys.h - Keytable for real_audio_220_32_keys Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Zogis Real Audio 220 - 32 keys IR */ - -static struct ir_scancode real_audio_220_32_keys[] = { - { 0x1c, KEY_RADIO}, - { 0x12, KEY_POWER2}, - - { 0x01, KEY_1}, - { 0x02, KEY_2}, - { 0x03, KEY_3}, - { 0x04, KEY_4}, - { 0x05, KEY_5}, - { 0x06, KEY_6}, - { 0x07, KEY_7}, - { 0x08, KEY_8}, - { 0x09, KEY_9}, - { 0x00, KEY_0}, - - { 0x0c, KEY_VOLUMEUP}, - { 0x18, KEY_VOLUMEDOWN}, - { 0x0b, KEY_CHANNELUP}, - { 0x15, KEY_CHANNELDOWN}, - { 0x16, KEY_ENTER}, - - { 0x11, KEY_LIST}, /* Source */ - { 0x0d, KEY_AUDIO}, /* stereo */ - - { 0x0f, KEY_PREVIOUS}, /* Prev */ - { 0x1b, KEY_TIME}, /* Timeshift */ - { 0x1a, KEY_NEXT}, /* Next */ - - { 0x0e, KEY_STOP}, - { 0x1f, KEY_PLAY}, - { 0x1e, KEY_PLAYPAUSE}, /* Pause */ - - { 0x1d, KEY_RECORD}, - { 0x13, KEY_MUTE}, - { 0x19, KEY_CAMERA}, /* Snapshot */ - -}; - -static struct rc_keymap real_audio_220_32_keys_map = { - .map = { - .scan = real_audio_220_32_keys, - .size = ARRAY_SIZE(real_audio_220_32_keys), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_REAL_AUDIO_220_32_KEYS, - } -}; - -static int __init init_rc_map_real_audio_220_32_keys(void) -{ - return ir_register_map(&real_audio_220_32_keys_map); -} - -static void __exit exit_rc_map_real_audio_220_32_keys(void) -{ - ir_unregister_map(&real_audio_220_32_keys_map); -} - -module_init(init_rc_map_real_audio_220_32_keys) -module_exit(exit_rc_map_real_audio_220_32_keys) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-streamzap.c b/drivers/media/IR/keymaps/rc-streamzap.c deleted file mode 100644 index df32013..0000000 --- a/drivers/media/IR/keymaps/rc-streamzap.c +++ /dev/null @@ -1,82 +0,0 @@ -/* rc-streamzap.c - Keytable for Streamzap PC Remote, for use - * with the Streamzap PC Remote IR Receiver. - * - * Copyright (c) 2010 by Jarod Wilson - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode streamzap[] = { -/* - * The Streamzap remote is almost, but not quite, RC-5, as it has an extra - * bit in it, which throws the in-kernel RC-5 decoder for a loop. Currently, - * an additional RC-5-sz decoder is being deployed to support it, but it - * may be possible to merge it back with the standard RC-5 decoder. - */ - { 0x28c0, KEY_NUMERIC_0 }, - { 0x28c1, KEY_NUMERIC_1 }, - { 0x28c2, KEY_NUMERIC_2 }, - { 0x28c3, KEY_NUMERIC_3 }, - { 0x28c4, KEY_NUMERIC_4 }, - { 0x28c5, KEY_NUMERIC_5 }, - { 0x28c6, KEY_NUMERIC_6 }, - { 0x28c7, KEY_NUMERIC_7 }, - { 0x28c8, KEY_NUMERIC_8 }, - { 0x28c9, KEY_NUMERIC_9 }, - { 0x28ca, KEY_POWER }, - { 0x28cb, KEY_MUTE }, - { 0x28cc, KEY_CHANNELUP }, - { 0x28cd, KEY_VOLUMEUP }, - { 0x28ce, KEY_CHANNELDOWN }, - { 0x28cf, KEY_VOLUMEDOWN }, - { 0x28d0, KEY_UP }, - { 0x28d1, KEY_LEFT }, - { 0x28d2, KEY_OK }, - { 0x28d3, KEY_RIGHT }, - { 0x28d4, KEY_DOWN }, - { 0x28d5, KEY_MENU }, - { 0x28d6, KEY_EXIT }, - { 0x28d7, KEY_PLAY }, - { 0x28d8, KEY_PAUSE }, - { 0x28d9, KEY_STOP }, - { 0x28da, KEY_BACK }, - { 0x28db, KEY_FORWARD }, - { 0x28dc, KEY_RECORD }, - { 0x28dd, KEY_REWIND }, - { 0x28de, KEY_FASTFORWARD }, - { 0x28e0, KEY_RED }, - { 0x28e1, KEY_GREEN }, - { 0x28e2, KEY_YELLOW }, - { 0x28e3, KEY_BLUE }, - -}; - -static struct rc_keymap streamzap_map = { - .map = { - .scan = streamzap, - .size = ARRAY_SIZE(streamzap), - .ir_type = IR_TYPE_RC5_SZ, - .name = RC_MAP_STREAMZAP, - } -}; - -static int __init init_rc_map_streamzap(void) -{ - return ir_register_map(&streamzap_map); -} - -static void __exit exit_rc_map_streamzap(void) -{ - ir_unregister_map(&streamzap_map); -} - -module_init(init_rc_map_streamzap) -module_exit(exit_rc_map_streamzap) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jarod Wilson "); diff --git a/drivers/media/IR/keymaps/rc-tbs-nec.c b/drivers/media/IR/keymaps/rc-tbs-nec.c deleted file mode 100644 index 3309631..0000000 --- a/drivers/media/IR/keymaps/rc-tbs-nec.c +++ /dev/null @@ -1,73 +0,0 @@ -/* tbs-nec.h - Keytable for tbs_nec Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode tbs_nec[] = { - { 0x04, KEY_POWER2}, /*power*/ - { 0x14, KEY_MUTE}, /*mute*/ - { 0x07, KEY_1}, - { 0x06, KEY_2}, - { 0x05, KEY_3}, - { 0x0b, KEY_4}, - { 0x0a, KEY_5}, - { 0x09, KEY_6}, - { 0x0f, KEY_7}, - { 0x0e, KEY_8}, - { 0x0d, KEY_9}, - { 0x12, KEY_0}, - { 0x16, KEY_CHANNELUP}, /*ch+*/ - { 0x11, KEY_CHANNELDOWN},/*ch-*/ - { 0x13, KEY_VOLUMEUP}, /*vol+*/ - { 0x0c, KEY_VOLUMEDOWN},/*vol-*/ - { 0x03, KEY_RECORD}, /*rec*/ - { 0x18, KEY_PAUSE}, /*pause*/ - { 0x19, KEY_OK}, /*ok*/ - { 0x1a, KEY_CAMERA}, /* snapshot */ - { 0x01, KEY_UP}, - { 0x10, KEY_LEFT}, - { 0x02, KEY_RIGHT}, - { 0x08, KEY_DOWN}, - { 0x15, KEY_FAVORITES}, - { 0x17, KEY_SUBTITLE}, - { 0x1d, KEY_ZOOM}, - { 0x1f, KEY_EXIT}, - { 0x1e, KEY_MENU}, - { 0x1c, KEY_EPG}, - { 0x00, KEY_PREVIOUS}, - { 0x1b, KEY_MODE}, -}; - -static struct rc_keymap tbs_nec_map = { - .map = { - .scan = tbs_nec, - .size = ARRAY_SIZE(tbs_nec), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_TBS_NEC, - } -}; - -static int __init init_rc_map_tbs_nec(void) -{ - return ir_register_map(&tbs_nec_map); -} - -static void __exit exit_rc_map_tbs_nec(void) -{ - ir_unregister_map(&tbs_nec_map); -} - -module_init(init_rc_map_tbs_nec) -module_exit(exit_rc_map_tbs_nec) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-terratec-cinergy-xs.c b/drivers/media/IR/keymaps/rc-terratec-cinergy-xs.c deleted file mode 100644 index 5326a0b..0000000 --- a/drivers/media/IR/keymaps/rc-terratec-cinergy-xs.c +++ /dev/null @@ -1,92 +0,0 @@ -/* terratec-cinergy-xs.h - Keytable for terratec_cinergy_xs Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Terratec Cinergy Hybrid T USB XS - Devin Heitmueller - */ - -static struct ir_scancode terratec_cinergy_xs[] = { - { 0x41, KEY_HOME}, - { 0x01, KEY_POWER}, - { 0x42, KEY_MENU}, - { 0x02, KEY_1}, - { 0x03, KEY_2}, - { 0x04, KEY_3}, - { 0x43, KEY_SUBTITLE}, - { 0x05, KEY_4}, - { 0x06, KEY_5}, - { 0x07, KEY_6}, - { 0x44, KEY_TEXT}, - { 0x08, KEY_7}, - { 0x09, KEY_8}, - { 0x0a, KEY_9}, - { 0x45, KEY_DELETE}, - { 0x0b, KEY_TUNER}, - { 0x0c, KEY_0}, - { 0x0d, KEY_MODE}, - { 0x46, KEY_TV}, - { 0x47, KEY_DVD}, - { 0x49, KEY_VIDEO}, - { 0x4b, KEY_AUX}, - { 0x10, KEY_UP}, - { 0x11, KEY_LEFT}, - { 0x12, KEY_OK}, - { 0x13, KEY_RIGHT}, - { 0x14, KEY_DOWN}, - { 0x0f, KEY_EPG}, - { 0x16, KEY_INFO}, - { 0x4d, KEY_BACKSPACE}, - { 0x1c, KEY_VOLUMEUP}, - { 0x4c, KEY_PLAY}, - { 0x1b, KEY_CHANNELUP}, - { 0x1e, KEY_VOLUMEDOWN}, - { 0x1d, KEY_MUTE}, - { 0x1f, KEY_CHANNELDOWN}, - { 0x17, KEY_RED}, - { 0x18, KEY_GREEN}, - { 0x19, KEY_YELLOW}, - { 0x1a, KEY_BLUE}, - { 0x58, KEY_RECORD}, - { 0x48, KEY_STOP}, - { 0x40, KEY_PAUSE}, - { 0x54, KEY_LAST}, - { 0x4e, KEY_REWIND}, - { 0x4f, KEY_FASTFORWARD}, - { 0x5c, KEY_NEXT}, -}; - -static struct rc_keymap terratec_cinergy_xs_map = { - .map = { - .scan = terratec_cinergy_xs, - .size = ARRAY_SIZE(terratec_cinergy_xs), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_TERRATEC_CINERGY_XS, - } -}; - -static int __init init_rc_map_terratec_cinergy_xs(void) -{ - return ir_register_map(&terratec_cinergy_xs_map); -} - -static void __exit exit_rc_map_terratec_cinergy_xs(void) -{ - ir_unregister_map(&terratec_cinergy_xs_map); -} - -module_init(init_rc_map_terratec_cinergy_xs) -module_exit(exit_rc_map_terratec_cinergy_xs) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-terratec-slim.c b/drivers/media/IR/keymaps/rc-terratec-slim.c deleted file mode 100644 index 10dee4c..0000000 --- a/drivers/media/IR/keymaps/rc-terratec-slim.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * TerraTec remote controller keytable - * - * Copyright (C) 2010 Antti Palosaari - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -/* TerraTec slim remote, 7 rows, 4 columns. */ -/* Uses NEC extended 0x02bd. */ -static struct ir_scancode terratec_slim[] = { - { 0x02bd00, KEY_1 }, - { 0x02bd01, KEY_2 }, - { 0x02bd02, KEY_3 }, - { 0x02bd03, KEY_4 }, - { 0x02bd04, KEY_5 }, - { 0x02bd05, KEY_6 }, - { 0x02bd06, KEY_7 }, - { 0x02bd07, KEY_8 }, - { 0x02bd08, KEY_9 }, - { 0x02bd09, KEY_0 }, - { 0x02bd0a, KEY_MUTE }, - { 0x02bd0b, KEY_NEW }, /* symbol: PIP */ - { 0x02bd0e, KEY_VOLUMEDOWN }, - { 0x02bd0f, KEY_PLAYPAUSE }, - { 0x02bd10, KEY_RIGHT }, - { 0x02bd11, KEY_LEFT }, - { 0x02bd12, KEY_UP }, - { 0x02bd13, KEY_DOWN }, - { 0x02bd15, KEY_OK }, - { 0x02bd16, KEY_STOP }, - { 0x02bd17, KEY_CAMERA }, /* snapshot */ - { 0x02bd18, KEY_CHANNELUP }, - { 0x02bd19, KEY_RECORD }, - { 0x02bd1a, KEY_CHANNELDOWN }, - { 0x02bd1c, KEY_ESC }, - { 0x02bd1f, KEY_VOLUMEUP }, - { 0x02bd44, KEY_EPG }, - { 0x02bd45, KEY_POWER2 }, /* [red power button] */ -}; - -static struct rc_keymap terratec_slim_map = { - .map = { - .scan = terratec_slim, - .size = ARRAY_SIZE(terratec_slim), - .ir_type = IR_TYPE_NEC, - .name = RC_MAP_TERRATEC_SLIM, - } -}; - -static int __init init_rc_map_terratec_slim(void) -{ - return ir_register_map(&terratec_slim_map); -} - -static void __exit exit_rc_map_terratec_slim(void) -{ - ir_unregister_map(&terratec_slim_map); -} - -module_init(init_rc_map_terratec_slim) -module_exit(exit_rc_map_terratec_slim) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/IR/keymaps/rc-tevii-nec.c b/drivers/media/IR/keymaps/rc-tevii-nec.c deleted file mode 100644 index e30d411..0000000 --- a/drivers/media/IR/keymaps/rc-tevii-nec.c +++ /dev/null @@ -1,88 +0,0 @@ -/* tevii-nec.h - Keytable for tevii_nec Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode tevii_nec[] = { - { 0x0a, KEY_POWER2}, - { 0x0c, KEY_MUTE}, - { 0x11, KEY_1}, - { 0x12, KEY_2}, - { 0x13, KEY_3}, - { 0x14, KEY_4}, - { 0x15, KEY_5}, - { 0x16, KEY_6}, - { 0x17, KEY_7}, - { 0x18, KEY_8}, - { 0x19, KEY_9}, - { 0x10, KEY_0}, - { 0x1c, KEY_MENU}, - { 0x0f, KEY_VOLUMEDOWN}, - { 0x1a, KEY_LAST}, - { 0x0e, KEY_OPEN}, - { 0x04, KEY_RECORD}, - { 0x09, KEY_VOLUMEUP}, - { 0x08, KEY_CHANNELUP}, - { 0x07, KEY_PVR}, - { 0x0b, KEY_TIME}, - { 0x02, KEY_RIGHT}, - { 0x03, KEY_LEFT}, - { 0x00, KEY_UP}, - { 0x1f, KEY_OK}, - { 0x01, KEY_DOWN}, - { 0x05, KEY_TUNER}, - { 0x06, KEY_CHANNELDOWN}, - { 0x40, KEY_PLAYPAUSE}, - { 0x1e, KEY_REWIND}, - { 0x1b, KEY_FAVORITES}, - { 0x1d, KEY_BACK}, - { 0x4d, KEY_FASTFORWARD}, - { 0x44, KEY_EPG}, - { 0x4c, KEY_INFO}, - { 0x41, KEY_AB}, - { 0x43, KEY_AUDIO}, - { 0x45, KEY_SUBTITLE}, - { 0x4a, KEY_LIST}, - { 0x46, KEY_F1}, - { 0x47, KEY_F2}, - { 0x5e, KEY_F3}, - { 0x5c, KEY_F4}, - { 0x52, KEY_F5}, - { 0x5a, KEY_F6}, - { 0x56, KEY_MODE}, - { 0x58, KEY_SWITCHVIDEOMODE}, -}; - -static struct rc_keymap tevii_nec_map = { - .map = { - .scan = tevii_nec, - .size = ARRAY_SIZE(tevii_nec), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_TEVII_NEC, - } -}; - -static int __init init_rc_map_tevii_nec(void) -{ - return ir_register_map(&tevii_nec_map); -} - -static void __exit exit_rc_map_tevii_nec(void) -{ - ir_unregister_map(&tevii_nec_map); -} - -module_init(init_rc_map_tevii_nec) -module_exit(exit_rc_map_tevii_nec) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-total-media-in-hand.c b/drivers/media/IR/keymaps/rc-total-media-in-hand.c deleted file mode 100644 index fd19857..0000000 --- a/drivers/media/IR/keymaps/rc-total-media-in-hand.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Total Media In Hand remote controller keytable - * - * Copyright (C) 2010 Antti Palosaari - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -/* Uses NEC extended 0x02bd */ -static struct ir_scancode total_media_in_hand[] = { - { 0x02bd00, KEY_1 }, - { 0x02bd01, KEY_2 }, - { 0x02bd02, KEY_3 }, - { 0x02bd03, KEY_4 }, - { 0x02bd04, KEY_5 }, - { 0x02bd05, KEY_6 }, - { 0x02bd06, KEY_7 }, - { 0x02bd07, KEY_8 }, - { 0x02bd08, KEY_9 }, - { 0x02bd09, KEY_0 }, - { 0x02bd0a, KEY_MUTE }, - { 0x02bd0b, KEY_CYCLEWINDOWS }, /* yellow, [min / max] */ - { 0x02bd0c, KEY_VIDEO }, /* TV / AV */ - { 0x02bd0e, KEY_VOLUMEDOWN }, - { 0x02bd0f, KEY_TIME }, /* TimeShift */ - { 0x02bd10, KEY_RIGHT }, /* right arrow */ - { 0x02bd11, KEY_LEFT }, /* left arrow */ - { 0x02bd12, KEY_UP }, /* up arrow */ - { 0x02bd13, KEY_DOWN }, /* down arrow */ - { 0x02bd14, KEY_POWER2 }, /* [red] */ - { 0x02bd15, KEY_OK }, /* OK */ - { 0x02bd16, KEY_STOP }, - { 0x02bd17, KEY_CAMERA }, /* Snapshot */ - { 0x02bd18, KEY_CHANNELUP }, - { 0x02bd19, KEY_RECORD }, - { 0x02bd1a, KEY_CHANNELDOWN }, - { 0x02bd1c, KEY_ESC }, /* Esc */ - { 0x02bd1e, KEY_PLAY }, - { 0x02bd1f, KEY_VOLUMEUP }, - { 0x02bd40, KEY_PAUSE }, - { 0x02bd41, KEY_FASTFORWARD }, /* FF >> */ - { 0x02bd42, KEY_REWIND }, /* FR << */ - { 0x02bd43, KEY_ZOOM }, /* [window + mouse pointer] */ - { 0x02bd44, KEY_SHUFFLE }, /* Shuffle */ - { 0x02bd45, KEY_INFO }, /* [red (I)] */ -}; - -static struct rc_keymap total_media_in_hand_map = { - .map = { - .scan = total_media_in_hand, - .size = ARRAY_SIZE(total_media_in_hand), - .ir_type = IR_TYPE_NEC, - .name = RC_MAP_TOTAL_MEDIA_IN_HAND, - } -}; - -static int __init init_rc_map_total_media_in_hand(void) -{ - return ir_register_map(&total_media_in_hand_map); -} - -static void __exit exit_rc_map_total_media_in_hand(void) -{ - ir_unregister_map(&total_media_in_hand_map); -} - -module_init(init_rc_map_total_media_in_hand) -module_exit(exit_rc_map_total_media_in_hand) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/IR/keymaps/rc-trekstor.c b/drivers/media/IR/keymaps/rc-trekstor.c deleted file mode 100644 index 91092ca..0000000 --- a/drivers/media/IR/keymaps/rc-trekstor.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * TrekStor remote controller keytable - * - * Copyright (C) 2010 Antti Palosaari - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -/* TrekStor DVB-T USB Stick remote controller. */ -/* Imported from af9015.h. - Initial keytable was from Marc Schneider */ -static struct ir_scancode trekstor[] = { - { 0x0084, KEY_0 }, - { 0x0085, KEY_MUTE }, /* Mute */ - { 0x0086, KEY_HOMEPAGE }, /* Home */ - { 0x0087, KEY_UP }, /* Up */ - { 0x0088, KEY_OK }, /* OK */ - { 0x0089, KEY_RIGHT }, /* Right */ - { 0x008a, KEY_FASTFORWARD }, /* Fast forward */ - { 0x008b, KEY_VOLUMEUP }, /* Volume + */ - { 0x008c, KEY_DOWN }, /* Down */ - { 0x008d, KEY_PLAY }, /* Play/Pause */ - { 0x008e, KEY_STOP }, /* Stop */ - { 0x008f, KEY_EPG }, /* Info/EPG */ - { 0x0090, KEY_7 }, - { 0x0091, KEY_4 }, - { 0x0092, KEY_1 }, - { 0x0093, KEY_CHANNELDOWN }, /* Channel - */ - { 0x0094, KEY_8 }, - { 0x0095, KEY_5 }, - { 0x0096, KEY_2 }, - { 0x0097, KEY_CHANNELUP }, /* Channel + */ - { 0x0098, KEY_9 }, - { 0x0099, KEY_6 }, - { 0x009a, KEY_3 }, - { 0x009b, KEY_VOLUMEDOWN }, /* Volume - */ - { 0x009c, KEY_TV }, /* TV */ - { 0x009d, KEY_RECORD }, /* Record */ - { 0x009e, KEY_REWIND }, /* Rewind */ - { 0x009f, KEY_LEFT }, /* Left */ -}; - -static struct rc_keymap trekstor_map = { - .map = { - .scan = trekstor, - .size = ARRAY_SIZE(trekstor), - .ir_type = IR_TYPE_NEC, - .name = RC_MAP_TREKSTOR, - } -}; - -static int __init init_rc_map_trekstor(void) -{ - return ir_register_map(&trekstor_map); -} - -static void __exit exit_rc_map_trekstor(void) -{ - ir_unregister_map(&trekstor_map); -} - -module_init(init_rc_map_trekstor) -module_exit(exit_rc_map_trekstor) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/IR/keymaps/rc-tt-1500.c b/drivers/media/IR/keymaps/rc-tt-1500.c deleted file mode 100644 index bc88de0..0000000 --- a/drivers/media/IR/keymaps/rc-tt-1500.c +++ /dev/null @@ -1,82 +0,0 @@ -/* tt-1500.h - Keytable for tt_1500 Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* for the Technotrend 1500 bundled remotes (grey and black): */ - -static struct ir_scancode tt_1500[] = { - { 0x01, KEY_POWER }, - { 0x02, KEY_SHUFFLE }, /* ? double-arrow key */ - { 0x03, KEY_1 }, - { 0x04, KEY_2 }, - { 0x05, KEY_3 }, - { 0x06, KEY_4 }, - { 0x07, KEY_5 }, - { 0x08, KEY_6 }, - { 0x09, KEY_7 }, - { 0x0a, KEY_8 }, - { 0x0b, KEY_9 }, - { 0x0c, KEY_0 }, - { 0x0d, KEY_UP }, - { 0x0e, KEY_LEFT }, - { 0x0f, KEY_OK }, - { 0x10, KEY_RIGHT }, - { 0x11, KEY_DOWN }, - { 0x12, KEY_INFO }, - { 0x13, KEY_EXIT }, - { 0x14, KEY_RED }, - { 0x15, KEY_GREEN }, - { 0x16, KEY_YELLOW }, - { 0x17, KEY_BLUE }, - { 0x18, KEY_MUTE }, - { 0x19, KEY_TEXT }, - { 0x1a, KEY_MODE }, /* ? TV/Radio */ - { 0x21, KEY_OPTION }, - { 0x22, KEY_EPG }, - { 0x23, KEY_CHANNELUP }, - { 0x24, KEY_CHANNELDOWN }, - { 0x25, KEY_VOLUMEUP }, - { 0x26, KEY_VOLUMEDOWN }, - { 0x27, KEY_SETUP }, - { 0x3a, KEY_RECORD }, /* these keys are only in the black remote */ - { 0x3b, KEY_PLAY }, - { 0x3c, KEY_STOP }, - { 0x3d, KEY_REWIND }, - { 0x3e, KEY_PAUSE }, - { 0x3f, KEY_FORWARD }, -}; - -static struct rc_keymap tt_1500_map = { - .map = { - .scan = tt_1500, - .size = ARRAY_SIZE(tt_1500), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_TT_1500, - } -}; - -static int __init init_rc_map_tt_1500(void) -{ - return ir_register_map(&tt_1500_map); -} - -static void __exit exit_rc_map_tt_1500(void) -{ - ir_unregister_map(&tt_1500_map); -} - -module_init(init_rc_map_tt_1500) -module_exit(exit_rc_map_tt_1500) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-twinhan1027.c b/drivers/media/IR/keymaps/rc-twinhan1027.c deleted file mode 100644 index 0b5d356..0000000 --- a/drivers/media/IR/keymaps/rc-twinhan1027.c +++ /dev/null @@ -1,87 +0,0 @@ -#include - -static struct ir_scancode twinhan_vp1027[] = { - { 0x16, KEY_POWER2 }, - { 0x17, KEY_FAVORITES }, - { 0x0f, KEY_TEXT }, - { 0x48, KEY_INFO}, - { 0x1c, KEY_EPG }, - { 0x04, KEY_LIST }, - - { 0x03, KEY_1 }, - { 0x01, KEY_2 }, - { 0x06, KEY_3 }, - { 0x09, KEY_4 }, - { 0x1d, KEY_5 }, - { 0x1f, KEY_6 }, - { 0x0d, KEY_7 }, - { 0x19, KEY_8 }, - { 0x1b, KEY_9 }, - { 0x15, KEY_0 }, - - { 0x0c, KEY_CANCEL }, - { 0x4a, KEY_CLEAR }, - { 0x13, KEY_BACKSPACE }, - { 0x00, KEY_TAB }, - - { 0x4b, KEY_UP }, - { 0x51, KEY_DOWN }, - { 0x4e, KEY_LEFT }, - { 0x52, KEY_RIGHT }, - { 0x4f, KEY_ENTER }, - - { 0x1e, KEY_VOLUMEUP }, - { 0x0a, KEY_VOLUMEDOWN }, - { 0x02, KEY_CHANNELDOWN }, - { 0x05, KEY_CHANNELUP }, - { 0x11, KEY_RECORD }, - - { 0x14, KEY_PLAY }, - { 0x4c, KEY_PAUSE }, - { 0x1a, KEY_STOP }, - { 0x40, KEY_REWIND }, - { 0x12, KEY_FASTFORWARD }, - { 0x41, KEY_PREVIOUSSONG }, - { 0x42, KEY_NEXTSONG }, - { 0x54, KEY_SAVE }, - { 0x50, KEY_LANGUAGE }, - { 0x47, KEY_MEDIA }, - { 0x4d, KEY_SCREEN }, - { 0x43, KEY_SUBTITLE }, - { 0x10, KEY_MUTE }, - { 0x49, KEY_AUDIO }, - { 0x07, KEY_SLEEP }, - { 0x08, KEY_VIDEO }, - { 0x0e, KEY_AGAIN }, - { 0x45, KEY_EQUAL }, - { 0x46, KEY_MINUS }, - { 0x18, KEY_RED }, - { 0x53, KEY_GREEN }, - { 0x5e, KEY_YELLOW }, - { 0x5f, KEY_BLUE }, -}; - -static struct rc_keymap twinhan_vp1027_map = { - .map = { - .scan = twinhan_vp1027, - .size = ARRAY_SIZE(twinhan_vp1027), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_TWINHAN_VP1027_DVBS, - } -}; - -static int __init init_rc_map_twinhan_vp1027(void) -{ - return ir_register_map(&twinhan_vp1027_map); -} - -static void __exit exit_rc_map_twinhan_vp1027(void) -{ - ir_unregister_map(&twinhan_vp1027_map); -} - -module_init(init_rc_map_twinhan_vp1027) -module_exit(exit_rc_map_twinhan_vp1027) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Sergey Ivanov <123kash@gmail.com>"); diff --git a/drivers/media/IR/keymaps/rc-videomate-s350.c b/drivers/media/IR/keymaps/rc-videomate-s350.c deleted file mode 100644 index 4df7fcd..0000000 --- a/drivers/media/IR/keymaps/rc-videomate-s350.c +++ /dev/null @@ -1,85 +0,0 @@ -/* videomate-s350.h - Keytable for videomate_s350 Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode videomate_s350[] = { - { 0x00, KEY_TV}, - { 0x01, KEY_DVD}, - { 0x04, KEY_RECORD}, - { 0x05, KEY_VIDEO}, /* TV/Video */ - { 0x07, KEY_STOP}, - { 0x08, KEY_PLAYPAUSE}, - { 0x0a, KEY_REWIND}, - { 0x0f, KEY_FASTFORWARD}, - { 0x10, KEY_CHANNELUP}, - { 0x12, KEY_VOLUMEUP}, - { 0x13, KEY_CHANNELDOWN}, - { 0x14, KEY_MUTE}, - { 0x15, KEY_VOLUMEDOWN}, - { 0x16, KEY_1}, - { 0x17, KEY_2}, - { 0x18, KEY_3}, - { 0x19, KEY_4}, - { 0x1a, KEY_5}, - { 0x1b, KEY_6}, - { 0x1c, KEY_7}, - { 0x1d, KEY_8}, - { 0x1e, KEY_9}, - { 0x1f, KEY_0}, - { 0x21, KEY_SLEEP}, - { 0x24, KEY_ZOOM}, - { 0x25, KEY_LAST}, /* Recall */ - { 0x26, KEY_SUBTITLE}, /* CC */ - { 0x27, KEY_LANGUAGE}, /* MTS */ - { 0x29, KEY_CHANNEL}, /* SURF */ - { 0x2b, KEY_A}, - { 0x2c, KEY_B}, - { 0x2f, KEY_CAMERA}, /* Snapshot */ - { 0x23, KEY_RADIO}, - { 0x02, KEY_PREVIOUSSONG}, - { 0x06, KEY_NEXTSONG}, - { 0x03, KEY_EPG}, - { 0x09, KEY_SETUP}, - { 0x22, KEY_BACKSPACE}, - { 0x0c, KEY_UP}, - { 0x0e, KEY_DOWN}, - { 0x0b, KEY_LEFT}, - { 0x0d, KEY_RIGHT}, - { 0x11, KEY_ENTER}, - { 0x20, KEY_TEXT}, -}; - -static struct rc_keymap videomate_s350_map = { - .map = { - .scan = videomate_s350, - .size = ARRAY_SIZE(videomate_s350), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_VIDEOMATE_S350, - } -}; - -static int __init init_rc_map_videomate_s350(void) -{ - return ir_register_map(&videomate_s350_map); -} - -static void __exit exit_rc_map_videomate_s350(void) -{ - ir_unregister_map(&videomate_s350_map); -} - -module_init(init_rc_map_videomate_s350) -module_exit(exit_rc_map_videomate_s350) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-videomate-tv-pvr.c b/drivers/media/IR/keymaps/rc-videomate-tv-pvr.c deleted file mode 100644 index 776b0a6..0000000 --- a/drivers/media/IR/keymaps/rc-videomate-tv-pvr.c +++ /dev/null @@ -1,87 +0,0 @@ -/* videomate-tv-pvr.h - Keytable for videomate_tv_pvr Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -static struct ir_scancode videomate_tv_pvr[] = { - { 0x14, KEY_MUTE }, - { 0x24, KEY_ZOOM }, - - { 0x01, KEY_DVD }, - { 0x23, KEY_RADIO }, - { 0x00, KEY_TV }, - - { 0x0a, KEY_REWIND }, - { 0x08, KEY_PLAYPAUSE }, - { 0x0f, KEY_FORWARD }, - - { 0x02, KEY_PREVIOUS }, - { 0x07, KEY_STOP }, - { 0x06, KEY_NEXT }, - - { 0x0c, KEY_UP }, - { 0x0e, KEY_DOWN }, - { 0x0b, KEY_LEFT }, - { 0x0d, KEY_RIGHT }, - { 0x11, KEY_OK }, - - { 0x03, KEY_MENU }, - { 0x09, KEY_SETUP }, - { 0x05, KEY_VIDEO }, - { 0x22, KEY_CHANNEL }, - - { 0x12, KEY_VOLUMEUP }, - { 0x15, KEY_VOLUMEDOWN }, - { 0x10, KEY_CHANNELUP }, - { 0x13, KEY_CHANNELDOWN }, - - { 0x04, KEY_RECORD }, - - { 0x16, KEY_1 }, - { 0x17, KEY_2 }, - { 0x18, KEY_3 }, - { 0x19, KEY_4 }, - { 0x1a, KEY_5 }, - { 0x1b, KEY_6 }, - { 0x1c, KEY_7 }, - { 0x1d, KEY_8 }, - { 0x1e, KEY_9 }, - { 0x1f, KEY_0 }, - - { 0x20, KEY_LANGUAGE }, - { 0x21, KEY_SLEEP }, -}; - -static struct rc_keymap videomate_tv_pvr_map = { - .map = { - .scan = videomate_tv_pvr, - .size = ARRAY_SIZE(videomate_tv_pvr), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_VIDEOMATE_TV_PVR, - } -}; - -static int __init init_rc_map_videomate_tv_pvr(void) -{ - return ir_register_map(&videomate_tv_pvr_map); -} - -static void __exit exit_rc_map_videomate_tv_pvr(void) -{ - ir_unregister_map(&videomate_tv_pvr_map); -} - -module_init(init_rc_map_videomate_tv_pvr) -module_exit(exit_rc_map_videomate_tv_pvr) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-winfast-usbii-deluxe.c b/drivers/media/IR/keymaps/rc-winfast-usbii-deluxe.c deleted file mode 100644 index 9d2d550..0000000 --- a/drivers/media/IR/keymaps/rc-winfast-usbii-deluxe.c +++ /dev/null @@ -1,82 +0,0 @@ -/* winfast-usbii-deluxe.h - Keytable for winfast_usbii_deluxe Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Leadtek Winfast TV USB II Deluxe remote - Magnus Alm - */ - -static struct ir_scancode winfast_usbii_deluxe[] = { - { 0x62, KEY_0}, - { 0x75, KEY_1}, - { 0x76, KEY_2}, - { 0x77, KEY_3}, - { 0x79, KEY_4}, - { 0x7a, KEY_5}, - { 0x7b, KEY_6}, - { 0x7d, KEY_7}, - { 0x7e, KEY_8}, - { 0x7f, KEY_9}, - - { 0x38, KEY_CAMERA}, /* SNAPSHOT */ - { 0x37, KEY_RECORD}, /* RECORD */ - { 0x35, KEY_TIME}, /* TIMESHIFT */ - - { 0x74, KEY_VOLUMEUP}, /* VOLUMEUP */ - { 0x78, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */ - { 0x64, KEY_MUTE}, /* MUTE */ - - { 0x21, KEY_CHANNEL}, /* SURF */ - { 0x7c, KEY_CHANNELUP}, /* CHANNELUP */ - { 0x60, KEY_CHANNELDOWN}, /* CHANNELDOWN */ - { 0x61, KEY_LAST}, /* LAST CHANNEL (RECALL) */ - - { 0x72, KEY_VIDEO}, /* INPUT MODES (TV/FM) */ - - { 0x70, KEY_POWER2}, /* TV ON/OFF */ - - { 0x39, KEY_CYCLEWINDOWS}, /* MINIMIZE (BOSS) */ - { 0x3a, KEY_NEW}, /* PIP */ - { 0x73, KEY_ZOOM}, /* FULLSECREEN */ - - { 0x66, KEY_INFO}, /* OSD (DISPLAY) */ - - { 0x31, KEY_DOT}, /* '.' */ - { 0x63, KEY_ENTER}, /* ENTER */ - -}; - -static struct rc_keymap winfast_usbii_deluxe_map = { - .map = { - .scan = winfast_usbii_deluxe, - .size = ARRAY_SIZE(winfast_usbii_deluxe), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_WINFAST_USBII_DELUXE, - } -}; - -static int __init init_rc_map_winfast_usbii_deluxe(void) -{ - return ir_register_map(&winfast_usbii_deluxe_map); -} - -static void __exit exit_rc_map_winfast_usbii_deluxe(void) -{ - ir_unregister_map(&winfast_usbii_deluxe_map); -} - -module_init(init_rc_map_winfast_usbii_deluxe) -module_exit(exit_rc_map_winfast_usbii_deluxe) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-winfast.c b/drivers/media/IR/keymaps/rc-winfast.c deleted file mode 100644 index 0e90a3b..0000000 --- a/drivers/media/IR/keymaps/rc-winfast.c +++ /dev/null @@ -1,102 +0,0 @@ -/* winfast.h - Keytable for winfast Remote Controller - * - * keymap imported from ir-keymaps.c - * - * Copyright (c) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include - -/* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ - -static struct ir_scancode winfast[] = { - /* Keys 0 to 9 */ - { 0x12, KEY_0 }, - { 0x05, KEY_1 }, - { 0x06, KEY_2 }, - { 0x07, KEY_3 }, - { 0x09, KEY_4 }, - { 0x0a, KEY_5 }, - { 0x0b, KEY_6 }, - { 0x0d, KEY_7 }, - { 0x0e, KEY_8 }, - { 0x0f, KEY_9 }, - - { 0x00, KEY_POWER }, - { 0x1b, KEY_AUDIO }, /* Audio Source */ - { 0x02, KEY_TUNER }, /* TV/FM, not on Y0400052 */ - { 0x1e, KEY_VIDEO }, /* Video Source */ - { 0x16, KEY_INFO }, /* Display information */ - { 0x04, KEY_VOLUMEUP }, - { 0x08, KEY_VOLUMEDOWN }, - { 0x0c, KEY_CHANNELUP }, - { 0x10, KEY_CHANNELDOWN }, - { 0x03, KEY_ZOOM }, /* fullscreen */ - { 0x1f, KEY_TEXT }, /* closed caption/teletext */ - { 0x20, KEY_SLEEP }, - { 0x29, KEY_CLEAR }, /* boss key */ - { 0x14, KEY_MUTE }, - { 0x2b, KEY_RED }, - { 0x2c, KEY_GREEN }, - { 0x2d, KEY_YELLOW }, - { 0x2e, KEY_BLUE }, - { 0x18, KEY_KPPLUS }, /* fine tune + , not on Y040052 */ - { 0x19, KEY_KPMINUS }, /* fine tune - , not on Y040052 */ - { 0x2a, KEY_MEDIA }, /* PIP (Picture in picture */ - { 0x21, KEY_DOT }, - { 0x13, KEY_ENTER }, - { 0x11, KEY_LAST }, /* Recall (last channel */ - { 0x22, KEY_PREVIOUS }, - { 0x23, KEY_PLAYPAUSE }, - { 0x24, KEY_NEXT }, - { 0x25, KEY_TIME }, /* Time Shifting */ - { 0x26, KEY_STOP }, - { 0x27, KEY_RECORD }, - { 0x28, KEY_SAVE }, /* Screenshot */ - { 0x2f, KEY_MENU }, - { 0x30, KEY_CANCEL }, - { 0x31, KEY_CHANNEL }, /* Channel Surf */ - { 0x32, KEY_SUBTITLE }, - { 0x33, KEY_LANGUAGE }, - { 0x34, KEY_REWIND }, - { 0x35, KEY_FASTFORWARD }, - { 0x36, KEY_TV }, - { 0x37, KEY_RADIO }, /* FM */ - { 0x38, KEY_DVD }, - - { 0x1a, KEY_MODE}, /* change to MCE mode on Y04G0051 */ - { 0x3e, KEY_F21 }, /* MCE +VOL, on Y04G0033 */ - { 0x3a, KEY_F22 }, /* MCE -VOL, on Y04G0033 */ - { 0x3b, KEY_F23 }, /* MCE +CH, on Y04G0033 */ - { 0x3f, KEY_F24 } /* MCE -CH, on Y04G0033 */ -}; - -static struct rc_keymap winfast_map = { - .map = { - .scan = winfast, - .size = ARRAY_SIZE(winfast), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_WINFAST, - } -}; - -static int __init init_rc_map_winfast(void) -{ - return ir_register_map(&winfast_map); -} - -static void __exit exit_rc_map_winfast(void) -{ - ir_unregister_map(&winfast_map); -} - -module_init(init_rc_map_winfast) -module_exit(exit_rc_map_winfast) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/lirc_dev.c b/drivers/media/IR/lirc_dev.c deleted file mode 100644 index 756656e..0000000 --- a/drivers/media/IR/lirc_dev.c +++ /dev/null @@ -1,814 +0,0 @@ -/* - * LIRC base driver - * - * by Artur Lipowski - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -static int debug; - -#define IRCTL_DEV_NAME "BaseRemoteCtl" -#define NOPLUG -1 -#define LOGHEAD "lirc_dev (%s[%d]): " - -static dev_t lirc_base_dev; - -struct irctl { - struct lirc_driver d; - int attached; - int open; - - struct mutex irctl_lock; - struct lirc_buffer *buf; - unsigned int chunk_size; - - struct task_struct *task; - long jiffies_to_wait; -}; - -static DEFINE_MUTEX(lirc_dev_lock); - -static struct irctl *irctls[MAX_IRCTL_DEVICES]; -static struct cdev cdevs[MAX_IRCTL_DEVICES]; - -/* Only used for sysfs but defined to void otherwise */ -static struct class *lirc_class; - -/* helper function - * initializes the irctl structure - */ -static void lirc_irctl_init(struct irctl *ir) -{ - mutex_init(&ir->irctl_lock); - ir->d.minor = NOPLUG; -} - -static void lirc_irctl_cleanup(struct irctl *ir) -{ - dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor); - - device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor)); - - if (ir->buf != ir->d.rbuf) { - lirc_buffer_free(ir->buf); - kfree(ir->buf); - } - ir->buf = NULL; -} - -/* helper function - * reads key codes from driver and puts them into buffer - * returns 0 on success - */ -static int lirc_add_to_buf(struct irctl *ir) -{ - if (ir->d.add_to_buf) { - int res = -ENODATA; - int got_data = 0; - - /* - * service the device as long as it is returning - * data and we have space - */ -get_data: - res = ir->d.add_to_buf(ir->d.data, ir->buf); - if (res == 0) { - got_data++; - goto get_data; - } - - if (res == -ENODEV) - kthread_stop(ir->task); - - return got_data ? 0 : res; - } - - return 0; -} - -/* main function of the polling thread - */ -static int lirc_thread(void *irctl) -{ - struct irctl *ir = irctl; - - dev_dbg(ir->d.dev, LOGHEAD "poll thread started\n", - ir->d.name, ir->d.minor); - - do { - if (ir->open) { - if (ir->jiffies_to_wait) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(ir->jiffies_to_wait); - } - if (kthread_should_stop()) - break; - if (!lirc_add_to_buf(ir)) - wake_up_interruptible(&ir->buf->wait_poll); - } else { - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - } - } while (!kthread_should_stop()); - - dev_dbg(ir->d.dev, LOGHEAD "poll thread ended\n", - ir->d.name, ir->d.minor); - - return 0; -} - - -static struct file_operations lirc_dev_fops = { - .owner = THIS_MODULE, - .read = lirc_dev_fop_read, - .write = lirc_dev_fop_write, - .poll = lirc_dev_fop_poll, - .unlocked_ioctl = lirc_dev_fop_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = lirc_dev_fop_ioctl, -#endif - .open = lirc_dev_fop_open, - .release = lirc_dev_fop_close, - .llseek = noop_llseek, -}; - -static int lirc_cdev_add(struct irctl *ir) -{ - int retval; - struct lirc_driver *d = &ir->d; - struct cdev *cdev = &cdevs[d->minor]; - - if (d->fops) { - cdev_init(cdev, d->fops); - cdev->owner = d->owner; - } else { - cdev_init(cdev, &lirc_dev_fops); - cdev->owner = THIS_MODULE; - } - kobject_set_name(&cdev->kobj, "lirc%d", d->minor); - - retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1); - if (retval) - kobject_put(&cdev->kobj); - - return retval; -} - -int lirc_register_driver(struct lirc_driver *d) -{ - struct irctl *ir; - int minor; - int bytes_in_key; - unsigned int chunk_size; - unsigned int buffer_size; - int err; - - if (!d) { - printk(KERN_ERR "lirc_dev: lirc_register_driver: " - "driver pointer must be not NULL!\n"); - err = -EBADRQC; - goto out; - } - - if (!d->dev) { - printk(KERN_ERR "%s: dev pointer not filled in!\n", __func__); - err = -EINVAL; - goto out; - } - - if (MAX_IRCTL_DEVICES <= d->minor) { - dev_err(d->dev, "lirc_dev: lirc_register_driver: " - "\"minor\" must be between 0 and %d (%d)!\n", - MAX_IRCTL_DEVICES-1, d->minor); - err = -EBADRQC; - goto out; - } - - if (1 > d->code_length || (BUFLEN * 8) < d->code_length) { - dev_err(d->dev, "lirc_dev: lirc_register_driver: " - "code length in bits for minor (%d) " - "must be less than %d!\n", - d->minor, BUFLEN * 8); - err = -EBADRQC; - goto out; - } - - dev_dbg(d->dev, "lirc_dev: lirc_register_driver: sample_rate: %d\n", - d->sample_rate); - if (d->sample_rate) { - if (2 > d->sample_rate || HZ < d->sample_rate) { - dev_err(d->dev, "lirc_dev: lirc_register_driver: " - "sample_rate must be between 2 and %d!\n", HZ); - err = -EBADRQC; - goto out; - } - if (!d->add_to_buf) { - dev_err(d->dev, "lirc_dev: lirc_register_driver: " - "add_to_buf cannot be NULL when " - "sample_rate is set\n"); - err = -EBADRQC; - goto out; - } - } else if (!(d->fops && d->fops->read) && !d->rbuf) { - dev_err(d->dev, "lirc_dev: lirc_register_driver: " - "fops->read and rbuf cannot all be NULL!\n"); - err = -EBADRQC; - goto out; - } else if (!d->rbuf) { - if (!(d->fops && d->fops->read && d->fops->poll && - d->fops->unlocked_ioctl)) { - dev_err(d->dev, "lirc_dev: lirc_register_driver: " - "neither read, poll nor unlocked_ioctl can be NULL!\n"); - err = -EBADRQC; - goto out; - } - } - - mutex_lock(&lirc_dev_lock); - - minor = d->minor; - - if (minor < 0) { - /* find first free slot for driver */ - for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++) - if (!irctls[minor]) - break; - if (MAX_IRCTL_DEVICES == minor) { - dev_err(d->dev, "lirc_dev: lirc_register_driver: " - "no free slots for drivers!\n"); - err = -ENOMEM; - goto out_lock; - } - } else if (irctls[minor]) { - dev_err(d->dev, "lirc_dev: lirc_register_driver: " - "minor (%d) just registered!\n", minor); - err = -EBUSY; - goto out_lock; - } - - ir = kzalloc(sizeof(struct irctl), GFP_KERNEL); - if (!ir) { - err = -ENOMEM; - goto out_lock; - } - lirc_irctl_init(ir); - irctls[minor] = ir; - d->minor = minor; - - if (d->sample_rate) { - ir->jiffies_to_wait = HZ / d->sample_rate; - } else { - /* it means - wait for external event in task queue */ - ir->jiffies_to_wait = 0; - } - - /* some safety check 8-) */ - d->name[sizeof(d->name)-1] = '\0'; - - bytes_in_key = BITS_TO_LONGS(d->code_length) + - (d->code_length % 8 ? 1 : 0); - buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key; - chunk_size = d->chunk_size ? d->chunk_size : bytes_in_key; - - if (d->rbuf) { - ir->buf = d->rbuf; - } else { - ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); - if (!ir->buf) { - err = -ENOMEM; - goto out_lock; - } - err = lirc_buffer_init(ir->buf, chunk_size, buffer_size); - if (err) { - kfree(ir->buf); - goto out_lock; - } - } - ir->chunk_size = ir->buf->chunk_size; - - if (d->features == 0) - d->features = LIRC_CAN_REC_LIRCCODE; - - ir->d = *d; - - device_create(lirc_class, ir->d.dev, - MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL, - "lirc%u", ir->d.minor); - - if (d->sample_rate) { - /* try to fire up polling thread */ - ir->task = kthread_run(lirc_thread, (void *)ir, "lirc_dev"); - if (IS_ERR(ir->task)) { - dev_err(d->dev, "lirc_dev: lirc_register_driver: " - "cannot run poll thread for minor = %d\n", - d->minor); - err = -ECHILD; - goto out_sysfs; - } - } - - err = lirc_cdev_add(ir); - if (err) - goto out_sysfs; - - ir->attached = 1; - mutex_unlock(&lirc_dev_lock); - - dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n", - ir->d.name, ir->d.minor); - return minor; - -out_sysfs: - device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor)); -out_lock: - mutex_unlock(&lirc_dev_lock); -out: - return err; -} -EXPORT_SYMBOL(lirc_register_driver); - -int lirc_unregister_driver(int minor) -{ - struct irctl *ir; - struct cdev *cdev; - - if (minor < 0 || minor >= MAX_IRCTL_DEVICES) { - printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between " - "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES-1); - return -EBADRQC; - } - - ir = irctls[minor]; - if (!ir) { - printk(KERN_ERR "lirc_dev: %s: failed to get irctl struct " - "for minor %d!\n", __func__, minor); - return -ENOENT; - } - - cdev = &cdevs[minor]; - - mutex_lock(&lirc_dev_lock); - - if (ir->d.minor != minor) { - printk(KERN_ERR "lirc_dev: %s: minor (%d) device not " - "registered!\n", __func__, minor); - mutex_unlock(&lirc_dev_lock); - return -ENOENT; - } - - /* end up polling thread */ - if (ir->task) - kthread_stop(ir->task); - - dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n", - ir->d.name, ir->d.minor); - - ir->attached = 0; - if (ir->open) { - dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n", - ir->d.name, ir->d.minor); - wake_up_interruptible(&ir->buf->wait_poll); - mutex_lock(&ir->irctl_lock); - ir->d.set_use_dec(ir->d.data); - module_put(cdev->owner); - mutex_unlock(&ir->irctl_lock); - } else { - lirc_irctl_cleanup(ir); - cdev_del(cdev); - kfree(ir); - irctls[minor] = NULL; - } - - mutex_unlock(&lirc_dev_lock); - - return 0; -} -EXPORT_SYMBOL(lirc_unregister_driver); - -int lirc_dev_fop_open(struct inode *inode, struct file *file) -{ - struct irctl *ir; - struct cdev *cdev; - int retval = 0; - - if (iminor(inode) >= MAX_IRCTL_DEVICES) { - printk(KERN_WARNING "lirc_dev [%d]: open result = -ENODEV\n", - iminor(inode)); - return -ENODEV; - } - - if (mutex_lock_interruptible(&lirc_dev_lock)) - return -ERESTARTSYS; - - ir = irctls[iminor(inode)]; - if (!ir) { - retval = -ENODEV; - goto error; - } - - dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor); - - if (ir->d.minor == NOPLUG) { - retval = -ENODEV; - goto error; - } - - if (ir->open) { - retval = -EBUSY; - goto error; - } - - cdev = &cdevs[iminor(inode)]; - if (try_module_get(cdev->owner)) { - ir->open++; - retval = ir->d.set_use_inc(ir->d.data); - - if (retval) { - module_put(cdev->owner); - ir->open--; - } else { - lirc_buffer_clear(ir->buf); - } - if (ir->task) - wake_up_process(ir->task); - } - -error: - if (ir) - dev_dbg(ir->d.dev, LOGHEAD "open result = %d\n", - ir->d.name, ir->d.minor, retval); - - mutex_unlock(&lirc_dev_lock); - - nonseekable_open(inode, file); - - return retval; -} -EXPORT_SYMBOL(lirc_dev_fop_open); - -int lirc_dev_fop_close(struct inode *inode, struct file *file) -{ - struct irctl *ir = irctls[iminor(inode)]; - struct cdev *cdev = &cdevs[iminor(inode)]; - - if (!ir) { - printk(KERN_ERR "%s: called with invalid irctl\n", __func__); - return -EINVAL; - } - - dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor); - - WARN_ON(mutex_lock_killable(&lirc_dev_lock)); - - ir->open--; - if (ir->attached) { - ir->d.set_use_dec(ir->d.data); - module_put(cdev->owner); - } else { - lirc_irctl_cleanup(ir); - cdev_del(cdev); - irctls[ir->d.minor] = NULL; - kfree(ir); - } - - mutex_unlock(&lirc_dev_lock); - - return 0; -} -EXPORT_SYMBOL(lirc_dev_fop_close); - -unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait) -{ - struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; - unsigned int ret; - - if (!ir) { - printk(KERN_ERR "%s: called with invalid irctl\n", __func__); - return POLLERR; - } - - dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor); - - if (!ir->attached) - return POLLERR; - - poll_wait(file, &ir->buf->wait_poll, wait); - - if (ir->buf) - if (lirc_buffer_empty(ir->buf)) - ret = 0; - else - ret = POLLIN | POLLRDNORM; - else - ret = POLLERR; - - dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n", - ir->d.name, ir->d.minor, ret); - - return ret; -} -EXPORT_SYMBOL(lirc_dev_fop_poll); - -long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - __u32 mode; - int result = 0; - struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; - - if (!ir) { - printk(KERN_ERR "lirc_dev: %s: no irctl found!\n", __func__); - return -ENODEV; - } - - dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n", - ir->d.name, ir->d.minor, cmd); - - if (ir->d.minor == NOPLUG || !ir->attached) { - dev_dbg(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n", - ir->d.name, ir->d.minor); - return -ENODEV; - } - - mutex_lock(&ir->irctl_lock); - - switch (cmd) { - case LIRC_GET_FEATURES: - result = put_user(ir->d.features, (__u32 *)arg); - break; - case LIRC_GET_REC_MODE: - if (!(ir->d.features & LIRC_CAN_REC_MASK)) { - result = -ENOSYS; - break; - } - - result = put_user(LIRC_REC2MODE - (ir->d.features & LIRC_CAN_REC_MASK), - (__u32 *)arg); - break; - case LIRC_SET_REC_MODE: - if (!(ir->d.features & LIRC_CAN_REC_MASK)) { - result = -ENOSYS; - break; - } - - result = get_user(mode, (__u32 *)arg); - if (!result && !(LIRC_MODE2REC(mode) & ir->d.features)) - result = -EINVAL; - /* - * FIXME: We should actually set the mode somehow but - * for now, lirc_serial doesn't support mode changing either - */ - break; - case LIRC_GET_LENGTH: - result = put_user(ir->d.code_length, (__u32 *)arg); - break; - case LIRC_GET_MIN_TIMEOUT: - if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || - ir->d.min_timeout == 0) { - result = -ENOSYS; - break; - } - - result = put_user(ir->d.min_timeout, (__u32 *)arg); - break; - case LIRC_GET_MAX_TIMEOUT: - if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || - ir->d.max_timeout == 0) { - result = -ENOSYS; - break; - } - - result = put_user(ir->d.max_timeout, (__u32 *)arg); - break; - default: - result = -EINVAL; - } - - dev_dbg(ir->d.dev, LOGHEAD "ioctl result = %d\n", - ir->d.name, ir->d.minor, result); - - mutex_unlock(&ir->irctl_lock); - - return result; -} -EXPORT_SYMBOL(lirc_dev_fop_ioctl); - -ssize_t lirc_dev_fop_read(struct file *file, - char *buffer, - size_t length, - loff_t *ppos) -{ - struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; - unsigned char *buf; - int ret = 0, written = 0; - DECLARE_WAITQUEUE(wait, current); - - if (!ir) { - printk(KERN_ERR "%s: called with invalid irctl\n", __func__); - return -ENODEV; - } - - dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor); - - buf = kzalloc(ir->chunk_size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - if (mutex_lock_interruptible(&ir->irctl_lock)) { - ret = -ERESTARTSYS; - goto out_unlocked; - } - if (!ir->attached) { - ret = -ENODEV; - goto out_locked; - } - - if (length % ir->chunk_size) { - ret = -EINVAL; - goto out_locked; - } - - /* - * we add ourselves to the task queue before buffer check - * to avoid losing scan code (in case when queue is awaken somewhere - * between while condition checking and scheduling) - */ - add_wait_queue(&ir->buf->wait_poll, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - /* - * while we didn't provide 'length' bytes, device is opened in blocking - * mode and 'copy_to_user' is happy, wait for data. - */ - while (written < length && ret == 0) { - if (lirc_buffer_empty(ir->buf)) { - /* According to the read(2) man page, 'written' can be - * returned as less than 'length', instead of blocking - * again, returning -EWOULDBLOCK, or returning - * -ERESTARTSYS */ - if (written) - break; - if (file->f_flags & O_NONBLOCK) { - ret = -EWOULDBLOCK; - break; - } - if (signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - - mutex_unlock(&ir->irctl_lock); - schedule(); - set_current_state(TASK_INTERRUPTIBLE); - - if (mutex_lock_interruptible(&ir->irctl_lock)) { - ret = -ERESTARTSYS; - remove_wait_queue(&ir->buf->wait_poll, &wait); - set_current_state(TASK_RUNNING); - goto out_unlocked; - } - - if (!ir->attached) { - ret = -ENODEV; - break; - } - } else { - lirc_buffer_read(ir->buf, buf); - ret = copy_to_user((void *)buffer+written, buf, - ir->buf->chunk_size); - if (!ret) - written += ir->buf->chunk_size; - else - ret = -EFAULT; - } - } - - remove_wait_queue(&ir->buf->wait_poll, &wait); - set_current_state(TASK_RUNNING); - -out_locked: - mutex_unlock(&ir->irctl_lock); - -out_unlocked: - kfree(buf); - dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n", - ir->d.name, ir->d.minor, ret ? "" : "", ret); - - return ret ? ret : written; -} -EXPORT_SYMBOL(lirc_dev_fop_read); - -void *lirc_get_pdata(struct file *file) -{ - void *data = NULL; - - if (file && file->f_dentry && file->f_dentry->d_inode && - file->f_dentry->d_inode->i_rdev) { - struct irctl *ir; - ir = irctls[iminor(file->f_dentry->d_inode)]; - data = ir->d.data; - } - - return data; -} -EXPORT_SYMBOL(lirc_get_pdata); - - -ssize_t lirc_dev_fop_write(struct file *file, const char *buffer, - size_t length, loff_t *ppos) -{ - struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; - - if (!ir) { - printk(KERN_ERR "%s: called with invalid irctl\n", __func__); - return -ENODEV; - } - - dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor); - - if (!ir->attached) - return -ENODEV; - - return -EINVAL; -} -EXPORT_SYMBOL(lirc_dev_fop_write); - - -static int __init lirc_dev_init(void) -{ - int retval; - - lirc_class = class_create(THIS_MODULE, "lirc"); - if (IS_ERR(lirc_class)) { - retval = PTR_ERR(lirc_class); - printk(KERN_ERR "lirc_dev: class_create failed\n"); - goto error; - } - - retval = alloc_chrdev_region(&lirc_base_dev, 0, MAX_IRCTL_DEVICES, - IRCTL_DEV_NAME); - if (retval) { - class_destroy(lirc_class); - printk(KERN_ERR "lirc_dev: alloc_chrdev_region failed\n"); - goto error; - } - - - printk(KERN_INFO "lirc_dev: IR Remote Control driver registered, " - "major %d \n", MAJOR(lirc_base_dev)); - -error: - return retval; -} - - - -static void __exit lirc_dev_exit(void) -{ - class_destroy(lirc_class); - unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES); - printk(KERN_INFO "lirc_dev: module unloaded\n"); -} - -module_init(lirc_dev_init); -module_exit(lirc_dev_exit); - -MODULE_DESCRIPTION("LIRC base driver module"); -MODULE_AUTHOR("Artur Lipowski"); -MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging messages"); diff --git a/drivers/media/IR/mceusb.c b/drivers/media/IR/mceusb.c deleted file mode 100644 index 392ca24..0000000 --- a/drivers/media/IR/mceusb.c +++ /dev/null @@ -1,1333 +0,0 @@ -/* - * Driver for USB Windows Media Center Ed. eHome Infrared Transceivers - * - * Copyright (c) 2010 by Jarod Wilson - * - * Based on the original lirc_mceusb and lirc_mceusb2 drivers, by Dan - * Conti, Martin Blatter and Daniel Melander, the latter of which was - * in turn also based on the lirc_atiusb driver by Paul Miller. The - * two mce drivers were merged into one by Jarod Wilson, with transmit - * support for the 1st-gen device added primarily by Patrick Calhoun, - * with a bit of tweaks by Jarod. Debugging improvements and proper - * support for what appears to be 3rd-gen hardware added by Jarod. - * Initial port from lirc driver to ir-core drivery by Jarod, based - * partially on a port to an earlier proposed IR infrastructure by - * Jon Smirl, which included enhancements and simplifications to the - * incoming IR buffer parsing routines. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_VERSION "1.91" -#define DRIVER_AUTHOR "Jarod Wilson " -#define DRIVER_DESC "Windows Media Center Ed. eHome Infrared Transceiver " \ - "device driver" -#define DRIVER_NAME "mceusb" - -#define USB_BUFLEN 32 /* USB reception buffer length */ -#define USB_CTRL_MSG_SZ 2 /* Size of usb ctrl msg on gen1 hw */ -#define MCE_G1_INIT_MSGS 40 /* Init messages on gen1 hw to throw out */ -#define MS_TO_NS(msec) ((msec) * 1000) - -/* MCE constants */ -#define MCE_CMDBUF_SIZE 384 /* MCE Command buffer length */ -#define MCE_TIME_UNIT 50 /* Approx 50us resolution */ -#define MCE_CODE_LENGTH 5 /* Normal length of packet (with header) */ -#define MCE_PACKET_SIZE 4 /* Normal length of packet (without header) */ -#define MCE_IRDATA_HEADER 0x84 /* Actual header format is 0x80 + num_bytes */ -#define MCE_IRDATA_TRAILER 0x80 /* End of IR data */ -#define MCE_TX_HEADER_LENGTH 3 /* # of bytes in the initializing tx header */ -#define MCE_MAX_CHANNELS 2 /* Two transmitters, hardware dependent? */ -#define MCE_DEFAULT_TX_MASK 0x03 /* Vals: TX1=0x01, TX2=0x02, ALL=0x03 */ -#define MCE_PULSE_BIT 0x80 /* Pulse bit, MSB set == PULSE else SPACE */ -#define MCE_PULSE_MASK 0x7f /* Pulse mask */ -#define MCE_MAX_PULSE_LENGTH 0x7f /* Longest transmittable pulse symbol */ - -#define MCE_HW_CMD_HEADER 0xff /* MCE hardware command header */ -#define MCE_COMMAND_HEADER 0x9f /* MCE command header */ -#define MCE_COMMAND_MASK 0xe0 /* Mask out command bits */ -#define MCE_COMMAND_NULL 0x00 /* These show up various places... */ -/* if buf[i] & MCE_COMMAND_MASK == 0x80 and buf[i] != MCE_COMMAND_HEADER, - * then we're looking at a raw IR data sample */ -#define MCE_COMMAND_IRDATA 0x80 -#define MCE_PACKET_LENGTH_MASK 0x1f /* Packet length mask */ - -/* Sub-commands, which follow MCE_COMMAND_HEADER or MCE_HW_CMD_HEADER */ -#define MCE_CMD_SIG_END 0x01 /* End of signal */ -#define MCE_CMD_PING 0x03 /* Ping device */ -#define MCE_CMD_UNKNOWN 0x04 /* Unknown */ -#define MCE_CMD_UNKNOWN2 0x05 /* Unknown */ -#define MCE_CMD_S_CARRIER 0x06 /* Set TX carrier frequency */ -#define MCE_CMD_G_CARRIER 0x07 /* Get TX carrier frequency */ -#define MCE_CMD_S_TXMASK 0x08 /* Set TX port bitmask */ -#define MCE_CMD_UNKNOWN3 0x09 /* Unknown */ -#define MCE_CMD_UNKNOWN4 0x0a /* Unknown */ -#define MCE_CMD_G_REVISION 0x0b /* Get hw/sw revision */ -#define MCE_CMD_S_TIMEOUT 0x0c /* Set RX timeout value */ -#define MCE_CMD_G_TIMEOUT 0x0d /* Get RX timeout value */ -#define MCE_CMD_UNKNOWN5 0x0e /* Unknown */ -#define MCE_CMD_UNKNOWN6 0x0f /* Unknown */ -#define MCE_CMD_G_RXPORTSTS 0x11 /* Get RX port status */ -#define MCE_CMD_G_TXMASK 0x13 /* Set TX port bitmask */ -#define MCE_CMD_S_RXSENSOR 0x14 /* Set RX sensor (std/learning) */ -#define MCE_CMD_G_RXSENSOR 0x15 /* Get RX sensor (std/learning) */ -#define MCE_RSP_PULSE_COUNT 0x15 /* RX pulse count (only if learning) */ -#define MCE_CMD_TX_PORTS 0x16 /* Get number of TX ports */ -#define MCE_CMD_G_WAKESRC 0x17 /* Get wake source */ -#define MCE_CMD_UNKNOWN7 0x18 /* Unknown */ -#define MCE_CMD_UNKNOWN8 0x19 /* Unknown */ -#define MCE_CMD_UNKNOWN9 0x1b /* Unknown */ -#define MCE_CMD_DEVICE_RESET 0xaa /* Reset the hardware */ -#define MCE_RSP_CMD_INVALID 0xfe /* Invalid command issued */ - - -/* module parameters */ -#ifdef CONFIG_USB_DEBUG -static int debug = 1; -#else -static int debug; -#endif - -/* general constants */ -#define SEND_FLAG_IN_PROGRESS 1 -#define SEND_FLAG_COMPLETE 2 -#define RECV_FLAG_IN_PROGRESS 3 -#define RECV_FLAG_COMPLETE 4 - -#define MCEUSB_RX 1 -#define MCEUSB_TX 2 - -#define VENDOR_PHILIPS 0x0471 -#define VENDOR_SMK 0x0609 -#define VENDOR_TATUNG 0x1460 -#define VENDOR_GATEWAY 0x107b -#define VENDOR_SHUTTLE 0x1308 -#define VENDOR_SHUTTLE2 0x051c -#define VENDOR_MITSUMI 0x03ee -#define VENDOR_TOPSEED 0x1784 -#define VENDOR_RICAVISION 0x179d -#define VENDOR_ITRON 0x195d -#define VENDOR_FIC 0x1509 -#define VENDOR_LG 0x043e -#define VENDOR_MICROSOFT 0x045e -#define VENDOR_FORMOSA 0x147a -#define VENDOR_FINTEK 0x1934 -#define VENDOR_PINNACLE 0x2304 -#define VENDOR_ECS 0x1019 -#define VENDOR_WISTRON 0x0fb8 -#define VENDOR_COMPRO 0x185b -#define VENDOR_NORTHSTAR 0x04eb -#define VENDOR_REALTEK 0x0bda -#define VENDOR_TIVO 0x105a -#define VENDOR_CONEXANT 0x0572 - -enum mceusb_model_type { - MCE_GEN2 = 0, /* Most boards */ - MCE_GEN1, - MCE_GEN3, - MCE_GEN2_TX_INV, - POLARIS_EVK, - CX_HYBRID_TV, -}; - -struct mceusb_model { - u32 mce_gen1:1; - u32 mce_gen2:1; - u32 mce_gen3:1; - u32 tx_mask_normal:1; - u32 is_polaris:1; - u32 no_tx:1; - - const char *rc_map; /* Allow specify a per-board map */ - const char *name; /* per-board name */ -}; - -static const struct mceusb_model mceusb_model[] = { - [MCE_GEN1] = { - .mce_gen1 = 1, - .tx_mask_normal = 1, - }, - [MCE_GEN2] = { - .mce_gen2 = 1, - }, - [MCE_GEN2_TX_INV] = { - .mce_gen2 = 1, - .tx_mask_normal = 1, - }, - [MCE_GEN3] = { - .mce_gen3 = 1, - .tx_mask_normal = 1, - }, - [POLARIS_EVK] = { - .is_polaris = 1, - /* - * In fact, the EVK is shipped without - * remotes, but we should have something handy, - * to allow testing it - */ - .rc_map = RC_MAP_RC5_HAUPPAUGE_NEW, - .name = "Conexant Hybrid TV (cx231xx) MCE IR", - }, - [CX_HYBRID_TV] = { - .is_polaris = 1, - .no_tx = 1, /* tx isn't wired up at all */ - .name = "Conexant Hybrid TV (cx231xx) MCE IR", - }, -}; - -static struct usb_device_id mceusb_dev_table[] = { - /* Original Microsoft MCE IR Transceiver (often HP-branded) */ - { USB_DEVICE(VENDOR_MICROSOFT, 0x006d), - .driver_info = MCE_GEN1 }, - /* Philips Infrared Transceiver - Sahara branded */ - { USB_DEVICE(VENDOR_PHILIPS, 0x0608) }, - /* Philips Infrared Transceiver - HP branded */ - { USB_DEVICE(VENDOR_PHILIPS, 0x060c), - .driver_info = MCE_GEN2_TX_INV }, - /* Philips SRM5100 */ - { USB_DEVICE(VENDOR_PHILIPS, 0x060d) }, - /* Philips Infrared Transceiver - Omaura */ - { USB_DEVICE(VENDOR_PHILIPS, 0x060f) }, - /* Philips Infrared Transceiver - Spinel plus */ - { USB_DEVICE(VENDOR_PHILIPS, 0x0613) }, - /* Philips eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_PHILIPS, 0x0815) }, - /* Philips/Spinel plus IR transceiver for ASUS */ - { USB_DEVICE(VENDOR_PHILIPS, 0x206c) }, - /* Philips/Spinel plus IR transceiver for ASUS */ - { USB_DEVICE(VENDOR_PHILIPS, 0x2088) }, - /* Realtek MCE IR Receiver */ - { USB_DEVICE(VENDOR_REALTEK, 0x0161) }, - /* SMK/Toshiba G83C0004D410 */ - { USB_DEVICE(VENDOR_SMK, 0x031d), - .driver_info = MCE_GEN2_TX_INV }, - /* SMK eHome Infrared Transceiver (Sony VAIO) */ - { USB_DEVICE(VENDOR_SMK, 0x0322), - .driver_info = MCE_GEN2_TX_INV }, - /* bundled with Hauppauge PVR-150 */ - { USB_DEVICE(VENDOR_SMK, 0x0334), - .driver_info = MCE_GEN2_TX_INV }, - /* SMK eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_SMK, 0x0338) }, - /* Tatung eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_TATUNG, 0x9150) }, - /* Shuttle eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_SHUTTLE, 0xc001) }, - /* Shuttle eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_SHUTTLE2, 0xc001) }, - /* Gateway eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_GATEWAY, 0x3009) }, - /* Mitsumi */ - { USB_DEVICE(VENDOR_MITSUMI, 0x2501) }, - /* Topseed eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_TOPSEED, 0x0001), - .driver_info = MCE_GEN2_TX_INV }, - /* Topseed HP eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_TOPSEED, 0x0006), - .driver_info = MCE_GEN2_TX_INV }, - /* Topseed eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_TOPSEED, 0x0007), - .driver_info = MCE_GEN2_TX_INV }, - /* Topseed eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_TOPSEED, 0x0008), - .driver_info = MCE_GEN3 }, - /* Topseed eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_TOPSEED, 0x000a), - .driver_info = MCE_GEN2_TX_INV }, - /* Topseed eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_TOPSEED, 0x0011), - .driver_info = MCE_GEN2_TX_INV }, - /* Ricavision internal Infrared Transceiver */ - { USB_DEVICE(VENDOR_RICAVISION, 0x0010) }, - /* Itron ione Libra Q-11 */ - { USB_DEVICE(VENDOR_ITRON, 0x7002) }, - /* FIC eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_FIC, 0x9242) }, - /* LG eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_LG, 0x9803) }, - /* Microsoft MCE Infrared Transceiver */ - { USB_DEVICE(VENDOR_MICROSOFT, 0x00a0) }, - /* Formosa eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_FORMOSA, 0xe015) }, - /* Formosa21 / eHome Infrared Receiver */ - { USB_DEVICE(VENDOR_FORMOSA, 0xe016) }, - /* Formosa aim / Trust MCE Infrared Receiver */ - { USB_DEVICE(VENDOR_FORMOSA, 0xe017) }, - /* Formosa Industrial Computing / Beanbag Emulation Device */ - { USB_DEVICE(VENDOR_FORMOSA, 0xe018) }, - /* Formosa21 / eHome Infrared Receiver */ - { USB_DEVICE(VENDOR_FORMOSA, 0xe03a) }, - /* Formosa Industrial Computing AIM IR605/A */ - { USB_DEVICE(VENDOR_FORMOSA, 0xe03c) }, - /* Formosa Industrial Computing */ - { USB_DEVICE(VENDOR_FORMOSA, 0xe03e) }, - /* Fintek eHome Infrared Transceiver (HP branded) */ - { USB_DEVICE(VENDOR_FINTEK, 0x5168) }, - /* Fintek eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_FINTEK, 0x0602) }, - /* Fintek eHome Infrared Transceiver (in the AOpen MP45) */ - { USB_DEVICE(VENDOR_FINTEK, 0x0702) }, - /* Pinnacle Remote Kit */ - { USB_DEVICE(VENDOR_PINNACLE, 0x0225), - .driver_info = MCE_GEN3 }, - /* Elitegroup Computer Systems IR */ - { USB_DEVICE(VENDOR_ECS, 0x0f38) }, - /* Wistron Corp. eHome Infrared Receiver */ - { USB_DEVICE(VENDOR_WISTRON, 0x0002) }, - /* Compro K100 */ - { USB_DEVICE(VENDOR_COMPRO, 0x3020) }, - /* Compro K100 v2 */ - { USB_DEVICE(VENDOR_COMPRO, 0x3082) }, - /* Northstar Systems, Inc. eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) }, - /* TiVo PC IR Receiver */ - { USB_DEVICE(VENDOR_TIVO, 0x2000) }, - /* Conexant Hybrid TV "Shelby" Polaris SDK */ - { USB_DEVICE(VENDOR_CONEXANT, 0x58a1), - .driver_info = POLARIS_EVK }, - /* Conexant Hybrid TV RDU253S Polaris */ - { USB_DEVICE(VENDOR_CONEXANT, 0x58a5), - .driver_info = CX_HYBRID_TV }, - /* Terminating entry */ - { } -}; - -/* data structure for each usb transceiver */ -struct mceusb_dev { - /* ir-core bits */ - struct ir_dev_props *props; - - /* optional features we can enable */ - bool carrier_report_enabled; - bool learning_enabled; - - /* core device bits */ - struct device *dev; - struct input_dev *idev; - - /* usb */ - struct usb_device *usbdev; - struct urb *urb_in; - struct usb_endpoint_descriptor *usb_ep_in; - struct usb_endpoint_descriptor *usb_ep_out; - - /* buffers and dma */ - unsigned char *buf_in; - unsigned int len_in; - dma_addr_t dma_in; - dma_addr_t dma_out; - - enum { - CMD_HEADER = 0, - SUBCMD, - CMD_DATA, - PARSE_IRDATA, - } parser_state; - - u8 cmd, rem; /* Remaining IR data bytes in packet */ - - struct { - u32 connected:1; - u32 tx_mask_normal:1; - u32 microsoft_gen1:1; - u32 no_tx:1; - } flags; - - /* transmit support */ - int send_flags; - u32 carrier; - unsigned char tx_mask; - - char name[128]; - char phys[64]; - enum mceusb_model_type model; -}; - -/* - * MCE Device Command Strings - * Device command responses vary from device to device... - * - DEVICE_RESET resets the hardware to its default state - * - GET_REVISION fetches the hardware/software revision, common - * replies are ff 0b 45 ff 1b 08 and ff 0b 50 ff 1b 42 - * - GET_CARRIER_FREQ gets the carrier mode and frequency of the - * device, with replies in the form of 9f 06 MM FF, where MM is 0-3, - * meaning clk of 10000000, 2500000, 625000 or 156250, and FF is - * ((clk / frequency) - 1) - * - GET_RX_TIMEOUT fetches the receiver timeout in units of 50us, - * response in the form of 9f 0c msb lsb - * - GET_TX_BITMASK fetches the transmitter bitmask, replies in - * the form of 9f 08 bm, where bm is the bitmask - * - GET_RX_SENSOR fetches the RX sensor setting -- long-range - * general use one or short-range learning one, in the form of - * 9f 14 ss, where ss is either 01 for long-range or 02 for short - * - SET_CARRIER_FREQ sets a new carrier mode and frequency - * - SET_TX_BITMASK sets the transmitter bitmask - * - SET_RX_TIMEOUT sets the receiver timeout - * - SET_RX_SENSOR sets which receiver sensor to use - */ -static char DEVICE_RESET[] = {MCE_COMMAND_NULL, MCE_HW_CMD_HEADER, - MCE_CMD_DEVICE_RESET}; -static char GET_REVISION[] = {MCE_HW_CMD_HEADER, MCE_CMD_G_REVISION}; -static char GET_UNKNOWN[] = {MCE_HW_CMD_HEADER, MCE_CMD_UNKNOWN7}; -static char GET_UNKNOWN2[] = {MCE_COMMAND_HEADER, MCE_CMD_UNKNOWN2}; -static char GET_CARRIER_FREQ[] = {MCE_COMMAND_HEADER, MCE_CMD_G_CARRIER}; -static char GET_RX_TIMEOUT[] = {MCE_COMMAND_HEADER, MCE_CMD_G_TIMEOUT}; -static char GET_TX_BITMASK[] = {MCE_COMMAND_HEADER, MCE_CMD_G_TXMASK}; -static char GET_RX_SENSOR[] = {MCE_COMMAND_HEADER, MCE_CMD_G_RXSENSOR}; -/* sub in desired values in lower byte or bytes for full command */ -/* FIXME: make use of these for transmit. -static char SET_CARRIER_FREQ[] = {MCE_COMMAND_HEADER, - MCE_CMD_S_CARRIER, 0x00, 0x00}; -static char SET_TX_BITMASK[] = {MCE_COMMAND_HEADER, MCE_CMD_S_TXMASK, 0x00}; -static char SET_RX_TIMEOUT[] = {MCE_COMMAND_HEADER, - MCE_CMD_S_TIMEOUT, 0x00, 0x00}; -static char SET_RX_SENSOR[] = {MCE_COMMAND_HEADER, - MCE_CMD_S_RXSENSOR, 0x00}; -*/ - -static int mceusb_cmdsize(u8 cmd, u8 subcmd) -{ - int datasize = 0; - - switch (cmd) { - case MCE_COMMAND_NULL: - if (subcmd == MCE_HW_CMD_HEADER) - datasize = 1; - break; - case MCE_HW_CMD_HEADER: - switch (subcmd) { - case MCE_CMD_G_REVISION: - datasize = 2; - break; - } - case MCE_COMMAND_HEADER: - switch (subcmd) { - case MCE_CMD_UNKNOWN: - case MCE_CMD_S_CARRIER: - case MCE_CMD_S_TIMEOUT: - case MCE_RSP_PULSE_COUNT: - datasize = 2; - break; - case MCE_CMD_SIG_END: - case MCE_CMD_S_TXMASK: - case MCE_CMD_S_RXSENSOR: - datasize = 1; - break; - } - } - return datasize; -} - -static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, - int offset, int len, bool out) -{ - char codes[USB_BUFLEN * 3 + 1]; - char inout[9]; - u8 cmd, subcmd, data1, data2; - struct device *dev = ir->dev; - int i, start, skip = 0; - - if (!debug) - return; - - /* skip meaningless 0xb1 0x60 header bytes on orig receiver */ - if (ir->flags.microsoft_gen1 && !out && !offset) - skip = 2; - - if (len <= skip) - return; - - for (i = 0; i < len && i < USB_BUFLEN; i++) - snprintf(codes + i * 3, 4, "%02x ", buf[i + offset] & 0xff); - - dev_info(dev, "%sx data: %s(length=%d)\n", - (out ? "t" : "r"), codes, len); - - if (out) - strcpy(inout, "Request\0"); - else - strcpy(inout, "Got\0"); - - start = offset + skip; - cmd = buf[start] & 0xff; - subcmd = buf[start + 1] & 0xff; - data1 = buf[start + 2] & 0xff; - data2 = buf[start + 3] & 0xff; - - switch (cmd) { - case MCE_COMMAND_NULL: - if ((subcmd == MCE_HW_CMD_HEADER) && - (data1 == MCE_CMD_DEVICE_RESET)) - dev_info(dev, "Device reset requested\n"); - else - dev_info(dev, "Unknown command 0x%02x 0x%02x\n", - cmd, subcmd); - break; - case MCE_HW_CMD_HEADER: - switch (subcmd) { - case MCE_CMD_G_REVISION: - if (len == 2) - dev_info(dev, "Get hw/sw rev?\n"); - else - dev_info(dev, "hw/sw rev 0x%02x 0x%02x " - "0x%02x 0x%02x\n", data1, data2, - buf[start + 4], buf[start + 5]); - break; - case MCE_CMD_DEVICE_RESET: - dev_info(dev, "Device reset requested\n"); - break; - case MCE_RSP_CMD_INVALID: - dev_info(dev, "Previous command not supported\n"); - break; - case MCE_CMD_UNKNOWN7: - case MCE_CMD_UNKNOWN9: - default: - dev_info(dev, "Unknown command 0x%02x 0x%02x\n", - cmd, subcmd); - break; - } - break; - case MCE_COMMAND_HEADER: - switch (subcmd) { - case MCE_CMD_SIG_END: - dev_info(dev, "End of signal\n"); - break; - case MCE_CMD_PING: - dev_info(dev, "Ping\n"); - break; - case MCE_CMD_UNKNOWN: - dev_info(dev, "Resp to 9f 05 of 0x%02x 0x%02x\n", - data1, data2); - break; - case MCE_CMD_S_CARRIER: - dev_info(dev, "%s carrier mode and freq of " - "0x%02x 0x%02x\n", inout, data1, data2); - break; - case MCE_CMD_G_CARRIER: - dev_info(dev, "Get carrier mode and freq\n"); - break; - case MCE_CMD_S_TXMASK: - dev_info(dev, "%s transmit blaster mask of 0x%02x\n", - inout, data1); - break; - case MCE_CMD_S_TIMEOUT: - /* value is in units of 50us, so x*50/100 or x/2 ms */ - dev_info(dev, "%s receive timeout of %d ms\n", - inout, ((data1 << 8) | data2) / 2); - break; - case MCE_CMD_G_TIMEOUT: - dev_info(dev, "Get receive timeout\n"); - break; - case MCE_CMD_G_TXMASK: - dev_info(dev, "Get transmit blaster mask\n"); - break; - case MCE_CMD_S_RXSENSOR: - dev_info(dev, "%s %s-range receive sensor in use\n", - inout, data1 == 0x02 ? "short" : "long"); - break; - case MCE_CMD_G_RXSENSOR: - /* aka MCE_RSP_PULSE_COUNT */ - if (out) - dev_info(dev, "Get receive sensor\n"); - else if (ir->learning_enabled) - dev_info(dev, "RX pulse count: %d\n", - ((data1 << 8) | data2)); - break; - case MCE_RSP_CMD_INVALID: - dev_info(dev, "Error! Hardware is likely wedged...\n"); - break; - case MCE_CMD_UNKNOWN2: - case MCE_CMD_UNKNOWN3: - case MCE_CMD_UNKNOWN5: - default: - dev_info(dev, "Unknown command 0x%02x 0x%02x\n", - cmd, subcmd); - break; - } - break; - default: - break; - } - - if (cmd == MCE_IRDATA_TRAILER) - dev_info(dev, "End of raw IR data\n"); - else if ((cmd != MCE_COMMAND_HEADER) && - ((cmd & MCE_COMMAND_MASK) == MCE_COMMAND_IRDATA)) - dev_info(dev, "Raw IR data, %d pulse/space samples\n", ir->rem); -} - -static void mce_async_callback(struct urb *urb, struct pt_regs *regs) -{ - struct mceusb_dev *ir; - int len; - - if (!urb) - return; - - ir = urb->context; - if (ir) { - len = urb->actual_length; - - dev_dbg(ir->dev, "callback called (status=%d len=%d)\n", - urb->status, len); - - mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true); - } - -} - -/* request incoming or send outgoing usb packet - used to initialize remote */ -static void mce_request_packet(struct mceusb_dev *ir, - struct usb_endpoint_descriptor *ep, - unsigned char *data, int size, int urb_type) -{ - int res; - struct urb *async_urb; - struct device *dev = ir->dev; - unsigned char *async_buf; - - if (urb_type == MCEUSB_TX) { - async_urb = usb_alloc_urb(0, GFP_KERNEL); - if (unlikely(!async_urb)) { - dev_err(dev, "Error, couldn't allocate urb!\n"); - return; - } - - async_buf = kzalloc(size, GFP_KERNEL); - if (!async_buf) { - dev_err(dev, "Error, couldn't allocate buf!\n"); - usb_free_urb(async_urb); - return; - } - - /* outbound data */ - usb_fill_int_urb(async_urb, ir->usbdev, - usb_sndintpipe(ir->usbdev, ep->bEndpointAddress), - async_buf, size, (usb_complete_t)mce_async_callback, - ir, ep->bInterval); - memcpy(async_buf, data, size); - - } else if (urb_type == MCEUSB_RX) { - /* standard request */ - async_urb = ir->urb_in; - ir->send_flags = RECV_FLAG_IN_PROGRESS; - - } else { - dev_err(dev, "Error! Unknown urb type %d\n", urb_type); - return; - } - - dev_dbg(dev, "receive request called (size=%#x)\n", size); - - async_urb->transfer_buffer_length = size; - async_urb->dev = ir->usbdev; - - res = usb_submit_urb(async_urb, GFP_ATOMIC); - if (res) { - dev_dbg(dev, "receive request FAILED! (res=%d)\n", res); - return; - } - dev_dbg(dev, "receive request complete (res=%d)\n", res); -} - -static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size) -{ - mce_request_packet(ir, ir->usb_ep_out, data, size, MCEUSB_TX); -} - -static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size) -{ - mce_request_packet(ir, ir->usb_ep_in, data, size, MCEUSB_RX); -} - -/* Send data out the IR blaster port(s) */ -static int mceusb_tx_ir(void *priv, int *txbuf, u32 n) -{ - struct mceusb_dev *ir = priv; - int i, ret = 0; - int count, cmdcount = 0; - unsigned char *cmdbuf; /* MCE command buffer */ - long signal_duration = 0; /* Singnal length in us */ - struct timeval start_time, end_time; - - do_gettimeofday(&start_time); - - count = n / sizeof(int); - - cmdbuf = kzalloc(sizeof(int) * MCE_CMDBUF_SIZE, GFP_KERNEL); - if (!cmdbuf) - return -ENOMEM; - - /* MCE tx init header */ - cmdbuf[cmdcount++] = MCE_COMMAND_HEADER; - cmdbuf[cmdcount++] = MCE_CMD_S_TXMASK; - cmdbuf[cmdcount++] = ir->tx_mask; - - /* Generate mce packet data */ - for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) { - signal_duration += txbuf[i]; - txbuf[i] = txbuf[i] / MCE_TIME_UNIT; - - do { /* loop to support long pulses/spaces > 127*50us=6.35ms */ - - /* Insert mce packet header every 4th entry */ - if ((cmdcount < MCE_CMDBUF_SIZE) && - (cmdcount - MCE_TX_HEADER_LENGTH) % - MCE_CODE_LENGTH == 0) - cmdbuf[cmdcount++] = MCE_IRDATA_HEADER; - - /* Insert mce packet data */ - if (cmdcount < MCE_CMDBUF_SIZE) - cmdbuf[cmdcount++] = - (txbuf[i] < MCE_PULSE_BIT ? - txbuf[i] : MCE_MAX_PULSE_LENGTH) | - (i & 1 ? 0x00 : MCE_PULSE_BIT); - else { - ret = -EINVAL; - goto out; - } - - } while ((txbuf[i] > MCE_MAX_PULSE_LENGTH) && - (txbuf[i] -= MCE_MAX_PULSE_LENGTH)); - } - - /* Fix packet length in last header */ - cmdbuf[cmdcount - (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH] = - MCE_COMMAND_IRDATA + (cmdcount - MCE_TX_HEADER_LENGTH) % - MCE_CODE_LENGTH - 1; - - /* Check if we have room for the empty packet at the end */ - if (cmdcount >= MCE_CMDBUF_SIZE) { - ret = -EINVAL; - goto out; - } - - /* All mce commands end with an empty packet (0x80) */ - cmdbuf[cmdcount++] = MCE_IRDATA_TRAILER; - - /* Transmit the command to the mce device */ - mce_async_out(ir, cmdbuf, cmdcount); - - /* - * The lircd gap calculation expects the write function to - * wait the time it takes for the ircommand to be sent before - * it returns. - */ - do_gettimeofday(&end_time); - signal_duration -= (end_time.tv_usec - start_time.tv_usec) + - (end_time.tv_sec - start_time.tv_sec) * 1000000; - - /* delay with the closest number of ticks */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(usecs_to_jiffies(signal_duration)); - -out: - kfree(cmdbuf); - return ret ? ret : n; -} - -/* Sets active IR outputs -- mce devices typically have two */ -static int mceusb_set_tx_mask(void *priv, u32 mask) -{ - struct mceusb_dev *ir = priv; - - if (ir->flags.tx_mask_normal) - ir->tx_mask = mask; - else - ir->tx_mask = (mask != MCE_DEFAULT_TX_MASK ? - mask ^ MCE_DEFAULT_TX_MASK : mask) << 1; - - return 0; -} - -/* Sets the send carrier frequency and mode */ -static int mceusb_set_tx_carrier(void *priv, u32 carrier) -{ - struct mceusb_dev *ir = priv; - int clk = 10000000; - int prescaler = 0, divisor = 0; - unsigned char cmdbuf[4] = { MCE_COMMAND_HEADER, - MCE_CMD_S_CARRIER, 0x00, 0x00 }; - - /* Carrier has changed */ - if (ir->carrier != carrier) { - - if (carrier == 0) { - ir->carrier = carrier; - cmdbuf[2] = MCE_CMD_SIG_END; - cmdbuf[3] = MCE_IRDATA_TRAILER; - dev_dbg(ir->dev, "%s: disabling carrier " - "modulation\n", __func__); - mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); - return carrier; - } - - for (prescaler = 0; prescaler < 4; ++prescaler) { - divisor = (clk >> (2 * prescaler)) / carrier; - if (divisor <= 0xff) { - ir->carrier = carrier; - cmdbuf[2] = prescaler; - cmdbuf[3] = divisor; - dev_dbg(ir->dev, "%s: requesting %u HZ " - "carrier\n", __func__, carrier); - - /* Transmit new carrier to mce device */ - mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); - return carrier; - } - } - - return -EINVAL; - - } - - return carrier; -} - -/* - * We don't do anything but print debug spew for many of the command bits - * we receive from the hardware, but some of them are useful information - * we want to store so that we can use them. - */ -static void mceusb_handle_command(struct mceusb_dev *ir, int index) -{ - u8 hi = ir->buf_in[index + 1] & 0xff; - u8 lo = ir->buf_in[index + 2] & 0xff; - - switch (ir->buf_in[index]) { - /* 2-byte return value commands */ - case MCE_CMD_S_TIMEOUT: - ir->props->timeout = MS_TO_NS((hi << 8 | lo) / 2); - break; - - /* 1-byte return value commands */ - case MCE_CMD_S_TXMASK: - ir->tx_mask = hi; - break; - case MCE_CMD_S_RXSENSOR: - ir->learning_enabled = (hi == 0x02); - break; - default: - break; - } -} - -static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) -{ - DEFINE_IR_RAW_EVENT(rawir); - int i = 0; - - /* skip meaningless 0xb1 0x60 header bytes on orig receiver */ - if (ir->flags.microsoft_gen1) - i = 2; - - /* if there's no data, just return now */ - if (buf_len <= i) - return; - - for (; i < buf_len; i++) { - switch (ir->parser_state) { - case SUBCMD: - ir->rem = mceusb_cmdsize(ir->cmd, ir->buf_in[i]); - mceusb_dev_printdata(ir, ir->buf_in, i - 1, - ir->rem + 2, false); - mceusb_handle_command(ir, i); - ir->parser_state = CMD_DATA; - break; - case PARSE_IRDATA: - ir->rem--; - rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0); - rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK) - * MS_TO_NS(MCE_TIME_UNIT); - - dev_dbg(ir->dev, "Storing %s with duration %d\n", - rawir.pulse ? "pulse" : "space", - rawir.duration); - - ir_raw_event_store_with_filter(ir->idev, &rawir); - break; - case CMD_DATA: - ir->rem--; - break; - case CMD_HEADER: - /* decode mce packets of the form (84),AA,BB,CC,DD */ - /* IR data packets can span USB messages - rem */ - ir->cmd = ir->buf_in[i]; - if ((ir->cmd == MCE_COMMAND_HEADER) || - ((ir->cmd & MCE_COMMAND_MASK) != - MCE_COMMAND_IRDATA)) { - ir->parser_state = SUBCMD; - continue; - } - ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK); - mceusb_dev_printdata(ir, ir->buf_in, - i, ir->rem + 1, false); - if (ir->rem) - ir->parser_state = PARSE_IRDATA; - break; - } - - if (ir->parser_state != CMD_HEADER && !ir->rem) - ir->parser_state = CMD_HEADER; - } - dev_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n"); - ir_raw_event_handle(ir->idev); -} - -static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs) -{ - struct mceusb_dev *ir; - int buf_len; - - if (!urb) - return; - - ir = urb->context; - if (!ir) { - usb_unlink_urb(urb); - return; - } - - buf_len = urb->actual_length; - - if (ir->send_flags == RECV_FLAG_IN_PROGRESS) { - ir->send_flags = SEND_FLAG_COMPLETE; - dev_dbg(ir->dev, "setup answer received %d bytes\n", - buf_len); - } - - switch (urb->status) { - /* success */ - case 0: - mceusb_process_ir_data(ir, buf_len); - break; - - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - usb_unlink_urb(urb); - return; - - case -EPIPE: - default: - dev_dbg(ir->dev, "Error: urb status = %d\n", urb->status); - break; - } - - usb_submit_urb(urb, GFP_ATOMIC); -} - -static void mceusb_gen1_init(struct mceusb_dev *ir) -{ - int ret; - int maxp = ir->len_in; - struct device *dev = ir->dev; - char *data; - - data = kzalloc(USB_CTRL_MSG_SZ, GFP_KERNEL); - if (!data) { - dev_err(dev, "%s: memory allocation failed!\n", __func__); - return; - } - - /* - * This is a strange one. Windows issues a set address to the device - * on the receive control pipe and expect a certain value pair back - */ - ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), - USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0, - data, USB_CTRL_MSG_SZ, HZ * 3); - dev_dbg(dev, "%s - ret = %d\n", __func__, ret); - dev_dbg(dev, "%s - data[0] = %d, data[1] = %d\n", - __func__, data[0], data[1]); - - /* set feature: bit rate 38400 bps */ - ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), - USB_REQ_SET_FEATURE, USB_TYPE_VENDOR, - 0xc04e, 0x0000, NULL, 0, HZ * 3); - - dev_dbg(dev, "%s - ret = %d\n", __func__, ret); - - /* bRequest 4: set char length to 8 bits */ - ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), - 4, USB_TYPE_VENDOR, - 0x0808, 0x0000, NULL, 0, HZ * 3); - dev_dbg(dev, "%s - retB = %d\n", __func__, ret); - - /* bRequest 2: set handshaking to use DTR/DSR */ - ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), - 2, USB_TYPE_VENDOR, - 0x0000, 0x0100, NULL, 0, HZ * 3); - dev_dbg(dev, "%s - retC = %d\n", __func__, ret); - - /* device reset */ - mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET)); - mce_sync_in(ir, NULL, maxp); - - /* get hw/sw revision? */ - mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION)); - mce_sync_in(ir, NULL, maxp); - - kfree(data); -}; - -static void mceusb_gen2_init(struct mceusb_dev *ir) -{ - int maxp = ir->len_in; - - /* device reset */ - mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET)); - mce_sync_in(ir, NULL, maxp); - - /* get hw/sw revision? */ - mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION)); - mce_sync_in(ir, NULL, maxp); - - /* unknown what the next two actually return... */ - mce_async_out(ir, GET_UNKNOWN, sizeof(GET_UNKNOWN)); - mce_sync_in(ir, NULL, maxp); - mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2)); - mce_sync_in(ir, NULL, maxp); -} - -static void mceusb_get_parameters(struct mceusb_dev *ir) -{ - int maxp = ir->len_in; - - /* get the carrier and frequency */ - mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ)); - mce_sync_in(ir, NULL, maxp); - - if (!ir->flags.no_tx) { - /* get the transmitter bitmask */ - mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK)); - mce_sync_in(ir, NULL, maxp); - } - - /* get receiver timeout value */ - mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT)); - mce_sync_in(ir, NULL, maxp); - - /* get receiver sensor setting */ - mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR)); - mce_sync_in(ir, NULL, maxp); -} - -static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir) -{ - struct input_dev *idev; - struct ir_dev_props *props; - struct device *dev = ir->dev; - const char *rc_map = RC_MAP_RC6_MCE; - const char *name = "Media Center Ed. eHome Infrared Remote Transceiver"; - int ret = -ENODEV; - - idev = input_allocate_device(); - if (!idev) { - dev_err(dev, "remote input dev allocation failed\n"); - goto idev_alloc_failed; - } - - ret = -ENOMEM; - props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); - if (!props) { - dev_err(dev, "remote ir dev props allocation failed\n"); - goto props_alloc_failed; - } - - if (mceusb_model[ir->model].name) - name = mceusb_model[ir->model].name; - - snprintf(ir->name, sizeof(ir->name), "%s (%04x:%04x)", - name, - le16_to_cpu(ir->usbdev->descriptor.idVendor), - le16_to_cpu(ir->usbdev->descriptor.idProduct)); - - idev->name = ir->name; - usb_make_path(ir->usbdev, ir->phys, sizeof(ir->phys)); - strlcat(ir->phys, "/input0", sizeof(ir->phys)); - idev->phys = ir->phys; - - props->priv = ir; - props->driver_type = RC_DRIVER_IR_RAW; - props->allowed_protos = IR_TYPE_ALL; - props->timeout = MS_TO_NS(1000); - if (!ir->flags.no_tx) { - props->s_tx_mask = mceusb_set_tx_mask; - props->s_tx_carrier = mceusb_set_tx_carrier; - props->tx_ir = mceusb_tx_ir; - } - - ir->props = props; - - usb_to_input_id(ir->usbdev, &idev->id); - idev->dev.parent = ir->dev; - - if (mceusb_model[ir->model].rc_map) - rc_map = mceusb_model[ir->model].rc_map; - - ret = ir_input_register(idev, rc_map, props, DRIVER_NAME); - if (ret < 0) { - dev_err(dev, "remote input device register failed\n"); - goto irdev_failed; - } - - return idev; - -irdev_failed: - kfree(props); -props_alloc_failed: - input_free_device(idev); -idev_alloc_failed: - return NULL; -} - -static int __devinit mceusb_dev_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_host_interface *idesc; - struct usb_endpoint_descriptor *ep = NULL; - struct usb_endpoint_descriptor *ep_in = NULL; - struct usb_endpoint_descriptor *ep_out = NULL; - struct mceusb_dev *ir = NULL; - int pipe, maxp, i; - char buf[63], name[128] = ""; - enum mceusb_model_type model = id->driver_info; - bool is_gen3; - bool is_microsoft_gen1; - bool tx_mask_normal; - bool is_polaris; - - dev_dbg(&intf->dev, "%s called\n", __func__); - - idesc = intf->cur_altsetting; - - is_gen3 = mceusb_model[model].mce_gen3; - is_microsoft_gen1 = mceusb_model[model].mce_gen1; - tx_mask_normal = mceusb_model[model].tx_mask_normal; - is_polaris = mceusb_model[model].is_polaris; - - if (is_polaris) { - /* Interface 0 is IR */ - if (idesc->desc.bInterfaceNumber) - return -ENODEV; - } - - /* step through the endpoints to find first bulk in and out endpoint */ - for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { - ep = &idesc->endpoint[i].desc; - - if ((ep_in == NULL) - && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) - == USB_DIR_IN) - && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_BULK) - || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_INT))) { - - ep_in = ep; - ep_in->bmAttributes = USB_ENDPOINT_XFER_INT; - ep_in->bInterval = 1; - dev_dbg(&intf->dev, "acceptable inbound endpoint " - "found\n"); - } - - if ((ep_out == NULL) - && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) - == USB_DIR_OUT) - && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_BULK) - || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_INT))) { - - ep_out = ep; - ep_out->bmAttributes = USB_ENDPOINT_XFER_INT; - ep_out->bInterval = 1; - dev_dbg(&intf->dev, "acceptable outbound endpoint " - "found\n"); - } - } - if (ep_in == NULL) { - dev_dbg(&intf->dev, "inbound and/or endpoint not found\n"); - return -ENODEV; - } - - pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress); - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - ir = kzalloc(sizeof(struct mceusb_dev), GFP_KERNEL); - if (!ir) - goto mem_alloc_fail; - - ir->buf_in = usb_alloc_coherent(dev, maxp, GFP_ATOMIC, &ir->dma_in); - if (!ir->buf_in) - goto buf_in_alloc_fail; - - ir->urb_in = usb_alloc_urb(0, GFP_KERNEL); - if (!ir->urb_in) - goto urb_in_alloc_fail; - - ir->usbdev = dev; - ir->dev = &intf->dev; - ir->len_in = maxp; - ir->flags.microsoft_gen1 = is_microsoft_gen1; - ir->flags.tx_mask_normal = tx_mask_normal; - ir->flags.no_tx = mceusb_model[model].no_tx; - ir->model = model; - - /* Saving usb interface data for use by the transmitter routine */ - ir->usb_ep_in = ep_in; - ir->usb_ep_out = ep_out; - - if (dev->descriptor.iManufacturer - && usb_string(dev, dev->descriptor.iManufacturer, - buf, sizeof(buf)) > 0) - strlcpy(name, buf, sizeof(name)); - if (dev->descriptor.iProduct - && usb_string(dev, dev->descriptor.iProduct, - buf, sizeof(buf)) > 0) - snprintf(name + strlen(name), sizeof(name) - strlen(name), - " %s", buf); - - ir->idev = mceusb_init_input_dev(ir); - if (!ir->idev) - goto input_dev_fail; - - /* flush buffers on the device */ - mce_sync_in(ir, NULL, maxp); - mce_sync_in(ir, NULL, maxp); - - /* wire up inbound data handler */ - usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, - maxp, (usb_complete_t) mceusb_dev_recv, ir, ep_in->bInterval); - ir->urb_in->transfer_dma = ir->dma_in; - ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - /* initialize device */ - if (ir->flags.microsoft_gen1) - mceusb_gen1_init(ir); - else if (!is_gen3) - mceusb_gen2_init(ir); - - mceusb_get_parameters(ir); - - if (!ir->flags.no_tx) - mceusb_set_tx_mask(ir, MCE_DEFAULT_TX_MASK); - - usb_set_intfdata(intf, ir); - - dev_info(&intf->dev, "Registered %s on usb%d:%d\n", name, - dev->bus->busnum, dev->devnum); - - return 0; - - /* Error-handling path */ -input_dev_fail: - usb_free_urb(ir->urb_in); -urb_in_alloc_fail: - usb_free_coherent(dev, maxp, ir->buf_in, ir->dma_in); -buf_in_alloc_fail: - kfree(ir); -mem_alloc_fail: - dev_err(&intf->dev, "%s: device setup failed!\n", __func__); - - return -ENOMEM; -} - - -static void __devexit mceusb_dev_disconnect(struct usb_interface *intf) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct mceusb_dev *ir = usb_get_intfdata(intf); - - usb_set_intfdata(intf, NULL); - - if (!ir) - return; - - ir->usbdev = NULL; - ir_input_unregister(ir->idev); - usb_kill_urb(ir->urb_in); - usb_free_urb(ir->urb_in); - usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in); - - kfree(ir); -} - -static int mceusb_dev_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct mceusb_dev *ir = usb_get_intfdata(intf); - dev_info(ir->dev, "suspend\n"); - usb_kill_urb(ir->urb_in); - return 0; -} - -static int mceusb_dev_resume(struct usb_interface *intf) -{ - struct mceusb_dev *ir = usb_get_intfdata(intf); - dev_info(ir->dev, "resume\n"); - if (usb_submit_urb(ir->urb_in, GFP_ATOMIC)) - return -EIO; - return 0; -} - -static struct usb_driver mceusb_dev_driver = { - .name = DRIVER_NAME, - .probe = mceusb_dev_probe, - .disconnect = mceusb_dev_disconnect, - .suspend = mceusb_dev_suspend, - .resume = mceusb_dev_resume, - .reset_resume = mceusb_dev_resume, - .id_table = mceusb_dev_table -}; - -static int __init mceusb_dev_init(void) -{ - int ret; - - ret = usb_register(&mceusb_dev_driver); - if (ret < 0) - printk(KERN_ERR DRIVER_NAME - ": usb register failed, result = %d\n", ret); - - return ret; -} - -static void __exit mceusb_dev_exit(void) -{ - usb_deregister(&mceusb_dev_driver); -} - -module_init(mceusb_dev_init); -module_exit(mceusb_dev_exit); - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(usb, mceusb_dev_table); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); diff --git a/drivers/media/IR/nuvoton-cir.c b/drivers/media/IR/nuvoton-cir.c deleted file mode 100644 index acc729c..0000000 --- a/drivers/media/IR/nuvoton-cir.c +++ /dev/null @@ -1,1252 +0,0 @@ -/* - * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR - * - * Copyright (C) 2010 Jarod Wilson - * Copyright (C) 2009 Nuvoton PS Team - * - * Special thanks to Nuvoton for providing hardware, spec sheets and - * sample code upon which portions of this driver are based. Indirect - * thanks also to Maxim Levitsky, whose ene_ir driver this driver is - * modeled after. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nuvoton-cir.h" - -static char *chip_id = "w836x7hg"; - -/* write val to config reg */ -static inline void nvt_cr_write(struct nvt_dev *nvt, u8 val, u8 reg) -{ - outb(reg, nvt->cr_efir); - outb(val, nvt->cr_efdr); -} - -/* read val from config reg */ -static inline u8 nvt_cr_read(struct nvt_dev *nvt, u8 reg) -{ - outb(reg, nvt->cr_efir); - return inb(nvt->cr_efdr); -} - -/* update config register bit without changing other bits */ -static inline void nvt_set_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg) -{ - u8 tmp = nvt_cr_read(nvt, reg) | val; - nvt_cr_write(nvt, tmp, reg); -} - -/* clear config register bit without changing other bits */ -static inline void nvt_clear_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg) -{ - u8 tmp = nvt_cr_read(nvt, reg) & ~val; - nvt_cr_write(nvt, tmp, reg); -} - -/* enter extended function mode */ -static inline void nvt_efm_enable(struct nvt_dev *nvt) -{ - /* Enabling Extended Function Mode explicitly requires writing 2x */ - outb(EFER_EFM_ENABLE, nvt->cr_efir); - outb(EFER_EFM_ENABLE, nvt->cr_efir); -} - -/* exit extended function mode */ -static inline void nvt_efm_disable(struct nvt_dev *nvt) -{ - outb(EFER_EFM_DISABLE, nvt->cr_efir); -} - -/* - * When you want to address a specific logical device, write its logical - * device number to CR_LOGICAL_DEV_SEL, then enable/disable by writing - * 0x1/0x0 respectively to CR_LOGICAL_DEV_EN. - */ -static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev) -{ - outb(CR_LOGICAL_DEV_SEL, nvt->cr_efir); - outb(ldev, nvt->cr_efdr); -} - -/* write val to cir config register */ -static inline void nvt_cir_reg_write(struct nvt_dev *nvt, u8 val, u8 offset) -{ - outb(val, nvt->cir_addr + offset); -} - -/* read val from cir config register */ -static u8 nvt_cir_reg_read(struct nvt_dev *nvt, u8 offset) -{ - u8 val; - - val = inb(nvt->cir_addr + offset); - - return val; -} - -/* write val to cir wake register */ -static inline void nvt_cir_wake_reg_write(struct nvt_dev *nvt, - u8 val, u8 offset) -{ - outb(val, nvt->cir_wake_addr + offset); -} - -/* read val from cir wake config register */ -static u8 nvt_cir_wake_reg_read(struct nvt_dev *nvt, u8 offset) -{ - u8 val; - - val = inb(nvt->cir_wake_addr + offset); - - return val; -} - -#define pr_reg(text, ...) \ - printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__) - -/* dump current cir register contents */ -static void cir_dump_regs(struct nvt_dev *nvt) -{ - nvt_efm_enable(nvt); - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - - pr_reg("%s: Dump CIR logical device registers:\n", NVT_DRIVER_NAME); - pr_reg(" * CR CIR ACTIVE : 0x%x\n", - nvt_cr_read(nvt, CR_LOGICAL_DEV_EN)); - pr_reg(" * CR CIR BASE ADDR: 0x%x\n", - (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) | - nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO)); - pr_reg(" * CR CIR IRQ NUM: 0x%x\n", - nvt_cr_read(nvt, CR_CIR_IRQ_RSRC)); - - nvt_efm_disable(nvt); - - pr_reg("%s: Dump CIR registers:\n", NVT_DRIVER_NAME); - pr_reg(" * IRCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRCON)); - pr_reg(" * IRSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRSTS)); - pr_reg(" * IREN: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IREN)); - pr_reg(" * RXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_RXFCONT)); - pr_reg(" * CP: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CP)); - pr_reg(" * CC: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CC)); - pr_reg(" * SLCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCH)); - pr_reg(" * SLCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCL)); - pr_reg(" * FIFOCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FIFOCON)); - pr_reg(" * IRFIFOSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFIFOSTS)); - pr_reg(" * SRXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SRXFIFO)); - pr_reg(" * TXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_TXFCONT)); - pr_reg(" * STXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_STXFIFO)); - pr_reg(" * FCCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCH)); - pr_reg(" * FCCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCL)); - pr_reg(" * IRFSM: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFSM)); -} - -/* dump current cir wake register contents */ -static void cir_wake_dump_regs(struct nvt_dev *nvt) -{ - u8 i, fifo_len; - - nvt_efm_enable(nvt); - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); - - pr_reg("%s: Dump CIR WAKE logical device registers:\n", - NVT_DRIVER_NAME); - pr_reg(" * CR CIR WAKE ACTIVE : 0x%x\n", - nvt_cr_read(nvt, CR_LOGICAL_DEV_EN)); - pr_reg(" * CR CIR WAKE BASE ADDR: 0x%x\n", - (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) | - nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO)); - pr_reg(" * CR CIR WAKE IRQ NUM: 0x%x\n", - nvt_cr_read(nvt, CR_CIR_IRQ_RSRC)); - - nvt_efm_disable(nvt); - - pr_reg("%s: Dump CIR WAKE registers\n", NVT_DRIVER_NAME); - pr_reg(" * IRCON: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON)); - pr_reg(" * IRSTS: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS)); - pr_reg(" * IREN: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN)); - pr_reg(" * FIFO CMP DEEP: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_DEEP)); - pr_reg(" * FIFO CMP TOL: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_TOL)); - pr_reg(" * FIFO COUNT: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT)); - pr_reg(" * SLCH: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCH)); - pr_reg(" * SLCL: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCL)); - pr_reg(" * FIFOCON: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON)); - pr_reg(" * SRXFSTS: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_SRXFSTS)); - pr_reg(" * SAMPLE RX FIFO: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_SAMPLE_RX_FIFO)); - pr_reg(" * WR FIFO DATA: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_WR_FIFO_DATA)); - pr_reg(" * RD FIFO ONLY: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY)); - pr_reg(" * RD FIFO ONLY IDX: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)); - pr_reg(" * FIFO IGNORE: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_IGNORE)); - pr_reg(" * IRFSM: 0x%x\n", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRFSM)); - - fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT); - pr_reg("%s: Dump CIR WAKE FIFO (len %d)\n", NVT_DRIVER_NAME, fifo_len); - pr_reg("* Contents = "); - for (i = 0; i < fifo_len; i++) - printk(KERN_CONT "%02x ", - nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY)); - printk(KERN_CONT "\n"); -} - -/* detect hardware features */ -static int nvt_hw_detect(struct nvt_dev *nvt) -{ - unsigned long flags; - u8 chip_major, chip_minor; - int ret = 0; - - nvt_efm_enable(nvt); - - /* Check if we're wired for the alternate EFER setup */ - chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); - if (chip_major == 0xff) { - nvt->cr_efir = CR_EFIR2; - nvt->cr_efdr = CR_EFDR2; - nvt_efm_enable(nvt); - chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); - } - - chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO); - nvt_dbg("%s: chip id: 0x%02x 0x%02x", chip_id, chip_major, chip_minor); - - if (chip_major != CHIP_ID_HIGH && - (chip_minor != CHIP_ID_LOW || chip_minor != CHIP_ID_LOW2)) - ret = -ENODEV; - - nvt_efm_disable(nvt); - - spin_lock_irqsave(&nvt->nvt_lock, flags); - nvt->chip_major = chip_major; - nvt->chip_minor = chip_minor; - spin_unlock_irqrestore(&nvt->nvt_lock, flags); - - return ret; -} - -static void nvt_cir_ldev_init(struct nvt_dev *nvt) -{ - u8 val; - - /* output pin selection (Pin95=CIRRX, Pin96=CIRTX1, WB enabled */ - val = nvt_cr_read(nvt, CR_OUTPUT_PIN_SEL); - val &= OUTPUT_PIN_SEL_MASK; - val |= (OUTPUT_ENABLE_CIR | OUTPUT_ENABLE_CIRWB); - nvt_cr_write(nvt, val, CR_OUTPUT_PIN_SEL); - - /* Select CIR logical device and enable */ - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); - - nvt_cr_write(nvt, nvt->cir_addr >> 8, CR_CIR_BASE_ADDR_HI); - nvt_cr_write(nvt, nvt->cir_addr & 0xff, CR_CIR_BASE_ADDR_LO); - - nvt_cr_write(nvt, nvt->cir_irq, CR_CIR_IRQ_RSRC); - - nvt_dbg("CIR initialized, base io port address: 0x%lx, irq: %d", - nvt->cir_addr, nvt->cir_irq); -} - -static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt) -{ - /* Select ACPI logical device, enable it and CIR Wake */ - nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI); - nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); - - /* Enable CIR Wake via PSOUT# (Pin60) */ - nvt_set_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE); - - /* enable cir interrupt of mouse/keyboard IRQ event */ - nvt_set_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS); - - /* enable pme interrupt of cir wakeup event */ - nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2); - - /* Select CIR Wake logical device and enable */ - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); - nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); - - nvt_cr_write(nvt, nvt->cir_wake_addr >> 8, CR_CIR_BASE_ADDR_HI); - nvt_cr_write(nvt, nvt->cir_wake_addr & 0xff, CR_CIR_BASE_ADDR_LO); - - nvt_cr_write(nvt, nvt->cir_wake_irq, CR_CIR_IRQ_RSRC); - - nvt_dbg("CIR Wake initialized, base io port address: 0x%lx, irq: %d", - nvt->cir_wake_addr, nvt->cir_wake_irq); -} - -/* clear out the hardware's cir rx fifo */ -static void nvt_clear_cir_fifo(struct nvt_dev *nvt) -{ - u8 val; - - val = nvt_cir_reg_read(nvt, CIR_FIFOCON); - nvt_cir_reg_write(nvt, val | CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON); -} - -/* clear out the hardware's cir wake rx fifo */ -static void nvt_clear_cir_wake_fifo(struct nvt_dev *nvt) -{ - u8 val; - - val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON); - nvt_cir_wake_reg_write(nvt, val | CIR_WAKE_FIFOCON_RXFIFOCLR, - CIR_WAKE_FIFOCON); -} - -/* clear out the hardware's cir tx fifo */ -static void nvt_clear_tx_fifo(struct nvt_dev *nvt) -{ - u8 val; - - val = nvt_cir_reg_read(nvt, CIR_FIFOCON); - nvt_cir_reg_write(nvt, val | CIR_FIFOCON_TXFIFOCLR, CIR_FIFOCON); -} - -/* enable RX Trigger Level Reach and Packet End interrupts */ -static void nvt_set_cir_iren(struct nvt_dev *nvt) -{ - u8 iren; - - iren = CIR_IREN_RTR | CIR_IREN_PE; - nvt_cir_reg_write(nvt, iren, CIR_IREN); -} - -static void nvt_cir_regs_init(struct nvt_dev *nvt) -{ - /* set sample limit count (PE interrupt raised when reached) */ - nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_SLCH); - nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_SLCL); - - /* set fifo irq trigger levels */ - nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV | - CIR_FIFOCON_RX_TRIGGER_LEV, CIR_FIFOCON); - - /* - * Enable TX and RX, specify carrier on = low, off = high, and set - * sample period (currently 50us) - */ - nvt_cir_reg_write(nvt, - CIR_IRCON_TXEN | CIR_IRCON_RXEN | - CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, - CIR_IRCON); - - /* clear hardware rx and tx fifos */ - nvt_clear_cir_fifo(nvt); - nvt_clear_tx_fifo(nvt); - - /* clear any and all stray interrupts */ - nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); - - /* and finally, enable interrupts */ - nvt_set_cir_iren(nvt); -} - -static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) -{ - /* set number of bytes needed for wake key comparison (default 67) */ - nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFO_LEN, CIR_WAKE_FIFO_CMP_DEEP); - - /* set tolerance/variance allowed per byte during wake compare */ - nvt_cir_wake_reg_write(nvt, CIR_WAKE_CMP_TOLERANCE, - CIR_WAKE_FIFO_CMP_TOL); - - /* set sample limit count (PE interrupt raised when reached) */ - nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_WAKE_SLCH); - nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_WAKE_SLCL); - - /* set cir wake fifo rx trigger level (currently 67) */ - nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFOCON_RX_TRIGGER_LEV, - CIR_WAKE_FIFOCON); - - /* - * Enable TX and RX, specific carrier on = low, off = high, and set - * sample period (currently 50us) - */ - nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | - CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | - CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, - CIR_WAKE_IRCON); - - /* clear cir wake rx fifo */ - nvt_clear_cir_wake_fifo(nvt); - - /* clear any and all stray interrupts */ - nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); -} - -static void nvt_enable_wake(struct nvt_dev *nvt) -{ - nvt_efm_enable(nvt); - - nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI); - nvt_set_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE); - nvt_set_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS); - nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2); - - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); - nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); - - nvt_efm_disable(nvt); - - nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | - CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | - CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, - CIR_WAKE_IRCON); - nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); - nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN); -} - -/* rx carrier detect only works in learning mode, must be called w/nvt_lock */ -static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt) -{ - u32 count, carrier, duration = 0; - int i; - - count = nvt_cir_reg_read(nvt, CIR_FCCL) | - nvt_cir_reg_read(nvt, CIR_FCCH) << 8; - - for (i = 0; i < nvt->pkts; i++) { - if (nvt->buf[i] & BUF_PULSE_BIT) - duration += nvt->buf[i] & BUF_LEN_MASK; - } - - duration *= SAMPLE_PERIOD; - - if (!count || !duration) { - nvt_pr(KERN_NOTICE, "Unable to determine carrier! (c:%u, d:%u)", - count, duration); - return 0; - } - - carrier = (count * 1000000) / duration; - - if ((carrier > MAX_CARRIER) || (carrier < MIN_CARRIER)) - nvt_dbg("WTF? Carrier frequency out of range!"); - - nvt_dbg("Carrier frequency: %u (count %u, duration %u)", - carrier, count, duration); - - return carrier; -} - -/* - * set carrier frequency - * - * set carrier on 2 registers: CP & CC - * always set CP as 0x81 - * set CC by SPEC, CC = 3MHz/carrier - 1 - */ -static int nvt_set_tx_carrier(void *data, u32 carrier) -{ - struct nvt_dev *nvt = data; - u16 val; - - nvt_cir_reg_write(nvt, 1, CIR_CP); - val = 3000000 / (carrier) - 1; - nvt_cir_reg_write(nvt, val & 0xff, CIR_CC); - - nvt_dbg("cp: 0x%x cc: 0x%x\n", - nvt_cir_reg_read(nvt, CIR_CP), nvt_cir_reg_read(nvt, CIR_CC)); - - return 0; -} - -/* - * nvt_tx_ir - * - * 1) clean TX fifo first (handled by AP) - * 2) copy data from user space - * 3) disable RX interrupts, enable TX interrupts: TTR & TFU - * 4) send 9 packets to TX FIFO to open TTR - * in interrupt_handler: - * 5) send all data out - * go back to write(): - * 6) disable TX interrupts, re-enable RX interupts - * - * The key problem of this function is user space data may larger than - * driver's data buf length. So nvt_tx_ir() will only copy TX_BUF_LEN data to - * buf, and keep current copied data buf num in cur_buf_num. But driver's buf - * number may larger than TXFCONT (0xff). So in interrupt_handler, it has to - * set TXFCONT as 0xff, until buf_count less than 0xff. - */ -static int nvt_tx_ir(void *priv, int *txbuf, u32 n) -{ - struct nvt_dev *nvt = priv; - unsigned long flags; - size_t cur_count; - unsigned int i; - u8 iren; - int ret; - - spin_lock_irqsave(&nvt->tx.lock, flags); - - if (n >= TX_BUF_LEN) { - nvt->tx.buf_count = cur_count = TX_BUF_LEN; - ret = TX_BUF_LEN; - } else { - nvt->tx.buf_count = cur_count = n; - ret = n; - } - - memcpy(nvt->tx.buf, txbuf, nvt->tx.buf_count); - - nvt->tx.cur_buf_num = 0; - - /* save currently enabled interrupts */ - iren = nvt_cir_reg_read(nvt, CIR_IREN); - - /* now disable all interrupts, save TFU & TTR */ - nvt_cir_reg_write(nvt, CIR_IREN_TFU | CIR_IREN_TTR, CIR_IREN); - - nvt->tx.tx_state = ST_TX_REPLY; - - nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV_8 | - CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON); - - /* trigger TTR interrupt by writing out ones, (yes, it's ugly) */ - for (i = 0; i < 9; i++) - nvt_cir_reg_write(nvt, 0x01, CIR_STXFIFO); - - spin_unlock_irqrestore(&nvt->tx.lock, flags); - - wait_event(nvt->tx.queue, nvt->tx.tx_state == ST_TX_REQUEST); - - spin_lock_irqsave(&nvt->tx.lock, flags); - nvt->tx.tx_state = ST_TX_NONE; - spin_unlock_irqrestore(&nvt->tx.lock, flags); - - /* restore enabled interrupts to prior state */ - nvt_cir_reg_write(nvt, iren, CIR_IREN); - - return ret; -} - -/* dump contents of the last rx buffer we got from the hw rx fifo */ -static void nvt_dump_rx_buf(struct nvt_dev *nvt) -{ - int i; - - printk(KERN_DEBUG "%s (len %d): ", __func__, nvt->pkts); - for (i = 0; (i < nvt->pkts) && (i < RX_BUF_LEN); i++) - printk(KERN_CONT "0x%02x ", nvt->buf[i]); - printk(KERN_CONT "\n"); -} - -/* - * Process raw data in rx driver buffer, store it in raw IR event kfifo, - * trigger decode when appropriate. - * - * We get IR data samples one byte at a time. If the msb is set, its a pulse, - * otherwise its a space. The lower 7 bits are the count of SAMPLE_PERIOD - * (default 50us) intervals for that pulse/space. A discrete signal is - * followed by a series of 0x7f packets, then either 0x7 or 0x80 - * to signal more IR coming (repeats) or end of IR, respectively. We store - * sample data in the raw event kfifo until we see 0x7 (except f) - * or 0x80, at which time, we trigger a decode operation. - */ -static void nvt_process_rx_ir_data(struct nvt_dev *nvt) -{ - DEFINE_IR_RAW_EVENT(rawir); - unsigned int count; - u32 carrier; - u8 sample; - int i; - - nvt_dbg_verbose("%s firing", __func__); - - if (debug) - nvt_dump_rx_buf(nvt); - - if (nvt->carrier_detect_enabled) - carrier = nvt_rx_carrier_detect(nvt); - - count = nvt->pkts; - nvt_dbg_verbose("Processing buffer of len %d", count); - - init_ir_raw_event(&rawir); - - for (i = 0; i < count; i++) { - nvt->pkts--; - sample = nvt->buf[i]; - - rawir.pulse = ((sample & BUF_PULSE_BIT) != 0); - rawir.duration = (sample & BUF_LEN_MASK) - * SAMPLE_PERIOD * 1000; - - if ((sample & BUF_LEN_MASK) == BUF_LEN_MASK) { - if (nvt->rawir.pulse == rawir.pulse) - nvt->rawir.duration += rawir.duration; - else { - nvt->rawir.duration = rawir.duration; - nvt->rawir.pulse = rawir.pulse; - } - continue; - } - - rawir.duration += nvt->rawir.duration; - - init_ir_raw_event(&nvt->rawir); - nvt->rawir.duration = 0; - nvt->rawir.pulse = rawir.pulse; - - if (sample == BUF_PULSE_BIT) - rawir.pulse = false; - - if (rawir.duration) { - nvt_dbg("Storing %s with duration %d", - rawir.pulse ? "pulse" : "space", - rawir.duration); - - ir_raw_event_store(nvt->rdev, &rawir); - } - - /* - * BUF_PULSE_BIT indicates end of IR data, BUF_REPEAT_BYTE - * indicates end of IR signal, but new data incoming. In both - * cases, it means we're ready to call ir_raw_event_handle - */ - if ((sample == BUF_PULSE_BIT) && nvt->pkts) { - nvt_dbg("Calling ir_raw_event_handle (signal end)\n"); - ir_raw_event_handle(nvt->rdev); - } - } - - nvt_dbg("Calling ir_raw_event_handle (buffer empty)\n"); - ir_raw_event_handle(nvt->rdev); - - if (nvt->pkts) { - nvt_dbg("Odd, pkts should be 0 now... (its %u)", nvt->pkts); - nvt->pkts = 0; - } - - nvt_dbg_verbose("%s done", __func__); -} - -static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt) -{ - nvt_pr(KERN_WARNING, "RX FIFO overrun detected, flushing data!"); - - nvt->pkts = 0; - nvt_clear_cir_fifo(nvt); - ir_raw_event_reset(nvt->rdev); -} - -/* copy data from hardware rx fifo into driver buffer */ -static void nvt_get_rx_ir_data(struct nvt_dev *nvt) -{ - unsigned long flags; - u8 fifocount, val; - unsigned int b_idx; - bool overrun = false; - int i; - - /* Get count of how many bytes to read from RX FIFO */ - fifocount = nvt_cir_reg_read(nvt, CIR_RXFCONT); - /* if we get 0xff, probably means the logical dev is disabled */ - if (fifocount == 0xff) - return; - /* watch out for a fifo overrun condition */ - else if (fifocount > RX_BUF_LEN) { - overrun = true; - fifocount = RX_BUF_LEN; - } - - nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount); - - spin_lock_irqsave(&nvt->nvt_lock, flags); - - b_idx = nvt->pkts; - - /* This should never happen, but lets check anyway... */ - if (b_idx + fifocount > RX_BUF_LEN) { - nvt_process_rx_ir_data(nvt); - b_idx = 0; - } - - /* Read fifocount bytes from CIR Sample RX FIFO register */ - for (i = 0; i < fifocount; i++) { - val = nvt_cir_reg_read(nvt, CIR_SRXFIFO); - nvt->buf[b_idx + i] = val; - } - - nvt->pkts += fifocount; - nvt_dbg("%s: pkts now %d", __func__, nvt->pkts); - - nvt_process_rx_ir_data(nvt); - - if (overrun) - nvt_handle_rx_fifo_overrun(nvt); - - spin_unlock_irqrestore(&nvt->nvt_lock, flags); -} - -static void nvt_cir_log_irqs(u8 status, u8 iren) -{ - nvt_pr(KERN_INFO, "IRQ 0x%02x (IREN 0x%02x) :%s%s%s%s%s%s%s%s%s", - status, iren, - status & CIR_IRSTS_RDR ? " RDR" : "", - status & CIR_IRSTS_RTR ? " RTR" : "", - status & CIR_IRSTS_PE ? " PE" : "", - status & CIR_IRSTS_RFO ? " RFO" : "", - status & CIR_IRSTS_TE ? " TE" : "", - status & CIR_IRSTS_TTR ? " TTR" : "", - status & CIR_IRSTS_TFU ? " TFU" : "", - status & CIR_IRSTS_GH ? " GH" : "", - status & ~(CIR_IRSTS_RDR | CIR_IRSTS_RTR | CIR_IRSTS_PE | - CIR_IRSTS_RFO | CIR_IRSTS_TE | CIR_IRSTS_TTR | - CIR_IRSTS_TFU | CIR_IRSTS_GH) ? " ?" : ""); -} - -static bool nvt_cir_tx_inactive(struct nvt_dev *nvt) -{ - unsigned long flags; - bool tx_inactive; - u8 tx_state; - - spin_lock_irqsave(&nvt->tx.lock, flags); - tx_state = nvt->tx.tx_state; - spin_unlock_irqrestore(&nvt->tx.lock, flags); - - tx_inactive = (tx_state == ST_TX_NONE); - - return tx_inactive; -} - -/* interrupt service routine for incoming and outgoing CIR data */ -static irqreturn_t nvt_cir_isr(int irq, void *data) -{ - struct nvt_dev *nvt = data; - u8 status, iren, cur_state; - unsigned long flags; - - nvt_dbg_verbose("%s firing", __func__); - - nvt_efm_enable(nvt); - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_efm_disable(nvt); - - /* - * Get IR Status register contents. Write 1 to ack/clear - * - * bit: reg name - description - * 7: CIR_IRSTS_RDR - RX Data Ready - * 6: CIR_IRSTS_RTR - RX FIFO Trigger Level Reach - * 5: CIR_IRSTS_PE - Packet End - * 4: CIR_IRSTS_RFO - RX FIFO Overrun (RDR will also be set) - * 3: CIR_IRSTS_TE - TX FIFO Empty - * 2: CIR_IRSTS_TTR - TX FIFO Trigger Level Reach - * 1: CIR_IRSTS_TFU - TX FIFO Underrun - * 0: CIR_IRSTS_GH - Min Length Detected - */ - status = nvt_cir_reg_read(nvt, CIR_IRSTS); - if (!status) { - nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__); - nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); - return IRQ_RETVAL(IRQ_NONE); - } - - /* ack/clear all irq flags we've got */ - nvt_cir_reg_write(nvt, status, CIR_IRSTS); - nvt_cir_reg_write(nvt, 0, CIR_IRSTS); - - /* Interrupt may be shared with CIR Wake, bail if CIR not enabled */ - iren = nvt_cir_reg_read(nvt, CIR_IREN); - if (!iren) { - nvt_dbg_verbose("%s exiting, CIR not enabled", __func__); - return IRQ_RETVAL(IRQ_NONE); - } - - if (debug) - nvt_cir_log_irqs(status, iren); - - if (status & CIR_IRSTS_RTR) { - /* FIXME: add code for study/learn mode */ - /* We only do rx if not tx'ing */ - if (nvt_cir_tx_inactive(nvt)) - nvt_get_rx_ir_data(nvt); - } - - if (status & CIR_IRSTS_PE) { - if (nvt_cir_tx_inactive(nvt)) - nvt_get_rx_ir_data(nvt); - - spin_lock_irqsave(&nvt->nvt_lock, flags); - - cur_state = nvt->study_state; - - spin_unlock_irqrestore(&nvt->nvt_lock, flags); - - if (cur_state == ST_STUDY_NONE) - nvt_clear_cir_fifo(nvt); - } - - if (status & CIR_IRSTS_TE) - nvt_clear_tx_fifo(nvt); - - if (status & CIR_IRSTS_TTR) { - unsigned int pos, count; - u8 tmp; - - spin_lock_irqsave(&nvt->tx.lock, flags); - - pos = nvt->tx.cur_buf_num; - count = nvt->tx.buf_count; - - /* Write data into the hardware tx fifo while pos < count */ - if (pos < count) { - nvt_cir_reg_write(nvt, nvt->tx.buf[pos], CIR_STXFIFO); - nvt->tx.cur_buf_num++; - /* Disable TX FIFO Trigger Level Reach (TTR) interrupt */ - } else { - tmp = nvt_cir_reg_read(nvt, CIR_IREN); - nvt_cir_reg_write(nvt, tmp & ~CIR_IREN_TTR, CIR_IREN); - } - - spin_unlock_irqrestore(&nvt->tx.lock, flags); - - } - - if (status & CIR_IRSTS_TFU) { - spin_lock_irqsave(&nvt->tx.lock, flags); - if (nvt->tx.tx_state == ST_TX_REPLY) { - nvt->tx.tx_state = ST_TX_REQUEST; - wake_up(&nvt->tx.queue); - } - spin_unlock_irqrestore(&nvt->tx.lock, flags); - } - - nvt_dbg_verbose("%s done", __func__); - return IRQ_RETVAL(IRQ_HANDLED); -} - -/* Interrupt service routine for CIR Wake */ -static irqreturn_t nvt_cir_wake_isr(int irq, void *data) -{ - u8 status, iren, val; - struct nvt_dev *nvt = data; - unsigned long flags; - - nvt_dbg_wake("%s firing", __func__); - - status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS); - if (!status) - return IRQ_RETVAL(IRQ_NONE); - - if (status & CIR_WAKE_IRSTS_IR_PENDING) - nvt_clear_cir_wake_fifo(nvt); - - nvt_cir_wake_reg_write(nvt, status, CIR_WAKE_IRSTS); - nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IRSTS); - - /* Interrupt may be shared with CIR, bail if Wake not enabled */ - iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN); - if (!iren) { - nvt_dbg_wake("%s exiting, wake not enabled", __func__); - return IRQ_RETVAL(IRQ_HANDLED); - } - - if ((status & CIR_WAKE_IRSTS_PE) && - (nvt->wake_state == ST_WAKE_START)) { - while (nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)) { - val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY); - nvt_dbg("setting wake up key: 0x%x", val); - } - - nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN); - spin_lock_irqsave(&nvt->nvt_lock, flags); - nvt->wake_state = ST_WAKE_FINISH; - spin_unlock_irqrestore(&nvt->nvt_lock, flags); - } - - nvt_dbg_wake("%s done", __func__); - return IRQ_RETVAL(IRQ_HANDLED); -} - -static void nvt_enable_cir(struct nvt_dev *nvt) -{ - /* set function enable flags */ - nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN | - CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, - CIR_IRCON); - - nvt_efm_enable(nvt); - - /* enable the CIR logical device */ - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); - - nvt_efm_disable(nvt); - - /* clear all pending interrupts */ - nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); - - /* enable interrupts */ - nvt_set_cir_iren(nvt); -} - -static void nvt_disable_cir(struct nvt_dev *nvt) -{ - /* disable CIR interrupts */ - nvt_cir_reg_write(nvt, 0, CIR_IREN); - - /* clear any and all pending interrupts */ - nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); - - /* clear all function enable flags */ - nvt_cir_reg_write(nvt, 0, CIR_IRCON); - - /* clear hardware rx and tx fifos */ - nvt_clear_cir_fifo(nvt); - nvt_clear_tx_fifo(nvt); - - nvt_efm_enable(nvt); - - /* disable the CIR logical device */ - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); - - nvt_efm_disable(nvt); -} - -static int nvt_open(void *data) -{ - struct nvt_dev *nvt = (struct nvt_dev *)data; - unsigned long flags; - - spin_lock_irqsave(&nvt->nvt_lock, flags); - nvt->in_use = true; - nvt_enable_cir(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); - - return 0; -} - -static void nvt_close(void *data) -{ - struct nvt_dev *nvt = (struct nvt_dev *)data; - unsigned long flags; - - spin_lock_irqsave(&nvt->nvt_lock, flags); - nvt->in_use = false; - nvt_disable_cir(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); -} - -/* Allocate memory, probe hardware, and initialize everything */ -static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) -{ - struct nvt_dev *nvt = NULL; - struct input_dev *rdev = NULL; - struct ir_dev_props *props = NULL; - int ret = -ENOMEM; - - nvt = kzalloc(sizeof(struct nvt_dev), GFP_KERNEL); - if (!nvt) - return ret; - - props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); - if (!props) - goto failure; - - /* input device for IR remote (and tx) */ - rdev = input_allocate_device(); - if (!rdev) - goto failure; - - ret = -ENODEV; - /* validate pnp resources */ - if (!pnp_port_valid(pdev, 0) || - pnp_port_len(pdev, 0) < CIR_IOREG_LENGTH) { - dev_err(&pdev->dev, "IR PNP Port not valid!\n"); - goto failure; - } - - if (!pnp_irq_valid(pdev, 0)) { - dev_err(&pdev->dev, "PNP IRQ not valid!\n"); - goto failure; - } - - if (!pnp_port_valid(pdev, 1) || - pnp_port_len(pdev, 1) < CIR_IOREG_LENGTH) { - dev_err(&pdev->dev, "Wake PNP Port not valid!\n"); - goto failure; - } - - nvt->cir_addr = pnp_port_start(pdev, 0); - nvt->cir_irq = pnp_irq(pdev, 0); - - nvt->cir_wake_addr = pnp_port_start(pdev, 1); - /* irq is always shared between cir and cir wake */ - nvt->cir_wake_irq = nvt->cir_irq; - - nvt->cr_efir = CR_EFIR; - nvt->cr_efdr = CR_EFDR; - - spin_lock_init(&nvt->nvt_lock); - spin_lock_init(&nvt->tx.lock); - init_ir_raw_event(&nvt->rawir); - - ret = -EBUSY; - /* now claim resources */ - if (!request_region(nvt->cir_addr, - CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) - goto failure; - - if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED, - NVT_DRIVER_NAME, (void *)nvt)) - goto failure; - - if (!request_region(nvt->cir_wake_addr, - CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) - goto failure; - - if (request_irq(nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED, - NVT_DRIVER_NAME, (void *)nvt)) - goto failure; - - pnp_set_drvdata(pdev, nvt); - nvt->pdev = pdev; - - init_waitqueue_head(&nvt->tx.queue); - - ret = nvt_hw_detect(nvt); - if (ret) - goto failure; - - /* Initialize CIR & CIR Wake Logical Devices */ - nvt_efm_enable(nvt); - nvt_cir_ldev_init(nvt); - nvt_cir_wake_ldev_init(nvt); - nvt_efm_disable(nvt); - - /* Initialize CIR & CIR Wake Config Registers */ - nvt_cir_regs_init(nvt); - nvt_cir_wake_regs_init(nvt); - - /* Set up ir-core props */ - props->priv = nvt; - props->driver_type = RC_DRIVER_IR_RAW; - props->allowed_protos = IR_TYPE_ALL; - props->open = nvt_open; - props->close = nvt_close; -#if 0 - props->min_timeout = XYZ; - props->max_timeout = XYZ; - props->timeout = XYZ; - /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ - props->rx_resolution = XYZ; - - /* tx bits */ - props->tx_resolution = XYZ; -#endif - props->tx_ir = nvt_tx_ir; - props->s_tx_carrier = nvt_set_tx_carrier; - - rdev->name = "Nuvoton w836x7hg Infrared Remote Transceiver"; - rdev->id.bustype = BUS_HOST; - rdev->id.vendor = PCI_VENDOR_ID_WINBOND2; - rdev->id.product = nvt->chip_major; - rdev->id.version = nvt->chip_minor; - - nvt->props = props; - nvt->rdev = rdev; - - device_set_wakeup_capable(&pdev->dev, 1); - device_set_wakeup_enable(&pdev->dev, 1); - - ret = ir_input_register(rdev, RC_MAP_RC6_MCE, props, NVT_DRIVER_NAME); - if (ret) - goto failure; - - nvt_pr(KERN_NOTICE, "driver has been successfully loaded\n"); - if (debug) { - cir_dump_regs(nvt); - cir_wake_dump_regs(nvt); - } - - return 0; - -failure: - if (nvt->cir_irq) - free_irq(nvt->cir_irq, nvt); - if (nvt->cir_addr) - release_region(nvt->cir_addr, CIR_IOREG_LENGTH); - - if (nvt->cir_wake_irq) - free_irq(nvt->cir_wake_irq, nvt); - if (nvt->cir_wake_addr) - release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH); - - input_free_device(rdev); - kfree(props); - kfree(nvt); - - return ret; -} - -static void __devexit nvt_remove(struct pnp_dev *pdev) -{ - struct nvt_dev *nvt = pnp_get_drvdata(pdev); - unsigned long flags; - - spin_lock_irqsave(&nvt->nvt_lock, flags); - /* disable CIR */ - nvt_cir_reg_write(nvt, 0, CIR_IREN); - nvt_disable_cir(nvt); - /* enable CIR Wake (for IR power-on) */ - nvt_enable_wake(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); - - /* free resources */ - free_irq(nvt->cir_irq, nvt); - free_irq(nvt->cir_wake_irq, nvt); - release_region(nvt->cir_addr, CIR_IOREG_LENGTH); - release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH); - - ir_input_unregister(nvt->rdev); - - kfree(nvt->props); - kfree(nvt); -} - -static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) -{ - struct nvt_dev *nvt = pnp_get_drvdata(pdev); - unsigned long flags; - - nvt_dbg("%s called", __func__); - - /* zero out misc state tracking */ - spin_lock_irqsave(&nvt->nvt_lock, flags); - nvt->study_state = ST_STUDY_NONE; - nvt->wake_state = ST_WAKE_NONE; - spin_unlock_irqrestore(&nvt->nvt_lock, flags); - - spin_lock_irqsave(&nvt->tx.lock, flags); - nvt->tx.tx_state = ST_TX_NONE; - spin_unlock_irqrestore(&nvt->tx.lock, flags); - - /* disable all CIR interrupts */ - nvt_cir_reg_write(nvt, 0, CIR_IREN); - - nvt_efm_enable(nvt); - - /* disable cir logical dev */ - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); - - nvt_efm_disable(nvt); - - /* make sure wake is enabled */ - nvt_enable_wake(nvt); - - return 0; -} - -static int nvt_resume(struct pnp_dev *pdev) -{ - int ret = 0; - struct nvt_dev *nvt = pnp_get_drvdata(pdev); - - nvt_dbg("%s called", __func__); - - /* open interrupt */ - nvt_set_cir_iren(nvt); - - /* Enable CIR logical device */ - nvt_efm_enable(nvt); - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); - - nvt_efm_disable(nvt); - - nvt_cir_regs_init(nvt); - nvt_cir_wake_regs_init(nvt); - - return ret; -} - -static void nvt_shutdown(struct pnp_dev *pdev) -{ - struct nvt_dev *nvt = pnp_get_drvdata(pdev); - nvt_enable_wake(nvt); -} - -static const struct pnp_device_id nvt_ids[] = { - { "WEC0530", 0 }, /* CIR */ - { "NTN0530", 0 }, /* CIR for new chip's pnp id*/ - { "", 0 }, -}; - -static struct pnp_driver nvt_driver = { - .name = NVT_DRIVER_NAME, - .id_table = nvt_ids, - .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, - .probe = nvt_probe, - .remove = __devexit_p(nvt_remove), - .suspend = nvt_suspend, - .resume = nvt_resume, - .shutdown = nvt_shutdown, -}; - -int nvt_init(void) -{ - return pnp_register_driver(&nvt_driver); -} - -void nvt_exit(void) -{ - pnp_unregister_driver(&nvt_driver); -} - -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging output"); - -MODULE_DEVICE_TABLE(pnp, nvt_ids); -MODULE_DESCRIPTION("Nuvoton W83667HG-A & W83677HG-I CIR driver"); - -MODULE_AUTHOR("Jarod Wilson "); -MODULE_LICENSE("GPL"); - -module_init(nvt_init); -module_exit(nvt_exit); diff --git a/drivers/media/IR/nuvoton-cir.h b/drivers/media/IR/nuvoton-cir.h deleted file mode 100644 index 62dc530..0000000 --- a/drivers/media/IR/nuvoton-cir.h +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR - * - * Copyright (C) 2010 Jarod Wilson - * Copyright (C) 2009 Nuvoton PS Team - * - * Special thanks to Nuvoton for providing hardware, spec sheets and - * sample code upon which portions of this driver are based. Indirect - * thanks also to Maxim Levitsky, whose ene_ir driver this driver is - * modeled after. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#include -#include - -/* platform driver name to register */ -#define NVT_DRIVER_NAME "nuvoton-cir" - -/* debugging module parameter */ -static int debug; - - -#define nvt_pr(level, text, ...) \ - printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__) - -#define nvt_dbg(text, ...) \ - if (debug) \ - printk(KERN_DEBUG \ - KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) - -#define nvt_dbg_verbose(text, ...) \ - if (debug > 1) \ - printk(KERN_DEBUG \ - KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) - -#define nvt_dbg_wake(text, ...) \ - if (debug > 2) \ - printk(KERN_DEBUG \ - KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) - - -/* - * Original lirc driver said min value of 76, and recommended value of 256 - * for the buffer length, but then used 2048. Never mind that the size of the - * RX FIFO is 32 bytes... So I'm using 32 for RX and 256 for TX atm, but I'm - * not sure if maybe that TX value is off by a factor of 8 (bits vs. bytes), - * and I don't have TX-capable hardware to test/debug on... - */ -#define TX_BUF_LEN 256 -#define RX_BUF_LEN 32 - -struct nvt_dev { - struct pnp_dev *pdev; - struct input_dev *rdev; - struct ir_dev_props *props; - struct ir_raw_event rawir; - - spinlock_t nvt_lock; - bool in_use; - - /* for rx */ - u8 buf[RX_BUF_LEN]; - unsigned int pkts; - - struct { - spinlock_t lock; - u8 buf[TX_BUF_LEN]; - unsigned int buf_count; - unsigned int cur_buf_num; - wait_queue_head_t queue; - u8 tx_state; - } tx; - - /* EFER Config register index/data pair */ - u8 cr_efir; - u8 cr_efdr; - - /* hardware I/O settings */ - unsigned long cir_addr; - unsigned long cir_wake_addr; - int cir_irq; - int cir_wake_irq; - - /* hardware id */ - u8 chip_major; - u8 chip_minor; - - /* hardware features */ - bool hw_learning_capable; - bool hw_tx_capable; - - /* rx settings */ - bool learning_enabled; - bool carrier_detect_enabled; - - /* track cir wake state */ - u8 wake_state; - /* for study */ - u8 study_state; - /* carrier period = 1 / frequency */ - u32 carrier; -}; - -/* study states */ -#define ST_STUDY_NONE 0x0 -#define ST_STUDY_START 0x1 -#define ST_STUDY_CARRIER 0x2 -#define ST_STUDY_ALL_RECV 0x4 - -/* wake states */ -#define ST_WAKE_NONE 0x0 -#define ST_WAKE_START 0x1 -#define ST_WAKE_FINISH 0x2 - -/* receive states */ -#define ST_RX_WAIT_7F 0x1 -#define ST_RX_WAIT_HEAD 0x2 -#define ST_RX_WAIT_SILENT_END 0x4 - -/* send states */ -#define ST_TX_NONE 0x0 -#define ST_TX_REQUEST 0x2 -#define ST_TX_REPLY 0x4 - -/* buffer packet constants */ -#define BUF_PULSE_BIT 0x80 -#define BUF_LEN_MASK 0x7f -#define BUF_REPEAT_BYTE 0x70 -#define BUF_REPEAT_MASK 0xf0 - -/* CIR settings */ - -/* total length of CIR and CIR WAKE */ -#define CIR_IOREG_LENGTH 0x0f - -/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL (0x7d0 = 2000) */ -#define CIR_RX_LIMIT_COUNT 0x7d0 - -/* CIR Regs */ -#define CIR_IRCON 0x00 -#define CIR_IRSTS 0x01 -#define CIR_IREN 0x02 -#define CIR_RXFCONT 0x03 -#define CIR_CP 0x04 -#define CIR_CC 0x05 -#define CIR_SLCH 0x06 -#define CIR_SLCL 0x07 -#define CIR_FIFOCON 0x08 -#define CIR_IRFIFOSTS 0x09 -#define CIR_SRXFIFO 0x0a -#define CIR_TXFCONT 0x0b -#define CIR_STXFIFO 0x0c -#define CIR_FCCH 0x0d -#define CIR_FCCL 0x0e -#define CIR_IRFSM 0x0f - -/* CIR IRCON settings */ -#define CIR_IRCON_RECV 0x80 -#define CIR_IRCON_WIREN 0x40 -#define CIR_IRCON_TXEN 0x20 -#define CIR_IRCON_RXEN 0x10 -#define CIR_IRCON_WRXINV 0x08 -#define CIR_IRCON_RXINV 0x04 - -#define CIR_IRCON_SAMPLE_PERIOD_SEL_1 0x00 -#define CIR_IRCON_SAMPLE_PERIOD_SEL_25 0x01 -#define CIR_IRCON_SAMPLE_PERIOD_SEL_50 0x02 -#define CIR_IRCON_SAMPLE_PERIOD_SEL_100 0x03 - -/* FIXME: make this a runtime option */ -/* select sample period as 50us */ -#define CIR_IRCON_SAMPLE_PERIOD_SEL CIR_IRCON_SAMPLE_PERIOD_SEL_50 - -/* CIR IRSTS settings */ -#define CIR_IRSTS_RDR 0x80 -#define CIR_IRSTS_RTR 0x40 -#define CIR_IRSTS_PE 0x20 -#define CIR_IRSTS_RFO 0x10 -#define CIR_IRSTS_TE 0x08 -#define CIR_IRSTS_TTR 0x04 -#define CIR_IRSTS_TFU 0x02 -#define CIR_IRSTS_GH 0x01 - -/* CIR IREN settings */ -#define CIR_IREN_RDR 0x80 -#define CIR_IREN_RTR 0x40 -#define CIR_IREN_PE 0x20 -#define CIR_IREN_RFO 0x10 -#define CIR_IREN_TE 0x08 -#define CIR_IREN_TTR 0x04 -#define CIR_IREN_TFU 0x02 -#define CIR_IREN_GH 0x01 - -/* CIR FIFOCON settings */ -#define CIR_FIFOCON_TXFIFOCLR 0x80 - -#define CIR_FIFOCON_TX_TRIGGER_LEV_31 0x00 -#define CIR_FIFOCON_TX_TRIGGER_LEV_24 0x10 -#define CIR_FIFOCON_TX_TRIGGER_LEV_16 0x20 -#define CIR_FIFOCON_TX_TRIGGER_LEV_8 0x30 - -/* FIXME: make this a runtime option */ -/* select TX trigger level as 16 */ -#define CIR_FIFOCON_TX_TRIGGER_LEV CIR_FIFOCON_TX_TRIGGER_LEV_16 - -#define CIR_FIFOCON_RXFIFOCLR 0x08 - -#define CIR_FIFOCON_RX_TRIGGER_LEV_1 0x00 -#define CIR_FIFOCON_RX_TRIGGER_LEV_8 0x01 -#define CIR_FIFOCON_RX_TRIGGER_LEV_16 0x02 -#define CIR_FIFOCON_RX_TRIGGER_LEV_24 0x03 - -/* FIXME: make this a runtime option */ -/* select RX trigger level as 24 */ -#define CIR_FIFOCON_RX_TRIGGER_LEV CIR_FIFOCON_RX_TRIGGER_LEV_24 - -/* CIR IRFIFOSTS settings */ -#define CIR_IRFIFOSTS_IR_PENDING 0x80 -#define CIR_IRFIFOSTS_RX_GS 0x40 -#define CIR_IRFIFOSTS_RX_FTA 0x20 -#define CIR_IRFIFOSTS_RX_EMPTY 0x10 -#define CIR_IRFIFOSTS_RX_FULL 0x08 -#define CIR_IRFIFOSTS_TX_FTA 0x04 -#define CIR_IRFIFOSTS_TX_EMPTY 0x02 -#define CIR_IRFIFOSTS_TX_FULL 0x01 - - -/* CIR WAKE UP Regs */ -#define CIR_WAKE_IRCON 0x00 -#define CIR_WAKE_IRSTS 0x01 -#define CIR_WAKE_IREN 0x02 -#define CIR_WAKE_FIFO_CMP_DEEP 0x03 -#define CIR_WAKE_FIFO_CMP_TOL 0x04 -#define CIR_WAKE_FIFO_COUNT 0x05 -#define CIR_WAKE_SLCH 0x06 -#define CIR_WAKE_SLCL 0x07 -#define CIR_WAKE_FIFOCON 0x08 -#define CIR_WAKE_SRXFSTS 0x09 -#define CIR_WAKE_SAMPLE_RX_FIFO 0x0a -#define CIR_WAKE_WR_FIFO_DATA 0x0b -#define CIR_WAKE_RD_FIFO_ONLY 0x0c -#define CIR_WAKE_RD_FIFO_ONLY_IDX 0x0d -#define CIR_WAKE_FIFO_IGNORE 0x0e -#define CIR_WAKE_IRFSM 0x0f - -/* CIR WAKE UP IRCON settings */ -#define CIR_WAKE_IRCON_DEC_RST 0x80 -#define CIR_WAKE_IRCON_MODE1 0x40 -#define CIR_WAKE_IRCON_MODE0 0x20 -#define CIR_WAKE_IRCON_RXEN 0x10 -#define CIR_WAKE_IRCON_R 0x08 -#define CIR_WAKE_IRCON_RXINV 0x04 - -/* FIXME/jarod: make this a runtime option */ -/* select a same sample period like cir register */ -#define CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL CIR_IRCON_SAMPLE_PERIOD_SEL_50 - -/* CIR WAKE IRSTS Bits */ -#define CIR_WAKE_IRSTS_RDR 0x80 -#define CIR_WAKE_IRSTS_RTR 0x40 -#define CIR_WAKE_IRSTS_PE 0x20 -#define CIR_WAKE_IRSTS_RFO 0x10 -#define CIR_WAKE_IRSTS_GH 0x08 -#define CIR_WAKE_IRSTS_IR_PENDING 0x01 - -/* CIR WAKE UP IREN Bits */ -#define CIR_WAKE_IREN_RDR 0x80 -#define CIR_WAKE_IREN_RTR 0x40 -#define CIR_WAKE_IREN_PE 0x20 -#define CIR_WAKE_IREN_RFO 0x10 -#define CIR_WAKE_IREN_TE 0x08 -#define CIR_WAKE_IREN_TTR 0x04 -#define CIR_WAKE_IREN_TFU 0x02 -#define CIR_WAKE_IREN_GH 0x01 - -/* CIR WAKE FIFOCON settings */ -#define CIR_WAKE_FIFOCON_RXFIFOCLR 0x08 - -#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67 0x00 -#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_66 0x01 -#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_65 0x02 -#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_64 0x03 - -/* FIXME: make this a runtime option */ -/* select WAKE UP RX trigger level as 67 */ -#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67 - -/* CIR WAKE SRXFSTS settings */ -#define CIR_WAKE_IRFIFOSTS_RX_GS 0x80 -#define CIR_WAKE_IRFIFOSTS_RX_FTA 0x40 -#define CIR_WAKE_IRFIFOSTS_RX_EMPTY 0x20 -#define CIR_WAKE_IRFIFOSTS_RX_FULL 0x10 - -/* CIR Wake FIFO buffer is 67 bytes long */ -#define CIR_WAKE_FIFO_LEN 67 -/* CIR Wake byte comparison tolerance */ -#define CIR_WAKE_CMP_TOLERANCE 5 - -/* - * Extended Function Enable Registers: - * Extended Function Index Register - * Extended Function Data Register - */ -#define CR_EFIR 0x2e -#define CR_EFDR 0x2f - -/* Possible alternate EFER values, depends on how the chip is wired */ -#define CR_EFIR2 0x4e -#define CR_EFDR2 0x4f - -/* Extended Function Mode enable/disable magic values */ -#define EFER_EFM_ENABLE 0x87 -#define EFER_EFM_DISABLE 0xaa - -/* Chip IDs found in CR_CHIP_ID_{HI,LO} */ -#define CHIP_ID_HIGH 0xb4 -#define CHIP_ID_LOW 0x72 -#define CHIP_ID_LOW2 0x73 - -/* Config regs we need to care about */ -#define CR_SOFTWARE_RESET 0x02 -#define CR_LOGICAL_DEV_SEL 0x07 -#define CR_CHIP_ID_HI 0x20 -#define CR_CHIP_ID_LO 0x21 -#define CR_DEV_POWER_DOWN 0x22 /* bit 2 is CIR power, default power on */ -#define CR_OUTPUT_PIN_SEL 0x27 -#define CR_LOGICAL_DEV_EN 0x30 /* valid for all logical devices */ -/* next three regs valid for both the CIR and CIR_WAKE logical devices */ -#define CR_CIR_BASE_ADDR_HI 0x60 -#define CR_CIR_BASE_ADDR_LO 0x61 -#define CR_CIR_IRQ_RSRC 0x70 -/* next three regs valid only for ACPI logical dev */ -#define CR_ACPI_CIR_WAKE 0xe0 -#define CR_ACPI_IRQ_EVENTS 0xf6 -#define CR_ACPI_IRQ_EVENTS2 0xf7 - -/* Logical devices that we need to care about */ -#define LOGICAL_DEV_LPT 0x01 -#define LOGICAL_DEV_CIR 0x06 -#define LOGICAL_DEV_ACPI 0x0a -#define LOGICAL_DEV_CIR_WAKE 0x0e - -#define LOGICAL_DEV_DISABLE 0x00 -#define LOGICAL_DEV_ENABLE 0x01 - -#define CIR_WAKE_ENABLE_BIT 0x08 -#define CIR_INTR_MOUSE_IRQ_BIT 0x80 -#define PME_INTR_CIR_PASS_BIT 0x08 - -#define OUTPUT_PIN_SEL_MASK 0xbc -#define OUTPUT_ENABLE_CIR 0x01 /* Pin95=CIRRX, Pin96=CIRTX1 */ -#define OUTPUT_ENABLE_CIRWB 0x40 /* enable wide-band sensor */ - -/* MCE CIR signal length, related on sample period */ - -/* MCE CIR controller signal length: about 43ms - * 43ms / 50us (sample period) * 0.85 (inaccuracy) - */ -#define CONTROLLER_BUF_LEN_MIN 830 - -/* MCE CIR keyboard signal length: about 26ms - * 26ms / 50us (sample period) * 0.85 (inaccuracy) - */ -#define KEYBOARD_BUF_LEN_MAX 650 -#define KEYBOARD_BUF_LEN_MIN 610 - -/* MCE CIR mouse signal length: about 24ms - * 24ms / 50us (sample period) * 0.85 (inaccuracy) - */ -#define MOUSE_BUF_LEN_MIN 565 - -#define CIR_SAMPLE_PERIOD 50 -#define CIR_SAMPLE_LOW_INACCURACY 0.85 - -/* MAX silence time that driver will sent to lirc */ -#define MAX_SILENCE_TIME 60000 - -#if CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_100 -#define SAMPLE_PERIOD 100 - -#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_50 -#define SAMPLE_PERIOD 50 - -#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_25 -#define SAMPLE_PERIOD 25 - -#else -#define SAMPLE_PERIOD 1 -#endif - -/* as VISTA MCE definition, valid carrier value */ -#define MAX_CARRIER 60000 -#define MIN_CARRIER 30000 diff --git a/drivers/media/IR/rc-map.c b/drivers/media/IR/rc-map.c deleted file mode 100644 index 689143f..0000000 --- a/drivers/media/IR/rc-map.c +++ /dev/null @@ -1,107 +0,0 @@ -/* ir-raw-event.c - handle IR Pulse/Space event - * - * Copyright (C) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include - -/* Used to handle IR raw handler extensions */ -static LIST_HEAD(rc_map_list); -static DEFINE_SPINLOCK(rc_map_lock); - -static struct rc_keymap *seek_rc_map(const char *name) -{ - struct rc_keymap *map = NULL; - - spin_lock(&rc_map_lock); - list_for_each_entry(map, &rc_map_list, list) { - if (!strcmp(name, map->map.name)) { - spin_unlock(&rc_map_lock); - return map; - } - } - spin_unlock(&rc_map_lock); - - return NULL; -} - -struct ir_scancode_table *get_rc_map(const char *name) -{ - - struct rc_keymap *map; - - map = seek_rc_map(name); -#ifdef MODULE - if (!map) { - int rc = request_module(name); - if (rc < 0) { - printk(KERN_ERR "Couldn't load IR keymap %s\n", name); - return NULL; - } - msleep(20); /* Give some time for IR to register */ - - map = seek_rc_map(name); - } -#endif - if (!map) { - printk(KERN_ERR "IR keymap %s not found\n", name); - return NULL; - } - - printk(KERN_INFO "Registered IR keymap %s\n", map->map.name); - - return &map->map; -} -EXPORT_SYMBOL_GPL(get_rc_map); - -int ir_register_map(struct rc_keymap *map) -{ - spin_lock(&rc_map_lock); - list_add_tail(&map->list, &rc_map_list); - spin_unlock(&rc_map_lock); - return 0; -} -EXPORT_SYMBOL_GPL(ir_register_map); - -void ir_unregister_map(struct rc_keymap *map) -{ - spin_lock(&rc_map_lock); - list_del(&map->list); - spin_unlock(&rc_map_lock); -} -EXPORT_SYMBOL_GPL(ir_unregister_map); - - -static struct ir_scancode empty[] = { - { 0x2a, KEY_COFFEE }, -}; - -static struct rc_keymap empty_map = { - .map = { - .scan = empty, - .size = ARRAY_SIZE(empty), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_EMPTY, - } -}; - -int ir_rcmap_init(void) -{ - return ir_register_map(&empty_map); -} - -void ir_rcmap_cleanup(void) -{ - ir_unregister_map(&empty_map); -} diff --git a/drivers/media/IR/streamzap.c b/drivers/media/IR/streamzap.c deleted file mode 100644 index 3a20aef..0000000 --- a/drivers/media/IR/streamzap.c +++ /dev/null @@ -1,572 +0,0 @@ -/* - * Streamzap Remote Control driver - * - * Copyright (c) 2005 Christoph Bartelmus - * Copyright (c) 2010 Jarod Wilson - * - * This driver was based on the work of Greg Wickham and Adrian - * Dewhurst. It was substantially rewritten to support correct signal - * gaps and now maintains a delay buffer, which is used to present - * consistent timing behaviour to user space applications. Without the - * delay buffer an ugly hack would be required in lircd, which can - * cause sluggish signal decoding in certain situations. - * - * Ported to in-kernel ir-core interface by Jarod Wilson - * - * This driver is based on the USB skeleton driver packaged with the - * kernel; copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_VERSION "1.61" -#define DRIVER_NAME "streamzap" -#define DRIVER_DESC "Streamzap Remote Control driver" - -#ifdef CONFIG_USB_DEBUG -static int debug = 1; -#else -static int debug; -#endif - -#define USB_STREAMZAP_VENDOR_ID 0x0e9c -#define USB_STREAMZAP_PRODUCT_ID 0x0000 - -/* table of devices that work with this driver */ -static struct usb_device_id streamzap_table[] = { - /* Streamzap Remote Control */ - { USB_DEVICE(USB_STREAMZAP_VENDOR_ID, USB_STREAMZAP_PRODUCT_ID) }, - /* Terminating entry */ - { } -}; - -MODULE_DEVICE_TABLE(usb, streamzap_table); - -#define SZ_PULSE_MASK 0xf0 -#define SZ_SPACE_MASK 0x0f -#define SZ_TIMEOUT 0xff -#define SZ_RESOLUTION 256 - -/* number of samples buffered */ -#define SZ_BUF_LEN 128 - -/* from ir-rc5-sz-decoder.c */ -#ifdef CONFIG_IR_RC5_SZ_DECODER_MODULE -#define load_rc5_sz_decode() request_module("ir-rc5-sz-decoder") -#else -#define load_rc5_sz_decode() 0 -#endif - -enum StreamzapDecoderState { - PulseSpace, - FullPulse, - FullSpace, - IgnorePulse -}; - -/* structure to hold our device specific stuff */ -struct streamzap_ir { - - /* ir-core */ - struct ir_dev_props *props; - - /* core device info */ - struct device *dev; - struct input_dev *idev; - - /* usb */ - struct usb_device *usbdev; - struct usb_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct urb *urb_in; - - /* buffer & dma */ - unsigned char *buf_in; - dma_addr_t dma_in; - unsigned int buf_in_len; - - /* track what state we're in */ - enum StreamzapDecoderState decoder_state; - /* tracks whether we are currently receiving some signal */ - bool idle; - /* sum of signal lengths received since signal start */ - unsigned long sum; - /* start time of signal; necessary for gap tracking */ - struct timeval signal_last; - struct timeval signal_start; - bool timeout_enabled; - - char name[128]; - char phys[64]; -}; - - -/* local function prototypes */ -static int streamzap_probe(struct usb_interface *interface, - const struct usb_device_id *id); -static void streamzap_disconnect(struct usb_interface *interface); -static void streamzap_callback(struct urb *urb); -static int streamzap_suspend(struct usb_interface *intf, pm_message_t message); -static int streamzap_resume(struct usb_interface *intf); - -/* usb specific object needed to register this driver with the usb subsystem */ -static struct usb_driver streamzap_driver = { - .name = DRIVER_NAME, - .probe = streamzap_probe, - .disconnect = streamzap_disconnect, - .suspend = streamzap_suspend, - .resume = streamzap_resume, - .id_table = streamzap_table, -}; - -static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir) -{ - dev_dbg(sz->dev, "Storing %s with duration %u us\n", - (rawir.pulse ? "pulse" : "space"), rawir.duration); - ir_raw_event_store_with_filter(sz->idev, &rawir); -} - -static void sz_push_full_pulse(struct streamzap_ir *sz, - unsigned char value) -{ - DEFINE_IR_RAW_EVENT(rawir); - - if (sz->idle) { - long deltv; - - sz->signal_last = sz->signal_start; - do_gettimeofday(&sz->signal_start); - - deltv = sz->signal_start.tv_sec - sz->signal_last.tv_sec; - rawir.pulse = false; - if (deltv > 15) { - /* really long time */ - rawir.duration = IR_MAX_DURATION; - } else { - rawir.duration = (int)(deltv * 1000000 + - sz->signal_start.tv_usec - - sz->signal_last.tv_usec); - rawir.duration -= sz->sum; - rawir.duration *= 1000; - rawir.duration &= IR_MAX_DURATION; - } - sz_push(sz, rawir); - - sz->idle = false; - sz->sum = 0; - } - - rawir.pulse = true; - rawir.duration = ((int) value) * SZ_RESOLUTION; - rawir.duration += SZ_RESOLUTION / 2; - sz->sum += rawir.duration; - rawir.duration *= 1000; - rawir.duration &= IR_MAX_DURATION; - sz_push(sz, rawir); -} - -static void sz_push_half_pulse(struct streamzap_ir *sz, - unsigned char value) -{ - sz_push_full_pulse(sz, (value & SZ_PULSE_MASK) >> 4); -} - -static void sz_push_full_space(struct streamzap_ir *sz, - unsigned char value) -{ - DEFINE_IR_RAW_EVENT(rawir); - - rawir.pulse = false; - rawir.duration = ((int) value) * SZ_RESOLUTION; - rawir.duration += SZ_RESOLUTION / 2; - sz->sum += rawir.duration; - rawir.duration *= 1000; - sz_push(sz, rawir); -} - -static void sz_push_half_space(struct streamzap_ir *sz, - unsigned long value) -{ - sz_push_full_space(sz, value & SZ_SPACE_MASK); -} - -/** - * streamzap_callback - usb IRQ handler callback - * - * This procedure is invoked on reception of data from - * the usb remote. - */ -static void streamzap_callback(struct urb *urb) -{ - struct streamzap_ir *sz; - unsigned int i; - int len; - - if (!urb) - return; - - sz = urb->context; - len = urb->actual_length; - - switch (urb->status) { - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* - * this urb is terminated, clean up. - * sz might already be invalid at this point - */ - dev_err(sz->dev, "urb terminated, status: %d\n", urb->status); - return; - default: - break; - } - - dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len); - for (i = 0; i < len; i++) { - dev_dbg(sz->dev, "sz->buf_in[%d]: %x\n", - i, (unsigned char)sz->buf_in[i]); - switch (sz->decoder_state) { - case PulseSpace: - if ((sz->buf_in[i] & SZ_PULSE_MASK) == - SZ_PULSE_MASK) { - sz->decoder_state = FullPulse; - continue; - } else if ((sz->buf_in[i] & SZ_SPACE_MASK) - == SZ_SPACE_MASK) { - sz_push_half_pulse(sz, sz->buf_in[i]); - sz->decoder_state = FullSpace; - continue; - } else { - sz_push_half_pulse(sz, sz->buf_in[i]); - sz_push_half_space(sz, sz->buf_in[i]); - } - break; - case FullPulse: - sz_push_full_pulse(sz, sz->buf_in[i]); - sz->decoder_state = IgnorePulse; - break; - case FullSpace: - if (sz->buf_in[i] == SZ_TIMEOUT) { - DEFINE_IR_RAW_EVENT(rawir); - - rawir.pulse = false; - rawir.duration = sz->props->timeout; - sz->idle = true; - if (sz->timeout_enabled) - sz_push(sz, rawir); - ir_raw_event_handle(sz->idev); - } else { - sz_push_full_space(sz, sz->buf_in[i]); - } - sz->decoder_state = PulseSpace; - break; - case IgnorePulse: - if ((sz->buf_in[i] & SZ_SPACE_MASK) == - SZ_SPACE_MASK) { - sz->decoder_state = FullSpace; - continue; - } - sz_push_half_space(sz, sz->buf_in[i]); - sz->decoder_state = PulseSpace; - break; - } - } - - usb_submit_urb(urb, GFP_ATOMIC); - - return; -} - -static struct input_dev *streamzap_init_input_dev(struct streamzap_ir *sz) -{ - struct input_dev *idev; - struct ir_dev_props *props; - struct device *dev = sz->dev; - int ret; - - idev = input_allocate_device(); - if (!idev) { - dev_err(dev, "remote input dev allocation failed\n"); - goto idev_alloc_failed; - } - - props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); - if (!props) { - dev_err(dev, "remote ir dev props allocation failed\n"); - goto props_alloc_failed; - } - - snprintf(sz->name, sizeof(sz->name), "Streamzap PC Remote Infrared " - "Receiver (%04x:%04x)", - le16_to_cpu(sz->usbdev->descriptor.idVendor), - le16_to_cpu(sz->usbdev->descriptor.idProduct)); - - idev->name = sz->name; - usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys)); - strlcat(sz->phys, "/input0", sizeof(sz->phys)); - idev->phys = sz->phys; - - props->priv = sz; - props->driver_type = RC_DRIVER_IR_RAW; - props->allowed_protos = IR_TYPE_ALL; - - sz->props = props; - - usb_to_input_id(sz->usbdev, &idev->id); - idev->dev.parent = sz->dev; - - ret = ir_input_register(idev, RC_MAP_STREAMZAP, props, DRIVER_NAME); - if (ret < 0) { - dev_err(dev, "remote input device register failed\n"); - goto irdev_failed; - } - - return idev; - -irdev_failed: - kfree(props); -props_alloc_failed: - input_free_device(idev); -idev_alloc_failed: - return NULL; -} - -/** - * streamzap_probe - * - * Called by usb-core to associated with a candidate device - * On any failure the return value is the ERROR - * On success return 0 - */ -static int __devinit streamzap_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *usbdev = interface_to_usbdev(intf); - struct usb_host_interface *iface_host; - struct streamzap_ir *sz = NULL; - char buf[63], name[128] = ""; - int retval = -ENOMEM; - int pipe, maxp; - - /* Allocate space for device driver specific data */ - sz = kzalloc(sizeof(struct streamzap_ir), GFP_KERNEL); - if (!sz) - return -ENOMEM; - - sz->usbdev = usbdev; - sz->interface = intf; - - /* Check to ensure endpoint information matches requirements */ - iface_host = intf->cur_altsetting; - - if (iface_host->desc.bNumEndpoints != 1) { - dev_err(&intf->dev, "%s: Unexpected desc.bNumEndpoints (%d)\n", - __func__, iface_host->desc.bNumEndpoints); - retval = -ENODEV; - goto free_sz; - } - - sz->endpoint = &(iface_host->endpoint[0].desc); - if ((sz->endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) - != USB_DIR_IN) { - dev_err(&intf->dev, "%s: endpoint doesn't match input device " - "02%02x\n", __func__, sz->endpoint->bEndpointAddress); - retval = -ENODEV; - goto free_sz; - } - - if ((sz->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - != USB_ENDPOINT_XFER_INT) { - dev_err(&intf->dev, "%s: endpoint attributes don't match xfer " - "02%02x\n", __func__, sz->endpoint->bmAttributes); - retval = -ENODEV; - goto free_sz; - } - - pipe = usb_rcvintpipe(usbdev, sz->endpoint->bEndpointAddress); - maxp = usb_maxpacket(usbdev, pipe, usb_pipeout(pipe)); - - if (maxp == 0) { - dev_err(&intf->dev, "%s: endpoint Max Packet Size is 0!?!\n", - __func__); - retval = -ENODEV; - goto free_sz; - } - - /* Allocate the USB buffer and IRQ URB */ - sz->buf_in = usb_alloc_coherent(usbdev, maxp, GFP_ATOMIC, &sz->dma_in); - if (!sz->buf_in) - goto free_sz; - - sz->urb_in = usb_alloc_urb(0, GFP_KERNEL); - if (!sz->urb_in) - goto free_buf_in; - - sz->dev = &intf->dev; - sz->buf_in_len = maxp; - - if (usbdev->descriptor.iManufacturer - && usb_string(usbdev, usbdev->descriptor.iManufacturer, - buf, sizeof(buf)) > 0) - strlcpy(name, buf, sizeof(name)); - - if (usbdev->descriptor.iProduct - && usb_string(usbdev, usbdev->descriptor.iProduct, - buf, sizeof(buf)) > 0) - snprintf(name + strlen(name), sizeof(name) - strlen(name), - " %s", buf); - - sz->idev = streamzap_init_input_dev(sz); - if (!sz->idev) - goto input_dev_fail; - - sz->idle = true; - sz->decoder_state = PulseSpace; - /* FIXME: don't yet have a way to set this */ - sz->timeout_enabled = true; - sz->props->timeout = (((SZ_TIMEOUT * SZ_RESOLUTION * 1000) & - IR_MAX_DURATION) | 0x03000000); - #if 0 - /* not yet supported, depends on patches from maxim */ - /* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */ - sz->min_timeout = SZ_TIMEOUT * SZ_RESOLUTION * 1000; - sz->max_timeout = SZ_TIMEOUT * SZ_RESOLUTION * 1000; - #endif - - do_gettimeofday(&sz->signal_start); - - /* Complete final initialisations */ - usb_fill_int_urb(sz->urb_in, usbdev, pipe, sz->buf_in, - maxp, (usb_complete_t)streamzap_callback, - sz, sz->endpoint->bInterval); - sz->urb_in->transfer_dma = sz->dma_in; - sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - usb_set_intfdata(intf, sz); - - if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) - dev_err(sz->dev, "urb submit failed\n"); - - dev_info(sz->dev, "Registered %s on usb%d:%d\n", name, - usbdev->bus->busnum, usbdev->devnum); - - /* Load the streamzap not-quite-rc5 decoder too */ - load_rc5_sz_decode(); - - return 0; - -input_dev_fail: - usb_free_urb(sz->urb_in); -free_buf_in: - usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in); -free_sz: - kfree(sz); - - return retval; -} - -/** - * streamzap_disconnect - * - * Called by the usb core when the device is removed from the system. - * - * This routine guarantees that the driver will not submit any more urbs - * by clearing dev->usbdev. It is also supposed to terminate any currently - * active urbs. Unfortunately, usb_bulk_msg(), used in streamzap_read(), - * does not provide any way to do this. - */ -static void streamzap_disconnect(struct usb_interface *interface) -{ - struct streamzap_ir *sz = usb_get_intfdata(interface); - struct usb_device *usbdev = interface_to_usbdev(interface); - - usb_set_intfdata(interface, NULL); - - if (!sz) - return; - - sz->usbdev = NULL; - ir_input_unregister(sz->idev); - usb_kill_urb(sz->urb_in); - usb_free_urb(sz->urb_in); - usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in); - - kfree(sz); -} - -static int streamzap_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct streamzap_ir *sz = usb_get_intfdata(intf); - - usb_kill_urb(sz->urb_in); - - return 0; -} - -static int streamzap_resume(struct usb_interface *intf) -{ - struct streamzap_ir *sz = usb_get_intfdata(intf); - - if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) { - dev_err(sz->dev, "Error sumbiting urb\n"); - return -EIO; - } - - return 0; -} - -/** - * streamzap_init - */ -static int __init streamzap_init(void) -{ - int ret; - - /* register this driver with the USB subsystem */ - ret = usb_register(&streamzap_driver); - if (ret < 0) - printk(KERN_ERR DRIVER_NAME ": usb register failed, " - "result = %d\n", ret); - - return ret; -} - -/** - * streamzap_exit - */ -static void __exit streamzap_exit(void) -{ - usb_deregister(&streamzap_driver); -} - - -module_init(streamzap_init); -module_exit(streamzap_exit); - -MODULE_AUTHOR("Jarod Wilson "); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging messages"); diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index a28541b..c21dfc2 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -99,7 +99,7 @@ config VIDEO_MEDIA comment "Multimedia drivers" source "drivers/media/common/Kconfig" -source "drivers/media/IR/Kconfig" +source "drivers/media/rc/Kconfig" # # Tuner drivers for DVB and V4L diff --git a/drivers/media/Makefile b/drivers/media/Makefile index 499b081..b603ea6 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile @@ -2,7 +2,7 @@ # Makefile for the kernel multimedia device drivers. # -obj-y += common/ IR/ video/ +obj-y += common/ rc/ video/ obj-$(CONFIG_VIDEO_DEV) += radio/ obj-$(CONFIG_DVB_CORE) += dvb/ diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig new file mode 100644 index 0000000..d05003d --- /dev/null +++ b/drivers/media/rc/Kconfig @@ -0,0 +1,167 @@ +menuconfig IR_CORE + tristate "Infrared remote controller adapters" + depends on INPUT + default INPUT + ---help--- + Enable support for Remote Controllers on Linux. This is + needed in order to support several video capture adapters. + + Enable this option if you have a video capture board even + if you don't need IR, as otherwise, you may not be able to + compile the driver for your adapter. + +config IR_LEGACY + tristate + depends on IR_CORE + default IR_CORE + +if IR_CORE + +config LIRC + tristate + default y + + ---help--- + Enable this option to build the Linux Infrared Remote + Control (LIRC) core device interface driver. The LIRC + interface passes raw IR to and from userspace, where the + LIRC daemon handles protocol decoding for IR reception and + encoding for IR transmitting (aka "blasting"). + +source "drivers/media/rc/keymaps/Kconfig" + +config IR_NEC_DECODER + tristate "Enable IR raw decoder for the NEC protocol" + depends on IR_CORE + select BITREVERSE + default y + + ---help--- + Enable this option if you have IR with NEC protocol, and + if the IR is decoded in software + +config IR_RC5_DECODER + tristate "Enable IR raw decoder for the RC-5 protocol" + depends on IR_CORE + select BITREVERSE + default y + + ---help--- + Enable this option if you have IR with RC-5 protocol, and + if the IR is decoded in software + +config IR_RC6_DECODER + tristate "Enable IR raw decoder for the RC6 protocol" + depends on IR_CORE + select BITREVERSE + default y + + ---help--- + Enable this option if you have an infrared remote control which + uses the RC6 protocol, and you need software decoding support. + +config IR_JVC_DECODER + tristate "Enable IR raw decoder for the JVC protocol" + depends on IR_CORE + select BITREVERSE + default y + + ---help--- + Enable this option if you have an infrared remote control which + uses the JVC protocol, and you need software decoding support. + +config IR_SONY_DECODER + tristate "Enable IR raw decoder for the Sony protocol" + depends on IR_CORE + default y + + ---help--- + Enable this option if you have an infrared remote control which + uses the Sony protocol, and you need software decoding support. + +config IR_RC5_SZ_DECODER + tristate "Enable IR raw decoder for the RC-5 (streamzap) protocol" + depends on IR_CORE + select BITREVERSE + default y + + ---help--- + Enable this option if you have IR with RC-5 (streamzap) protocol, + and if the IR is decoded in software. (The Streamzap PC Remote + uses an IR protocol that is almost standard RC-5, but not quite, + as it uses an additional bit). + +config IR_LIRC_CODEC + tristate "Enable IR to LIRC bridge" + depends on IR_CORE + depends on LIRC + default y + + ---help--- + Enable this option to pass raw IR to and from userspace via + the LIRC interface. + +config IR_ENE + tristate "ENE eHome Receiver/Transceiver (pnp id: ENE0100/ENE02xxx)" + depends on PNP + depends on IR_CORE + ---help--- + Say Y here to enable support for integrated infrared receiver + /transceiver made by ENE. + + You can see if you have it by looking at lspnp output. + Output should include ENE0100 ENE0200 or something similar. + + To compile this driver as a module, choose M here: the + module will be called ene_ir. + +config IR_IMON + tristate "SoundGraph iMON Receiver and Display" + depends on USB_ARCH_HAS_HCD + depends on IR_CORE + select USB + ---help--- + Say Y here if you want to use a SoundGraph iMON (aka Antec Veris) + IR Receiver and/or LCD/VFD/VGA display. + + To compile this driver as a module, choose M here: the + module will be called imon. + +config IR_MCEUSB + tristate "Windows Media Center Ed. eHome Infrared Transceiver" + depends on USB_ARCH_HAS_HCD + depends on IR_CORE + select USB + ---help--- + Say Y here if you want to use a Windows Media Center Edition + eHome Infrared Transceiver. + + To compile this driver as a module, choose M here: the + module will be called mceusb. + +config IR_NUVOTON + tristate "Nuvoton w836x7hg Consumer Infrared Transceiver" + depends on PNP + depends on IR_CORE + ---help--- + Say Y here to enable support for integrated infrared receiver + /transciever made by Nuvoton (formerly Winbond). This chip is + found in the ASRock ION 330HT, as well as assorted Intel + DP55-series motherboards (and of course, possibly others). + + To compile this driver as a module, choose M here: the + module will be called nuvoton-cir. + +config IR_STREAMZAP + tristate "Streamzap PC Remote IR Receiver" + depends on USB_ARCH_HAS_HCD + depends on IR_CORE + select USB + ---help--- + Say Y here if you want to use a Streamzap PC Remote + Infrared Receiver. + + To compile this driver as a module, choose M here: the + module will be called streamzap. + +endif #IR_CORE diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile new file mode 100644 index 0000000..38873cf --- /dev/null +++ b/drivers/media/rc/Makefile @@ -0,0 +1,22 @@ +ir-common-objs := ir-functions.o +ir-core-objs := ir-keytable.o ir-sysfs.o ir-raw-event.o rc-map.o + +obj-y += keymaps/ + +obj-$(CONFIG_IR_CORE) += ir-core.o +obj-$(CONFIG_IR_LEGACY) += ir-common.o +obj-$(CONFIG_LIRC) += lirc_dev.o +obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o +obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o +obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o +obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o +obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o +obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o +obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o + +# stand-alone IR receivers/transmitters +obj-$(CONFIG_IR_IMON) += imon.o +obj-$(CONFIG_IR_MCEUSB) += mceusb.o +obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o +obj-$(CONFIG_IR_ENE) += ene_ir.o +obj-$(CONFIG_IR_STREAMZAP) += streamzap.o diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c new file mode 100644 index 0000000..7637bab --- /dev/null +++ b/drivers/media/rc/ene_ir.c @@ -0,0 +1,1217 @@ +/* + * driver for ENE KB3926 B/C/D/E/F CIR (pnp id: ENE0XXX) + * + * Copyright (C) 2010 Maxim Levitsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * Special thanks to: + * Sami R. for lot of help in debugging and therefore + * bringing to life support for transmission & learning mode. + * + * Charlie Andrews for lots of help in + * bringing up the support of new firmware buffer that is popular + * on latest notebooks + * + * ENE for partial device documentation + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ene_ir.h" + +static int sample_period; +static bool learning_mode_force; +static int debug; +static bool txsim; + +static void ene_set_reg_addr(struct ene_device *dev, u16 reg) +{ + outb(reg >> 8, dev->hw_io + ENE_ADDR_HI); + outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO); +} + +/* read a hardware register */ +static u8 ene_read_reg(struct ene_device *dev, u16 reg) +{ + u8 retval; + ene_set_reg_addr(dev, reg); + retval = inb(dev->hw_io + ENE_IO); + dbg_regs("reg %04x == %02x", reg, retval); + return retval; +} + +/* write a hardware register */ +static void ene_write_reg(struct ene_device *dev, u16 reg, u8 value) +{ + dbg_regs("reg %04x <- %02x", reg, value); + ene_set_reg_addr(dev, reg); + outb(value, dev->hw_io + ENE_IO); +} + +/* Set bits in hardware register */ +static void ene_set_reg_mask(struct ene_device *dev, u16 reg, u8 mask) +{ + dbg_regs("reg %04x |= %02x", reg, mask); + ene_set_reg_addr(dev, reg); + outb(inb(dev->hw_io + ENE_IO) | mask, dev->hw_io + ENE_IO); +} + +/* Clear bits in hardware register */ +static void ene_clear_reg_mask(struct ene_device *dev, u16 reg, u8 mask) +{ + dbg_regs("reg %04x &= ~%02x ", reg, mask); + ene_set_reg_addr(dev, reg); + outb(inb(dev->hw_io + ENE_IO) & ~mask, dev->hw_io + ENE_IO); +} + +/* A helper to set/clear a bit in register according to boolean variable */ +static void ene_set_clear_reg_mask(struct ene_device *dev, u16 reg, u8 mask, + bool set) +{ + if (set) + ene_set_reg_mask(dev, reg, mask); + else + ene_clear_reg_mask(dev, reg, mask); +} + +/* detect hardware features */ +static int ene_hw_detect(struct ene_device *dev) +{ + u8 chip_major, chip_minor; + u8 hw_revision, old_ver; + u8 fw_reg2, fw_reg1; + + ene_clear_reg_mask(dev, ENE_ECSTS, ENE_ECSTS_RSRVD); + chip_major = ene_read_reg(dev, ENE_ECVER_MAJOR); + chip_minor = ene_read_reg(dev, ENE_ECVER_MINOR); + ene_set_reg_mask(dev, ENE_ECSTS, ENE_ECSTS_RSRVD); + + hw_revision = ene_read_reg(dev, ENE_ECHV); + old_ver = ene_read_reg(dev, ENE_HW_VER_OLD); + + dev->pll_freq = (ene_read_reg(dev, ENE_PLLFRH) << 4) + + (ene_read_reg(dev, ENE_PLLFRL) >> 4); + + if (sample_period != ENE_DEFAULT_SAMPLE_PERIOD) + dev->rx_period_adjust = + dev->pll_freq == ENE_DEFAULT_PLL_FREQ ? 2 : 4; + + if (hw_revision == 0xFF) { + ene_warn("device seems to be disabled"); + ene_warn("send a mail to lirc-list@lists.sourceforge.net"); + ene_warn("please attach output of acpidump and dmidecode"); + return -ENODEV; + } + + ene_notice("chip is 0x%02x%02x - kbver = 0x%02x, rev = 0x%02x", + chip_major, chip_minor, old_ver, hw_revision); + + ene_notice("PLL freq = %d", dev->pll_freq); + + if (chip_major == 0x33) { + ene_warn("chips 0x33xx aren't supported"); + return -ENODEV; + } + + if (chip_major == 0x39 && chip_minor == 0x26 && hw_revision == 0xC0) { + dev->hw_revision = ENE_HW_C; + ene_notice("KB3926C detected"); + } else if (old_ver == 0x24 && hw_revision == 0xC0) { + dev->hw_revision = ENE_HW_B; + ene_notice("KB3926B detected"); + } else { + dev->hw_revision = ENE_HW_D; + ene_notice("KB3926D or higher detected"); + } + + /* detect features hardware supports */ + if (dev->hw_revision < ENE_HW_C) + return 0; + + fw_reg1 = ene_read_reg(dev, ENE_FW1); + fw_reg2 = ene_read_reg(dev, ENE_FW2); + + ene_notice("Firmware regs: %02x %02x", fw_reg1, fw_reg2); + + dev->hw_use_gpio_0a = !!(fw_reg2 & ENE_FW2_GP0A); + dev->hw_learning_and_tx_capable = !!(fw_reg2 & ENE_FW2_LEARNING); + dev->hw_extra_buffer = !!(fw_reg1 & ENE_FW1_HAS_EXTRA_BUF); + + if (dev->hw_learning_and_tx_capable) + dev->hw_fan_input = !!(fw_reg2 & ENE_FW2_FAN_INPUT); + + ene_notice("Hardware features:"); + + if (dev->hw_learning_and_tx_capable) { + ene_notice("* Supports transmitting & learning mode"); + ene_notice(" This feature is rare and therefore,"); + ene_notice(" you are welcome to test it,"); + ene_notice(" and/or contact the author via:"); + ene_notice(" lirc-list@lists.sourceforge.net"); + ene_notice(" or maximlevitsky@gmail.com"); + + ene_notice("* Uses GPIO %s for IR raw input", + dev->hw_use_gpio_0a ? "40" : "0A"); + + if (dev->hw_fan_input) + ene_notice("* Uses unused fan feedback input as source" + " of demodulated IR data"); + } + + if (!dev->hw_fan_input) + ene_notice("* Uses GPIO %s for IR demodulated input", + dev->hw_use_gpio_0a ? "0A" : "40"); + + if (dev->hw_extra_buffer) + ene_notice("* Uses new style input buffer"); + return 0; +} + +/* Read properities of hw sample buffer */ +static void ene_rx_setup_hw_buffer(struct ene_device *dev) +{ + u16 tmp; + + ene_rx_read_hw_pointer(dev); + dev->r_pointer = dev->w_pointer; + + if (!dev->hw_extra_buffer) { + dev->buffer_len = ENE_FW_PACKET_SIZE * 2; + return; + } + + tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER); + tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER+1) << 8; + dev->extra_buf1_address = tmp; + + dev->extra_buf1_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 2); + + tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 3); + tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 4) << 8; + dev->extra_buf2_address = tmp; + + dev->extra_buf2_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 5); + + dev->buffer_len = dev->extra_buf1_len + dev->extra_buf2_len + 8; + + ene_notice("Hardware uses 2 extended buffers:"); + ene_notice(" 0x%04x - len : %d", dev->extra_buf1_address, + dev->extra_buf1_len); + ene_notice(" 0x%04x - len : %d", dev->extra_buf2_address, + dev->extra_buf2_len); + + ene_notice("Total buffer len = %d", dev->buffer_len); + + if (dev->buffer_len > 64 || dev->buffer_len < 16) + goto error; + + if (dev->extra_buf1_address > 0xFBFC || + dev->extra_buf1_address < 0xEC00) + goto error; + + if (dev->extra_buf2_address > 0xFBFC || + dev->extra_buf2_address < 0xEC00) + goto error; + + if (dev->r_pointer > dev->buffer_len) + goto error; + + ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND); + return; +error: + ene_warn("Error validating extra buffers, device probably won't work"); + dev->hw_extra_buffer = false; + ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND); +} + + +/* Restore the pointers to extra buffers - to make module reload work*/ +static void ene_rx_restore_hw_buffer(struct ene_device *dev) +{ + if (!dev->hw_extra_buffer) + return; + + ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 0, + dev->extra_buf1_address & 0xFF); + ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 1, + dev->extra_buf1_address >> 8); + ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 2, dev->extra_buf1_len); + + ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 3, + dev->extra_buf2_address & 0xFF); + ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 4, + dev->extra_buf2_address >> 8); + ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 5, + dev->extra_buf2_len); + ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND); +} + +/* Read hardware write pointer */ +static void ene_rx_read_hw_pointer(struct ene_device *dev) +{ + if (dev->hw_extra_buffer) + dev->w_pointer = ene_read_reg(dev, ENE_FW_RX_POINTER); + else + dev->w_pointer = ene_read_reg(dev, ENE_FW2) + & ENE_FW2_BUF_WPTR ? 0 : ENE_FW_PACKET_SIZE; + + dbg_verbose("RB: HW write pointer: %02x, driver read pointer: %02x", + dev->w_pointer, dev->r_pointer); +} + +/* Gets address of next sample from HW ring buffer */ +static int ene_rx_get_sample_reg(struct ene_device *dev) +{ + int r_pointer; + + if (dev->r_pointer == dev->w_pointer) { + dbg_verbose("RB: hit end, try update w_pointer"); + ene_rx_read_hw_pointer(dev); + } + + if (dev->r_pointer == dev->w_pointer) { + dbg_verbose("RB: end of data at %d", dev->r_pointer); + return 0; + } + + dbg_verbose("RB: reading at offset %d", dev->r_pointer); + r_pointer = dev->r_pointer; + + dev->r_pointer++; + if (dev->r_pointer == dev->buffer_len) + dev->r_pointer = 0; + + dbg_verbose("RB: next read will be from offset %d", dev->r_pointer); + + if (r_pointer < 8) { + dbg_verbose("RB: read at main buffer at %d", r_pointer); + return ENE_FW_SAMPLE_BUFFER + r_pointer; + } + + r_pointer -= 8; + + if (r_pointer < dev->extra_buf1_len) { + dbg_verbose("RB: read at 1st extra buffer at %d", r_pointer); + return dev->extra_buf1_address + r_pointer; + } + + r_pointer -= dev->extra_buf1_len; + + if (r_pointer < dev->extra_buf2_len) { + dbg_verbose("RB: read at 2nd extra buffer at %d", r_pointer); + return dev->extra_buf2_address + r_pointer; + } + + dbg("attempt to read beyong ring bufer end"); + return 0; +} + +/* Sense current received carrier */ +void ene_rx_sense_carrier(struct ene_device *dev) +{ + DEFINE_IR_RAW_EVENT(ev); + + int carrier, duty_cycle; + int period = ene_read_reg(dev, ENE_CIRCAR_PRD); + int hperiod = ene_read_reg(dev, ENE_CIRCAR_HPRD); + + if (!(period & ENE_CIRCAR_PRD_VALID)) + return; + + period &= ~ENE_CIRCAR_PRD_VALID; + + if (!period) + return; + + dbg("RX: hardware carrier period = %02x", period); + dbg("RX: hardware carrier pulse period = %02x", hperiod); + + carrier = 2000000 / period; + duty_cycle = (hperiod * 100) / period; + dbg("RX: sensed carrier = %d Hz, duty cycle %d%%", + carrier, duty_cycle); + if (dev->carrier_detect_enabled) { + ev.carrier_report = true; + ev.carrier = carrier; + ev.duty_cycle = duty_cycle; + ir_raw_event_store(dev->idev, &ev); + } +} + +/* this enables/disables the CIR RX engine */ +static void ene_rx_enable_cir_engine(struct ene_device *dev, bool enable) +{ + ene_set_clear_reg_mask(dev, ENE_CIRCFG, + ENE_CIRCFG_RX_EN | ENE_CIRCFG_RX_IRQ, enable); +} + +/* this selects input for CIR engine. Ether GPIO 0A or GPIO40*/ +static void ene_rx_select_input(struct ene_device *dev, bool gpio_0a) +{ + ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_GPIO0A, gpio_0a); +} + +/* + * this enables alternative input via fan tachometer sensor and bypasses + * the hw CIR engine + */ +static void ene_rx_enable_fan_input(struct ene_device *dev, bool enable) +{ + if (!dev->hw_fan_input) + return; + + if (!enable) + ene_write_reg(dev, ENE_FAN_AS_IN1, 0); + else { + ene_write_reg(dev, ENE_FAN_AS_IN1, ENE_FAN_AS_IN1_EN); + ene_write_reg(dev, ENE_FAN_AS_IN2, ENE_FAN_AS_IN2_EN); + } +} + +/* setup the receiver for RX*/ +static void ene_rx_setup(struct ene_device *dev) +{ + bool learning_mode = dev->learning_mode_enabled || + dev->carrier_detect_enabled; + int sample_period_adjust = 0; + + dbg("RX: setup receiver, learning mode = %d", learning_mode); + + + /* This selects RLC input and clears CFG2 settings */ + ene_write_reg(dev, ENE_CIRCFG2, 0x00); + + /* set sample period*/ + if (sample_period == ENE_DEFAULT_SAMPLE_PERIOD) + sample_period_adjust = + dev->pll_freq == ENE_DEFAULT_PLL_FREQ ? 1 : 2; + + ene_write_reg(dev, ENE_CIRRLC_CFG, + (sample_period + sample_period_adjust) | + ENE_CIRRLC_CFG_OVERFLOW); + /* revB doesn't support inputs */ + if (dev->hw_revision < ENE_HW_C) + goto select_timeout; + + if (learning_mode) { + + WARN_ON(!dev->hw_learning_and_tx_capable); + + /* Enable the opposite of the normal input + That means that if GPIO40 is normally used, use GPIO0A + and vice versa. + This input will carry non demodulated + signal, and we will tell the hw to demodulate it itself */ + ene_rx_select_input(dev, !dev->hw_use_gpio_0a); + dev->rx_fan_input_inuse = false; + + /* Enable carrier demodulation */ + ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD); + + /* Enable carrier detection */ + ene_write_reg(dev, ENE_CIRCAR_PULS, 0x63); + ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_CARR_DETECT, + dev->carrier_detect_enabled || debug); + } else { + if (dev->hw_fan_input) + dev->rx_fan_input_inuse = true; + else + ene_rx_select_input(dev, dev->hw_use_gpio_0a); + + /* Disable carrier detection & demodulation */ + ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD); + ene_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_CARR_DETECT); + } + +select_timeout: + if (dev->rx_fan_input_inuse) { + dev->props->rx_resolution = MS_TO_NS(ENE_FW_SAMPLE_PERIOD_FAN); + + /* Fan input doesn't support timeouts, it just ends the + input with a maximum sample */ + dev->props->min_timeout = dev->props->max_timeout = + MS_TO_NS(ENE_FW_SMPL_BUF_FAN_MSK * + ENE_FW_SAMPLE_PERIOD_FAN); + } else { + dev->props->rx_resolution = MS_TO_NS(sample_period); + + /* Theoreticly timeout is unlimited, but we cap it + * because it was seen that on one device, it + * would stop sending spaces after around 250 msec. + * Besides, this is close to 2^32 anyway and timeout is u32. + */ + dev->props->min_timeout = MS_TO_NS(127 * sample_period); + dev->props->max_timeout = MS_TO_NS(200000); + } + + if (dev->hw_learning_and_tx_capable) + dev->props->tx_resolution = MS_TO_NS(sample_period); + + if (dev->props->timeout > dev->props->max_timeout) + dev->props->timeout = dev->props->max_timeout; + if (dev->props->timeout < dev->props->min_timeout) + dev->props->timeout = dev->props->min_timeout; +} + +/* Enable the device for receive */ +static void ene_rx_enable(struct ene_device *dev) +{ + u8 reg_value; + + /* Enable system interrupt */ + if (dev->hw_revision < ENE_HW_C) { + ene_write_reg(dev, ENEB_IRQ, dev->irq << 1); + ene_write_reg(dev, ENEB_IRQ_UNK1, 0x01); + } else { + reg_value = ene_read_reg(dev, ENE_IRQ) & 0xF0; + reg_value |= ENE_IRQ_UNK_EN; + reg_value &= ~ENE_IRQ_STATUS; + reg_value |= (dev->irq & ENE_IRQ_MASK); + ene_write_reg(dev, ENE_IRQ, reg_value); + } + + /* Enable inputs */ + ene_rx_enable_fan_input(dev, dev->rx_fan_input_inuse); + ene_rx_enable_cir_engine(dev, !dev->rx_fan_input_inuse); + + /* ack any pending irqs - just in case */ + ene_irq_status(dev); + + /* enable firmware bits */ + ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ); + + /* enter idle mode */ + ir_raw_event_set_idle(dev->idev, true); + dev->rx_enabled = true; +} + +/* Disable the device receiver */ +static void ene_rx_disable(struct ene_device *dev) +{ + /* disable inputs */ + ene_rx_enable_cir_engine(dev, false); + ene_rx_enable_fan_input(dev, false); + + /* disable hardware IRQ and firmware flag */ + ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ); + + ir_raw_event_set_idle(dev->idev, true); + dev->rx_enabled = false; +} + +/* This resets the receiver. Usefull to stop stream of spaces at end of + * transmission + */ +static void ene_rx_reset(struct ene_device *dev) +{ + ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN); + ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN); +} + +/* Set up the TX carrier frequency and duty cycle */ +static void ene_tx_set_carrier(struct ene_device *dev) +{ + u8 tx_puls_width; + unsigned long flags; + + spin_lock_irqsave(&dev->hw_lock, flags); + + ene_set_clear_reg_mask(dev, ENE_CIRCFG, + ENE_CIRCFG_TX_CARR, dev->tx_period > 0); + + if (!dev->tx_period) + goto unlock; + + BUG_ON(dev->tx_duty_cycle >= 100 || dev->tx_duty_cycle <= 0); + + tx_puls_width = dev->tx_period / (100 / dev->tx_duty_cycle); + + if (!tx_puls_width) + tx_puls_width = 1; + + dbg("TX: pulse distance = %d * 500 ns", dev->tx_period); + dbg("TX: pulse width = %d * 500 ns", tx_puls_width); + + ene_write_reg(dev, ENE_CIRMOD_PRD, dev->tx_period | ENE_CIRMOD_PRD_POL); + ene_write_reg(dev, ENE_CIRMOD_HPRD, tx_puls_width); +unlock: + spin_unlock_irqrestore(&dev->hw_lock, flags); +} + +/* Enable/disable transmitters */ +static void ene_tx_set_transmitters(struct ene_device *dev) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->hw_lock, flags); + ene_set_clear_reg_mask(dev, ENE_GPIOFS8, ENE_GPIOFS8_GPIO41, + !!(dev->transmitter_mask & 0x01)); + ene_set_clear_reg_mask(dev, ENE_GPIOFS1, ENE_GPIOFS1_GPIO0D, + !!(dev->transmitter_mask & 0x02)); + spin_unlock_irqrestore(&dev->hw_lock, flags); +} + +/* prepare transmission */ +static void ene_tx_enable(struct ene_device *dev) +{ + u8 conf1 = ene_read_reg(dev, ENE_CIRCFG); + u8 fwreg2 = ene_read_reg(dev, ENE_FW2); + + dev->saved_conf1 = conf1; + + /* Show information about currently connected transmitter jacks */ + if (fwreg2 & ENE_FW2_EMMITER1_CONN) + dbg("TX: Transmitter #1 is connected"); + + if (fwreg2 & ENE_FW2_EMMITER2_CONN) + dbg("TX: Transmitter #2 is connected"); + + if (!(fwreg2 & (ENE_FW2_EMMITER1_CONN | ENE_FW2_EMMITER2_CONN))) + ene_warn("TX: transmitter cable isn't connected!"); + + /* disable receive on revc */ + if (dev->hw_revision == ENE_HW_C) + conf1 &= ~ENE_CIRCFG_RX_EN; + + /* Enable TX engine */ + conf1 |= ENE_CIRCFG_TX_EN | ENE_CIRCFG_TX_IRQ; + ene_write_reg(dev, ENE_CIRCFG, conf1); +} + +/* end transmission */ +static void ene_tx_disable(struct ene_device *dev) +{ + ene_write_reg(dev, ENE_CIRCFG, dev->saved_conf1); + dev->tx_buffer = NULL; +} + + +/* TX one sample - must be called with dev->hw_lock*/ +static void ene_tx_sample(struct ene_device *dev) +{ + u8 raw_tx; + u32 sample; + bool pulse = dev->tx_sample_pulse; + + if (!dev->tx_buffer) { + ene_warn("TX: BUG: attempt to transmit NULL buffer"); + return; + } + + /* Grab next TX sample */ + if (!dev->tx_sample) { + + if (dev->tx_pos == dev->tx_len) { + if (!dev->tx_done) { + dbg("TX: no more data to send"); + dev->tx_done = true; + goto exit; + } else { + dbg("TX: last sample sent by hardware"); + ene_tx_disable(dev); + complete(&dev->tx_complete); + return; + } + } + + sample = dev->tx_buffer[dev->tx_pos++]; + dev->tx_sample_pulse = !dev->tx_sample_pulse; + + dev->tx_sample = DIV_ROUND_CLOSEST(sample, sample_period); + + if (!dev->tx_sample) + dev->tx_sample = 1; + } + + raw_tx = min(dev->tx_sample , (unsigned int)ENE_CIRRLC_OUT_MASK); + dev->tx_sample -= raw_tx; + + dbg("TX: sample %8d (%s)", raw_tx * sample_period, + pulse ? "pulse" : "space"); + if (pulse) + raw_tx |= ENE_CIRRLC_OUT_PULSE; + + ene_write_reg(dev, + dev->tx_reg ? ENE_CIRRLC_OUT1 : ENE_CIRRLC_OUT0, raw_tx); + + dev->tx_reg = !dev->tx_reg; +exit: + /* simulate TX done interrupt */ + if (txsim) + mod_timer(&dev->tx_sim_timer, jiffies + HZ / 500); +} + +/* timer to simulate tx done interrupt */ +static void ene_tx_irqsim(unsigned long data) +{ + struct ene_device *dev = (struct ene_device *)data; + unsigned long flags; + + spin_lock_irqsave(&dev->hw_lock, flags); + ene_tx_sample(dev); + spin_unlock_irqrestore(&dev->hw_lock, flags); +} + + +/* read irq status and ack it */ +static int ene_irq_status(struct ene_device *dev) +{ + u8 irq_status; + u8 fw_flags1, fw_flags2; + int retval = 0; + + fw_flags2 = ene_read_reg(dev, ENE_FW2); + + if (dev->hw_revision < ENE_HW_C) { + irq_status = ene_read_reg(dev, ENEB_IRQ_STATUS); + + if (!(irq_status & ENEB_IRQ_STATUS_IR)) + return 0; + + ene_clear_reg_mask(dev, ENEB_IRQ_STATUS, ENEB_IRQ_STATUS_IR); + return ENE_IRQ_RX; + } + + irq_status = ene_read_reg(dev, ENE_IRQ); + if (!(irq_status & ENE_IRQ_STATUS)) + return 0; + + /* original driver does that twice - a workaround ? */ + ene_write_reg(dev, ENE_IRQ, irq_status & ~ENE_IRQ_STATUS); + ene_write_reg(dev, ENE_IRQ, irq_status & ~ENE_IRQ_STATUS); + + /* check RX interrupt */ + if (fw_flags2 & ENE_FW2_RXIRQ) { + retval |= ENE_IRQ_RX; + ene_write_reg(dev, ENE_FW2, fw_flags2 & ~ENE_FW2_RXIRQ); + } + + /* check TX interrupt */ + fw_flags1 = ene_read_reg(dev, ENE_FW1); + if (fw_flags1 & ENE_FW1_TXIRQ) { + ene_write_reg(dev, ENE_FW1, fw_flags1 & ~ENE_FW1_TXIRQ); + retval |= ENE_IRQ_TX; + } + + return retval; +} + +/* interrupt handler */ +static irqreturn_t ene_isr(int irq, void *data) +{ + u16 hw_value, reg; + int hw_sample, irq_status; + bool pulse; + unsigned long flags; + irqreturn_t retval = IRQ_NONE; + struct ene_device *dev = (struct ene_device *)data; + DEFINE_IR_RAW_EVENT(ev); + + spin_lock_irqsave(&dev->hw_lock, flags); + + dbg_verbose("ISR called"); + ene_rx_read_hw_pointer(dev); + irq_status = ene_irq_status(dev); + + if (!irq_status) + goto unlock; + + retval = IRQ_HANDLED; + + if (irq_status & ENE_IRQ_TX) { + dbg_verbose("TX interrupt"); + if (!dev->hw_learning_and_tx_capable) { + dbg("TX interrupt on unsupported device!"); + goto unlock; + } + ene_tx_sample(dev); + } + + if (!(irq_status & ENE_IRQ_RX)) + goto unlock; + + dbg_verbose("RX interrupt"); + + if (dev->hw_learning_and_tx_capable) + ene_rx_sense_carrier(dev); + + /* On hardware that don't support extra buffer we need to trust + the interrupt and not track the read pointer */ + if (!dev->hw_extra_buffer) + dev->r_pointer = dev->w_pointer == 0 ? ENE_FW_PACKET_SIZE : 0; + + while (1) { + + reg = ene_rx_get_sample_reg(dev); + + dbg_verbose("next sample to read at: %04x", reg); + if (!reg) + break; + + hw_value = ene_read_reg(dev, reg); + + if (dev->rx_fan_input_inuse) { + + int offset = ENE_FW_SMPL_BUF_FAN - ENE_FW_SAMPLE_BUFFER; + + /* read high part of the sample */ + hw_value |= ene_read_reg(dev, reg + offset) << 8; + pulse = hw_value & ENE_FW_SMPL_BUF_FAN_PLS; + + /* clear space bit, and other unused bits */ + hw_value &= ENE_FW_SMPL_BUF_FAN_MSK; + hw_sample = hw_value * ENE_FW_SAMPLE_PERIOD_FAN; + + } else { + pulse = !(hw_value & ENE_FW_SAMPLE_SPACE); + hw_value &= ~ENE_FW_SAMPLE_SPACE; + hw_sample = hw_value * sample_period; + + if (dev->rx_period_adjust) { + hw_sample *= 100; + hw_sample /= (100 + dev->rx_period_adjust); + } + } + + if (!dev->hw_extra_buffer && !hw_sample) { + dev->r_pointer = dev->w_pointer; + continue; + } + + dbg("RX: %d (%s)", hw_sample, pulse ? "pulse" : "space"); + + ev.duration = MS_TO_NS(hw_sample); + ev.pulse = pulse; + ir_raw_event_store_with_filter(dev->idev, &ev); + } + + ir_raw_event_handle(dev->idev); +unlock: + spin_unlock_irqrestore(&dev->hw_lock, flags); + return retval; +} + +/* Initialize default settings */ +static void ene_setup_default_settings(struct ene_device *dev) +{ + dev->tx_period = 32; + dev->tx_duty_cycle = 50; /*%*/ + dev->transmitter_mask = 0x03; + dev->learning_mode_enabled = learning_mode_force; + + /* Set reasonable default timeout */ + dev->props->timeout = MS_TO_NS(150000); +} + +/* Upload all hardware settings at once. Used at load and resume time */ +static void ene_setup_hw_settings(struct ene_device *dev) +{ + if (dev->hw_learning_and_tx_capable) { + ene_tx_set_carrier(dev); + ene_tx_set_transmitters(dev); + } + + ene_rx_setup(dev); +} + +/* outside interface: called on first open*/ +static int ene_open(void *data) +{ + struct ene_device *dev = (struct ene_device *)data; + unsigned long flags; + + spin_lock_irqsave(&dev->hw_lock, flags); + ene_rx_enable(dev); + spin_unlock_irqrestore(&dev->hw_lock, flags); + return 0; +} + +/* outside interface: called on device close*/ +static void ene_close(void *data) +{ + struct ene_device *dev = (struct ene_device *)data; + unsigned long flags; + spin_lock_irqsave(&dev->hw_lock, flags); + + ene_rx_disable(dev); + spin_unlock_irqrestore(&dev->hw_lock, flags); +} + +/* outside interface: set transmitter mask */ +static int ene_set_tx_mask(void *data, u32 tx_mask) +{ + struct ene_device *dev = (struct ene_device *)data; + dbg("TX: attempt to set transmitter mask %02x", tx_mask); + + /* invalid txmask */ + if (!tx_mask || tx_mask & ~0x03) { + dbg("TX: invalid mask"); + /* return count of transmitters */ + return 2; + } + + dev->transmitter_mask = tx_mask; + ene_tx_set_transmitters(dev); + return 0; +} + +/* outside interface : set tx carrier */ +static int ene_set_tx_carrier(void *data, u32 carrier) +{ + struct ene_device *dev = (struct ene_device *)data; + u32 period = 2000000 / carrier; + + dbg("TX: attempt to set tx carrier to %d kHz", carrier); + + if (period && (period > ENE_CIRMOD_PRD_MAX || + period < ENE_CIRMOD_PRD_MIN)) { + + dbg("TX: out of range %d-%d kHz carrier", + 2000 / ENE_CIRMOD_PRD_MIN, 2000 / ENE_CIRMOD_PRD_MAX); + return -1; + } + + dev->tx_period = period; + ene_tx_set_carrier(dev); + return 0; +} + +/*outside interface : set tx duty cycle */ +static int ene_set_tx_duty_cycle(void *data, u32 duty_cycle) +{ + struct ene_device *dev = (struct ene_device *)data; + dbg("TX: setting duty cycle to %d%%", duty_cycle); + dev->tx_duty_cycle = duty_cycle; + ene_tx_set_carrier(dev); + return 0; +} + +/* outside interface: enable learning mode */ +static int ene_set_learning_mode(void *data, int enable) +{ + struct ene_device *dev = (struct ene_device *)data; + unsigned long flags; + if (enable == dev->learning_mode_enabled) + return 0; + + spin_lock_irqsave(&dev->hw_lock, flags); + dev->learning_mode_enabled = enable; + ene_rx_disable(dev); + ene_rx_setup(dev); + ene_rx_enable(dev); + spin_unlock_irqrestore(&dev->hw_lock, flags); + return 0; +} + +static int ene_set_carrier_report(void *data, int enable) +{ + struct ene_device *dev = (struct ene_device *)data; + unsigned long flags; + + if (enable == dev->carrier_detect_enabled) + return 0; + + spin_lock_irqsave(&dev->hw_lock, flags); + dev->carrier_detect_enabled = enable; + ene_rx_disable(dev); + ene_rx_setup(dev); + ene_rx_enable(dev); + spin_unlock_irqrestore(&dev->hw_lock, flags); + return 0; +} + +/* outside interface: enable or disable idle mode */ +static void ene_set_idle(void *data, bool idle) +{ + if (idle) { + ene_rx_reset((struct ene_device *)data); + dbg("RX: end of data"); + } +} + +/* outside interface: transmit */ +static int ene_transmit(void *data, int *buf, u32 n) +{ + struct ene_device *dev = (struct ene_device *)data; + unsigned long flags; + + dev->tx_buffer = buf; + dev->tx_len = n / sizeof(int); + dev->tx_pos = 0; + dev->tx_reg = 0; + dev->tx_done = 0; + dev->tx_sample = 0; + dev->tx_sample_pulse = 0; + + dbg("TX: %d samples", dev->tx_len); + + spin_lock_irqsave(&dev->hw_lock, flags); + + ene_tx_enable(dev); + + /* Transmit first two samples */ + ene_tx_sample(dev); + ene_tx_sample(dev); + + spin_unlock_irqrestore(&dev->hw_lock, flags); + + if (wait_for_completion_timeout(&dev->tx_complete, 2 * HZ) == 0) { + dbg("TX: timeout"); + spin_lock_irqsave(&dev->hw_lock, flags); + ene_tx_disable(dev); + spin_unlock_irqrestore(&dev->hw_lock, flags); + } else + dbg("TX: done"); + return n; +} + +/* probe entry */ +static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) +{ + int error = -ENOMEM; + struct ir_dev_props *ir_props; + struct input_dev *input_dev; + struct ene_device *dev; + + /* allocate memory */ + input_dev = input_allocate_device(); + ir_props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); + dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL); + + if (!input_dev || !ir_props || !dev) + goto error1; + + /* validate resources */ + error = -ENODEV; + + if (!pnp_port_valid(pnp_dev, 0) || + pnp_port_len(pnp_dev, 0) < ENE_IO_SIZE) + goto error; + + if (!pnp_irq_valid(pnp_dev, 0)) + goto error; + + spin_lock_init(&dev->hw_lock); + + /* claim the resources */ + error = -EBUSY; + dev->hw_io = pnp_port_start(pnp_dev, 0); + if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) { + dev->hw_io = -1; + dev->irq = -1; + goto error; + } + + dev->irq = pnp_irq(pnp_dev, 0); + if (request_irq(dev->irq, ene_isr, + IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) { + dev->irq = -1; + goto error; + } + + pnp_set_drvdata(pnp_dev, dev); + dev->pnp_dev = pnp_dev; + + /* don't allow too short/long sample periods */ + if (sample_period < 5 || sample_period > 0x7F) + sample_period = ENE_DEFAULT_SAMPLE_PERIOD; + + /* detect hardware version and features */ + error = ene_hw_detect(dev); + if (error) + goto error; + + if (!dev->hw_learning_and_tx_capable && txsim) { + dev->hw_learning_and_tx_capable = true; + setup_timer(&dev->tx_sim_timer, ene_tx_irqsim, + (long unsigned int)dev); + ene_warn("Simulation of TX activated"); + } + + if (!dev->hw_learning_and_tx_capable) + learning_mode_force = false; + + ir_props->driver_type = RC_DRIVER_IR_RAW; + ir_props->allowed_protos = IR_TYPE_ALL; + ir_props->priv = dev; + ir_props->open = ene_open; + ir_props->close = ene_close; + ir_props->s_idle = ene_set_idle; + + dev->props = ir_props; + dev->idev = input_dev; + + if (dev->hw_learning_and_tx_capable) { + ir_props->s_learning_mode = ene_set_learning_mode; + init_completion(&dev->tx_complete); + ir_props->tx_ir = ene_transmit; + ir_props->s_tx_mask = ene_set_tx_mask; + ir_props->s_tx_carrier = ene_set_tx_carrier; + ir_props->s_tx_duty_cycle = ene_set_tx_duty_cycle; + ir_props->s_carrier_report = ene_set_carrier_report; + } + + ene_rx_setup_hw_buffer(dev); + ene_setup_default_settings(dev); + ene_setup_hw_settings(dev); + + device_set_wakeup_capable(&pnp_dev->dev, true); + device_set_wakeup_enable(&pnp_dev->dev, true); + + if (dev->hw_learning_and_tx_capable) + input_dev->name = "ENE eHome Infrared Remote Transceiver"; + else + input_dev->name = "ENE eHome Infrared Remote Receiver"; + + error = -ENODEV; + if (ir_input_register(input_dev, RC_MAP_RC6_MCE, ir_props, + ENE_DRIVER_NAME)) + goto error; + + ene_notice("driver has been succesfully loaded"); + return 0; +error: + if (dev && dev->irq >= 0) + free_irq(dev->irq, dev); + if (dev && dev->hw_io >= 0) + release_region(dev->hw_io, ENE_IO_SIZE); +error1: + input_free_device(input_dev); + kfree(ir_props); + kfree(dev); + return error; +} + +/* main unload function */ +static void ene_remove(struct pnp_dev *pnp_dev) +{ + struct ene_device *dev = pnp_get_drvdata(pnp_dev); + unsigned long flags; + + spin_lock_irqsave(&dev->hw_lock, flags); + ene_rx_disable(dev); + ene_rx_restore_hw_buffer(dev); + spin_unlock_irqrestore(&dev->hw_lock, flags); + + free_irq(dev->irq, dev); + release_region(dev->hw_io, ENE_IO_SIZE); + ir_input_unregister(dev->idev); + kfree(dev->props); + kfree(dev); +} + +/* enable wake on IR (wakes on specific button on original remote) */ +static void ene_enable_wake(struct ene_device *dev, int enable) +{ + enable = enable && device_may_wakeup(&dev->pnp_dev->dev); + dbg("wake on IR %s", enable ? "enabled" : "disabled"); + ene_set_clear_reg_mask(dev, ENE_FW1, ENE_FW1_WAKE, enable); +} + +#ifdef CONFIG_PM +static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state) +{ + struct ene_device *dev = pnp_get_drvdata(pnp_dev); + ene_enable_wake(dev, true); + + /* TODO: add support for wake pattern */ + return 0; +} + +static int ene_resume(struct pnp_dev *pnp_dev) +{ + struct ene_device *dev = pnp_get_drvdata(pnp_dev); + ene_setup_hw_settings(dev); + + if (dev->rx_enabled) + ene_rx_enable(dev); + + ene_enable_wake(dev, false); + return 0; +} +#endif + +static void ene_shutdown(struct pnp_dev *pnp_dev) +{ + struct ene_device *dev = pnp_get_drvdata(pnp_dev); + ene_enable_wake(dev, true); +} + +static const struct pnp_device_id ene_ids[] = { + {.id = "ENE0100",}, + {.id = "ENE0200",}, + {.id = "ENE0201",}, + {.id = "ENE0202",}, + {}, +}; + +static struct pnp_driver ene_driver = { + .name = ENE_DRIVER_NAME, + .id_table = ene_ids, + .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, + + .probe = ene_probe, + .remove = __devexit_p(ene_remove), +#ifdef CONFIG_PM + .suspend = ene_suspend, + .resume = ene_resume, +#endif + .shutdown = ene_shutdown, +}; + +static int __init ene_init(void) +{ + return pnp_register_driver(&ene_driver); +} + +static void ene_exit(void) +{ + pnp_unregister_driver(&ene_driver); +} + +module_param(sample_period, int, S_IRUGO); +MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)"); + +module_param(learning_mode_force, bool, S_IRUGO); +MODULE_PARM_DESC(learning_mode_force, "Enable learning mode by default"); + +module_param(debug, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug level"); + +module_param(txsim, bool, S_IRUGO); +MODULE_PARM_DESC(txsim, + "Simulate TX features on unsupported hardware (dangerous)"); + +MODULE_DEVICE_TABLE(pnp, ene_ids); +MODULE_DESCRIPTION + ("Infrared input driver for KB3926B/C/D/E/F " + "(aka ENE0100/ENE0200/ENE0201/ENE0202) CIR port"); + +MODULE_AUTHOR("Maxim Levitsky"); +MODULE_LICENSE("GPL"); + +module_init(ene_init); +module_exit(ene_exit); diff --git a/drivers/media/rc/ene_ir.h b/drivers/media/rc/ene_ir.h new file mode 100644 index 0000000..f587066 --- /dev/null +++ b/drivers/media/rc/ene_ir.h @@ -0,0 +1,262 @@ +/* + * driver for ENE KB3926 B/C/D/E/F CIR (also known as ENE0XXX) + * + * Copyright (C) 2010 Maxim Levitsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ +#include + + +/* hardware address */ +#define ENE_STATUS 0 /* hardware status - unused */ +#define ENE_ADDR_HI 1 /* hi byte of register address */ +#define ENE_ADDR_LO 2 /* low byte of register address */ +#define ENE_IO 3 /* read/write window */ +#define ENE_IO_SIZE 4 + +/* 8 bytes of samples, divided in 2 packets*/ +#define ENE_FW_SAMPLE_BUFFER 0xF8F0 /* sample buffer */ +#define ENE_FW_SAMPLE_SPACE 0x80 /* sample is space */ +#define ENE_FW_PACKET_SIZE 4 + +/* first firmware flag register */ +#define ENE_FW1 0xF8F8 /* flagr */ +#define ENE_FW1_ENABLE 0x01 /* enable fw processing */ +#define ENE_FW1_TXIRQ 0x02 /* TX interrupt pending */ +#define ENE_FW1_HAS_EXTRA_BUF 0x04 /* fw uses extra buffer*/ +#define ENE_FW1_EXTRA_BUF_HND 0x08 /* extra buffer handshake bit*/ +#define ENE_FW1_LED_ON 0x10 /* turn on a led */ + +#define ENE_FW1_WPATTERN 0x20 /* enable wake pattern */ +#define ENE_FW1_WAKE 0x40 /* enable wake from S3 */ +#define ENE_FW1_IRQ 0x80 /* enable interrupt */ + +/* second firmware flag register */ +#define ENE_FW2 0xF8F9 /* flagw */ +#define ENE_FW2_BUF_WPTR 0x01 /* which half of the buffer to read */ +#define ENE_FW2_RXIRQ 0x04 /* RX IRQ pending*/ +#define ENE_FW2_GP0A 0x08 /* Use GPIO0A for demodulated input */ +#define ENE_FW2_EMMITER1_CONN 0x10 /* TX emmiter 1 connected */ +#define ENE_FW2_EMMITER2_CONN 0x20 /* TX emmiter 2 connected */ + +#define ENE_FW2_FAN_INPUT 0x40 /* fan input used for demodulated data*/ +#define ENE_FW2_LEARNING 0x80 /* hardware supports learning and TX */ + +/* firmware RX pointer for new style buffer */ +#define ENE_FW_RX_POINTER 0xF8FA + +/* high parts of samples for fan input (8 samples)*/ +#define ENE_FW_SMPL_BUF_FAN 0xF8FB +#define ENE_FW_SMPL_BUF_FAN_PLS 0x8000 /* combined sample is pulse */ +#define ENE_FW_SMPL_BUF_FAN_MSK 0x0FFF /* combined sample maximum value */ +#define ENE_FW_SAMPLE_PERIOD_FAN 61 /* fan input has fixed sample period */ + +/* transmitter ports */ +#define ENE_GPIOFS1 0xFC01 +#define ENE_GPIOFS1_GPIO0D 0x20 /* enable tx output on GPIO0D */ +#define ENE_GPIOFS8 0xFC08 +#define ENE_GPIOFS8_GPIO41 0x02 /* enable tx output on GPIO40 */ + +/* IRQ registers block (for revision B) */ +#define ENEB_IRQ 0xFD09 /* IRQ number */ +#define ENEB_IRQ_UNK1 0xFD17 /* unknown setting = 1 */ +#define ENEB_IRQ_STATUS 0xFD80 /* irq status */ +#define ENEB_IRQ_STATUS_IR 0x20 /* IR irq */ + +/* fan as input settings */ +#define ENE_FAN_AS_IN1 0xFE30 /* fan init reg 1 */ +#define ENE_FAN_AS_IN1_EN 0xCD +#define ENE_FAN_AS_IN2 0xFE31 /* fan init reg 2 */ +#define ENE_FAN_AS_IN2_EN 0x03 + +/* IRQ registers block (for revision C,D) */ +#define ENE_IRQ 0xFE9B /* new irq settings register */ +#define ENE_IRQ_MASK 0x0F /* irq number mask */ +#define ENE_IRQ_UNK_EN 0x10 /* always enabled */ +#define ENE_IRQ_STATUS 0x20 /* irq status and ACK */ + +/* CIR Config register #1 */ +#define ENE_CIRCFG 0xFEC0 +#define ENE_CIRCFG_RX_EN 0x01 /* RX enable */ +#define ENE_CIRCFG_RX_IRQ 0x02 /* Enable hardware interrupt */ +#define ENE_CIRCFG_REV_POL 0x04 /* Input polarity reversed */ +#define ENE_CIRCFG_CARR_DEMOD 0x08 /* Enable carrier demodulator */ + +#define ENE_CIRCFG_TX_EN 0x10 /* TX enable */ +#define ENE_CIRCFG_TX_IRQ 0x20 /* Send interrupt on TX done */ +#define ENE_CIRCFG_TX_POL_REV 0x40 /* TX polarity reversed */ +#define ENE_CIRCFG_TX_CARR 0x80 /* send TX carrier or not */ + +/* CIR config register #2 */ +#define ENE_CIRCFG2 0xFEC1 +#define ENE_CIRCFG2_RLC 0x00 +#define ENE_CIRCFG2_RC5 0x01 +#define ENE_CIRCFG2_RC6 0x02 +#define ENE_CIRCFG2_NEC 0x03 +#define ENE_CIRCFG2_CARR_DETECT 0x10 /* Enable carrier detection */ +#define ENE_CIRCFG2_GPIO0A 0x20 /* Use GPIO0A instead of GPIO40 for input */ +#define ENE_CIRCFG2_FAST_SAMPL1 0x40 /* Fast leading pulse detection for RC6 */ +#define ENE_CIRCFG2_FAST_SAMPL2 0x80 /* Fast data detection for RC6 */ + +/* Knobs for protocol decoding - will document when/if will use them */ +#define ENE_CIRPF 0xFEC2 +#define ENE_CIRHIGH 0xFEC3 +#define ENE_CIRBIT 0xFEC4 +#define ENE_CIRSTART 0xFEC5 +#define ENE_CIRSTART2 0xFEC6 + +/* Actual register which contains RLC RX data - read by firmware */ +#define ENE_CIRDAT_IN 0xFEC7 + + +/* RLC configuration - sample period (1us resulution) + idle mode */ +#define ENE_CIRRLC_CFG 0xFEC8 +#define ENE_CIRRLC_CFG_OVERFLOW 0x80 /* interrupt on overflows if set */ +#define ENE_DEFAULT_SAMPLE_PERIOD 50 + +/* Two byte RLC TX buffer */ +#define ENE_CIRRLC_OUT0 0xFEC9 +#define ENE_CIRRLC_OUT1 0xFECA +#define ENE_CIRRLC_OUT_PULSE 0x80 /* Transmitted sample is pulse */ +#define ENE_CIRRLC_OUT_MASK 0x7F + + +/* Carrier detect setting + * Low nibble - number of carrier pulses to average + * High nibble - number of initial carrier pulses to discard + */ +#define ENE_CIRCAR_PULS 0xFECB + +/* detected RX carrier period (resolution: 500 ns) */ +#define ENE_CIRCAR_PRD 0xFECC +#define ENE_CIRCAR_PRD_VALID 0x80 /* data valid content valid */ + +/* detected RX carrier pulse width (resolution: 500 ns) */ +#define ENE_CIRCAR_HPRD 0xFECD + +/* TX period (resolution: 500 ns, minimum 2)*/ +#define ENE_CIRMOD_PRD 0xFECE +#define ENE_CIRMOD_PRD_POL 0x80 /* TX carrier polarity*/ + +#define ENE_CIRMOD_PRD_MAX 0x7F /* 15.87 kHz */ +#define ENE_CIRMOD_PRD_MIN 0x02 /* 1 Mhz */ + +/* TX pulse width (resolution: 500 ns)*/ +#define ENE_CIRMOD_HPRD 0xFECF + +/* Hardware versions */ +#define ENE_ECHV 0xFF00 /* hardware revision */ +#define ENE_PLLFRH 0xFF16 +#define ENE_PLLFRL 0xFF17 +#define ENE_DEFAULT_PLL_FREQ 1000 + +#define ENE_ECSTS 0xFF1D +#define ENE_ECSTS_RSRVD 0x04 + +#define ENE_ECVER_MAJOR 0xFF1E /* chip version */ +#define ENE_ECVER_MINOR 0xFF1F +#define ENE_HW_VER_OLD 0xFD00 + +/******************************************************************************/ + +#define ENE_DRIVER_NAME "ene_ir" + +#define ENE_IRQ_RX 1 +#define ENE_IRQ_TX 2 + +#define ENE_HW_B 1 /* 3926B */ +#define ENE_HW_C 2 /* 3926C */ +#define ENE_HW_D 3 /* 3926D or later */ + +#define ene_printk(level, text, ...) \ + printk(level ENE_DRIVER_NAME ": " text "\n", ## __VA_ARGS__) + +#define ene_notice(text, ...) ene_printk(KERN_NOTICE, text, ## __VA_ARGS__) +#define ene_warn(text, ...) ene_printk(KERN_WARNING, text, ## __VA_ARGS__) + + +#define __dbg(level, format, ...) \ + do { \ + if (debug >= level) \ + printk(KERN_DEBUG ENE_DRIVER_NAME \ + ": " format "\n", ## __VA_ARGS__); \ + } while (0) + + +#define dbg(format, ...) __dbg(1, format, ## __VA_ARGS__) +#define dbg_verbose(format, ...) __dbg(2, format, ## __VA_ARGS__) +#define dbg_regs(format, ...) __dbg(3, format, ## __VA_ARGS__) + +#define MS_TO_NS(msec) ((msec) * 1000) + +struct ene_device { + struct pnp_dev *pnp_dev; + struct input_dev *idev; + struct ir_dev_props *props; + + /* hw IO settings */ + long hw_io; + int irq; + spinlock_t hw_lock; + + /* HW features */ + int hw_revision; /* hardware revision */ + bool hw_use_gpio_0a; /* gpio0a is demodulated input*/ + bool hw_extra_buffer; /* hardware has 'extra buffer' */ + bool hw_fan_input; /* fan input is IR data source */ + bool hw_learning_and_tx_capable; /* learning & tx capable */ + int pll_freq; + int buffer_len; + + /* Extra RX buffer location */ + int extra_buf1_address; + int extra_buf1_len; + int extra_buf2_address; + int extra_buf2_len; + + /* HW state*/ + int r_pointer; /* pointer to next sample to read */ + int w_pointer; /* pointer to next sample hw will write */ + bool rx_fan_input_inuse; /* is fan input in use for rx*/ + int tx_reg; /* current reg used for TX */ + u8 saved_conf1; /* saved FEC0 reg */ + unsigned int tx_sample; /* current sample for TX */ + bool tx_sample_pulse; /* current sample is pulse */ + + /* TX buffer */ + int *tx_buffer; /* input samples buffer*/ + int tx_pos; /* position in that bufer */ + int tx_len; /* current len of tx buffer */ + int tx_done; /* done transmitting */ + /* one more sample pending*/ + struct completion tx_complete; /* TX completion */ + struct timer_list tx_sim_timer; + + /* TX settings */ + int tx_period; + int tx_duty_cycle; + int transmitter_mask; + + /* RX settings */ + bool learning_mode_enabled; /* learning input enabled */ + bool carrier_detect_enabled; /* carrier detect enabled */ + int rx_period_adjust; + bool rx_enabled; +}; + +static int ene_irq_status(struct ene_device *dev); +static void ene_rx_read_hw_pointer(struct ene_device *dev); diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c new file mode 100644 index 0000000..79f4f58 --- /dev/null +++ b/drivers/media/rc/imon.c @@ -0,0 +1,2465 @@ +/* + * imon.c: input and display driver for SoundGraph iMON IR/VFD/LCD + * + * Copyright(C) 2010 Jarod Wilson + * Portions based on the original lirc_imon driver, + * Copyright(C) 2004 Venky Raju(dev@venky.ws) + * + * Huge thanks to R. Geoff Newbury for invaluable debugging on the + * 0xffdc iMON devices, and for sending me one to hack on, without + * which the support for them wouldn't be nearly as good. Thanks + * also to the numerous 0xffdc device owners that tested auto-config + * support for me and provided debug dumps from their devices. + * + * imon is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#define MOD_AUTHOR "Jarod Wilson " +#define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display" +#define MOD_NAME "imon" +#define MOD_VERSION "0.9.2" + +#define DISPLAY_MINOR_BASE 144 +#define DEVICE_NAME "lcd%d" + +#define BUF_CHUNK_SIZE 8 +#define BUF_SIZE 128 + +#define BIT_DURATION 250 /* each bit received is 250us */ + +#define IMON_CLOCK_ENABLE_PACKETS 2 + +/*** P R O T O T Y P E S ***/ + +/* USB Callback prototypes */ +static int imon_probe(struct usb_interface *interface, + const struct usb_device_id *id); +static void imon_disconnect(struct usb_interface *interface); +static void usb_rx_callback_intf0(struct urb *urb); +static void usb_rx_callback_intf1(struct urb *urb); +static void usb_tx_callback(struct urb *urb); + +/* suspend/resume support */ +static int imon_resume(struct usb_interface *intf); +static int imon_suspend(struct usb_interface *intf, pm_message_t message); + +/* Display file_operations function prototypes */ +static int display_open(struct inode *inode, struct file *file); +static int display_close(struct inode *inode, struct file *file); + +/* VFD write operation */ +static ssize_t vfd_write(struct file *file, const char *buf, + size_t n_bytes, loff_t *pos); + +/* LCD file_operations override function prototypes */ +static ssize_t lcd_write(struct file *file, const char *buf, + size_t n_bytes, loff_t *pos); + +/*** G L O B A L S ***/ + +struct imon_context { + struct device *dev; + struct ir_dev_props *props; + /* Newer devices have two interfaces */ + struct usb_device *usbdev_intf0; + struct usb_device *usbdev_intf1; + + bool display_supported; /* not all controllers do */ + bool display_isopen; /* display port has been opened */ + bool rf_device; /* true if iMON 2.4G LT/DT RF device */ + bool rf_isassociating; /* RF remote associating */ + bool dev_present_intf0; /* USB device presence, interface 0 */ + bool dev_present_intf1; /* USB device presence, interface 1 */ + + struct mutex lock; /* to lock this object */ + wait_queue_head_t remove_ok; /* For unexpected USB disconnects */ + + struct usb_endpoint_descriptor *rx_endpoint_intf0; + struct usb_endpoint_descriptor *rx_endpoint_intf1; + struct usb_endpoint_descriptor *tx_endpoint; + struct urb *rx_urb_intf0; + struct urb *rx_urb_intf1; + struct urb *tx_urb; + bool tx_control; + unsigned char usb_rx_buf[8]; + unsigned char usb_tx_buf[8]; + + struct tx_t { + unsigned char data_buf[35]; /* user data buffer */ + struct completion finished; /* wait for write to finish */ + bool busy; /* write in progress */ + int status; /* status of tx completion */ + } tx; + + u16 vendor; /* usb vendor ID */ + u16 product; /* usb product ID */ + + struct input_dev *rdev; /* input device for remote */ + struct input_dev *idev; /* input device for panel & IR mouse */ + struct input_dev *touch; /* input device for touchscreen */ + + spinlock_t kc_lock; /* make sure we get keycodes right */ + u32 kc; /* current input keycode */ + u32 last_keycode; /* last reported input keycode */ + u32 rc_scancode; /* the computed remote scancode */ + u8 rc_toggle; /* the computed remote toggle bit */ + u64 ir_type; /* iMON or MCE (RC6) IR protocol? */ + bool release_code; /* some keys send a release code */ + + u8 display_type; /* store the display type */ + bool pad_mouse; /* toggle kbd(0)/mouse(1) mode */ + + char name_rdev[128]; /* rc input device name */ + char phys_rdev[64]; /* rc input device phys path */ + + char name_idev[128]; /* input device name */ + char phys_idev[64]; /* input device phys path */ + + char name_touch[128]; /* touch screen name */ + char phys_touch[64]; /* touch screen phys path */ + struct timer_list ttimer; /* touch screen timer */ + int touch_x; /* x coordinate on touchscreen */ + int touch_y; /* y coordinate on touchscreen */ +}; + +#define TOUCH_TIMEOUT (HZ/30) + +/* vfd character device file operations */ +static const struct file_operations vfd_fops = { + .owner = THIS_MODULE, + .open = &display_open, + .write = &vfd_write, + .release = &display_close, + .llseek = noop_llseek, +}; + +/* lcd character device file operations */ +static const struct file_operations lcd_fops = { + .owner = THIS_MODULE, + .open = &display_open, + .write = &lcd_write, + .release = &display_close, + .llseek = noop_llseek, +}; + +enum { + IMON_DISPLAY_TYPE_AUTO = 0, + IMON_DISPLAY_TYPE_VFD = 1, + IMON_DISPLAY_TYPE_LCD = 2, + IMON_DISPLAY_TYPE_VGA = 3, + IMON_DISPLAY_TYPE_NONE = 4, +}; + +enum { + IMON_KEY_IMON = 0, + IMON_KEY_MCE = 1, + IMON_KEY_PANEL = 2, +}; + +/* + * USB Device ID for iMON USB Control Boards + * + * The Windows drivers contain 6 different inf files, more or less one for + * each new device until the 0x0034-0x0046 devices, which all use the same + * driver. Some of the devices in the 34-46 range haven't been definitively + * identified yet. Early devices have either a TriGem Computer, Inc. or a + * Samsung vendor ID (0x0aa8 and 0x04e8 respectively), while all later + * devices use the SoundGraph vendor ID (0x15c2). This driver only supports + * the ffdc and later devices, which do onboard decoding. + */ +static struct usb_device_id imon_usb_id_table[] = { + /* + * Several devices with this same device ID, all use iMON_PAD.inf + * SoundGraph iMON PAD (IR & VFD) + * SoundGraph iMON PAD (IR & LCD) + * SoundGraph iMON Knob (IR only) + */ + { USB_DEVICE(0x15c2, 0xffdc) }, + + /* + * Newer devices, all driven by the latest iMON Windows driver, full + * list of device IDs extracted via 'strings Setup/data1.hdr |grep 15c2' + * Need user input to fill in details on unknown devices. + */ + /* SoundGraph iMON OEM Touch LCD (IR & 7" VGA LCD) */ + { USB_DEVICE(0x15c2, 0x0034) }, + /* SoundGraph iMON OEM Touch LCD (IR & 4.3" VGA LCD) */ + { USB_DEVICE(0x15c2, 0x0035) }, + /* SoundGraph iMON OEM VFD (IR & VFD) */ + { USB_DEVICE(0x15c2, 0x0036) }, + /* device specifics unknown */ + { USB_DEVICE(0x15c2, 0x0037) }, + /* SoundGraph iMON OEM LCD (IR & LCD) */ + { USB_DEVICE(0x15c2, 0x0038) }, + /* SoundGraph iMON UltraBay (IR & LCD) */ + { USB_DEVICE(0x15c2, 0x0039) }, + /* device specifics unknown */ + { USB_DEVICE(0x15c2, 0x003a) }, + /* device specifics unknown */ + { USB_DEVICE(0x15c2, 0x003b) }, + /* SoundGraph iMON OEM Inside (IR only) */ + { USB_DEVICE(0x15c2, 0x003c) }, + /* device specifics unknown */ + { USB_DEVICE(0x15c2, 0x003d) }, + /* device specifics unknown */ + { USB_DEVICE(0x15c2, 0x003e) }, + /* device specifics unknown */ + { USB_DEVICE(0x15c2, 0x003f) }, + /* device specifics unknown */ + { USB_DEVICE(0x15c2, 0x0040) }, + /* SoundGraph iMON MINI (IR only) */ + { USB_DEVICE(0x15c2, 0x0041) }, + /* Antec Veris Multimedia Station EZ External (IR only) */ + { USB_DEVICE(0x15c2, 0x0042) }, + /* Antec Veris Multimedia Station Basic Internal (IR only) */ + { USB_DEVICE(0x15c2, 0x0043) }, + /* Antec Veris Multimedia Station Elite (IR & VFD) */ + { USB_DEVICE(0x15c2, 0x0044) }, + /* Antec Veris Multimedia Station Premiere (IR & LCD) */ + { USB_DEVICE(0x15c2, 0x0045) }, + /* device specifics unknown */ + { USB_DEVICE(0x15c2, 0x0046) }, + {} +}; + +/* USB Device data */ +static struct usb_driver imon_driver = { + .name = MOD_NAME, + .probe = imon_probe, + .disconnect = imon_disconnect, + .suspend = imon_suspend, + .resume = imon_resume, + .id_table = imon_usb_id_table, +}; + +static struct usb_class_driver imon_vfd_class = { + .name = DEVICE_NAME, + .fops = &vfd_fops, + .minor_base = DISPLAY_MINOR_BASE, +}; + +static struct usb_class_driver imon_lcd_class = { + .name = DEVICE_NAME, + .fops = &lcd_fops, + .minor_base = DISPLAY_MINOR_BASE, +}; + +/* imon receiver front panel/knob key table */ +static const struct { + u64 hw_code; + u32 keycode; +} imon_panel_key_table[] = { + { 0x000000000f00ffeell, KEY_PROG1 }, /* Go */ + { 0x000000001f00ffeell, KEY_AUDIO }, + { 0x000000002000ffeell, KEY_VIDEO }, + { 0x000000002100ffeell, KEY_CAMERA }, + { 0x000000002700ffeell, KEY_DVD }, + { 0x000000002300ffeell, KEY_TV }, + { 0x000000000500ffeell, KEY_PREVIOUS }, + { 0x000000000700ffeell, KEY_REWIND }, + { 0x000000000400ffeell, KEY_STOP }, + { 0x000000003c00ffeell, KEY_PLAYPAUSE }, + { 0x000000000800ffeell, KEY_FASTFORWARD }, + { 0x000000000600ffeell, KEY_NEXT }, + { 0x000000010000ffeell, KEY_RIGHT }, + { 0x000001000000ffeell, KEY_LEFT }, + { 0x000000003d00ffeell, KEY_SELECT }, + { 0x000100000000ffeell, KEY_VOLUMEUP }, + { 0x010000000000ffeell, KEY_VOLUMEDOWN }, + { 0x000000000100ffeell, KEY_MUTE }, + /* 0xffdc iMON MCE VFD */ + { 0x00010000ffffffeell, KEY_VOLUMEUP }, + { 0x01000000ffffffeell, KEY_VOLUMEDOWN }, + /* iMON Knob values */ + { 0x000100ffffffffeell, KEY_VOLUMEUP }, + { 0x010000ffffffffeell, KEY_VOLUMEDOWN }, + { 0x000008ffffffffeell, KEY_MUTE }, +}; + +/* to prevent races between open() and disconnect(), probing, etc */ +static DEFINE_MUTEX(driver_lock); + +/* Module bookkeeping bits */ +MODULE_AUTHOR(MOD_AUTHOR); +MODULE_DESCRIPTION(MOD_DESC); +MODULE_VERSION(MOD_VERSION); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(usb, imon_usb_id_table); + +static bool debug; +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes (default: no)"); + +/* lcd, vfd, vga or none? should be auto-detected, but can be overridden... */ +static int display_type; +module_param(display_type, int, S_IRUGO); +MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, " + "1=vfd, 2=lcd, 3=vga, 4=none (default: autodetect)"); + +static int pad_stabilize = 1; +module_param(pad_stabilize, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(pad_stabilize, "Apply stabilization algorithm to iMON PAD " + "presses in arrow key mode. 0=disable, 1=enable (default)."); + +/* + * In certain use cases, mouse mode isn't really helpful, and could actually + * cause confusion, so allow disabling it when the IR device is open. + */ +static bool nomouse; +module_param(nomouse, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(nomouse, "Disable mouse input device mode when IR device is " + "open. 0=don't disable, 1=disable. (default: don't disable)"); + +/* threshold at which a pad push registers as an arrow key in kbd mode */ +static int pad_thresh; +module_param(pad_thresh, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(pad_thresh, "Threshold at which a pad push registers as an " + "arrow key in kbd mode (default: 28)"); + + +static void free_imon_context(struct imon_context *ictx) +{ + struct device *dev = ictx->dev; + + usb_free_urb(ictx->tx_urb); + usb_free_urb(ictx->rx_urb_intf0); + usb_free_urb(ictx->rx_urb_intf1); + kfree(ictx); + + dev_dbg(dev, "%s: iMON context freed\n", __func__); +} + +/** + * Called when the Display device (e.g. /dev/lcd0) + * is opened by the application. + */ +static int display_open(struct inode *inode, struct file *file) +{ + struct usb_interface *interface; + struct imon_context *ictx = NULL; + int subminor; + int retval = 0; + + /* prevent races with disconnect */ + mutex_lock(&driver_lock); + + subminor = iminor(inode); + interface = usb_find_interface(&imon_driver, subminor); + if (!interface) { + pr_err("could not find interface for minor %d\n", subminor); + retval = -ENODEV; + goto exit; + } + ictx = usb_get_intfdata(interface); + + if (!ictx) { + pr_err("no context found for minor %d\n", subminor); + retval = -ENODEV; + goto exit; + } + + mutex_lock(&ictx->lock); + + if (!ictx->display_supported) { + pr_err("display not supported by device\n"); + retval = -ENODEV; + } else if (ictx->display_isopen) { + pr_err("display port is already open\n"); + retval = -EBUSY; + } else { + ictx->display_isopen = true; + file->private_data = ictx; + dev_dbg(ictx->dev, "display port opened\n"); + } + + mutex_unlock(&ictx->lock); + +exit: + mutex_unlock(&driver_lock); + return retval; +} + +/** + * Called when the display device (e.g. /dev/lcd0) + * is closed by the application. + */ +static int display_close(struct inode *inode, struct file *file) +{ + struct imon_context *ictx = NULL; + int retval = 0; + + ictx = file->private_data; + + if (!ictx) { + pr_err("no context for device\n"); + return -ENODEV; + } + + mutex_lock(&ictx->lock); + + if (!ictx->display_supported) { + pr_err("display not supported by device\n"); + retval = -ENODEV; + } else if (!ictx->display_isopen) { + pr_err("display is not open\n"); + retval = -EIO; + } else { + ictx->display_isopen = false; + dev_dbg(ictx->dev, "display port closed\n"); + if (!ictx->dev_present_intf0) { + /* + * Device disconnected before close and IR port is not + * open. If IR port is open, context will be deleted by + * ir_close. + */ + mutex_unlock(&ictx->lock); + free_imon_context(ictx); + return retval; + } + } + + mutex_unlock(&ictx->lock); + return retval; +} + +/** + * Sends a packet to the device -- this function must be called + * with ictx->lock held. + */ +static int send_packet(struct imon_context *ictx) +{ + unsigned int pipe; + unsigned long timeout; + int interval = 0; + int retval = 0; + struct usb_ctrlrequest *control_req = NULL; + + /* Check if we need to use control or interrupt urb */ + if (!ictx->tx_control) { + pipe = usb_sndintpipe(ictx->usbdev_intf0, + ictx->tx_endpoint->bEndpointAddress); + interval = ictx->tx_endpoint->bInterval; + + usb_fill_int_urb(ictx->tx_urb, ictx->usbdev_intf0, pipe, + ictx->usb_tx_buf, + sizeof(ictx->usb_tx_buf), + usb_tx_callback, ictx, interval); + + ictx->tx_urb->actual_length = 0; + } else { + /* fill request into kmalloc'ed space: */ + control_req = kmalloc(sizeof(struct usb_ctrlrequest), + GFP_KERNEL); + if (control_req == NULL) + return -ENOMEM; + + /* setup packet is '21 09 0200 0001 0008' */ + control_req->bRequestType = 0x21; + control_req->bRequest = 0x09; + control_req->wValue = cpu_to_le16(0x0200); + control_req->wIndex = cpu_to_le16(0x0001); + control_req->wLength = cpu_to_le16(0x0008); + + /* control pipe is endpoint 0x00 */ + pipe = usb_sndctrlpipe(ictx->usbdev_intf0, 0); + + /* build the control urb */ + usb_fill_control_urb(ictx->tx_urb, ictx->usbdev_intf0, + pipe, (unsigned char *)control_req, + ictx->usb_tx_buf, + sizeof(ictx->usb_tx_buf), + usb_tx_callback, ictx); + ictx->tx_urb->actual_length = 0; + } + + init_completion(&ictx->tx.finished); + ictx->tx.busy = true; + smp_rmb(); /* ensure later readers know we're busy */ + + retval = usb_submit_urb(ictx->tx_urb, GFP_KERNEL); + if (retval) { + ictx->tx.busy = false; + smp_rmb(); /* ensure later readers know we're not busy */ + pr_err("error submitting urb(%d)\n", retval); + } else { + /* Wait for transmission to complete (or abort) */ + mutex_unlock(&ictx->lock); + retval = wait_for_completion_interruptible( + &ictx->tx.finished); + if (retval) + pr_err("task interrupted\n"); + mutex_lock(&ictx->lock); + + retval = ictx->tx.status; + if (retval) + pr_err("packet tx failed (%d)\n", retval); + } + + kfree(control_req); + + /* + * Induce a mandatory 5ms delay before returning, as otherwise, + * send_packet can get called so rapidly as to overwhelm the device, + * particularly on faster systems and/or those with quirky usb. + */ + timeout = msecs_to_jiffies(5); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(timeout); + + return retval; +} + +/** + * Sends an associate packet to the iMON 2.4G. + * + * This might not be such a good idea, since it has an id collision with + * some versions of the "IR & VFD" combo. The only way to determine if it + * is an RF version is to look at the product description string. (Which + * we currently do not fetch). + */ +static int send_associate_24g(struct imon_context *ictx) +{ + int retval; + const unsigned char packet[8] = { 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20 }; + + if (!ictx) { + pr_err("no context for device\n"); + return -ENODEV; + } + + if (!ictx->dev_present_intf0) { + pr_err("no iMON device present\n"); + return -ENODEV; + } + + memcpy(ictx->usb_tx_buf, packet, sizeof(packet)); + retval = send_packet(ictx); + + return retval; +} + +/** + * Sends packets to setup and show clock on iMON display + * + * Arguments: year - last 2 digits of year, month - 1..12, + * day - 1..31, dow - day of the week (0-Sun...6-Sat), + * hour - 0..23, minute - 0..59, second - 0..59 + */ +static int send_set_imon_clock(struct imon_context *ictx, + unsigned int year, unsigned int month, + unsigned int day, unsigned int dow, + unsigned int hour, unsigned int minute, + unsigned int second) +{ + unsigned char clock_enable_pkt[IMON_CLOCK_ENABLE_PACKETS][8]; + int retval = 0; + int i; + + if (!ictx) { + pr_err("no context for device\n"); + return -ENODEV; + } + + switch (ictx->display_type) { + case IMON_DISPLAY_TYPE_LCD: + clock_enable_pkt[0][0] = 0x80; + clock_enable_pkt[0][1] = year; + clock_enable_pkt[0][2] = month-1; + clock_enable_pkt[0][3] = day; + clock_enable_pkt[0][4] = hour; + clock_enable_pkt[0][5] = minute; + clock_enable_pkt[0][6] = second; + + clock_enable_pkt[1][0] = 0x80; + clock_enable_pkt[1][1] = 0; + clock_enable_pkt[1][2] = 0; + clock_enable_pkt[1][3] = 0; + clock_enable_pkt[1][4] = 0; + clock_enable_pkt[1][5] = 0; + clock_enable_pkt[1][6] = 0; + + if (ictx->product == 0xffdc) { + clock_enable_pkt[0][7] = 0x50; + clock_enable_pkt[1][7] = 0x51; + } else { + clock_enable_pkt[0][7] = 0x88; + clock_enable_pkt[1][7] = 0x8a; + } + + break; + + case IMON_DISPLAY_TYPE_VFD: + clock_enable_pkt[0][0] = year; + clock_enable_pkt[0][1] = month-1; + clock_enable_pkt[0][2] = day; + clock_enable_pkt[0][3] = dow; + clock_enable_pkt[0][4] = hour; + clock_enable_pkt[0][5] = minute; + clock_enable_pkt[0][6] = second; + clock_enable_pkt[0][7] = 0x40; + + clock_enable_pkt[1][0] = 0; + clock_enable_pkt[1][1] = 0; + clock_enable_pkt[1][2] = 1; + clock_enable_pkt[1][3] = 0; + clock_enable_pkt[1][4] = 0; + clock_enable_pkt[1][5] = 0; + clock_enable_pkt[1][6] = 0; + clock_enable_pkt[1][7] = 0x42; + + break; + + default: + return -ENODEV; + } + + for (i = 0; i < IMON_CLOCK_ENABLE_PACKETS; i++) { + memcpy(ictx->usb_tx_buf, clock_enable_pkt[i], 8); + retval = send_packet(ictx); + if (retval) { + pr_err("send_packet failed for packet %d\n", i); + break; + } + } + + return retval; +} + +/** + * These are the sysfs functions to handle the association on the iMON 2.4G LT. + */ +static ssize_t show_associate_remote(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct imon_context *ictx = dev_get_drvdata(d); + + if (!ictx) + return -ENODEV; + + mutex_lock(&ictx->lock); + if (ictx->rf_isassociating) + strcpy(buf, "associating\n"); + else + strcpy(buf, "closed\n"); + + dev_info(d, "Visit http://www.lirc.org/html/imon-24g.html for " + "instructions on how to associate your iMON 2.4G DT/LT " + "remote\n"); + mutex_unlock(&ictx->lock); + return strlen(buf); +} + +static ssize_t store_associate_remote(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct imon_context *ictx; + + ictx = dev_get_drvdata(d); + + if (!ictx) + return -ENODEV; + + mutex_lock(&ictx->lock); + ictx->rf_isassociating = true; + send_associate_24g(ictx); + mutex_unlock(&ictx->lock); + + return count; +} + +/** + * sysfs functions to control internal imon clock + */ +static ssize_t show_imon_clock(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct imon_context *ictx = dev_get_drvdata(d); + size_t len; + + if (!ictx) + return -ENODEV; + + mutex_lock(&ictx->lock); + + if (!ictx->display_supported) { + len = snprintf(buf, PAGE_SIZE, "Not supported."); + } else { + len = snprintf(buf, PAGE_SIZE, + "To set the clock on your iMON display:\n" + "# date \"+%%y %%m %%d %%w %%H %%M %%S\" > imon_clock\n" + "%s", ictx->display_isopen ? + "\nNOTE: imon device must be closed\n" : ""); + } + + mutex_unlock(&ictx->lock); + + return len; +} + +static ssize_t store_imon_clock(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct imon_context *ictx = dev_get_drvdata(d); + ssize_t retval; + unsigned int year, month, day, dow, hour, minute, second; + + if (!ictx) + return -ENODEV; + + mutex_lock(&ictx->lock); + + if (!ictx->display_supported) { + retval = -ENODEV; + goto exit; + } else if (ictx->display_isopen) { + retval = -EBUSY; + goto exit; + } + + if (sscanf(buf, "%u %u %u %u %u %u %u", &year, &month, &day, &dow, + &hour, &minute, &second) != 7) { + retval = -EINVAL; + goto exit; + } + + if ((month < 1 || month > 12) || + (day < 1 || day > 31) || (dow > 6) || + (hour > 23) || (minute > 59) || (second > 59)) { + retval = -EINVAL; + goto exit; + } + + retval = send_set_imon_clock(ictx, year, month, day, dow, + hour, minute, second); + if (retval) + goto exit; + + retval = count; +exit: + mutex_unlock(&ictx->lock); + + return retval; +} + + +static DEVICE_ATTR(imon_clock, S_IWUSR | S_IRUGO, show_imon_clock, + store_imon_clock); + +static DEVICE_ATTR(associate_remote, S_IWUSR | S_IRUGO, show_associate_remote, + store_associate_remote); + +static struct attribute *imon_display_sysfs_entries[] = { + &dev_attr_imon_clock.attr, + NULL +}; + +static struct attribute_group imon_display_attr_group = { + .attrs = imon_display_sysfs_entries +}; + +static struct attribute *imon_rf_sysfs_entries[] = { + &dev_attr_associate_remote.attr, + NULL +}; + +static struct attribute_group imon_rf_attr_group = { + .attrs = imon_rf_sysfs_entries +}; + +/** + * Writes data to the VFD. The iMON VFD is 2x16 characters + * and requires data in 5 consecutive USB interrupt packets, + * each packet but the last carrying 7 bytes. + * + * I don't know if the VFD board supports features such as + * scrolling, clearing rows, blanking, etc. so at + * the caller must provide a full screen of data. If fewer + * than 32 bytes are provided spaces will be appended to + * generate a full screen. + */ +static ssize_t vfd_write(struct file *file, const char *buf, + size_t n_bytes, loff_t *pos) +{ + int i; + int offset; + int seq; + int retval = 0; + struct imon_context *ictx; + const unsigned char vfd_packet6[] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF }; + + ictx = file->private_data; + if (!ictx) { + pr_err("no context for device\n"); + return -ENODEV; + } + + mutex_lock(&ictx->lock); + + if (!ictx->dev_present_intf0) { + pr_err("no iMON device present\n"); + retval = -ENODEV; + goto exit; + } + + if (n_bytes <= 0 || n_bytes > 32) { + pr_err("invalid payload size\n"); + retval = -EINVAL; + goto exit; + } + + if (copy_from_user(ictx->tx.data_buf, buf, n_bytes)) { + retval = -EFAULT; + goto exit; + } + + /* Pad with spaces */ + for (i = n_bytes; i < 32; ++i) + ictx->tx.data_buf[i] = ' '; + + for (i = 32; i < 35; ++i) + ictx->tx.data_buf[i] = 0xFF; + + offset = 0; + seq = 0; + + do { + memcpy(ictx->usb_tx_buf, ictx->tx.data_buf + offset, 7); + ictx->usb_tx_buf[7] = (unsigned char) seq; + + retval = send_packet(ictx); + if (retval) { + pr_err("send packet failed for packet #%d\n", seq / 2); + goto exit; + } else { + seq += 2; + offset += 7; + } + + } while (offset < 35); + + /* Send packet #6 */ + memcpy(ictx->usb_tx_buf, &vfd_packet6, sizeof(vfd_packet6)); + ictx->usb_tx_buf[7] = (unsigned char) seq; + retval = send_packet(ictx); + if (retval) + pr_err("send packet failed for packet #%d\n", seq / 2); + +exit: + mutex_unlock(&ictx->lock); + + return (!retval) ? n_bytes : retval; +} + +/** + * Writes data to the LCD. The iMON OEM LCD screen expects 8-byte + * packets. We accept data as 16 hexadecimal digits, followed by a + * newline (to make it easy to drive the device from a command-line + * -- even though the actual binary data is a bit complicated). + * + * The device itself is not a "traditional" text-mode display. It's + * actually a 16x96 pixel bitmap display. That means if you want to + * display text, you've got to have your own "font" and translate the + * text into bitmaps for display. This is really flexible (you can + * display whatever diacritics you need, and so on), but it's also + * a lot more complicated than most LCDs... + */ +static ssize_t lcd_write(struct file *file, const char *buf, + size_t n_bytes, loff_t *pos) +{ + int retval = 0; + struct imon_context *ictx; + + ictx = file->private_data; + if (!ictx) { + pr_err("no context for device\n"); + return -ENODEV; + } + + mutex_lock(&ictx->lock); + + if (!ictx->display_supported) { + pr_err("no iMON display present\n"); + retval = -ENODEV; + goto exit; + } + + if (n_bytes != 8) { + pr_err("invalid payload size: %d (expected 8)\n", (int)n_bytes); + retval = -EINVAL; + goto exit; + } + + if (copy_from_user(ictx->usb_tx_buf, buf, 8)) { + retval = -EFAULT; + goto exit; + } + + retval = send_packet(ictx); + if (retval) { + pr_err("send packet failed!\n"); + goto exit; + } else { + dev_dbg(ictx->dev, "%s: write %d bytes to LCD\n", + __func__, (int) n_bytes); + } +exit: + mutex_unlock(&ictx->lock); + return (!retval) ? n_bytes : retval; +} + +/** + * Callback function for USB core API: transmit data + */ +static void usb_tx_callback(struct urb *urb) +{ + struct imon_context *ictx; + + if (!urb) + return; + ictx = (struct imon_context *)urb->context; + if (!ictx) + return; + + ictx->tx.status = urb->status; + + /* notify waiters that write has finished */ + ictx->tx.busy = false; + smp_rmb(); /* ensure later readers know we're not busy */ + complete(&ictx->tx.finished); +} + +/** + * report touchscreen input + */ +static void imon_touch_display_timeout(unsigned long data) +{ + struct imon_context *ictx = (struct imon_context *)data; + + if (ictx->display_type != IMON_DISPLAY_TYPE_VGA) + return; + + input_report_abs(ictx->touch, ABS_X, ictx->touch_x); + input_report_abs(ictx->touch, ABS_Y, ictx->touch_y); + input_report_key(ictx->touch, BTN_TOUCH, 0x00); + input_sync(ictx->touch); +} + +/** + * iMON IR receivers support two different signal sets -- those used by + * the iMON remotes, and those used by the Windows MCE remotes (which is + * really just RC-6), but only one or the other at a time, as the signals + * are decoded onboard the receiver. + */ +int imon_ir_change_protocol(void *priv, u64 ir_type) +{ + int retval; + struct imon_context *ictx = priv; + struct device *dev = ictx->dev; + bool pad_mouse; + unsigned char ir_proto_packet[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 }; + + if (ir_type && !(ir_type & ictx->props->allowed_protos)) + dev_warn(dev, "Looks like you're trying to use an IR protocol " + "this device does not support\n"); + + switch (ir_type) { + case IR_TYPE_RC6: + dev_dbg(dev, "Configuring IR receiver for MCE protocol\n"); + ir_proto_packet[0] = 0x01; + pad_mouse = false; + break; + case IR_TYPE_UNKNOWN: + case IR_TYPE_OTHER: + dev_dbg(dev, "Configuring IR receiver for iMON protocol\n"); + if (pad_stabilize && !nomouse) + pad_mouse = true; + else { + dev_dbg(dev, "PAD stabilize functionality disabled\n"); + pad_mouse = false; + } + /* ir_proto_packet[0] = 0x00; // already the default */ + ir_type = IR_TYPE_OTHER; + break; + default: + dev_warn(dev, "Unsupported IR protocol specified, overriding " + "to iMON IR protocol\n"); + if (pad_stabilize && !nomouse) + pad_mouse = true; + else { + dev_dbg(dev, "PAD stabilize functionality disabled\n"); + pad_mouse = false; + } + /* ir_proto_packet[0] = 0x00; // already the default */ + ir_type = IR_TYPE_OTHER; + break; + } + + memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet)); + + retval = send_packet(ictx); + if (retval) + goto out; + + ictx->ir_type = ir_type; + ictx->pad_mouse = pad_mouse; + +out: + return retval; +} + +static inline int tv2int(const struct timeval *a, const struct timeval *b) +{ + int usecs = 0; + int sec = 0; + + if (b->tv_usec > a->tv_usec) { + usecs = 1000000; + sec--; + } + + usecs += a->tv_usec - b->tv_usec; + + sec += a->tv_sec - b->tv_sec; + sec *= 1000; + usecs /= 1000; + sec += usecs; + + if (sec < 0) + sec = 1000; + + return sec; +} + +/** + * The directional pad behaves a bit differently, depending on whether this is + * one of the older ffdc devices or a newer device. Newer devices appear to + * have a higher resolution matrix for more precise mouse movement, but it + * makes things overly sensitive in keyboard mode, so we do some interesting + * contortions to make it less touchy. Older devices run through the same + * routine with shorter timeout and a smaller threshold. + */ +static int stabilize(int a, int b, u16 timeout, u16 threshold) +{ + struct timeval ct; + static struct timeval prev_time = {0, 0}; + static struct timeval hit_time = {0, 0}; + static int x, y, prev_result, hits; + int result = 0; + int msec, msec_hit; + + do_gettimeofday(&ct); + msec = tv2int(&ct, &prev_time); + msec_hit = tv2int(&ct, &hit_time); + + if (msec > 100) { + x = 0; + y = 0; + hits = 0; + } + + x += a; + y += b; + + prev_time = ct; + + if (abs(x) > threshold || abs(y) > threshold) { + if (abs(y) > abs(x)) + result = (y > 0) ? 0x7F : 0x80; + else + result = (x > 0) ? 0x7F00 : 0x8000; + + x = 0; + y = 0; + + if (result == prev_result) { + hits++; + + if (hits > 3) { + switch (result) { + case 0x7F: + y = 17 * threshold / 30; + break; + case 0x80: + y -= 17 * threshold / 30; + break; + case 0x7F00: + x = 17 * threshold / 30; + break; + case 0x8000: + x -= 17 * threshold / 30; + break; + } + } + + if (hits == 2 && msec_hit < timeout) { + result = 0; + hits = 1; + } + } else { + prev_result = result; + hits = 1; + hit_time = ct; + } + } + + return result; +} + +static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 scancode) +{ + u32 keycode; + u32 release; + bool is_release_code = false; + + /* Look for the initial press of a button */ + keycode = ir_g_keycode_from_table(ictx->rdev, scancode); + ictx->rc_toggle = 0x0; + ictx->rc_scancode = scancode; + + /* Look for the release of a button */ + if (keycode == KEY_RESERVED) { + release = scancode & ~0x4000; + keycode = ir_g_keycode_from_table(ictx->rdev, release); + if (keycode != KEY_RESERVED) + is_release_code = true; + } + + ictx->release_code = is_release_code; + + return keycode; +} + +static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 scancode) +{ + u32 keycode; + +#define MCE_KEY_MASK 0x7000 +#define MCE_TOGGLE_BIT 0x8000 + + /* + * On some receivers, mce keys decode to 0x8000f04xx and 0x8000f84xx + * (the toggle bit flipping between alternating key presses), while + * on other receivers, we see 0x8000f74xx and 0x8000ff4xx. To keep + * the table trim, we always or in the bits to look up 0x8000ff4xx, + * but we can't or them into all codes, as some keys are decoded in + * a different way w/o the same use of the toggle bit... + */ + if (scancode & 0x80000000) + scancode = scancode | MCE_KEY_MASK | MCE_TOGGLE_BIT; + + ictx->rc_scancode = scancode; + keycode = ir_g_keycode_from_table(ictx->rdev, scancode); + + /* not used in mce mode, but make sure we know its false */ + ictx->release_code = false; + + return keycode; +} + +static u32 imon_panel_key_lookup(u64 code) +{ + int i; + u32 keycode = KEY_RESERVED; + + for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) { + if (imon_panel_key_table[i].hw_code == (code | 0xffee)) { + keycode = imon_panel_key_table[i].keycode; + break; + } + } + + return keycode; +} + +static bool imon_mouse_event(struct imon_context *ictx, + unsigned char *buf, int len) +{ + char rel_x = 0x00, rel_y = 0x00; + u8 right_shift = 1; + bool mouse_input = true; + int dir = 0; + unsigned long flags; + + spin_lock_irqsave(&ictx->kc_lock, flags); + + /* newer iMON device PAD or mouse button */ + if (ictx->product != 0xffdc && (buf[0] & 0x01) && len == 5) { + rel_x = buf[2]; + rel_y = buf[3]; + right_shift = 1; + /* 0xffdc iMON PAD or mouse button input */ + } else if (ictx->product == 0xffdc && (buf[0] & 0x40) && + !((buf[1] & 0x01) || ((buf[1] >> 2) & 0x01))) { + rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 | + (buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6; + if (buf[0] & 0x02) + rel_x |= ~0x0f; + rel_x = rel_x + rel_x / 2; + rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 | + (buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6; + if (buf[0] & 0x01) + rel_y |= ~0x0f; + rel_y = rel_y + rel_y / 2; + right_shift = 2; + /* some ffdc devices decode mouse buttons differently... */ + } else if (ictx->product == 0xffdc && (buf[0] == 0x68)) { + right_shift = 2; + /* ch+/- buttons, which we use for an emulated scroll wheel */ + } else if (ictx->kc == KEY_CHANNELUP && (buf[2] & 0x40) != 0x40) { + dir = 1; + } else if (ictx->kc == KEY_CHANNELDOWN && (buf[2] & 0x40) != 0x40) { + dir = -1; + } else + mouse_input = false; + + spin_unlock_irqrestore(&ictx->kc_lock, flags); + + if (mouse_input) { + dev_dbg(ictx->dev, "sending mouse data via input subsystem\n"); + + if (dir) { + input_report_rel(ictx->idev, REL_WHEEL, dir); + } else if (rel_x || rel_y) { + input_report_rel(ictx->idev, REL_X, rel_x); + input_report_rel(ictx->idev, REL_Y, rel_y); + } else { + input_report_key(ictx->idev, BTN_LEFT, buf[1] & 0x1); + input_report_key(ictx->idev, BTN_RIGHT, + buf[1] >> right_shift & 0x1); + } + input_sync(ictx->idev); + spin_lock_irqsave(&ictx->kc_lock, flags); + ictx->last_keycode = ictx->kc; + spin_unlock_irqrestore(&ictx->kc_lock, flags); + } + + return mouse_input; +} + +static void imon_touch_event(struct imon_context *ictx, unsigned char *buf) +{ + mod_timer(&ictx->ttimer, jiffies + TOUCH_TIMEOUT); + ictx->touch_x = (buf[0] << 4) | (buf[1] >> 4); + ictx->touch_y = 0xfff - ((buf[2] << 4) | (buf[1] & 0xf)); + input_report_abs(ictx->touch, ABS_X, ictx->touch_x); + input_report_abs(ictx->touch, ABS_Y, ictx->touch_y); + input_report_key(ictx->touch, BTN_TOUCH, 0x01); + input_sync(ictx->touch); +} + +static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) +{ + int dir = 0; + char rel_x = 0x00, rel_y = 0x00; + u16 timeout, threshold; + u32 scancode = KEY_RESERVED; + unsigned long flags; + + /* + * The imon directional pad functions more like a touchpad. Bytes 3 & 4 + * contain a position coordinate (x,y), with each component ranging + * from -14 to 14. We want to down-sample this to only 4 discrete values + * for up/down/left/right arrow keys. Also, when you get too close to + * diagonals, it has a tendancy to jump back and forth, so lets try to + * ignore when they get too close. + */ + if (ictx->product != 0xffdc) { + /* first, pad to 8 bytes so it conforms with everything else */ + buf[5] = buf[6] = buf[7] = 0; + timeout = 500; /* in msecs */ + /* (2*threshold) x (2*threshold) square */ + threshold = pad_thresh ? pad_thresh : 28; + rel_x = buf[2]; + rel_y = buf[3]; + + if (ictx->ir_type == IR_TYPE_OTHER && pad_stabilize) { + if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) { + dir = stabilize((int)rel_x, (int)rel_y, + timeout, threshold); + if (!dir) { + spin_lock_irqsave(&ictx->kc_lock, + flags); + ictx->kc = KEY_UNKNOWN; + spin_unlock_irqrestore(&ictx->kc_lock, + flags); + return; + } + buf[2] = dir & 0xFF; + buf[3] = (dir >> 8) & 0xFF; + scancode = be32_to_cpu(*((u32 *)buf)); + } + } else { + /* + * Hack alert: instead of using keycodes, we have + * to use hard-coded scancodes here... + */ + if (abs(rel_y) > abs(rel_x)) { + buf[2] = (rel_y > 0) ? 0x7F : 0x80; + buf[3] = 0; + if (rel_y > 0) + scancode = 0x01007f00; /* KEY_DOWN */ + else + scancode = 0x01008000; /* KEY_UP */ + } else { + buf[2] = 0; + buf[3] = (rel_x > 0) ? 0x7F : 0x80; + if (rel_x > 0) + scancode = 0x0100007f; /* KEY_RIGHT */ + else + scancode = 0x01000080; /* KEY_LEFT */ + } + } + + /* + * Handle on-board decoded pad events for e.g. older VFD/iMON-Pad + * device (15c2:ffdc). The remote generates various codes from + * 0x68nnnnB7 to 0x6AnnnnB7, the left mouse button generates + * 0x688301b7 and the right one 0x688481b7. All other keys generate + * 0x2nnnnnnn. Position coordinate is encoded in buf[1] and buf[2] with + * reversed endianess. Extract direction from buffer, rotate endianess, + * adjust sign and feed the values into stabilize(). The resulting codes + * will be 0x01008000, 0x01007F00, which match the newer devices. + */ + } else { + timeout = 10; /* in msecs */ + /* (2*threshold) x (2*threshold) square */ + threshold = pad_thresh ? pad_thresh : 15; + + /* buf[1] is x */ + rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 | + (buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6; + if (buf[0] & 0x02) + rel_x |= ~0x10+1; + /* buf[2] is y */ + rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 | + (buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6; + if (buf[0] & 0x01) + rel_y |= ~0x10+1; + + buf[0] = 0x01; + buf[1] = buf[4] = buf[5] = buf[6] = buf[7] = 0; + + if (ictx->ir_type == IR_TYPE_OTHER && pad_stabilize) { + dir = stabilize((int)rel_x, (int)rel_y, + timeout, threshold); + if (!dir) { + spin_lock_irqsave(&ictx->kc_lock, flags); + ictx->kc = KEY_UNKNOWN; + spin_unlock_irqrestore(&ictx->kc_lock, flags); + return; + } + buf[2] = dir & 0xFF; + buf[3] = (dir >> 8) & 0xFF; + scancode = be32_to_cpu(*((u32 *)buf)); + } else { + /* + * Hack alert: instead of using keycodes, we have + * to use hard-coded scancodes here... + */ + if (abs(rel_y) > abs(rel_x)) { + buf[2] = (rel_y > 0) ? 0x7F : 0x80; + buf[3] = 0; + if (rel_y > 0) + scancode = 0x01007f00; /* KEY_DOWN */ + else + scancode = 0x01008000; /* KEY_UP */ + } else { + buf[2] = 0; + buf[3] = (rel_x > 0) ? 0x7F : 0x80; + if (rel_x > 0) + scancode = 0x0100007f; /* KEY_RIGHT */ + else + scancode = 0x01000080; /* KEY_LEFT */ + } + } + } + + if (scancode) { + spin_lock_irqsave(&ictx->kc_lock, flags); + ictx->kc = imon_remote_key_lookup(ictx, scancode); + spin_unlock_irqrestore(&ictx->kc_lock, flags); + } +} + +/** + * figure out if these is a press or a release. We don't actually + * care about repeats, as those will be auto-generated within the IR + * subsystem for repeating scancodes. + */ +static int imon_parse_press_type(struct imon_context *ictx, + unsigned char *buf, u8 ktype) +{ + int press_type = 0; + unsigned long flags; + + spin_lock_irqsave(&ictx->kc_lock, flags); + + /* key release of 0x02XXXXXX key */ + if (ictx->kc == KEY_RESERVED && buf[0] == 0x02 && buf[3] == 0x00) + ictx->kc = ictx->last_keycode; + + /* mouse button release on (some) 0xffdc devices */ + else if (ictx->kc == KEY_RESERVED && buf[0] == 0x68 && buf[1] == 0x82 && + buf[2] == 0x81 && buf[3] == 0xb7) + ictx->kc = ictx->last_keycode; + + /* mouse button release on (some other) 0xffdc devices */ + else if (ictx->kc == KEY_RESERVED && buf[0] == 0x01 && buf[1] == 0x00 && + buf[2] == 0x81 && buf[3] == 0xb7) + ictx->kc = ictx->last_keycode; + + /* mce-specific button handling, no keyup events */ + else if (ktype == IMON_KEY_MCE) { + ictx->rc_toggle = buf[2]; + press_type = 1; + + /* incoherent or irrelevant data */ + } else if (ictx->kc == KEY_RESERVED) + press_type = -EINVAL; + + /* key release of 0xXXXXXXb7 key */ + else if (ictx->release_code) + press_type = 0; + + /* this is a button press */ + else + press_type = 1; + + spin_unlock_irqrestore(&ictx->kc_lock, flags); + + return press_type; +} + +/** + * Process the incoming packet + */ +static void imon_incoming_packet(struct imon_context *ictx, + struct urb *urb, int intf) +{ + int len = urb->actual_length; + unsigned char *buf = urb->transfer_buffer; + struct device *dev = ictx->dev; + unsigned long flags; + u32 kc; + bool norelease = false; + int i; + u64 scancode; + int press_type = 0; + int msec; + struct timeval t; + static struct timeval prev_time = { 0, 0 }; + u8 ktype; + + /* filter out junk data on the older 0xffdc imon devices */ + if ((buf[0] == 0xff) && (buf[1] == 0xff) && (buf[2] == 0xff)) + return; + + /* Figure out what key was pressed */ + if (len == 8 && buf[7] == 0xee) { + scancode = be64_to_cpu(*((u64 *)buf)); + ktype = IMON_KEY_PANEL; + kc = imon_panel_key_lookup(scancode); + } else { + scancode = be32_to_cpu(*((u32 *)buf)); + if (ictx->ir_type == IR_TYPE_RC6) { + ktype = IMON_KEY_IMON; + if (buf[0] == 0x80) + ktype = IMON_KEY_MCE; + kc = imon_mce_key_lookup(ictx, scancode); + } else { + ktype = IMON_KEY_IMON; + kc = imon_remote_key_lookup(ictx, scancode); + } + } + + spin_lock_irqsave(&ictx->kc_lock, flags); + /* keyboard/mouse mode toggle button */ + if (kc == KEY_KEYBOARD && !ictx->release_code) { + ictx->last_keycode = kc; + if (!nomouse) { + ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1; + dev_dbg(dev, "toggling to %s mode\n", + ictx->pad_mouse ? "mouse" : "keyboard"); + spin_unlock_irqrestore(&ictx->kc_lock, flags); + return; + } else { + ictx->pad_mouse = 0; + dev_dbg(dev, "mouse mode disabled, passing key value\n"); + } + } + + ictx->kc = kc; + spin_unlock_irqrestore(&ictx->kc_lock, flags); + + /* send touchscreen events through input subsystem if touchpad data */ + if (ictx->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 && + buf[7] == 0x86) { + imon_touch_event(ictx, buf); + return; + + /* look for mouse events with pad in mouse mode */ + } else if (ictx->pad_mouse) { + if (imon_mouse_event(ictx, buf, len)) + return; + } + + /* Now for some special handling to convert pad input to arrow keys */ + if (((len == 5) && (buf[0] == 0x01) && (buf[4] == 0x00)) || + ((len == 8) && (buf[0] & 0x40) && + !(buf[1] & 0x1 || buf[1] >> 2 & 0x1))) { + len = 8; + imon_pad_to_keys(ictx, buf); + norelease = true; + } + + if (debug) { + printk(KERN_INFO "intf%d decoded packet: ", intf); + for (i = 0; i < len; ++i) + printk("%02x ", buf[i]); + printk("\n"); + } + + press_type = imon_parse_press_type(ictx, buf, ktype); + if (press_type < 0) + goto not_input_data; + + spin_lock_irqsave(&ictx->kc_lock, flags); + if (ictx->kc == KEY_UNKNOWN) + goto unknown_key; + spin_unlock_irqrestore(&ictx->kc_lock, flags); + + if (ktype != IMON_KEY_PANEL) { + if (press_type == 0) + ir_keyup(ictx->rdev); + else { + ir_keydown(ictx->rdev, ictx->rc_scancode, ictx->rc_toggle); + spin_lock_irqsave(&ictx->kc_lock, flags); + ictx->last_keycode = ictx->kc; + spin_unlock_irqrestore(&ictx->kc_lock, flags); + } + return; + } + + /* Only panel type events left to process now */ + spin_lock_irqsave(&ictx->kc_lock, flags); + + /* KEY_MUTE repeats from knob need to be suppressed */ + if (ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) { + do_gettimeofday(&t); + msec = tv2int(&t, &prev_time); + prev_time = t; + if (msec < ictx->idev->rep[REP_DELAY]) { + spin_unlock_irqrestore(&ictx->kc_lock, flags); + return; + } + } + kc = ictx->kc; + + spin_unlock_irqrestore(&ictx->kc_lock, flags); + + input_report_key(ictx->idev, kc, press_type); + input_sync(ictx->idev); + + /* panel keys don't generate a release */ + input_report_key(ictx->idev, kc, 0); + input_sync(ictx->idev); + + ictx->last_keycode = kc; + + return; + +unknown_key: + spin_unlock_irqrestore(&ictx->kc_lock, flags); + dev_info(dev, "%s: unknown keypress, code 0x%llx\n", __func__, + (long long)scancode); + return; + +not_input_data: + if (len != 8) { + dev_warn(dev, "imon %s: invalid incoming packet " + "size (len = %d, intf%d)\n", __func__, len, intf); + return; + } + + /* iMON 2.4G associate frame */ + if (buf[0] == 0x00 && + buf[2] == 0xFF && /* REFID */ + buf[3] == 0xFF && + buf[4] == 0xFF && + buf[5] == 0xFF && /* iMON 2.4G */ + ((buf[6] == 0x4E && buf[7] == 0xDF) || /* LT */ + (buf[6] == 0x5E && buf[7] == 0xDF))) { /* DT */ + dev_warn(dev, "%s: remote associated refid=%02X\n", + __func__, buf[1]); + ictx->rf_isassociating = false; + } +} + +/** + * Callback function for USB core API: receive data + */ +static void usb_rx_callback_intf0(struct urb *urb) +{ + struct imon_context *ictx; + int intfnum = 0; + + if (!urb) + return; + + ictx = (struct imon_context *)urb->context; + if (!ictx) + return; + + switch (urb->status) { + case -ENOENT: /* usbcore unlink successful! */ + return; + + case -ESHUTDOWN: /* transport endpoint was shut down */ + break; + + case 0: + imon_incoming_packet(ictx, urb, intfnum); + break; + + default: + dev_warn(ictx->dev, "imon %s: status(%d): ignored\n", + __func__, urb->status); + break; + } + + usb_submit_urb(ictx->rx_urb_intf0, GFP_ATOMIC); +} + +static void usb_rx_callback_intf1(struct urb *urb) +{ + struct imon_context *ictx; + int intfnum = 1; + + if (!urb) + return; + + ictx = (struct imon_context *)urb->context; + if (!ictx) + return; + + switch (urb->status) { + case -ENOENT: /* usbcore unlink successful! */ + return; + + case -ESHUTDOWN: /* transport endpoint was shut down */ + break; + + case 0: + imon_incoming_packet(ictx, urb, intfnum); + break; + + default: + dev_warn(ictx->dev, "imon %s: status(%d): ignored\n", + __func__, urb->status); + break; + } + + usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC); +} + +/* + * The 0x15c2:0xffdc device ID was used for umpteen different imon + * devices, and all of them constantly spew interrupts, even when there + * is no actual data to report. However, byte 6 of this buffer looks like + * its unique across device variants, so we're trying to key off that to + * figure out which display type (if any) and what IR protocol the device + * actually supports. These devices have their IR protocol hard-coded into + * their firmware, they can't be changed on the fly like the newer hardware. + */ +static void imon_get_ffdc_type(struct imon_context *ictx) +{ + u8 ffdc_cfg_byte = ictx->usb_rx_buf[6]; + u8 detected_display_type = IMON_DISPLAY_TYPE_NONE; + u64 allowed_protos = IR_TYPE_OTHER; + + switch (ffdc_cfg_byte) { + /* iMON Knob, no display, iMON IR + vol knob */ + case 0x21: + dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR"); + ictx->display_supported = false; + break; + /* iMON 2.4G LT (usb stick), no display, iMON RF */ + case 0x4e: + dev_info(ictx->dev, "0xffdc iMON 2.4G LT, iMON RF"); + ictx->display_supported = false; + ictx->rf_device = true; + break; + /* iMON VFD, no IR (does have vol knob tho) */ + case 0x35: + dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR"); + detected_display_type = IMON_DISPLAY_TYPE_VFD; + break; + /* iMON VFD, iMON IR */ + case 0x24: + case 0x85: + dev_info(ictx->dev, "0xffdc iMON VFD, iMON IR"); + detected_display_type = IMON_DISPLAY_TYPE_VFD; + break; + /* iMON VFD, MCE IR */ + case 0x9e: + dev_info(ictx->dev, "0xffdc iMON VFD, MCE IR"); + detected_display_type = IMON_DISPLAY_TYPE_VFD; + allowed_protos = IR_TYPE_RC6; + break; + /* iMON LCD, MCE IR */ + case 0x9f: + dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR"); + detected_display_type = IMON_DISPLAY_TYPE_LCD; + allowed_protos = IR_TYPE_RC6; + break; + default: + dev_info(ictx->dev, "Unknown 0xffdc device, " + "defaulting to VFD and iMON IR"); + detected_display_type = IMON_DISPLAY_TYPE_VFD; + break; + } + + printk(KERN_CONT " (id 0x%02x)\n", ffdc_cfg_byte); + + ictx->display_type = detected_display_type; + ictx->props->allowed_protos = allowed_protos; + ictx->ir_type = allowed_protos; +} + +static void imon_set_display_type(struct imon_context *ictx) +{ + u8 configured_display_type = IMON_DISPLAY_TYPE_VFD; + + /* + * Try to auto-detect the type of display if the user hasn't set + * it by hand via the display_type modparam. Default is VFD. + */ + + if (display_type == IMON_DISPLAY_TYPE_AUTO) { + switch (ictx->product) { + case 0xffdc: + /* set in imon_get_ffdc_type() */ + configured_display_type = ictx->display_type; + break; + case 0x0034: + case 0x0035: + configured_display_type = IMON_DISPLAY_TYPE_VGA; + break; + case 0x0038: + case 0x0039: + case 0x0045: + configured_display_type = IMON_DISPLAY_TYPE_LCD; + break; + case 0x003c: + case 0x0041: + case 0x0042: + case 0x0043: + configured_display_type = IMON_DISPLAY_TYPE_NONE; + ictx->display_supported = false; + break; + case 0x0036: + case 0x0044: + default: + configured_display_type = IMON_DISPLAY_TYPE_VFD; + break; + } + } else { + configured_display_type = display_type; + if (display_type == IMON_DISPLAY_TYPE_NONE) + ictx->display_supported = false; + else + ictx->display_supported = true; + dev_info(ictx->dev, "%s: overriding display type to %d via " + "modparam\n", __func__, display_type); + } + + ictx->display_type = configured_display_type; +} + +static struct input_dev *imon_init_rdev(struct imon_context *ictx) +{ + struct input_dev *rdev; + struct ir_dev_props *props; + int ret; + char *ir_codes = NULL; + const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x88 }; + + rdev = input_allocate_device(); + props = kzalloc(sizeof(*props), GFP_KERNEL); + if (!rdev || !props) { + dev_err(ictx->dev, "remote control dev allocation failed\n"); + goto out; + } + + snprintf(ictx->name_rdev, sizeof(ictx->name_rdev), + "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product); + usb_make_path(ictx->usbdev_intf0, ictx->phys_rdev, + sizeof(ictx->phys_rdev)); + strlcat(ictx->phys_rdev, "/input0", sizeof(ictx->phys_rdev)); + + rdev->name = ictx->name_rdev; + rdev->phys = ictx->phys_rdev; + usb_to_input_id(ictx->usbdev_intf0, &rdev->id); + rdev->dev.parent = ictx->dev; + rdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); + input_set_drvdata(rdev, ictx); + + props->priv = ictx; + props->driver_type = RC_DRIVER_SCANCODE; + props->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6; /* iMON PAD or MCE */ + props->change_protocol = imon_ir_change_protocol; + ictx->props = props; + + /* Enable front-panel buttons and/or knobs */ + memcpy(ictx->usb_tx_buf, &fp_packet, sizeof(fp_packet)); + ret = send_packet(ictx); + /* Not fatal, but warn about it */ + if (ret) + dev_info(ictx->dev, "panel buttons/knobs setup failed\n"); + + if (ictx->product == 0xffdc) + imon_get_ffdc_type(ictx); + + imon_set_display_type(ictx); + + if (ictx->ir_type == IR_TYPE_RC6) + ir_codes = RC_MAP_IMON_MCE; + else + ir_codes = RC_MAP_IMON_PAD; + + ret = ir_input_register(rdev, ir_codes, props, MOD_NAME); + if (ret < 0) { + dev_err(ictx->dev, "remote input dev register failed\n"); + goto out; + } + + return rdev; + +out: + kfree(props); + input_free_device(rdev); + return NULL; +} + +static struct input_dev *imon_init_idev(struct imon_context *ictx) +{ + struct input_dev *idev; + int ret, i; + + idev = input_allocate_device(); + if (!idev) { + dev_err(ictx->dev, "input dev allocation failed\n"); + goto out; + } + + snprintf(ictx->name_idev, sizeof(ictx->name_idev), + "iMON Panel, Knob and Mouse(%04x:%04x)", + ictx->vendor, ictx->product); + idev->name = ictx->name_idev; + + usb_make_path(ictx->usbdev_intf0, ictx->phys_idev, + sizeof(ictx->phys_idev)); + strlcat(ictx->phys_idev, "/input1", sizeof(ictx->phys_idev)); + idev->phys = ictx->phys_idev; + + idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | BIT_MASK(EV_REL); + + idev->keybit[BIT_WORD(BTN_MOUSE)] = + BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); + idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) | + BIT_MASK(REL_WHEEL); + + /* panel and/or knob code support */ + for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) { + u32 kc = imon_panel_key_table[i].keycode; + __set_bit(kc, idev->keybit); + } + + usb_to_input_id(ictx->usbdev_intf0, &idev->id); + idev->dev.parent = ictx->dev; + input_set_drvdata(idev, ictx); + + ret = input_register_device(idev); + if (ret < 0) { + dev_err(ictx->dev, "input dev register failed\n"); + goto out; + } + + return idev; + +out: + input_free_device(idev); + return NULL; +} + +static struct input_dev *imon_init_touch(struct imon_context *ictx) +{ + struct input_dev *touch; + int ret; + + touch = input_allocate_device(); + if (!touch) { + dev_err(ictx->dev, "touchscreen input dev allocation failed\n"); + goto touch_alloc_failed; + } + + snprintf(ictx->name_touch, sizeof(ictx->name_touch), + "iMON USB Touchscreen (%04x:%04x)", + ictx->vendor, ictx->product); + touch->name = ictx->name_touch; + + usb_make_path(ictx->usbdev_intf1, ictx->phys_touch, + sizeof(ictx->phys_touch)); + strlcat(ictx->phys_touch, "/input2", sizeof(ictx->phys_touch)); + touch->phys = ictx->phys_touch; + + touch->evbit[0] = + BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + touch->keybit[BIT_WORD(BTN_TOUCH)] = + BIT_MASK(BTN_TOUCH); + input_set_abs_params(touch, ABS_X, + 0x00, 0xfff, 0, 0); + input_set_abs_params(touch, ABS_Y, + 0x00, 0xfff, 0, 0); + + input_set_drvdata(touch, ictx); + + usb_to_input_id(ictx->usbdev_intf1, &touch->id); + touch->dev.parent = ictx->dev; + ret = input_register_device(touch); + if (ret < 0) { + dev_info(ictx->dev, "touchscreen input dev register failed\n"); + goto touch_register_failed; + } + + return touch; + +touch_register_failed: + input_free_device(ictx->touch); + +touch_alloc_failed: + return NULL; +} + +static bool imon_find_endpoints(struct imon_context *ictx, + struct usb_host_interface *iface_desc) +{ + struct usb_endpoint_descriptor *ep; + struct usb_endpoint_descriptor *rx_endpoint = NULL; + struct usb_endpoint_descriptor *tx_endpoint = NULL; + int ifnum = iface_desc->desc.bInterfaceNumber; + int num_endpts = iface_desc->desc.bNumEndpoints; + int i, ep_dir, ep_type; + bool ir_ep_found = false; + bool display_ep_found = false; + bool tx_control = false; + + /* + * Scan the endpoint list and set: + * first input endpoint = IR endpoint + * first output endpoint = display endpoint + */ + for (i = 0; i < num_endpts && !(ir_ep_found && display_ep_found); ++i) { + ep = &iface_desc->endpoint[i].desc; + ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK; + ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + + if (!ir_ep_found && ep_dir == USB_DIR_IN && + ep_type == USB_ENDPOINT_XFER_INT) { + + rx_endpoint = ep; + ir_ep_found = true; + dev_dbg(ictx->dev, "%s: found IR endpoint\n", __func__); + + } else if (!display_ep_found && ep_dir == USB_DIR_OUT && + ep_type == USB_ENDPOINT_XFER_INT) { + tx_endpoint = ep; + display_ep_found = true; + dev_dbg(ictx->dev, "%s: found display endpoint\n", __func__); + } + } + + if (ifnum == 0) { + ictx->rx_endpoint_intf0 = rx_endpoint; + /* + * tx is used to send characters to lcd/vfd, associate RF + * remotes, set IR protocol, and maybe more... + */ + ictx->tx_endpoint = tx_endpoint; + } else { + ictx->rx_endpoint_intf1 = rx_endpoint; + } + + /* + * If we didn't find a display endpoint, this is probably one of the + * newer iMON devices that use control urb instead of interrupt + */ + if (!display_ep_found) { + tx_control = true; + display_ep_found = true; + dev_dbg(ictx->dev, "%s: device uses control endpoint, not " + "interface OUT endpoint\n", __func__); + } + + /* + * Some iMON receivers have no display. Unfortunately, it seems + * that SoundGraph recycles device IDs between devices both with + * and without... :\ + */ + if (ictx->display_type == IMON_DISPLAY_TYPE_NONE) { + display_ep_found = false; + dev_dbg(ictx->dev, "%s: device has no display\n", __func__); + } + + /* + * iMON Touch devices have a VGA touchscreen, but no "display", as + * that refers to e.g. /dev/lcd0 (a character device LCD or VFD). + */ + if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { + display_ep_found = false; + dev_dbg(ictx->dev, "%s: iMON Touch device found\n", __func__); + } + + /* Input endpoint is mandatory */ + if (!ir_ep_found) + pr_err("no valid input (IR) endpoint found\n"); + + ictx->tx_control = tx_control; + + if (display_ep_found) + ictx->display_supported = true; + + return ir_ep_found; + +} + +static struct imon_context *imon_init_intf0(struct usb_interface *intf) +{ + struct imon_context *ictx; + struct urb *rx_urb; + struct urb *tx_urb; + struct device *dev = &intf->dev; + struct usb_host_interface *iface_desc; + int ret = -ENOMEM; + + ictx = kzalloc(sizeof(struct imon_context), GFP_KERNEL); + if (!ictx) { + dev_err(dev, "%s: kzalloc failed for context", __func__); + goto exit; + } + rx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!rx_urb) { + dev_err(dev, "%s: usb_alloc_urb failed for IR urb", __func__); + goto rx_urb_alloc_failed; + } + tx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!tx_urb) { + dev_err(dev, "%s: usb_alloc_urb failed for display urb", + __func__); + goto tx_urb_alloc_failed; + } + + mutex_init(&ictx->lock); + spin_lock_init(&ictx->kc_lock); + + mutex_lock(&ictx->lock); + + ictx->dev = dev; + ictx->usbdev_intf0 = usb_get_dev(interface_to_usbdev(intf)); + ictx->dev_present_intf0 = true; + ictx->rx_urb_intf0 = rx_urb; + ictx->tx_urb = tx_urb; + ictx->rf_device = false; + + ictx->vendor = le16_to_cpu(ictx->usbdev_intf0->descriptor.idVendor); + ictx->product = le16_to_cpu(ictx->usbdev_intf0->descriptor.idProduct); + + ret = -ENODEV; + iface_desc = intf->cur_altsetting; + if (!imon_find_endpoints(ictx, iface_desc)) { + goto find_endpoint_failed; + } + + ictx->idev = imon_init_idev(ictx); + if (!ictx->idev) { + dev_err(dev, "%s: input device setup failed\n", __func__); + goto idev_setup_failed; + } + + ictx->rdev = imon_init_rdev(ictx); + if (!ictx->rdev) { + dev_err(dev, "%s: rc device setup failed\n", __func__); + goto rdev_setup_failed; + } + + usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0, + usb_rcvintpipe(ictx->usbdev_intf0, + ictx->rx_endpoint_intf0->bEndpointAddress), + ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf), + usb_rx_callback_intf0, ictx, + ictx->rx_endpoint_intf0->bInterval); + + ret = usb_submit_urb(ictx->rx_urb_intf0, GFP_KERNEL); + if (ret) { + pr_err("usb_submit_urb failed for intf0 (%d)\n", ret); + goto urb_submit_failed; + } + + return ictx; + +urb_submit_failed: + ir_input_unregister(ictx->rdev); +rdev_setup_failed: + input_unregister_device(ictx->idev); +idev_setup_failed: +find_endpoint_failed: + mutex_unlock(&ictx->lock); + usb_free_urb(tx_urb); +tx_urb_alloc_failed: + usb_free_urb(rx_urb); +rx_urb_alloc_failed: + kfree(ictx); +exit: + dev_err(dev, "unable to initialize intf0, err %d\n", ret); + + return NULL; +} + +static struct imon_context *imon_init_intf1(struct usb_interface *intf, + struct imon_context *ictx) +{ + struct urb *rx_urb; + struct usb_host_interface *iface_desc; + int ret = -ENOMEM; + + rx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!rx_urb) { + pr_err("usb_alloc_urb failed for IR urb\n"); + goto rx_urb_alloc_failed; + } + + mutex_lock(&ictx->lock); + + if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { + init_timer(&ictx->ttimer); + ictx->ttimer.data = (unsigned long)ictx; + ictx->ttimer.function = imon_touch_display_timeout; + } + + ictx->usbdev_intf1 = usb_get_dev(interface_to_usbdev(intf)); + ictx->dev_present_intf1 = true; + ictx->rx_urb_intf1 = rx_urb; + + ret = -ENODEV; + iface_desc = intf->cur_altsetting; + if (!imon_find_endpoints(ictx, iface_desc)) + goto find_endpoint_failed; + + if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { + ictx->touch = imon_init_touch(ictx); + if (!ictx->touch) + goto touch_setup_failed; + } else + ictx->touch = NULL; + + usb_fill_int_urb(ictx->rx_urb_intf1, ictx->usbdev_intf1, + usb_rcvintpipe(ictx->usbdev_intf1, + ictx->rx_endpoint_intf1->bEndpointAddress), + ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf), + usb_rx_callback_intf1, ictx, + ictx->rx_endpoint_intf1->bInterval); + + ret = usb_submit_urb(ictx->rx_urb_intf1, GFP_KERNEL); + + if (ret) { + pr_err("usb_submit_urb failed for intf1 (%d)\n", ret); + goto urb_submit_failed; + } + + return ictx; + +urb_submit_failed: + if (ictx->touch) + input_unregister_device(ictx->touch); +touch_setup_failed: +find_endpoint_failed: + mutex_unlock(&ictx->lock); + usb_free_urb(rx_urb); +rx_urb_alloc_failed: + dev_err(ictx->dev, "unable to initialize intf0, err %d\n", ret); + + return NULL; +} + +static void imon_init_display(struct imon_context *ictx, + struct usb_interface *intf) +{ + int ret; + + dev_dbg(ictx->dev, "Registering iMON display with sysfs\n"); + + /* set up sysfs entry for built-in clock */ + ret = sysfs_create_group(&intf->dev.kobj, &imon_display_attr_group); + if (ret) + dev_err(ictx->dev, "Could not create display sysfs " + "entries(%d)", ret); + + if (ictx->display_type == IMON_DISPLAY_TYPE_LCD) + ret = usb_register_dev(intf, &imon_lcd_class); + else + ret = usb_register_dev(intf, &imon_vfd_class); + if (ret) + /* Not a fatal error, so ignore */ + dev_info(ictx->dev, "could not get a minor number for " + "display\n"); + +} + +/** + * Callback function for USB core API: Probe + */ +static int __devinit imon_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_device *usbdev = NULL; + struct usb_host_interface *iface_desc = NULL; + struct usb_interface *first_if; + struct device *dev = &interface->dev; + int ifnum, code_length, sysfs_err; + int ret = 0; + struct imon_context *ictx = NULL; + struct imon_context *first_if_ctx = NULL; + u16 vendor, product; + + code_length = BUF_CHUNK_SIZE * 8; + + usbdev = usb_get_dev(interface_to_usbdev(interface)); + iface_desc = interface->cur_altsetting; + ifnum = iface_desc->desc.bInterfaceNumber; + vendor = le16_to_cpu(usbdev->descriptor.idVendor); + product = le16_to_cpu(usbdev->descriptor.idProduct); + + dev_dbg(dev, "%s: found iMON device (%04x:%04x, intf%d)\n", + __func__, vendor, product, ifnum); + + /* prevent races probing devices w/multiple interfaces */ + mutex_lock(&driver_lock); + + first_if = usb_ifnum_to_if(usbdev, 0); + first_if_ctx = (struct imon_context *)usb_get_intfdata(first_if); + + if (ifnum == 0) { + ictx = imon_init_intf0(interface); + if (!ictx) { + pr_err("failed to initialize context!\n"); + ret = -ENODEV; + goto fail; + } + + } else { + /* this is the secondary interface on the device */ + ictx = imon_init_intf1(interface, first_if_ctx); + if (!ictx) { + pr_err("failed to attach to context!\n"); + ret = -ENODEV; + goto fail; + } + + } + + usb_set_intfdata(interface, ictx); + + if (ifnum == 0) { + if (product == 0xffdc && ictx->rf_device) { + sysfs_err = sysfs_create_group(&interface->dev.kobj, + &imon_rf_attr_group); + if (sysfs_err) + pr_err("Could not create RF sysfs entries(%d)\n", + sysfs_err); + } + + if (ictx->display_supported) + imon_init_display(ictx, interface); + } + + dev_info(dev, "iMON device (%04x:%04x, intf%d) on " + "usb<%d:%d> initialized\n", vendor, product, ifnum, + usbdev->bus->busnum, usbdev->devnum); + + mutex_unlock(&ictx->lock); + mutex_unlock(&driver_lock); + + return 0; + +fail: + mutex_unlock(&driver_lock); + dev_err(dev, "unable to register, err %d\n", ret); + + return ret; +} + +/** + * Callback function for USB core API: disconnect + */ +static void __devexit imon_disconnect(struct usb_interface *interface) +{ + struct imon_context *ictx; + struct device *dev; + int ifnum; + + /* prevent races with multi-interface device probing and display_open */ + mutex_lock(&driver_lock); + + ictx = usb_get_intfdata(interface); + dev = ictx->dev; + ifnum = interface->cur_altsetting->desc.bInterfaceNumber; + + mutex_lock(&ictx->lock); + + /* + * sysfs_remove_group is safe to call even if sysfs_create_group + * hasn't been called + */ + sysfs_remove_group(&interface->dev.kobj, &imon_display_attr_group); + sysfs_remove_group(&interface->dev.kobj, &imon_rf_attr_group); + + usb_set_intfdata(interface, NULL); + + /* Abort ongoing write */ + if (ictx->tx.busy) { + usb_kill_urb(ictx->tx_urb); + complete_all(&ictx->tx.finished); + } + + if (ifnum == 0) { + ictx->dev_present_intf0 = false; + usb_kill_urb(ictx->rx_urb_intf0); + input_unregister_device(ictx->idev); + ir_input_unregister(ictx->rdev); + if (ictx->display_supported) { + if (ictx->display_type == IMON_DISPLAY_TYPE_LCD) + usb_deregister_dev(interface, &imon_lcd_class); + else + usb_deregister_dev(interface, &imon_vfd_class); + } + } else { + ictx->dev_present_intf1 = false; + usb_kill_urb(ictx->rx_urb_intf1); + if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) + input_unregister_device(ictx->touch); + } + + if (!ictx->dev_present_intf0 && !ictx->dev_present_intf1) { + if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) + del_timer_sync(&ictx->ttimer); + mutex_unlock(&ictx->lock); + if (!ictx->display_isopen) + free_imon_context(ictx); + } else + mutex_unlock(&ictx->lock); + + mutex_unlock(&driver_lock); + + dev_dbg(dev, "%s: iMON device (intf%d) disconnected\n", + __func__, ifnum); +} + +static int imon_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct imon_context *ictx = usb_get_intfdata(intf); + int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; + + if (ifnum == 0) + usb_kill_urb(ictx->rx_urb_intf0); + else + usb_kill_urb(ictx->rx_urb_intf1); + + return 0; +} + +static int imon_resume(struct usb_interface *intf) +{ + int rc = 0; + struct imon_context *ictx = usb_get_intfdata(intf); + int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; + + if (ifnum == 0) { + usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0, + usb_rcvintpipe(ictx->usbdev_intf0, + ictx->rx_endpoint_intf0->bEndpointAddress), + ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf), + usb_rx_callback_intf0, ictx, + ictx->rx_endpoint_intf0->bInterval); + + rc = usb_submit_urb(ictx->rx_urb_intf0, GFP_ATOMIC); + + } else { + usb_fill_int_urb(ictx->rx_urb_intf1, ictx->usbdev_intf1, + usb_rcvintpipe(ictx->usbdev_intf1, + ictx->rx_endpoint_intf1->bEndpointAddress), + ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf), + usb_rx_callback_intf1, ictx, + ictx->rx_endpoint_intf1->bInterval); + + rc = usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC); + } + + return rc; +} + +static int __init imon_init(void) +{ + int rc; + + rc = usb_register(&imon_driver); + if (rc) { + pr_err("usb register failed(%d)\n", rc); + rc = -ENODEV; + } + + return rc; +} + +static void __exit imon_exit(void) +{ + usb_deregister(&imon_driver); +} + +module_init(imon_init); +module_exit(imon_exit); diff --git a/drivers/media/rc/ir-core-priv.h b/drivers/media/rc/ir-core-priv.h new file mode 100644 index 0000000..81c936b --- /dev/null +++ b/drivers/media/rc/ir-core-priv.h @@ -0,0 +1,203 @@ +/* + * Remote Controller core raw events header + * + * Copyright (C) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _IR_RAW_EVENT +#define _IR_RAW_EVENT + +#include +#include +#include + +struct ir_raw_handler { + struct list_head list; + + u64 protocols; /* which are handled by this handler */ + int (*decode)(struct input_dev *input_dev, struct ir_raw_event event); + + /* These two should only be used by the lirc decoder */ + int (*raw_register)(struct input_dev *input_dev); + int (*raw_unregister)(struct input_dev *input_dev); +}; + +struct ir_raw_event_ctrl { + struct list_head list; /* to keep track of raw clients */ + struct task_struct *thread; + spinlock_t lock; + struct kfifo kfifo; /* fifo for the pulse/space durations */ + ktime_t last_event; /* when last event occurred */ + enum raw_event_type last_type; /* last event type */ + struct input_dev *input_dev; /* pointer to the parent input_dev */ + u64 enabled_protocols; /* enabled raw protocol decoders */ + + /* raw decoder state follows */ + struct ir_raw_event prev_ev; + struct ir_raw_event this_ev; + struct nec_dec { + int state; + unsigned count; + u32 bits; + bool is_nec_x; + bool necx_repeat; + } nec; + struct rc5_dec { + int state; + u32 bits; + unsigned count; + unsigned wanted_bits; + } rc5; + struct rc6_dec { + int state; + u8 header; + u32 body; + bool toggle; + unsigned count; + unsigned wanted_bits; + } rc6; + struct sony_dec { + int state; + u32 bits; + unsigned count; + } sony; + struct jvc_dec { + int state; + u16 bits; + u16 old_bits; + unsigned count; + bool first; + bool toggle; + } jvc; + struct rc5_sz_dec { + int state; + u32 bits; + unsigned count; + unsigned wanted_bits; + } rc5_sz; + struct lirc_codec { + struct ir_input_dev *ir_dev; + struct lirc_driver *drv; + int carrier_low; + + ktime_t gap_start; + u64 gap_duration; + bool gap; + bool send_timeout_reports; + + } lirc; +}; + +/* macros for IR decoders */ +static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin) +{ + return d1 > (d2 - margin); +} + +static inline bool eq_margin(unsigned d1, unsigned d2, unsigned margin) +{ + return ((d1 > (d2 - margin)) && (d1 < (d2 + margin))); +} + +static inline bool is_transition(struct ir_raw_event *x, struct ir_raw_event *y) +{ + return x->pulse != y->pulse; +} + +static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration) +{ + if (duration > ev->duration) + ev->duration = 0; + else + ev->duration -= duration; +} + +/* Returns true if event is normal pulse/space event */ +static inline bool is_timing_event(struct ir_raw_event ev) +{ + return !ev.carrier_report && !ev.reset; +} + +#define TO_US(duration) DIV_ROUND_CLOSEST((duration), 1000) +#define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space") +/* + * Routines from ir-sysfs.c - Meant to be called only internally inside + * ir-core + */ +int ir_register_input(struct input_dev *input_dev); + +int ir_register_class(struct input_dev *input_dev); +void ir_unregister_class(struct input_dev *input_dev); + +/* + * Routines from ir-raw-event.c to be used internally and by decoders + */ +u64 ir_raw_get_allowed_protocols(void); +int ir_raw_event_register(struct input_dev *input_dev); +void ir_raw_event_unregister(struct input_dev *input_dev); +int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); +void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); +void ir_raw_init(void); + +int ir_rcmap_init(void); +void ir_rcmap_cleanup(void); +/* + * Decoder initialization code + * + * Those load logic are called during ir-core init, and automatically + * loads the compiled decoders for their usage with IR raw events + */ + +/* from ir-nec-decoder.c */ +#ifdef CONFIG_IR_NEC_DECODER_MODULE +#define load_nec_decode() request_module("ir-nec-decoder") +#else +#define load_nec_decode() 0 +#endif + +/* from ir-rc5-decoder.c */ +#ifdef CONFIG_IR_RC5_DECODER_MODULE +#define load_rc5_decode() request_module("ir-rc5-decoder") +#else +#define load_rc5_decode() 0 +#endif + +/* from ir-rc6-decoder.c */ +#ifdef CONFIG_IR_RC6_DECODER_MODULE +#define load_rc6_decode() request_module("ir-rc6-decoder") +#else +#define load_rc6_decode() 0 +#endif + +/* from ir-jvc-decoder.c */ +#ifdef CONFIG_IR_JVC_DECODER_MODULE +#define load_jvc_decode() request_module("ir-jvc-decoder") +#else +#define load_jvc_decode() 0 +#endif + +/* from ir-sony-decoder.c */ +#ifdef CONFIG_IR_SONY_DECODER_MODULE +#define load_sony_decode() request_module("ir-sony-decoder") +#else +#define load_sony_decode() 0 +#endif + +/* from ir-lirc-codec.c */ +#ifdef CONFIG_IR_LIRC_CODEC_MODULE +#define load_lirc_codec() request_module("ir-lirc-codec") +#else +#define load_lirc_codec() 0 +#endif + + +#endif /* _IR_RAW_EVENT */ diff --git a/drivers/media/rc/ir-functions.c b/drivers/media/rc/ir-functions.c new file mode 100644 index 0000000..ec021c9 --- /dev/null +++ b/drivers/media/rc/ir-functions.c @@ -0,0 +1,120 @@ +/* + * some common functions to handle infrared remote protocol decoding for + * drivers which have not yet been (or can't be) converted to use the + * regular protocol decoders... + * + * (c) 2003 Gerd Knorr [SuSE Labs] + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include "ir-core-priv.h" + +/* -------------------------------------------------------------------------- */ + +MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); +MODULE_LICENSE("GPL"); + +/* RC5 decoding stuff, moved from bttv-input.c to share it with + * saa7134 */ + +/* decode raw bit pattern to RC5 code */ +static u32 ir_rc5_decode(unsigned int code) +{ + unsigned int org_code = code; + unsigned int pair; + unsigned int rc5 = 0; + int i; + + for (i = 0; i < 14; ++i) { + pair = code & 0x3; + code >>= 2; + + rc5 <<= 1; + switch (pair) { + case 0: + case 2: + break; + case 1: + rc5 |= 1; + break; + case 3: + IR_dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code); + return 0; + } + } + IR_dprintk(1, "ir-common: code=%x, rc5=%x, start=%x, toggle=%x, address=%x, " + "instr=%x\n", rc5, org_code, RC5_START(rc5), + RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); + return rc5; +} + +void ir_rc5_timer_end(unsigned long data) +{ + struct card_ir *ir = (struct card_ir *)data; + struct timeval tv; + unsigned long current_jiffies; + u32 gap; + u32 rc5 = 0; + + /* get time */ + current_jiffies = jiffies; + do_gettimeofday(&tv); + + /* avoid overflow with gap >1s */ + if (tv.tv_sec - ir->base_time.tv_sec > 1) { + gap = 200000; + } else { + gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + + tv.tv_usec - ir->base_time.tv_usec; + } + + /* signal we're ready to start a new code */ + ir->active = 0; + + /* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */ + if (gap < 28000) { + IR_dprintk(1, "ir-common: spurious timer_end\n"); + return; + } + + if (ir->last_bit < 20) { + /* ignore spurious codes (caused by light/other remotes) */ + IR_dprintk(1, "ir-common: short code: %x\n", ir->code); + } else { + ir->code = (ir->code << ir->shift_by) | 1; + rc5 = ir_rc5_decode(ir->code); + + /* two start bits? */ + if (RC5_START(rc5) != ir->start) { + IR_dprintk(1, "ir-common: rc5 start bits invalid: %u\n", RC5_START(rc5)); + + /* right address? */ + } else if (RC5_ADDR(rc5) == ir->addr) { + u32 toggle = RC5_TOGGLE(rc5); + u32 instr = RC5_INSTR(rc5); + + /* Good code */ + ir_keydown(ir->dev, instr, toggle); + IR_dprintk(1, "ir-common: instruction %x, toggle %x\n", + instr, toggle); + } + } +} +EXPORT_SYMBOL_GPL(ir_rc5_timer_end); diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c new file mode 100644 index 0000000..63dca6e --- /dev/null +++ b/drivers/media/rc/ir-jvc-decoder.c @@ -0,0 +1,199 @@ +/* ir-jvc-decoder.c - handle JVC IR Pulse/Space protocol + * + * Copyright (C) 2010 by David Härdeman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include "ir-core-priv.h" + +#define JVC_NBITS 16 /* dev(8) + func(8) */ +#define JVC_UNIT 525000 /* ns */ +#define JVC_HEADER_PULSE (16 * JVC_UNIT) /* lack of header -> repeat */ +#define JVC_HEADER_SPACE (8 * JVC_UNIT) +#define JVC_BIT_PULSE (1 * JVC_UNIT) +#define JVC_BIT_0_SPACE (1 * JVC_UNIT) +#define JVC_BIT_1_SPACE (3 * JVC_UNIT) +#define JVC_TRAILER_PULSE (1 * JVC_UNIT) +#define JVC_TRAILER_SPACE (35 * JVC_UNIT) + +enum jvc_state { + STATE_INACTIVE, + STATE_HEADER_SPACE, + STATE_BIT_PULSE, + STATE_BIT_SPACE, + STATE_TRAILER_PULSE, + STATE_TRAILER_SPACE, + STATE_CHECK_REPEAT, +}; + +/** + * ir_jvc_decode() - Decode one JVC pulse or space + * @input_dev: the struct input_dev descriptor of the device + * @duration: the struct ir_raw_event descriptor of the pulse/space + * + * This function returns -EINVAL if the pulse violates the state machine + */ +static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct jvc_dec *data = &ir_dev->raw->jvc; + + if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC)) + return 0; + + if (!is_timing_event(ev)) { + if (ev.reset) + data->state = STATE_INACTIVE; + return 0; + } + + if (!geq_margin(ev.duration, JVC_UNIT, JVC_UNIT / 2)) + goto out; + + IR_dprintk(2, "JVC decode started at state %d (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + +again: + switch (data->state) { + + case STATE_INACTIVE: + if (!ev.pulse) + break; + + if (!eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2)) + break; + + data->count = 0; + data->first = true; + data->toggle = !data->toggle; + data->state = STATE_HEADER_SPACE; + return 0; + + case STATE_HEADER_SPACE: + if (ev.pulse) + break; + + if (!eq_margin(ev.duration, JVC_HEADER_SPACE, JVC_UNIT / 2)) + break; + + data->state = STATE_BIT_PULSE; + return 0; + + case STATE_BIT_PULSE: + if (!ev.pulse) + break; + + if (!eq_margin(ev.duration, JVC_BIT_PULSE, JVC_UNIT / 2)) + break; + + data->state = STATE_BIT_SPACE; + return 0; + + case STATE_BIT_SPACE: + if (ev.pulse) + break; + + data->bits <<= 1; + if (eq_margin(ev.duration, JVC_BIT_1_SPACE, JVC_UNIT / 2)) { + data->bits |= 1; + decrease_duration(&ev, JVC_BIT_1_SPACE); + } else if (eq_margin(ev.duration, JVC_BIT_0_SPACE, JVC_UNIT / 2)) + decrease_duration(&ev, JVC_BIT_0_SPACE); + else + break; + data->count++; + + if (data->count == JVC_NBITS) + data->state = STATE_TRAILER_PULSE; + else + data->state = STATE_BIT_PULSE; + return 0; + + case STATE_TRAILER_PULSE: + if (!ev.pulse) + break; + + if (!eq_margin(ev.duration, JVC_TRAILER_PULSE, JVC_UNIT / 2)) + break; + + data->state = STATE_TRAILER_SPACE; + return 0; + + case STATE_TRAILER_SPACE: + if (ev.pulse) + break; + + if (!geq_margin(ev.duration, JVC_TRAILER_SPACE, JVC_UNIT / 2)) + break; + + if (data->first) { + u32 scancode; + scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) | + (bitrev8((data->bits >> 0) & 0xff) << 0); + IR_dprintk(1, "JVC scancode 0x%04x\n", scancode); + ir_keydown(input_dev, scancode, data->toggle); + data->first = false; + data->old_bits = data->bits; + } else if (data->bits == data->old_bits) { + IR_dprintk(1, "JVC repeat\n"); + ir_repeat(input_dev); + } else { + IR_dprintk(1, "JVC invalid repeat msg\n"); + break; + } + + data->count = 0; + data->state = STATE_CHECK_REPEAT; + return 0; + + case STATE_CHECK_REPEAT: + if (!ev.pulse) + break; + + if (eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2)) + data->state = STATE_INACTIVE; + else + data->state = STATE_BIT_PULSE; + goto again; + } + +out: + IR_dprintk(1, "JVC decode failed at state %d (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + data->state = STATE_INACTIVE; + return -EINVAL; +} + +static struct ir_raw_handler jvc_handler = { + .protocols = IR_TYPE_JVC, + .decode = ir_jvc_decode, +}; + +static int __init ir_jvc_decode_init(void) +{ + ir_raw_handler_register(&jvc_handler); + + printk(KERN_INFO "IR JVC protocol handler initialized\n"); + return 0; +} + +static void __exit ir_jvc_decode_exit(void) +{ + ir_raw_handler_unregister(&jvc_handler); +} + +module_init(ir_jvc_decode_init); +module_exit(ir_jvc_decode_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Härdeman "); +MODULE_DESCRIPTION("JVC IR protocol decoder"); diff --git a/drivers/media/rc/ir-keytable.c b/drivers/media/rc/ir-keytable.c new file mode 100644 index 0000000..8039110 --- /dev/null +++ b/drivers/media/rc/ir-keytable.c @@ -0,0 +1,766 @@ +/* ir-keytable.c - handle IR scancode->keycode tables + * + * Copyright (C) 2009 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#include +#include +#include "ir-core-priv.h" + +/* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */ +#define IR_TAB_MIN_SIZE 256 +#define IR_TAB_MAX_SIZE 8192 + +/* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */ +#define IR_KEYPRESS_TIMEOUT 250 + +/** + * ir_create_table() - initializes a scancode table + * @rc_tab: the ir_scancode_table to initialize + * @name: name to assign to the table + * @ir_type: ir type to assign to the new table + * @size: initial size of the table + * @return: zero on success or a negative error code + * + * This routine will initialize the ir_scancode_table and will allocate + * memory to hold at least the specified number elements. + */ +static int ir_create_table(struct ir_scancode_table *rc_tab, + const char *name, u64 ir_type, size_t size) +{ + rc_tab->name = name; + rc_tab->ir_type = ir_type; + rc_tab->alloc = roundup_pow_of_two(size * sizeof(struct ir_scancode)); + rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode); + rc_tab->scan = kmalloc(rc_tab->alloc, GFP_KERNEL); + if (!rc_tab->scan) + return -ENOMEM; + + IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", + rc_tab->size, rc_tab->alloc); + return 0; +} + +/** + * ir_free_table() - frees memory allocated by a scancode table + * @rc_tab: the table whose mappings need to be freed + * + * This routine will free memory alloctaed for key mappings used by given + * scancode table. + */ +static void ir_free_table(struct ir_scancode_table *rc_tab) +{ + rc_tab->size = 0; + kfree(rc_tab->scan); + rc_tab->scan = NULL; +} + +/** + * ir_resize_table() - resizes a scancode table if necessary + * @rc_tab: the ir_scancode_table to resize + * @gfp_flags: gfp flags to use when allocating memory + * @return: zero on success or a negative error code + * + * This routine will shrink the ir_scancode_table if it has lots of + * unused entries and grow it if it is full. + */ +static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags) +{ + unsigned int oldalloc = rc_tab->alloc; + unsigned int newalloc = oldalloc; + struct ir_scancode *oldscan = rc_tab->scan; + struct ir_scancode *newscan; + + if (rc_tab->size == rc_tab->len) { + /* All entries in use -> grow keytable */ + if (rc_tab->alloc >= IR_TAB_MAX_SIZE) + return -ENOMEM; + + newalloc *= 2; + IR_dprintk(1, "Growing table to %u bytes\n", newalloc); + } + + if ((rc_tab->len * 3 < rc_tab->size) && (oldalloc > IR_TAB_MIN_SIZE)) { + /* Less than 1/3 of entries in use -> shrink keytable */ + newalloc /= 2; + IR_dprintk(1, "Shrinking table to %u bytes\n", newalloc); + } + + if (newalloc == oldalloc) + return 0; + + newscan = kmalloc(newalloc, gfp_flags); + if (!newscan) { + IR_dprintk(1, "Failed to kmalloc %u bytes\n", newalloc); + return -ENOMEM; + } + + memcpy(newscan, rc_tab->scan, rc_tab->len * sizeof(struct ir_scancode)); + rc_tab->scan = newscan; + rc_tab->alloc = newalloc; + rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode); + kfree(oldscan); + return 0; +} + +/** + * ir_update_mapping() - set a keycode in the scancode->keycode table + * @dev: the struct input_dev device descriptor + * @rc_tab: scancode table to be adjusted + * @index: index of the mapping that needs to be updated + * @keycode: the desired keycode + * @return: previous keycode assigned to the mapping + * + * This routine is used to update scancode->keycopde mapping at given + * position. + */ +static unsigned int ir_update_mapping(struct input_dev *dev, + struct ir_scancode_table *rc_tab, + unsigned int index, + unsigned int new_keycode) +{ + int old_keycode = rc_tab->scan[index].keycode; + int i; + + /* Did the user wish to remove the mapping? */ + if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) { + IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", + index, rc_tab->scan[index].scancode); + rc_tab->len--; + memmove(&rc_tab->scan[index], &rc_tab->scan[index+ 1], + (rc_tab->len - index) * sizeof(struct ir_scancode)); + } else { + IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n", + index, + old_keycode == KEY_RESERVED ? "New" : "Replacing", + rc_tab->scan[index].scancode, new_keycode); + rc_tab->scan[index].keycode = new_keycode; + __set_bit(new_keycode, dev->keybit); + } + + if (old_keycode != KEY_RESERVED) { + /* A previous mapping was updated... */ + __clear_bit(old_keycode, dev->keybit); + /* ... but another scancode might use the same keycode */ + for (i = 0; i < rc_tab->len; i++) { + if (rc_tab->scan[i].keycode == old_keycode) { + __set_bit(old_keycode, dev->keybit); + break; + } + } + + /* Possibly shrink the keytable, failure is not a problem */ + ir_resize_table(rc_tab, GFP_ATOMIC); + } + + return old_keycode; +} + +/** + * ir_locate_scancode() - set a keycode in the scancode->keycode table + * @ir_dev: the struct ir_input_dev device descriptor + * @rc_tab: scancode table to be searched + * @scancode: the desired scancode + * @resize: controls whether we allowed to resize the table to + * accomodate not yet present scancodes + * @return: index of the mapping containing scancode in question + * or -1U in case of failure. + * + * This routine is used to locate given scancode in ir_scancode_table. + * If scancode is not yet present the routine will allocate a new slot + * for it. + */ +static unsigned int ir_establish_scancode(struct ir_input_dev *ir_dev, + struct ir_scancode_table *rc_tab, + unsigned int scancode, + bool resize) +{ + unsigned int i; + + /* + * Unfortunately, some hardware-based IR decoders don't provide + * all bits for the complete IR code. In general, they provide only + * the command part of the IR code. Yet, as it is possible to replace + * the provided IR with another one, it is needed to allow loading + * IR tables from other remotes. So, + */ + if (ir_dev->props && ir_dev->props->scanmask) + scancode &= ir_dev->props->scanmask; + + /* First check if we already have a mapping for this ir command */ + for (i = 0; i < rc_tab->len; i++) { + if (rc_tab->scan[i].scancode == scancode) + return i; + + /* Keytable is sorted from lowest to highest scancode */ + if (rc_tab->scan[i].scancode >= scancode) + break; + } + + /* No previous mapping found, we might need to grow the table */ + if (rc_tab->size == rc_tab->len) { + if (!resize || ir_resize_table(rc_tab, GFP_ATOMIC)) + return -1U; + } + + /* i is the proper index to insert our new keycode */ + if (i < rc_tab->len) + memmove(&rc_tab->scan[i + 1], &rc_tab->scan[i], + (rc_tab->len - i) * sizeof(struct ir_scancode)); + rc_tab->scan[i].scancode = scancode; + rc_tab->scan[i].keycode = KEY_RESERVED; + rc_tab->len++; + + return i; +} + +/** + * ir_setkeycode() - set a keycode in the scancode->keycode table + * @dev: the struct input_dev device descriptor + * @scancode: the desired scancode + * @keycode: result + * @return: -EINVAL if the keycode could not be inserted, otherwise zero. + * + * This routine is used to handle evdev EVIOCSKEY ioctl. + */ +static int ir_setkeycode(struct input_dev *dev, + const struct input_keymap_entry *ke, + unsigned int *old_keycode) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(dev); + struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; + unsigned int index; + unsigned int scancode; + int retval; + unsigned long flags; + + spin_lock_irqsave(&rc_tab->lock, flags); + + if (ke->flags & INPUT_KEYMAP_BY_INDEX) { + index = ke->index; + if (index >= rc_tab->len) { + retval = -EINVAL; + goto out; + } + } else { + retval = input_scancode_to_scalar(ke, &scancode); + if (retval) + goto out; + + index = ir_establish_scancode(ir_dev, rc_tab, scancode, true); + if (index >= rc_tab->len) { + retval = -ENOMEM; + goto out; + } + } + + *old_keycode = ir_update_mapping(dev, rc_tab, index, ke->keycode); + +out: + spin_unlock_irqrestore(&rc_tab->lock, flags); + return retval; +} + +/** + * ir_setkeytable() - sets several entries in the scancode->keycode table + * @dev: the struct input_dev device descriptor + * @to: the struct ir_scancode_table to copy entries to + * @from: the struct ir_scancode_table to copy entries from + * @return: -ENOMEM if all keycodes could not be inserted, otherwise zero. + * + * This routine is used to handle table initialization. + */ +static int ir_setkeytable(struct ir_input_dev *ir_dev, + const struct ir_scancode_table *from) +{ + struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; + unsigned int i, index; + int rc; + + rc = ir_create_table(&ir_dev->rc_tab, + from->name, from->ir_type, from->size); + if (rc) + return rc; + + IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", + rc_tab->size, rc_tab->alloc); + + for (i = 0; i < from->size; i++) { + index = ir_establish_scancode(ir_dev, rc_tab, + from->scan[i].scancode, false); + if (index >= rc_tab->len) { + rc = -ENOMEM; + break; + } + + ir_update_mapping(ir_dev->input_dev, rc_tab, index, + from->scan[i].keycode); + } + + if (rc) + ir_free_table(rc_tab); + + return rc; +} + +/** + * ir_lookup_by_scancode() - locate mapping by scancode + * @rc_tab: the &struct ir_scancode_table to search + * @scancode: scancode to look for in the table + * @return: index in the table, -1U if not found + * + * This routine performs binary search in RC keykeymap table for + * given scancode. + */ +static unsigned int ir_lookup_by_scancode(const struct ir_scancode_table *rc_tab, + unsigned int scancode) +{ + int start = 0; + int end = rc_tab->len - 1; + int mid; + + while (start <= end) { + mid = (start + end) / 2; + if (rc_tab->scan[mid].scancode < scancode) + start = mid + 1; + else if (rc_tab->scan[mid].scancode > scancode) + end = mid - 1; + else + return mid; + } + + return -1U; +} + +/** + * ir_getkeycode() - get a keycode from the scancode->keycode table + * @dev: the struct input_dev device descriptor + * @scancode: the desired scancode + * @keycode: used to return the keycode, if found, or KEY_RESERVED + * @return: always returns zero. + * + * This routine is used to handle evdev EVIOCGKEY ioctl. + */ +static int ir_getkeycode(struct input_dev *dev, + struct input_keymap_entry *ke) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(dev); + struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; + struct ir_scancode *entry; + unsigned long flags; + unsigned int index; + unsigned int scancode; + int retval; + + spin_lock_irqsave(&rc_tab->lock, flags); + + if (ke->flags & INPUT_KEYMAP_BY_INDEX) { + index = ke->index; + } else { + retval = input_scancode_to_scalar(ke, &scancode); + if (retval) + goto out; + + index = ir_lookup_by_scancode(rc_tab, scancode); + } + + if (index >= rc_tab->len) { + if (!(ke->flags & INPUT_KEYMAP_BY_INDEX)) + IR_dprintk(1, "unknown key for scancode 0x%04x\n", + scancode); + retval = -EINVAL; + goto out; + } + + entry = &rc_tab->scan[index]; + + ke->index = index; + ke->keycode = entry->keycode; + ke->len = sizeof(entry->scancode); + memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode)); + + retval = 0; + +out: + spin_unlock_irqrestore(&rc_tab->lock, flags); + return retval; +} + +/** + * ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode + * @input_dev: the struct input_dev descriptor of the device + * @scancode: the scancode that we're seeking + * + * This routine is used by the input routines when a key is pressed at the + * IR. The scancode is received and needs to be converted into a keycode. + * If the key is not found, it returns KEY_RESERVED. Otherwise, returns the + * corresponding keycode from the table. + */ +u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(dev); + struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; + unsigned int keycode; + unsigned int index; + unsigned long flags; + + spin_lock_irqsave(&rc_tab->lock, flags); + + index = ir_lookup_by_scancode(rc_tab, scancode); + keycode = index < rc_tab->len ? + rc_tab->scan[index].keycode : KEY_RESERVED; + + spin_unlock_irqrestore(&rc_tab->lock, flags); + + if (keycode != KEY_RESERVED) + IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", + dev->name, scancode, keycode); + + return keycode; +} +EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); + +/** + * ir_do_keyup() - internal function to signal the release of a keypress + * @ir: the struct ir_input_dev descriptor of the device + * + * This function is used internally to release a keypress, it must be + * called with keylock held. + */ +static void ir_do_keyup(struct ir_input_dev *ir) +{ + if (!ir->keypressed) + return; + + IR_dprintk(1, "keyup key 0x%04x\n", ir->last_keycode); + input_report_key(ir->input_dev, ir->last_keycode, 0); + input_sync(ir->input_dev); + ir->keypressed = false; +} + +/** + * ir_keyup() - generates input event to signal the release of a keypress + * @dev: the struct input_dev descriptor of the device + * + * This routine is used to signal that a key has been released on the + * remote control. + */ +void ir_keyup(struct input_dev *dev) +{ + unsigned long flags; + struct ir_input_dev *ir = input_get_drvdata(dev); + + spin_lock_irqsave(&ir->keylock, flags); + ir_do_keyup(ir); + spin_unlock_irqrestore(&ir->keylock, flags); +} +EXPORT_SYMBOL_GPL(ir_keyup); + +/** + * ir_timer_keyup() - generates a keyup event after a timeout + * @cookie: a pointer to struct ir_input_dev passed to setup_timer() + * + * This routine will generate a keyup event some time after a keydown event + * is generated when no further activity has been detected. + */ +static void ir_timer_keyup(unsigned long cookie) +{ + struct ir_input_dev *ir = (struct ir_input_dev *)cookie; + unsigned long flags; + + /* + * ir->keyup_jiffies is used to prevent a race condition if a + * hardware interrupt occurs at this point and the keyup timer + * event is moved further into the future as a result. + * + * The timer will then be reactivated and this function called + * again in the future. We need to exit gracefully in that case + * to allow the input subsystem to do its auto-repeat magic or + * a keyup event might follow immediately after the keydown. + */ + spin_lock_irqsave(&ir->keylock, flags); + if (time_is_before_eq_jiffies(ir->keyup_jiffies)) + ir_do_keyup(ir); + spin_unlock_irqrestore(&ir->keylock, flags); +} + +/** + * ir_repeat() - notifies the IR core that a key is still pressed + * @dev: the struct input_dev descriptor of the device + * + * This routine is used by IR decoders when a repeat message which does + * not include the necessary bits to reproduce the scancode has been + * received. + */ +void ir_repeat(struct input_dev *dev) +{ + unsigned long flags; + struct ir_input_dev *ir = input_get_drvdata(dev); + + spin_lock_irqsave(&ir->keylock, flags); + + input_event(dev, EV_MSC, MSC_SCAN, ir->last_scancode); + + if (!ir->keypressed) + goto out; + + ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); + mod_timer(&ir->timer_keyup, ir->keyup_jiffies); + +out: + spin_unlock_irqrestore(&ir->keylock, flags); +} +EXPORT_SYMBOL_GPL(ir_repeat); + +/** + * ir_do_keydown() - internal function to process a keypress + * @dev: the struct input_dev descriptor of the device + * @scancode: the scancode of the keypress + * @keycode: the keycode of the keypress + * @toggle: the toggle value of the keypress + * + * This function is used internally to register a keypress, it must be + * called with keylock held. + */ +static void ir_do_keydown(struct input_dev *dev, int scancode, + u32 keycode, u8 toggle) +{ + struct ir_input_dev *ir = input_get_drvdata(dev); + + input_event(dev, EV_MSC, MSC_SCAN, scancode); + + /* Repeat event? */ + if (ir->keypressed && + ir->last_scancode == scancode && + ir->last_toggle == toggle) + return; + + /* Release old keypress */ + ir_do_keyup(ir); + + ir->last_scancode = scancode; + ir->last_toggle = toggle; + ir->last_keycode = keycode; + + if (keycode == KEY_RESERVED) + return; + + /* Register a keypress */ + ir->keypressed = true; + IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", + dev->name, keycode, scancode); + input_report_key(dev, ir->last_keycode, 1); + input_sync(dev); +} + +/** + * ir_keydown() - generates input event for a key press + * @dev: the struct input_dev descriptor of the device + * @scancode: the scancode that we're seeking + * @toggle: the toggle value (protocol dependent, if the protocol doesn't + * support toggle values, this should be set to zero) + * + * This routine is used by the input routines when a key is pressed at the + * IR. It gets the keycode for a scancode and reports an input event via + * input_report_key(). + */ +void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) +{ + unsigned long flags; + struct ir_input_dev *ir = input_get_drvdata(dev); + u32 keycode = ir_g_keycode_from_table(dev, scancode); + + spin_lock_irqsave(&ir->keylock, flags); + ir_do_keydown(dev, scancode, keycode, toggle); + + if (ir->keypressed) { + ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); + mod_timer(&ir->timer_keyup, ir->keyup_jiffies); + } + spin_unlock_irqrestore(&ir->keylock, flags); +} +EXPORT_SYMBOL_GPL(ir_keydown); + +/** + * ir_keydown_notimeout() - generates input event for a key press without + * an automatic keyup event at a later time + * @dev: the struct input_dev descriptor of the device + * @scancode: the scancode that we're seeking + * @toggle: the toggle value (protocol dependent, if the protocol doesn't + * support toggle values, this should be set to zero) + * + * This routine is used by the input routines when a key is pressed at the + * IR. It gets the keycode for a scancode and reports an input event via + * input_report_key(). The driver must manually call ir_keyup() at a later + * stage. + */ +void ir_keydown_notimeout(struct input_dev *dev, int scancode, u8 toggle) +{ + unsigned long flags; + struct ir_input_dev *ir = input_get_drvdata(dev); + u32 keycode = ir_g_keycode_from_table(dev, scancode); + + spin_lock_irqsave(&ir->keylock, flags); + ir_do_keydown(dev, scancode, keycode, toggle); + spin_unlock_irqrestore(&ir->keylock, flags); +} +EXPORT_SYMBOL_GPL(ir_keydown_notimeout); + +static int ir_open(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + + return ir_dev->props->open(ir_dev->props->priv); +} + +static void ir_close(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + + ir_dev->props->close(ir_dev->props->priv); +} + +/** + * __ir_input_register() - sets the IR keycode table and add the handlers + * for keymap table get/set + * @input_dev: the struct input_dev descriptor of the device + * @rc_tab: the struct ir_scancode_table table of scancode/keymap + * + * This routine is used to initialize the input infrastructure + * to work with an IR. + * It will register the input/evdev interface for the device and + * register the syfs code for IR class + */ +int __ir_input_register(struct input_dev *input_dev, + const struct ir_scancode_table *rc_tab, + struct ir_dev_props *props, + const char *driver_name) +{ + struct ir_input_dev *ir_dev; + int rc; + + if (rc_tab->scan == NULL || !rc_tab->size) + return -EINVAL; + + ir_dev = kzalloc(sizeof(*ir_dev), GFP_KERNEL); + if (!ir_dev) + return -ENOMEM; + + ir_dev->driver_name = kasprintf(GFP_KERNEL, "%s", driver_name); + if (!ir_dev->driver_name) { + rc = -ENOMEM; + goto out_dev; + } + + input_dev->getkeycode_new = ir_getkeycode; + input_dev->setkeycode_new = ir_setkeycode; + input_set_drvdata(input_dev, ir_dev); + ir_dev->input_dev = input_dev; + + spin_lock_init(&ir_dev->rc_tab.lock); + spin_lock_init(&ir_dev->keylock); + setup_timer(&ir_dev->timer_keyup, ir_timer_keyup, (unsigned long)ir_dev); + + if (props) { + ir_dev->props = props; + if (props->open) + input_dev->open = ir_open; + if (props->close) + input_dev->close = ir_close; + } + + set_bit(EV_KEY, input_dev->evbit); + set_bit(EV_REP, input_dev->evbit); + set_bit(EV_MSC, input_dev->evbit); + set_bit(MSC_SCAN, input_dev->mscbit); + + rc = ir_setkeytable(ir_dev, rc_tab); + if (rc) + goto out_name; + + rc = ir_register_class(input_dev); + if (rc < 0) + goto out_table; + + if (ir_dev->props) + if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) { + rc = ir_raw_event_register(input_dev); + if (rc < 0) + goto out_event; + } + + rc = ir_register_input(input_dev); + if (rc < 0) + goto out_event; + + IR_dprintk(1, "Registered input device on %s for %s remote%s.\n", + driver_name, rc_tab->name, + (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ? + " in raw mode" : ""); + + /* + * Default delay of 250ms is too short for some protocols, expecially + * since the timeout is currently set to 250ms. Increase it to 500ms, + * to avoid wrong repetition of the keycodes. + */ + input_dev->rep[REP_DELAY] = 500; + + return 0; + +out_event: + ir_unregister_class(input_dev); +out_table: + ir_free_table(&ir_dev->rc_tab); +out_name: + kfree(ir_dev->driver_name); +out_dev: + kfree(ir_dev); + return rc; +} +EXPORT_SYMBOL_GPL(__ir_input_register); + +/** + * ir_input_unregister() - unregisters IR and frees resources + * @input_dev: the struct input_dev descriptor of the device + + * This routine is used to free memory and de-register interfaces. + */ +void ir_input_unregister(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + + if (!ir_dev) + return; + + IR_dprintk(1, "Freed keycode table\n"); + + del_timer_sync(&ir_dev->timer_keyup); + if (ir_dev->props) + if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) + ir_raw_event_unregister(input_dev); + + ir_free_table(&ir_dev->rc_tab); + + ir_unregister_class(input_dev); + + kfree(ir_dev->driver_name); + kfree(ir_dev); +} +EXPORT_SYMBOL_GPL(ir_input_unregister); + +int ir_core_debug; /* ir_debug level (0,1,2) */ +EXPORT_SYMBOL_GPL(ir_core_debug); +module_param_named(debug, ir_core_debug, int, 0644); + +MODULE_AUTHOR("Mauro Carvalho Chehab "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c new file mode 100644 index 0000000..9fc0db9 --- /dev/null +++ b/drivers/media/rc/ir-lirc-codec.c @@ -0,0 +1,410 @@ +/* ir-lirc-codec.c - ir-core to classic lirc interface bridge + * + * Copyright (C) 2010 by Jarod Wilson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include "ir-core-priv.h" + +#define LIRCBUF_SIZE 256 + +/** + * ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the + * lircd userspace daemon for decoding. + * @input_dev: the struct input_dev descriptor of the device + * @duration: the struct ir_raw_event descriptor of the pulse/space + * + * This function returns -EINVAL if the lirc interfaces aren't wired up. + */ +static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct lirc_codec *lirc = &ir_dev->raw->lirc; + int sample; + + if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC)) + return 0; + + if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf) + return -EINVAL; + + /* Packet start */ + if (ev.reset) + return 0; + + /* Carrier reports */ + if (ev.carrier_report) { + sample = LIRC_FREQUENCY(ev.carrier); + + /* Packet end */ + } else if (ev.timeout) { + + if (lirc->gap) + return 0; + + lirc->gap_start = ktime_get(); + lirc->gap = true; + lirc->gap_duration = ev.duration; + + if (!lirc->send_timeout_reports) + return 0; + + sample = LIRC_TIMEOUT(ev.duration / 1000); + + /* Normal sample */ + } else { + + if (lirc->gap) { + int gap_sample; + + lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(), + lirc->gap_start)); + + /* Convert to ms and cap by LIRC_VALUE_MASK */ + do_div(lirc->gap_duration, 1000); + lirc->gap_duration = min(lirc->gap_duration, + (u64)LIRC_VALUE_MASK); + + gap_sample = LIRC_SPACE(lirc->gap_duration); + lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, + (unsigned char *) &gap_sample); + lirc->gap = false; + } + + sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) : + LIRC_SPACE(ev.duration / 1000); + } + + lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, + (unsigned char *) &sample); + wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll); + + return 0; +} + +static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf, + size_t n, loff_t *ppos) +{ + struct lirc_codec *lirc; + struct ir_input_dev *ir_dev; + int *txbuf; /* buffer with values to transmit */ + int ret = 0, count; + + lirc = lirc_get_pdata(file); + if (!lirc) + return -EFAULT; + + if (n % sizeof(int)) + return -EINVAL; + + count = n / sizeof(int); + if (count > LIRCBUF_SIZE || count % 2 == 0) + return -EINVAL; + + txbuf = memdup_user(buf, n); + if (IS_ERR(txbuf)) + return PTR_ERR(txbuf); + + ir_dev = lirc->ir_dev; + if (!ir_dev) { + ret = -EFAULT; + goto out; + } + + if (ir_dev->props && ir_dev->props->tx_ir) + ret = ir_dev->props->tx_ir(ir_dev->props->priv, txbuf, (u32)n); + +out: + kfree(txbuf); + return ret; +} + +static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, + unsigned long __user arg) +{ + struct lirc_codec *lirc; + struct ir_input_dev *ir_dev; + int ret = 0; + void *drv_data; + __u32 val = 0, tmp; + + lirc = lirc_get_pdata(filep); + if (!lirc) + return -EFAULT; + + ir_dev = lirc->ir_dev; + if (!ir_dev || !ir_dev->props || !ir_dev->props->priv) + return -EFAULT; + + drv_data = ir_dev->props->priv; + + if (_IOC_DIR(cmd) & _IOC_WRITE) { + ret = get_user(val, (__u32 *)arg); + if (ret) + return ret; + } + + switch (cmd) { + + /* legacy support */ + case LIRC_GET_SEND_MODE: + val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK; + break; + + case LIRC_SET_SEND_MODE: + if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK)) + return -EINVAL; + return 0; + + /* TX settings */ + case LIRC_SET_TRANSMITTER_MASK: + if (!ir_dev->props->s_tx_mask) + return -EINVAL; + + return ir_dev->props->s_tx_mask(drv_data, val); + + case LIRC_SET_SEND_CARRIER: + if (!ir_dev->props->s_tx_carrier) + return -EINVAL; + + return ir_dev->props->s_tx_carrier(drv_data, val); + + case LIRC_SET_SEND_DUTY_CYCLE: + if (!ir_dev->props->s_tx_duty_cycle) + return -ENOSYS; + + if (val <= 0 || val >= 100) + return -EINVAL; + + return ir_dev->props->s_tx_duty_cycle(drv_data, val); + + /* RX settings */ + case LIRC_SET_REC_CARRIER: + if (!ir_dev->props->s_rx_carrier_range) + return -ENOSYS; + + if (val <= 0) + return -EINVAL; + + return ir_dev->props->s_rx_carrier_range(drv_data, + ir_dev->raw->lirc.carrier_low, val); + + case LIRC_SET_REC_CARRIER_RANGE: + if (val <= 0) + return -EINVAL; + + ir_dev->raw->lirc.carrier_low = val; + return 0; + + case LIRC_GET_REC_RESOLUTION: + val = ir_dev->props->rx_resolution; + break; + + case LIRC_SET_WIDEBAND_RECEIVER: + if (!ir_dev->props->s_learning_mode) + return -ENOSYS; + + return ir_dev->props->s_learning_mode(drv_data, !!val); + + case LIRC_SET_MEASURE_CARRIER_MODE: + if (!ir_dev->props->s_carrier_report) + return -ENOSYS; + + return ir_dev->props->s_carrier_report(drv_data, !!val); + + /* Generic timeout support */ + case LIRC_GET_MIN_TIMEOUT: + if (!ir_dev->props->max_timeout) + return -ENOSYS; + val = ir_dev->props->min_timeout / 1000; + break; + + case LIRC_GET_MAX_TIMEOUT: + if (!ir_dev->props->max_timeout) + return -ENOSYS; + val = ir_dev->props->max_timeout / 1000; + break; + + case LIRC_SET_REC_TIMEOUT: + if (!ir_dev->props->max_timeout) + return -ENOSYS; + + tmp = val * 1000; + + if (tmp < ir_dev->props->min_timeout || + tmp > ir_dev->props->max_timeout) + return -EINVAL; + + ir_dev->props->timeout = tmp; + break; + + case LIRC_SET_REC_TIMEOUT_REPORTS: + lirc->send_timeout_reports = !!val; + break; + + default: + return lirc_dev_fop_ioctl(filep, cmd, arg); + } + + if (_IOC_DIR(cmd) & _IOC_READ) + ret = put_user(val, (__u32 *)arg); + + return ret; +} + +static int ir_lirc_open(void *data) +{ + return 0; +} + +static void ir_lirc_close(void *data) +{ + return; +} + +static struct file_operations lirc_fops = { + .owner = THIS_MODULE, + .write = ir_lirc_transmit_ir, + .unlocked_ioctl = ir_lirc_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = ir_lirc_ioctl, +#endif + .read = lirc_dev_fop_read, + .poll = lirc_dev_fop_poll, + .open = lirc_dev_fop_open, + .release = lirc_dev_fop_close, + .llseek = no_llseek, +}; + +static int ir_lirc_register(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct lirc_driver *drv; + struct lirc_buffer *rbuf; + int rc = -ENOMEM; + unsigned long features; + + drv = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); + if (!drv) + return rc; + + rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + if (!rbuf) + goto rbuf_alloc_failed; + + rc = lirc_buffer_init(rbuf, sizeof(int), LIRCBUF_SIZE); + if (rc) + goto rbuf_init_failed; + + features = LIRC_CAN_REC_MODE2; + if (ir_dev->props->tx_ir) { + + features |= LIRC_CAN_SEND_PULSE; + if (ir_dev->props->s_tx_mask) + features |= LIRC_CAN_SET_TRANSMITTER_MASK; + if (ir_dev->props->s_tx_carrier) + features |= LIRC_CAN_SET_SEND_CARRIER; + + if (ir_dev->props->s_tx_duty_cycle) + features |= LIRC_CAN_SET_SEND_DUTY_CYCLE; + } + + if (ir_dev->props->s_rx_carrier_range) + features |= LIRC_CAN_SET_REC_CARRIER | + LIRC_CAN_SET_REC_CARRIER_RANGE; + + if (ir_dev->props->s_learning_mode) + features |= LIRC_CAN_USE_WIDEBAND_RECEIVER; + + if (ir_dev->props->s_carrier_report) + features |= LIRC_CAN_MEASURE_CARRIER; + + + if (ir_dev->props->max_timeout) + features |= LIRC_CAN_SET_REC_TIMEOUT; + + + snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", + ir_dev->driver_name); + drv->minor = -1; + drv->features = features; + drv->data = &ir_dev->raw->lirc; + drv->rbuf = rbuf; + drv->set_use_inc = &ir_lirc_open; + drv->set_use_dec = &ir_lirc_close; + drv->code_length = sizeof(struct ir_raw_event) * 8; + drv->fops = &lirc_fops; + drv->dev = &ir_dev->dev; + drv->owner = THIS_MODULE; + + drv->minor = lirc_register_driver(drv); + if (drv->minor < 0) { + rc = -ENODEV; + goto lirc_register_failed; + } + + ir_dev->raw->lirc.drv = drv; + ir_dev->raw->lirc.ir_dev = ir_dev; + return 0; + +lirc_register_failed: +rbuf_init_failed: + kfree(rbuf); +rbuf_alloc_failed: + kfree(drv); + + return rc; +} + +static int ir_lirc_unregister(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct lirc_codec *lirc = &ir_dev->raw->lirc; + + lirc_unregister_driver(lirc->drv->minor); + lirc_buffer_free(lirc->drv->rbuf); + kfree(lirc->drv); + + return 0; +} + +static struct ir_raw_handler lirc_handler = { + .protocols = IR_TYPE_LIRC, + .decode = ir_lirc_decode, + .raw_register = ir_lirc_register, + .raw_unregister = ir_lirc_unregister, +}; + +static int __init ir_lirc_codec_init(void) +{ + ir_raw_handler_register(&lirc_handler); + + printk(KERN_INFO "IR LIRC bridge handler initialized\n"); + return 0; +} + +static void __exit ir_lirc_codec_exit(void) +{ + ir_raw_handler_unregister(&lirc_handler); +} + +module_init(ir_lirc_codec_init); +module_exit(ir_lirc_codec_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jarod Wilson "); +MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); +MODULE_DESCRIPTION("LIRC IR handler bridge"); diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c new file mode 100644 index 0000000..70993f7 --- /dev/null +++ b/drivers/media/rc/ir-nec-decoder.c @@ -0,0 +1,217 @@ +/* ir-nec-decoder.c - handle NEC IR Pulse/Space protocol + * + * Copyright (C) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include "ir-core-priv.h" + +#define NEC_NBITS 32 +#define NEC_UNIT 562500 /* ns */ +#define NEC_HEADER_PULSE (16 * NEC_UNIT) +#define NECX_HEADER_PULSE (8 * NEC_UNIT) /* Less common NEC variant */ +#define NEC_HEADER_SPACE (8 * NEC_UNIT) +#define NEC_REPEAT_SPACE (4 * NEC_UNIT) +#define NEC_BIT_PULSE (1 * NEC_UNIT) +#define NEC_BIT_0_SPACE (1 * NEC_UNIT) +#define NEC_BIT_1_SPACE (3 * NEC_UNIT) +#define NEC_TRAILER_PULSE (1 * NEC_UNIT) +#define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */ +#define NECX_REPEAT_BITS 1 + +enum nec_state { + STATE_INACTIVE, + STATE_HEADER_SPACE, + STATE_BIT_PULSE, + STATE_BIT_SPACE, + STATE_TRAILER_PULSE, + STATE_TRAILER_SPACE, +}; + +/** + * ir_nec_decode() - Decode one NEC pulse or space + * @input_dev: the struct input_dev descriptor of the device + * @duration: the struct ir_raw_event descriptor of the pulse/space + * + * This function returns -EINVAL if the pulse violates the state machine + */ +static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct nec_dec *data = &ir_dev->raw->nec; + u32 scancode; + u8 address, not_address, command, not_command; + + if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC)) + return 0; + + if (!is_timing_event(ev)) { + if (ev.reset) + data->state = STATE_INACTIVE; + return 0; + } + + IR_dprintk(2, "NEC decode started at state %d (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + + switch (data->state) { + + case STATE_INACTIVE: + if (!ev.pulse) + break; + + if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2)) { + data->is_nec_x = false; + data->necx_repeat = false; + } else if (eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2)) + data->is_nec_x = true; + else + break; + + data->count = 0; + data->state = STATE_HEADER_SPACE; + return 0; + + case STATE_HEADER_SPACE: + if (ev.pulse) + break; + + if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT / 2)) { + data->state = STATE_BIT_PULSE; + return 0; + } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) { + ir_repeat(input_dev); + IR_dprintk(1, "Repeat last key\n"); + data->state = STATE_TRAILER_PULSE; + return 0; + } + + break; + + case STATE_BIT_PULSE: + if (!ev.pulse) + break; + + if (!eq_margin(ev.duration, NEC_BIT_PULSE, NEC_UNIT / 2)) + break; + + data->state = STATE_BIT_SPACE; + return 0; + + case STATE_BIT_SPACE: + if (ev.pulse) + break; + + if (data->necx_repeat && data->count == NECX_REPEAT_BITS && + geq_margin(ev.duration, + NEC_TRAILER_SPACE, NEC_UNIT / 2)) { + IR_dprintk(1, "Repeat last key\n"); + ir_repeat(input_dev); + data->state = STATE_INACTIVE; + return 0; + + } else if (data->count > NECX_REPEAT_BITS) + data->necx_repeat = false; + + data->bits <<= 1; + if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2)) + data->bits |= 1; + else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2)) + break; + data->count++; + + if (data->count == NEC_NBITS) + data->state = STATE_TRAILER_PULSE; + else + data->state = STATE_BIT_PULSE; + + return 0; + + case STATE_TRAILER_PULSE: + if (!ev.pulse) + break; + + if (!eq_margin(ev.duration, NEC_TRAILER_PULSE, NEC_UNIT / 2)) + break; + + data->state = STATE_TRAILER_SPACE; + return 0; + + case STATE_TRAILER_SPACE: + if (ev.pulse) + break; + + if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2)) + break; + + address = bitrev8((data->bits >> 24) & 0xff); + not_address = bitrev8((data->bits >> 16) & 0xff); + command = bitrev8((data->bits >> 8) & 0xff); + not_command = bitrev8((data->bits >> 0) & 0xff); + + if ((command ^ not_command) != 0xff) { + IR_dprintk(1, "NEC checksum error: received 0x%08x\n", + data->bits); + break; + } + + if ((address ^ not_address) != 0xff) { + /* Extended NEC */ + scancode = address << 16 | + not_address << 8 | + command; + IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode); + } else { + /* Normal NEC */ + scancode = address << 8 | command; + IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); + } + + if (data->is_nec_x) + data->necx_repeat = true; + + ir_keydown(input_dev, scancode, 0); + data->state = STATE_INACTIVE; + return 0; + } + + IR_dprintk(1, "NEC decode failed at state %d (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + data->state = STATE_INACTIVE; + return -EINVAL; +} + +static struct ir_raw_handler nec_handler = { + .protocols = IR_TYPE_NEC, + .decode = ir_nec_decode, +}; + +static int __init ir_nec_decode_init(void) +{ + ir_raw_handler_register(&nec_handler); + + printk(KERN_INFO "IR NEC protocol handler initialized\n"); + return 0; +} + +static void __exit ir_nec_decode_exit(void) +{ + ir_raw_handler_unregister(&nec_handler); +} + +module_init(ir_nec_decode_init); +module_exit(ir_nec_decode_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); +MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); +MODULE_DESCRIPTION("NEC IR protocol decoder"); diff --git a/drivers/media/rc/ir-raw-event.c b/drivers/media/rc/ir-raw-event.c new file mode 100644 index 0000000..a06a07e --- /dev/null +++ b/drivers/media/rc/ir-raw-event.c @@ -0,0 +1,382 @@ +/* ir-raw-event.c - handle IR Pulse/Space event + * + * Copyright (C) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include "ir-core-priv.h" + +/* Define the max number of pulse/space transitions to buffer */ +#define MAX_IR_EVENT_SIZE 512 + +/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */ +static LIST_HEAD(ir_raw_client_list); + +/* Used to handle IR raw handler extensions */ +static DEFINE_MUTEX(ir_raw_handler_lock); +static LIST_HEAD(ir_raw_handler_list); +static u64 available_protocols; + +#ifdef MODULE +/* Used to load the decoders */ +static struct work_struct wq_load; +#endif + +static int ir_raw_event_thread(void *data) +{ + struct ir_raw_event ev; + struct ir_raw_handler *handler; + struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data; + int retval; + + while (!kthread_should_stop()) { + + spin_lock_irq(&raw->lock); + retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev)); + + if (!retval) { + set_current_state(TASK_INTERRUPTIBLE); + + if (kthread_should_stop()) + set_current_state(TASK_RUNNING); + + spin_unlock_irq(&raw->lock); + schedule(); + continue; + } + + spin_unlock_irq(&raw->lock); + + + BUG_ON(retval != sizeof(ev)); + + mutex_lock(&ir_raw_handler_lock); + list_for_each_entry(handler, &ir_raw_handler_list, list) + handler->decode(raw->input_dev, ev); + raw->prev_ev = ev; + mutex_unlock(&ir_raw_handler_lock); + } + + return 0; +} + +/** + * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders + * @input_dev: the struct input_dev device descriptor + * @ev: the struct ir_raw_event descriptor of the pulse/space + * + * This routine (which may be called from an interrupt context) stores a + * pulse/space duration for the raw ir decoding state machines. Pulses are + * signalled as positive values and spaces as negative values. A zero value + * will reset the decoding state machines. + */ +int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + + if (!ir->raw) + return -EINVAL; + + IR_dprintk(2, "sample: (%05dus %s)\n", + TO_US(ev->duration), TO_STR(ev->pulse)); + + if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) + return -ENOMEM; + + return 0; +} +EXPORT_SYMBOL_GPL(ir_raw_event_store); + +/** + * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space + * @input_dev: the struct input_dev device descriptor + * @type: the type of the event that has occurred + * + * This routine (which may be called from an interrupt context) is used to + * store the beginning of an ir pulse or space (or the start/end of ir + * reception) for the raw ir decoding state machines. This is used by + * hardware which does not provide durations directly but only interrupts + * (or similar events) on state change. + */ +int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + ktime_t now; + s64 delta; /* ns */ + struct ir_raw_event ev; + int rc = 0; + + if (!ir->raw) + return -EINVAL; + + now = ktime_get(); + delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event)); + + /* Check for a long duration since last event or if we're + * being called for the first time, note that delta can't + * possibly be negative. + */ + ev.duration = 0; + if (delta > IR_MAX_DURATION || !ir->raw->last_type) + type |= IR_START_EVENT; + else + ev.duration = delta; + + if (type & IR_START_EVENT) + ir_raw_event_reset(input_dev); + else if (ir->raw->last_type & IR_SPACE) { + ev.pulse = false; + rc = ir_raw_event_store(input_dev, &ev); + } else if (ir->raw->last_type & IR_PULSE) { + ev.pulse = true; + rc = ir_raw_event_store(input_dev, &ev); + } else + return 0; + + ir->raw->last_event = now; + ir->raw->last_type = type; + return rc; +} +EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); + +/** + * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing + * @input_dev: the struct input_dev device descriptor + * @type: the type of the event that has occurred + * + * This routine (which may be called from an interrupt context) works + * in similiar manner to ir_raw_event_store_edge. + * This routine is intended for devices with limited internal buffer + * It automerges samples of same type, and handles timeouts + */ +int ir_raw_event_store_with_filter(struct input_dev *input_dev, + struct ir_raw_event *ev) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + struct ir_raw_event_ctrl *raw = ir->raw; + + if (!raw || !ir->props) + return -EINVAL; + + /* Ignore spaces in idle mode */ + if (ir->idle && !ev->pulse) + return 0; + else if (ir->idle) + ir_raw_event_set_idle(input_dev, false); + + if (!raw->this_ev.duration) { + raw->this_ev = *ev; + } else if (ev->pulse == raw->this_ev.pulse) { + raw->this_ev.duration += ev->duration; + } else { + ir_raw_event_store(input_dev, &raw->this_ev); + raw->this_ev = *ev; + } + + /* Enter idle mode if nessesary */ + if (!ev->pulse && ir->props->timeout && + raw->this_ev.duration >= ir->props->timeout) { + ir_raw_event_set_idle(input_dev, true); + } + return 0; +} +EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter); + +/** + * ir_raw_event_set_idle() - hint the ir core if device is receiving + * IR data or not + * @input_dev: the struct input_dev device descriptor + * @idle: the hint value + */ +void ir_raw_event_set_idle(struct input_dev *input_dev, bool idle) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + struct ir_raw_event_ctrl *raw = ir->raw; + + if (!ir->props || !ir->raw) + return; + + IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave"); + + if (idle) { + raw->this_ev.timeout = true; + ir_raw_event_store(input_dev, &raw->this_ev); + init_ir_raw_event(&raw->this_ev); + } + + if (ir->props->s_idle) + ir->props->s_idle(ir->props->priv, idle); + ir->idle = idle; +} +EXPORT_SYMBOL_GPL(ir_raw_event_set_idle); + +/** + * ir_raw_event_handle() - schedules the decoding of stored ir data + * @input_dev: the struct input_dev device descriptor + * + * This routine will signal the workqueue to start decoding stored ir data. + */ +void ir_raw_event_handle(struct input_dev *input_dev) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + unsigned long flags; + + if (!ir->raw) + return; + + spin_lock_irqsave(&ir->raw->lock, flags); + wake_up_process(ir->raw->thread); + spin_unlock_irqrestore(&ir->raw->lock, flags); +} +EXPORT_SYMBOL_GPL(ir_raw_event_handle); + +/* used internally by the sysfs interface */ +u64 +ir_raw_get_allowed_protocols() +{ + u64 protocols; + mutex_lock(&ir_raw_handler_lock); + protocols = available_protocols; + mutex_unlock(&ir_raw_handler_lock); + return protocols; +} + +/* + * Used to (un)register raw event clients + */ +int ir_raw_event_register(struct input_dev *input_dev) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + int rc; + struct ir_raw_handler *handler; + + ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); + if (!ir->raw) + return -ENOMEM; + + ir->raw->input_dev = input_dev; + + ir->raw->enabled_protocols = ~0; + rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, + GFP_KERNEL); + if (rc < 0) { + kfree(ir->raw); + ir->raw = NULL; + return rc; + } + + spin_lock_init(&ir->raw->lock); + ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw, + "rc%u", (unsigned int)ir->devno); + + if (IS_ERR(ir->raw->thread)) { + int ret = PTR_ERR(ir->raw->thread); + + kfree(ir->raw); + ir->raw = NULL; + return ret; + } + + mutex_lock(&ir_raw_handler_lock); + list_add_tail(&ir->raw->list, &ir_raw_client_list); + list_for_each_entry(handler, &ir_raw_handler_list, list) + if (handler->raw_register) + handler->raw_register(ir->raw->input_dev); + mutex_unlock(&ir_raw_handler_lock); + + return 0; +} + +void ir_raw_event_unregister(struct input_dev *input_dev) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + struct ir_raw_handler *handler; + + if (!ir->raw) + return; + + kthread_stop(ir->raw->thread); + + mutex_lock(&ir_raw_handler_lock); + list_del(&ir->raw->list); + list_for_each_entry(handler, &ir_raw_handler_list, list) + if (handler->raw_unregister) + handler->raw_unregister(ir->raw->input_dev); + mutex_unlock(&ir_raw_handler_lock); + + kfifo_free(&ir->raw->kfifo); + kfree(ir->raw); + ir->raw = NULL; +} + +/* + * Extension interface - used to register the IR decoders + */ + +int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) +{ + struct ir_raw_event_ctrl *raw; + + mutex_lock(&ir_raw_handler_lock); + list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); + if (ir_raw_handler->raw_register) + list_for_each_entry(raw, &ir_raw_client_list, list) + ir_raw_handler->raw_register(raw->input_dev); + available_protocols |= ir_raw_handler->protocols; + mutex_unlock(&ir_raw_handler_lock); + + return 0; +} +EXPORT_SYMBOL(ir_raw_handler_register); + +void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) +{ + struct ir_raw_event_ctrl *raw; + + mutex_lock(&ir_raw_handler_lock); + list_del(&ir_raw_handler->list); + if (ir_raw_handler->raw_unregister) + list_for_each_entry(raw, &ir_raw_client_list, list) + ir_raw_handler->raw_unregister(raw->input_dev); + available_protocols &= ~ir_raw_handler->protocols; + mutex_unlock(&ir_raw_handler_lock); +} +EXPORT_SYMBOL(ir_raw_handler_unregister); + +#ifdef MODULE +static void init_decoders(struct work_struct *work) +{ + /* Load the decoder modules */ + + load_nec_decode(); + load_rc5_decode(); + load_rc6_decode(); + load_jvc_decode(); + load_sony_decode(); + load_lirc_codec(); + + /* If needed, we may later add some init code. In this case, + it is needed to change the CONFIG_MODULE test at ir-core.h + */ +} +#endif + +void ir_raw_init(void) +{ +#ifdef MODULE + INIT_WORK(&wq_load, init_decoders); + schedule_work(&wq_load); +#endif +} diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c new file mode 100644 index 0000000..572ed4c --- /dev/null +++ b/drivers/media/rc/ir-rc5-decoder.c @@ -0,0 +1,190 @@ +/* ir-rc5-decoder.c - handle RC5(x) IR Pulse/Space protocol + * + * Copyright (C) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * This code handles 14 bits RC5 protocols and 20 bits RC5x protocols. + * There are other variants that use a different number of bits. + * This is currently unsupported. + * It considers a carrier of 36 kHz, with a total of 14/20 bits, where + * the first two bits are start bits, and a third one is a filing bit + */ + +#include "ir-core-priv.h" + +#define RC5_NBITS 14 +#define RC5X_NBITS 20 +#define CHECK_RC5X_NBITS 8 +#define RC5_UNIT 888888 /* ns */ +#define RC5_BIT_START (1 * RC5_UNIT) +#define RC5_BIT_END (1 * RC5_UNIT) +#define RC5X_SPACE (4 * RC5_UNIT) + +enum rc5_state { + STATE_INACTIVE, + STATE_BIT_START, + STATE_BIT_END, + STATE_CHECK_RC5X, + STATE_FINISHED, +}; + +/** + * ir_rc5_decode() - Decode one RC-5 pulse or space + * @input_dev: the struct input_dev descriptor of the device + * @ev: the struct ir_raw_event descriptor of the pulse/space + * + * This function returns -EINVAL if the pulse violates the state machine + */ +static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct rc5_dec *data = &ir_dev->raw->rc5; + u8 toggle; + u32 scancode; + + if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5)) + return 0; + + if (!is_timing_event(ev)) { + if (ev.reset) + data->state = STATE_INACTIVE; + return 0; + } + + if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2)) + goto out; + +again: + IR_dprintk(2, "RC5(x) decode started at state %i (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + + if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2)) + return 0; + + switch (data->state) { + + case STATE_INACTIVE: + if (!ev.pulse) + break; + + data->state = STATE_BIT_START; + data->count = 1; + /* We just need enough bits to get to STATE_CHECK_RC5X */ + data->wanted_bits = RC5X_NBITS; + decrease_duration(&ev, RC5_BIT_START); + goto again; + + case STATE_BIT_START: + if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2)) + break; + + data->bits <<= 1; + if (!ev.pulse) + data->bits |= 1; + data->count++; + data->state = STATE_BIT_END; + return 0; + + case STATE_BIT_END: + if (!is_transition(&ev, &ir_dev->raw->prev_ev)) + break; + + if (data->count == data->wanted_bits) + data->state = STATE_FINISHED; + else if (data->count == CHECK_RC5X_NBITS) + data->state = STATE_CHECK_RC5X; + else + data->state = STATE_BIT_START; + + decrease_duration(&ev, RC5_BIT_END); + goto again; + + case STATE_CHECK_RC5X: + if (!ev.pulse && geq_margin(ev.duration, RC5X_SPACE, RC5_UNIT / 2)) { + /* RC5X */ + data->wanted_bits = RC5X_NBITS; + decrease_duration(&ev, RC5X_SPACE); + } else { + /* RC5 */ + data->wanted_bits = RC5_NBITS; + } + data->state = STATE_BIT_START; + goto again; + + case STATE_FINISHED: + if (ev.pulse) + break; + + if (data->wanted_bits == RC5X_NBITS) { + /* RC5X */ + u8 xdata, command, system; + xdata = (data->bits & 0x0003F) >> 0; + command = (data->bits & 0x00FC0) >> 6; + system = (data->bits & 0x1F000) >> 12; + toggle = (data->bits & 0x20000) ? 1 : 0; + command += (data->bits & 0x01000) ? 0 : 0x40; + scancode = system << 16 | command << 8 | xdata; + + IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n", + scancode, toggle); + + } else { + /* RC5 */ + u8 command, system; + command = (data->bits & 0x0003F) >> 0; + system = (data->bits & 0x007C0) >> 6; + toggle = (data->bits & 0x00800) ? 1 : 0; + command += (data->bits & 0x01000) ? 0 : 0x40; + scancode = system << 8 | command; + + IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n", + scancode, toggle); + } + + ir_keydown(input_dev, scancode, toggle); + data->state = STATE_INACTIVE; + return 0; + } + +out: + IR_dprintk(1, "RC5(x) decode failed at state %i (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + data->state = STATE_INACTIVE; + return -EINVAL; +} + +static struct ir_raw_handler rc5_handler = { + .protocols = IR_TYPE_RC5, + .decode = ir_rc5_decode, +}; + +static int __init ir_rc5_decode_init(void) +{ + ir_raw_handler_register(&rc5_handler); + + printk(KERN_INFO "IR RC5(x) protocol handler initialized\n"); + return 0; +} + +static void __exit ir_rc5_decode_exit(void) +{ + ir_raw_handler_unregister(&rc5_handler); +} + +module_init(ir_rc5_decode_init); +module_exit(ir_rc5_decode_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); +MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); +MODULE_DESCRIPTION("RC5(x) IR protocol decoder"); diff --git a/drivers/media/rc/ir-rc5-sz-decoder.c b/drivers/media/rc/ir-rc5-sz-decoder.c new file mode 100644 index 0000000..7c41350 --- /dev/null +++ b/drivers/media/rc/ir-rc5-sz-decoder.c @@ -0,0 +1,154 @@ +/* ir-rc5-sz-decoder.c - handle RC5 Streamzap IR Pulse/Space protocol + * + * Copyright (C) 2010 by Mauro Carvalho Chehab + * Copyright (C) 2010 by Jarod Wilson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * This code handles the 15 bit RC5-ish protocol used by the Streamzap + * PC Remote. + * It considers a carrier of 36 kHz, with a total of 15 bits, where + * the first two bits are start bits, and a third one is a filing bit + */ + +#include "ir-core-priv.h" + +#define RC5_SZ_NBITS 15 +#define RC5_UNIT 888888 /* ns */ +#define RC5_BIT_START (1 * RC5_UNIT) +#define RC5_BIT_END (1 * RC5_UNIT) + +enum rc5_sz_state { + STATE_INACTIVE, + STATE_BIT_START, + STATE_BIT_END, + STATE_FINISHED, +}; + +/** + * ir_rc5_sz_decode() - Decode one RC-5 Streamzap pulse or space + * @input_dev: the struct input_dev descriptor of the device + * @ev: the struct ir_raw_event descriptor of the pulse/space + * + * This function returns -EINVAL if the pulse violates the state machine + */ +static int ir_rc5_sz_decode(struct input_dev *input_dev, struct ir_raw_event ev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct rc5_sz_dec *data = &ir_dev->raw->rc5_sz; + u8 toggle, command, system; + u32 scancode; + + if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5_SZ)) + return 0; + + if (!is_timing_event(ev)) { + if (ev.reset) + data->state = STATE_INACTIVE; + return 0; + } + + if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2)) + goto out; + +again: + IR_dprintk(2, "RC5-sz decode started at state %i (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + + if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2)) + return 0; + + switch (data->state) { + + case STATE_INACTIVE: + if (!ev.pulse) + break; + + data->state = STATE_BIT_START; + data->count = 1; + data->wanted_bits = RC5_SZ_NBITS; + decrease_duration(&ev, RC5_BIT_START); + goto again; + + case STATE_BIT_START: + if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2)) + break; + + data->bits <<= 1; + if (!ev.pulse) + data->bits |= 1; + data->count++; + data->state = STATE_BIT_END; + return 0; + + case STATE_BIT_END: + if (!is_transition(&ev, &ir_dev->raw->prev_ev)) + break; + + if (data->count == data->wanted_bits) + data->state = STATE_FINISHED; + else + data->state = STATE_BIT_START; + + decrease_duration(&ev, RC5_BIT_END); + goto again; + + case STATE_FINISHED: + if (ev.pulse) + break; + + /* RC5-sz */ + command = (data->bits & 0x0003F) >> 0; + system = (data->bits & 0x02FC0) >> 6; + toggle = (data->bits & 0x01000) ? 1 : 0; + scancode = system << 6 | command; + + IR_dprintk(1, "RC5-sz scancode 0x%04x (toggle: %u)\n", + scancode, toggle); + + ir_keydown(input_dev, scancode, toggle); + data->state = STATE_INACTIVE; + return 0; + } + +out: + IR_dprintk(1, "RC5-sz decode failed at state %i (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + data->state = STATE_INACTIVE; + return -EINVAL; +} + +static struct ir_raw_handler rc5_sz_handler = { + .protocols = IR_TYPE_RC5_SZ, + .decode = ir_rc5_sz_decode, +}; + +static int __init ir_rc5_sz_decode_init(void) +{ + ir_raw_handler_register(&rc5_sz_handler); + + printk(KERN_INFO "IR RC5 (streamzap) protocol handler initialized\n"); + return 0; +} + +static void __exit ir_rc5_sz_decode_exit(void) +{ + ir_raw_handler_unregister(&rc5_sz_handler); +} + +module_init(ir_rc5_sz_decode_init); +module_exit(ir_rc5_sz_decode_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jarod Wilson "); +MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); +MODULE_DESCRIPTION("RC5 (streamzap) IR protocol decoder"); diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c new file mode 100644 index 0000000..d25da91 --- /dev/null +++ b/drivers/media/rc/ir-rc6-decoder.c @@ -0,0 +1,281 @@ +/* ir-rc6-decoder.c - A decoder for the RC6 IR protocol + * + * Copyright (C) 2010 by David Härdeman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "ir-core-priv.h" + +/* + * This decoder currently supports: + * RC6-0-16 (standard toggle bit in header) + * RC6-6A-24 (no toggle bit) + * RC6-6A-32 (MCE version with toggle bit in body) + */ + +#define RC6_UNIT 444444 /* us */ +#define RC6_HEADER_NBITS 4 /* not including toggle bit */ +#define RC6_0_NBITS 16 +#define RC6_6A_SMALL_NBITS 24 +#define RC6_6A_LARGE_NBITS 32 +#define RC6_PREFIX_PULSE (6 * RC6_UNIT) +#define RC6_PREFIX_SPACE (2 * RC6_UNIT) +#define RC6_BIT_START (1 * RC6_UNIT) +#define RC6_BIT_END (1 * RC6_UNIT) +#define RC6_TOGGLE_START (2 * RC6_UNIT) +#define RC6_TOGGLE_END (2 * RC6_UNIT) +#define RC6_MODE_MASK 0x07 /* for the header bits */ +#define RC6_STARTBIT_MASK 0x08 /* for the header bits */ +#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ + +enum rc6_mode { + RC6_MODE_0, + RC6_MODE_6A, + RC6_MODE_UNKNOWN, +}; + +enum rc6_state { + STATE_INACTIVE, + STATE_PREFIX_SPACE, + STATE_HEADER_BIT_START, + STATE_HEADER_BIT_END, + STATE_TOGGLE_START, + STATE_TOGGLE_END, + STATE_BODY_BIT_START, + STATE_BODY_BIT_END, + STATE_FINISHED, +}; + +static enum rc6_mode rc6_mode(struct rc6_dec *data) +{ + switch (data->header & RC6_MODE_MASK) { + case 0: + return RC6_MODE_0; + case 6: + if (!data->toggle) + return RC6_MODE_6A; + /* fall through */ + default: + return RC6_MODE_UNKNOWN; + } +} + +/** + * ir_rc6_decode() - Decode one RC6 pulse or space + * @input_dev: the struct input_dev descriptor of the device + * @ev: the struct ir_raw_event descriptor of the pulse/space + * + * This function returns -EINVAL if the pulse violates the state machine + */ +static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct rc6_dec *data = &ir_dev->raw->rc6; + u32 scancode; + u8 toggle; + + if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6)) + return 0; + + if (!is_timing_event(ev)) { + if (ev.reset) + data->state = STATE_INACTIVE; + return 0; + } + + if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) + goto out; + +again: + IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + + if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) + return 0; + + switch (data->state) { + + case STATE_INACTIVE: + if (!ev.pulse) + break; + + /* Note: larger margin on first pulse since each RC6_UNIT + is quite short and some hardware takes some time to + adjust to the signal */ + if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT)) + break; + + data->state = STATE_PREFIX_SPACE; + data->count = 0; + return 0; + + case STATE_PREFIX_SPACE: + if (ev.pulse) + break; + + if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2)) + break; + + data->state = STATE_HEADER_BIT_START; + return 0; + + case STATE_HEADER_BIT_START: + if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) + break; + + data->header <<= 1; + if (ev.pulse) + data->header |= 1; + data->count++; + data->state = STATE_HEADER_BIT_END; + return 0; + + case STATE_HEADER_BIT_END: + if (!is_transition(&ev, &ir_dev->raw->prev_ev)) + break; + + if (data->count == RC6_HEADER_NBITS) + data->state = STATE_TOGGLE_START; + else + data->state = STATE_HEADER_BIT_START; + + decrease_duration(&ev, RC6_BIT_END); + goto again; + + case STATE_TOGGLE_START: + if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2)) + break; + + data->toggle = ev.pulse; + data->state = STATE_TOGGLE_END; + return 0; + + case STATE_TOGGLE_END: + if (!is_transition(&ev, &ir_dev->raw->prev_ev) || + !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2)) + break; + + if (!(data->header & RC6_STARTBIT_MASK)) { + IR_dprintk(1, "RC6 invalid start bit\n"); + break; + } + + data->state = STATE_BODY_BIT_START; + decrease_duration(&ev, RC6_TOGGLE_END); + data->count = 0; + + switch (rc6_mode(data)) { + case RC6_MODE_0: + data->wanted_bits = RC6_0_NBITS; + break; + case RC6_MODE_6A: + /* This might look weird, but we basically + check the value of the first body bit to + determine the number of bits in mode 6A */ + if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) || + geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) + data->wanted_bits = RC6_6A_LARGE_NBITS; + else + data->wanted_bits = RC6_6A_SMALL_NBITS; + break; + default: + IR_dprintk(1, "RC6 unknown mode\n"); + goto out; + } + goto again; + + case STATE_BODY_BIT_START: + if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) + break; + + data->body <<= 1; + if (ev.pulse) + data->body |= 1; + data->count++; + data->state = STATE_BODY_BIT_END; + return 0; + + case STATE_BODY_BIT_END: + if (!is_transition(&ev, &ir_dev->raw->prev_ev)) + break; + + if (data->count == data->wanted_bits) + data->state = STATE_FINISHED; + else + data->state = STATE_BODY_BIT_START; + + decrease_duration(&ev, RC6_BIT_END); + goto again; + + case STATE_FINISHED: + if (ev.pulse) + break; + + switch (rc6_mode(data)) { + case RC6_MODE_0: + scancode = data->body & 0xffff; + toggle = data->toggle; + IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n", + scancode, toggle); + break; + case RC6_MODE_6A: + if (data->wanted_bits == RC6_6A_LARGE_NBITS) { + toggle = data->body & RC6_6A_MCE_TOGGLE_MASK ? 1 : 0; + scancode = data->body & ~RC6_6A_MCE_TOGGLE_MASK; + } else { + toggle = 0; + scancode = data->body & 0xffffff; + } + + IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n", + scancode, toggle); + break; + default: + IR_dprintk(1, "RC6 unknown mode\n"); + goto out; + } + + ir_keydown(input_dev, scancode, toggle); + data->state = STATE_INACTIVE; + return 0; + } + +out: + IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + data->state = STATE_INACTIVE; + return -EINVAL; +} + +static struct ir_raw_handler rc6_handler = { + .protocols = IR_TYPE_RC6, + .decode = ir_rc6_decode, +}; + +static int __init ir_rc6_decode_init(void) +{ + ir_raw_handler_register(&rc6_handler); + + printk(KERN_INFO "IR RC6 protocol handler initialized\n"); + return 0; +} + +static void __exit ir_rc6_decode_exit(void) +{ + ir_raw_handler_unregister(&rc6_handler); +} + +module_init(ir_rc6_decode_init); +module_exit(ir_rc6_decode_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Härdeman "); +MODULE_DESCRIPTION("RC6 IR protocol decoder"); diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c new file mode 100644 index 0000000..2d15730 --- /dev/null +++ b/drivers/media/rc/ir-sony-decoder.c @@ -0,0 +1,182 @@ +/* ir-sony-decoder.c - handle Sony IR Pulse/Space protocol + * + * Copyright (C) 2010 by David Härdeman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include "ir-core-priv.h" + +#define SONY_UNIT 600000 /* ns */ +#define SONY_HEADER_PULSE (4 * SONY_UNIT) +#define SONY_HEADER_SPACE (1 * SONY_UNIT) +#define SONY_BIT_0_PULSE (1 * SONY_UNIT) +#define SONY_BIT_1_PULSE (2 * SONY_UNIT) +#define SONY_BIT_SPACE (1 * SONY_UNIT) +#define SONY_TRAILER_SPACE (10 * SONY_UNIT) /* minimum */ + +enum sony_state { + STATE_INACTIVE, + STATE_HEADER_SPACE, + STATE_BIT_PULSE, + STATE_BIT_SPACE, + STATE_FINISHED, +}; + +/** + * ir_sony_decode() - Decode one Sony pulse or space + * @input_dev: the struct input_dev descriptor of the device + * @ev: the struct ir_raw_event descriptor of the pulse/space + * + * This function returns -EINVAL if the pulse violates the state machine + */ +static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct sony_dec *data = &ir_dev->raw->sony; + u32 scancode; + u8 device, subdevice, function; + + if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY)) + return 0; + + if (!is_timing_event(ev)) { + if (ev.reset) + data->state = STATE_INACTIVE; + return 0; + } + + if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2)) + goto out; + + IR_dprintk(2, "Sony decode started at state %d (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + + switch (data->state) { + + case STATE_INACTIVE: + if (!ev.pulse) + break; + + if (!eq_margin(ev.duration, SONY_HEADER_PULSE, SONY_UNIT / 2)) + break; + + data->count = 0; + data->state = STATE_HEADER_SPACE; + return 0; + + case STATE_HEADER_SPACE: + if (ev.pulse) + break; + + if (!eq_margin(ev.duration, SONY_HEADER_SPACE, SONY_UNIT / 2)) + break; + + data->state = STATE_BIT_PULSE; + return 0; + + case STATE_BIT_PULSE: + if (!ev.pulse) + break; + + data->bits <<= 1; + if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2)) + data->bits |= 1; + else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2)) + break; + + data->count++; + data->state = STATE_BIT_SPACE; + return 0; + + case STATE_BIT_SPACE: + if (ev.pulse) + break; + + if (!geq_margin(ev.duration, SONY_BIT_SPACE, SONY_UNIT / 2)) + break; + + decrease_duration(&ev, SONY_BIT_SPACE); + + if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2)) { + data->state = STATE_BIT_PULSE; + return 0; + } + + data->state = STATE_FINISHED; + /* Fall through */ + + case STATE_FINISHED: + if (ev.pulse) + break; + + if (!geq_margin(ev.duration, SONY_TRAILER_SPACE, SONY_UNIT / 2)) + break; + + switch (data->count) { + case 12: + device = bitrev8((data->bits << 3) & 0xF8); + subdevice = 0; + function = bitrev8((data->bits >> 4) & 0xFE); + break; + case 15: + device = bitrev8((data->bits >> 0) & 0xFF); + subdevice = 0; + function = bitrev8((data->bits >> 7) & 0xFD); + break; + case 20: + device = bitrev8((data->bits >> 5) & 0xF8); + subdevice = bitrev8((data->bits >> 0) & 0xFF); + function = bitrev8((data->bits >> 12) & 0xFE); + break; + default: + IR_dprintk(1, "Sony invalid bitcount %u\n", data->count); + goto out; + } + + scancode = device << 16 | subdevice << 8 | function; + IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode); + ir_keydown(input_dev, scancode, 0); + data->state = STATE_INACTIVE; + return 0; + } + +out: + IR_dprintk(1, "Sony decode failed at state %d (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + data->state = STATE_INACTIVE; + return -EINVAL; +} + +static struct ir_raw_handler sony_handler = { + .protocols = IR_TYPE_SONY, + .decode = ir_sony_decode, +}; + +static int __init ir_sony_decode_init(void) +{ + ir_raw_handler_register(&sony_handler); + + printk(KERN_INFO "IR Sony protocol handler initialized\n"); + return 0; +} + +static void __exit ir_sony_decode_exit(void) +{ + ir_raw_handler_unregister(&sony_handler); +} + +module_init(ir_sony_decode_init); +module_exit(ir_sony_decode_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Härdeman "); +MODULE_DESCRIPTION("Sony IR protocol decoder"); diff --git a/drivers/media/rc/ir-sysfs.c b/drivers/media/rc/ir-sysfs.c new file mode 100644 index 0000000..38423a8 --- /dev/null +++ b/drivers/media/rc/ir-sysfs.c @@ -0,0 +1,362 @@ +/* ir-sysfs.c - sysfs interface for RC devices (/sys/class/rc) + * + * Copyright (C) 2009-2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include "ir-core-priv.h" + +#define IRRCV_NUM_DEVICES 256 + +/* bit array to represent IR sysfs device number */ +static unsigned long ir_core_dev_number; + +/* class for /sys/class/rc */ +static char *ir_devnode(struct device *dev, mode_t *mode) +{ + return kasprintf(GFP_KERNEL, "rc/%s", dev_name(dev)); +} + +static struct class ir_input_class = { + .name = "rc", + .devnode = ir_devnode, +}; + +static struct { + u64 type; + char *name; +} proto_names[] = { + { IR_TYPE_UNKNOWN, "unknown" }, + { IR_TYPE_RC5, "rc-5" }, + { IR_TYPE_NEC, "nec" }, + { IR_TYPE_RC6, "rc-6" }, + { IR_TYPE_JVC, "jvc" }, + { IR_TYPE_SONY, "sony" }, + { IR_TYPE_RC5_SZ, "rc-5-sz" }, + { IR_TYPE_LIRC, "lirc" }, +}; + +#define PROTO_NONE "none" + +/** + * show_protocols() - shows the current IR protocol(s) + * @d: the device descriptor + * @mattr: the device attribute struct (unused) + * @buf: a pointer to the output buffer + * + * This routine is a callback routine for input read the IR protocol type(s). + * it is trigged by reading /sys/class/rc/rc?/protocols. + * It returns the protocol names of supported protocols. + * Enabled protocols are printed in brackets. + */ +static ssize_t show_protocols(struct device *d, + struct device_attribute *mattr, char *buf) +{ + struct ir_input_dev *ir_dev = dev_get_drvdata(d); + u64 allowed, enabled; + char *tmp = buf; + int i; + + /* Device is being removed */ + if (!ir_dev) + return -EINVAL; + + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { + enabled = ir_dev->rc_tab.ir_type; + allowed = ir_dev->props->allowed_protos; + } else if (ir_dev->raw) { + enabled = ir_dev->raw->enabled_protocols; + allowed = ir_raw_get_allowed_protocols(); + } else + return sprintf(tmp, "[builtin]\n"); + + IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", + (long long)allowed, + (long long)enabled); + + for (i = 0; i < ARRAY_SIZE(proto_names); i++) { + if (allowed & enabled & proto_names[i].type) + tmp += sprintf(tmp, "[%s] ", proto_names[i].name); + else if (allowed & proto_names[i].type) + tmp += sprintf(tmp, "%s ", proto_names[i].name); + } + + if (tmp != buf) + tmp--; + *tmp = '\n'; + return tmp + 1 - buf; +} + +/** + * store_protocols() - changes the current IR protocol(s) + * @d: the device descriptor + * @mattr: the device attribute struct (unused) + * @buf: a pointer to the input buffer + * @len: length of the input buffer + * + * This routine is a callback routine for changing the IR protocol type. + * It is trigged by writing to /sys/class/rc/rc?/protocols. + * Writing "+proto" will add a protocol to the list of enabled protocols. + * Writing "-proto" will remove a protocol from the list of enabled protocols. + * Writing "proto" will enable only "proto". + * Writing "none" will disable all protocols. + * Returns -EINVAL if an invalid protocol combination or unknown protocol name + * is used, otherwise @len. + */ +static ssize_t store_protocols(struct device *d, + struct device_attribute *mattr, + const char *data, + size_t len) +{ + struct ir_input_dev *ir_dev = dev_get_drvdata(d); + bool enable, disable; + const char *tmp; + u64 type; + u64 mask; + int rc, i, count = 0; + unsigned long flags; + + /* Device is being removed */ + if (!ir_dev) + return -EINVAL; + + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) + type = ir_dev->rc_tab.ir_type; + else if (ir_dev->raw) + type = ir_dev->raw->enabled_protocols; + else { + IR_dprintk(1, "Protocol switching not supported\n"); + return -EINVAL; + } + + while ((tmp = strsep((char **) &data, " \n")) != NULL) { + if (!*tmp) + break; + + if (*tmp == '+') { + enable = true; + disable = false; + tmp++; + } else if (*tmp == '-') { + enable = false; + disable = true; + tmp++; + } else { + enable = false; + disable = false; + } + + if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) { + tmp += sizeof(PROTO_NONE); + mask = 0; + count++; + } else { + for (i = 0; i < ARRAY_SIZE(proto_names); i++) { + if (!strncasecmp(tmp, proto_names[i].name, strlen(proto_names[i].name))) { + tmp += strlen(proto_names[i].name); + mask = proto_names[i].type; + break; + } + } + if (i == ARRAY_SIZE(proto_names)) { + IR_dprintk(1, "Unknown protocol: '%s'\n", tmp); + return -EINVAL; + } + count++; + } + + if (enable) + type |= mask; + else if (disable) + type &= ~mask; + else + type = mask; + } + + if (!count) { + IR_dprintk(1, "Protocol not specified\n"); + return -EINVAL; + } + + if (ir_dev->props && ir_dev->props->change_protocol) { + rc = ir_dev->props->change_protocol(ir_dev->props->priv, + type); + if (rc < 0) { + IR_dprintk(1, "Error setting protocols to 0x%llx\n", + (long long)type); + return -EINVAL; + } + } + + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { + spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); + ir_dev->rc_tab.ir_type = type; + spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); + } else { + ir_dev->raw->enabled_protocols = type; + } + + IR_dprintk(1, "Current protocol(s): 0x%llx\n", + (long long)type); + + return len; +} + +#define ADD_HOTPLUG_VAR(fmt, val...) \ + do { \ + int err = add_uevent_var(env, fmt, val); \ + if (err) \ + return err; \ + } while (0) + +static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) +{ + struct ir_input_dev *ir_dev = dev_get_drvdata(device); + + if (ir_dev->rc_tab.name) + ADD_HOTPLUG_VAR("NAME=%s", ir_dev->rc_tab.name); + if (ir_dev->driver_name) + ADD_HOTPLUG_VAR("DRV_NAME=%s", ir_dev->driver_name); + + return 0; +} + +/* + * Static device attribute struct with the sysfs attributes for IR's + */ +static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR, + show_protocols, store_protocols); + +static struct attribute *rc_dev_attrs[] = { + &dev_attr_protocols.attr, + NULL, +}; + +static struct attribute_group rc_dev_attr_grp = { + .attrs = rc_dev_attrs, +}; + +static const struct attribute_group *rc_dev_attr_groups[] = { + &rc_dev_attr_grp, + NULL +}; + +static struct device_type rc_dev_type = { + .groups = rc_dev_attr_groups, + .uevent = rc_dev_uevent, +}; + +/** + * ir_register_class() - creates the sysfs for /sys/class/rc/rc? + * @input_dev: the struct input_dev descriptor of the device + * + * This routine is used to register the syfs code for IR class + */ +int ir_register_class(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + int devno = find_first_zero_bit(&ir_core_dev_number, + IRRCV_NUM_DEVICES); + + if (unlikely(devno < 0)) + return devno; + + ir_dev->dev.type = &rc_dev_type; + ir_dev->devno = devno; + + ir_dev->dev.class = &ir_input_class; + ir_dev->dev.parent = input_dev->dev.parent; + input_dev->dev.parent = &ir_dev->dev; + dev_set_name(&ir_dev->dev, "rc%d", devno); + dev_set_drvdata(&ir_dev->dev, ir_dev); + return device_register(&ir_dev->dev); +}; + +/** + * ir_register_input - registers ir input device with input subsystem + * @input_dev: the struct input_dev descriptor of the device + */ + +int ir_register_input(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + int rc; + const char *path; + + + rc = input_register_device(input_dev); + if (rc < 0) { + device_del(&ir_dev->dev); + return rc; + } + + __module_get(THIS_MODULE); + + path = kobject_get_path(&ir_dev->dev.kobj, GFP_KERNEL); + printk(KERN_INFO "%s: %s as %s\n", + dev_name(&ir_dev->dev), + input_dev->name ? input_dev->name : "Unspecified device", + path ? path : "N/A"); + kfree(path); + + set_bit(ir_dev->devno, &ir_core_dev_number); + return 0; +} + +/** + * ir_unregister_class() - removes the sysfs for sysfs for + * /sys/class/rc/rc? + * @input_dev: the struct input_dev descriptor of the device + * + * This routine is used to unregister the syfs code for IR class + */ +void ir_unregister_class(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + + input_set_drvdata(input_dev, NULL); + clear_bit(ir_dev->devno, &ir_core_dev_number); + input_unregister_device(input_dev); + device_del(&ir_dev->dev); + + module_put(THIS_MODULE); +} + +/* + * Init/exit code for the module. Basically, creates/removes /sys/class/rc + */ + +static int __init ir_core_init(void) +{ + int rc = class_register(&ir_input_class); + if (rc) { + printk(KERN_ERR "ir_core: unable to register rc class\n"); + return rc; + } + + /* Initialize/load the decoders/keymap code that will be used */ + ir_raw_init(); + ir_rcmap_init(); + + return 0; +} + +static void __exit ir_core_exit(void) +{ + class_unregister(&ir_input_class); + ir_rcmap_cleanup(); +} + +module_init(ir_core_init); +module_exit(ir_core_exit); diff --git a/drivers/media/rc/keymaps/Kconfig b/drivers/media/rc/keymaps/Kconfig new file mode 100644 index 0000000..14b22f5 --- /dev/null +++ b/drivers/media/rc/keymaps/Kconfig @@ -0,0 +1,15 @@ +config RC_MAP + tristate "Compile Remote Controller keymap modules" + depends on IR_CORE + default y + + ---help--- + This option enables the compilation of lots of Remote + Controller tables. They are short tables, but if you + don't use a remote controller, or prefer to load the + tables on userspace, you should disable it. + + The ir-keytable program, available at v4l-utils package + provide the tool and the same RC maps for load from + userspace. Its available at + http://git.linuxtv.org/v4l-utils diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile new file mode 100644 index 0000000..3194d39 --- /dev/null +++ b/drivers/media/rc/keymaps/Makefile @@ -0,0 +1,86 @@ +obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ + rc-alink-dtu-m.o \ + rc-anysee.o \ + rc-apac-viewcomp.o \ + rc-asus-pc39.o \ + rc-ati-tv-wonder-hd-600.o \ + rc-avermedia-a16d.o \ + rc-avermedia.o \ + rc-avermedia-cardbus.o \ + rc-avermedia-dvbt.o \ + rc-avermedia-m135a.o \ + rc-avermedia-m733a-rm-k6.o \ + rc-avermedia-rm-ks.o \ + rc-avertv-303.o \ + rc-azurewave-ad-tu700.o \ + rc-behold.o \ + rc-behold-columbus.o \ + rc-budget-ci-old.o \ + rc-cinergy-1400.o \ + rc-cinergy.o \ + rc-dib0700-nec.o \ + rc-dib0700-rc5.o \ + rc-digitalnow-tinytwin.o \ + rc-digittrade.o \ + rc-dm1105-nec.o \ + rc-dntv-live-dvb-t.o \ + rc-dntv-live-dvbt-pro.o \ + rc-em-terratec.o \ + rc-encore-enltv2.o \ + rc-encore-enltv.o \ + rc-encore-enltv-fm53.o \ + rc-evga-indtube.o \ + rc-eztv.o \ + rc-flydvb.o \ + rc-flyvideo.o \ + rc-fusionhdtv-mce.o \ + rc-gadmei-rm008z.o \ + rc-genius-tvgo-a11mce.o \ + rc-gotview7135.o \ + rc-hauppauge-new.o \ + rc-imon-mce.o \ + rc-imon-pad.o \ + rc-iodata-bctv7e.o \ + rc-kaiomy.o \ + rc-kworld-315u.o \ + rc-kworld-plus-tv-analog.o \ + rc-leadtek-y04g0051.o \ + rc-lirc.o \ + rc-lme2510.o \ + rc-manli.o \ + rc-msi-digivox-ii.o \ + rc-msi-digivox-iii.o \ + rc-msi-tvanywhere.o \ + rc-msi-tvanywhere-plus.o \ + rc-nebula.o \ + rc-nec-terratec-cinergy-xs.o \ + rc-norwood.o \ + rc-npgtech.o \ + rc-pctv-sedna.o \ + rc-pinnacle-color.o \ + rc-pinnacle-grey.o \ + rc-pinnacle-pctv-hd.o \ + rc-pixelview.o \ + rc-pixelview-mk12.o \ + rc-pixelview-new.o \ + rc-powercolor-real-angel.o \ + rc-proteus-2309.o \ + rc-purpletv.o \ + rc-pv951.o \ + rc-rc5-hauppauge-new.o \ + rc-rc5-tv.o \ + rc-rc6-mce.o \ + rc-real-audio-220-32-keys.o \ + rc-streamzap.o \ + rc-tbs-nec.o \ + rc-terratec-cinergy-xs.o \ + rc-terratec-slim.o \ + rc-tevii-nec.o \ + rc-total-media-in-hand.o \ + rc-trekstor.o \ + rc-tt-1500.o \ + rc-twinhan1027.o \ + rc-videomate-s350.o \ + rc-videomate-tv-pvr.o \ + rc-winfast.o \ + rc-winfast-usbii-deluxe.o diff --git a/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c b/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c new file mode 100644 index 0000000..b172831 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c @@ -0,0 +1,89 @@ +/* adstech-dvb-t-pci.h - Keytable for adstech_dvb_t_pci Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* ADS Tech Instant TV DVB-T PCI Remote */ + +static struct ir_scancode adstech_dvb_t_pci[] = { + /* Keys 0 to 9 */ + { 0x4d, KEY_0 }, + { 0x57, KEY_1 }, + { 0x4f, KEY_2 }, + { 0x53, KEY_3 }, + { 0x56, KEY_4 }, + { 0x4e, KEY_5 }, + { 0x5e, KEY_6 }, + { 0x54, KEY_7 }, + { 0x4c, KEY_8 }, + { 0x5c, KEY_9 }, + + { 0x5b, KEY_POWER }, + { 0x5f, KEY_MUTE }, + { 0x55, KEY_GOTO }, + { 0x5d, KEY_SEARCH }, + { 0x17, KEY_EPG }, /* Guide */ + { 0x1f, KEY_MENU }, + { 0x0f, KEY_UP }, + { 0x46, KEY_DOWN }, + { 0x16, KEY_LEFT }, + { 0x1e, KEY_RIGHT }, + { 0x0e, KEY_SELECT }, /* Enter */ + { 0x5a, KEY_INFO }, + { 0x52, KEY_EXIT }, + { 0x59, KEY_PREVIOUS }, + { 0x51, KEY_NEXT }, + { 0x58, KEY_REWIND }, + { 0x50, KEY_FORWARD }, + { 0x44, KEY_PLAYPAUSE }, + { 0x07, KEY_STOP }, + { 0x1b, KEY_RECORD }, + { 0x13, KEY_TUNER }, /* Live */ + { 0x0a, KEY_A }, + { 0x12, KEY_B }, + { 0x03, KEY_PROG1 }, /* 1 */ + { 0x01, KEY_PROG2 }, /* 2 */ + { 0x00, KEY_PROG3 }, /* 3 */ + { 0x06, KEY_DVD }, + { 0x48, KEY_AUX }, /* Photo */ + { 0x40, KEY_VIDEO }, + { 0x19, KEY_AUDIO }, /* Music */ + { 0x0b, KEY_CHANNELUP }, + { 0x08, KEY_CHANNELDOWN }, + { 0x15, KEY_VOLUMEUP }, + { 0x1c, KEY_VOLUMEDOWN }, +}; + +static struct rc_keymap adstech_dvb_t_pci_map = { + .map = { + .scan = adstech_dvb_t_pci, + .size = ARRAY_SIZE(adstech_dvb_t_pci), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_ADSTECH_DVB_T_PCI, + } +}; + +static int __init init_rc_map_adstech_dvb_t_pci(void) +{ + return ir_register_map(&adstech_dvb_t_pci_map); +} + +static void __exit exit_rc_map_adstech_dvb_t_pci(void) +{ + ir_unregister_map(&adstech_dvb_t_pci_map); +} + +module_init(init_rc_map_adstech_dvb_t_pci) +module_exit(exit_rc_map_adstech_dvb_t_pci) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-alink-dtu-m.c b/drivers/media/rc/keymaps/rc-alink-dtu-m.c new file mode 100644 index 0000000..ddfee7f --- /dev/null +++ b/drivers/media/rc/keymaps/rc-alink-dtu-m.c @@ -0,0 +1,68 @@ +/* + * A-Link DTU(m) remote controller keytable + * + * Copyright (C) 2010 Antti Palosaari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +/* A-Link DTU(m) slim remote, 6 rows, 3 columns. */ +static struct ir_scancode alink_dtu_m[] = { + { 0x0800, KEY_VOLUMEUP }, + { 0x0801, KEY_1 }, + { 0x0802, KEY_3 }, + { 0x0803, KEY_7 }, + { 0x0804, KEY_9 }, + { 0x0805, KEY_NEW }, /* symbol: PIP */ + { 0x0806, KEY_0 }, + { 0x0807, KEY_CHANNEL }, /* JUMP */ + { 0x080d, KEY_5 }, + { 0x080f, KEY_2 }, + { 0x0812, KEY_POWER2 }, + { 0x0814, KEY_CHANNELUP }, + { 0x0816, KEY_VOLUMEDOWN }, + { 0x0818, KEY_6 }, + { 0x081a, KEY_MUTE }, + { 0x081b, KEY_8 }, + { 0x081c, KEY_4 }, + { 0x081d, KEY_CHANNELDOWN }, +}; + +static struct rc_keymap alink_dtu_m_map = { + .map = { + .scan = alink_dtu_m, + .size = ARRAY_SIZE(alink_dtu_m), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_ALINK_DTU_M, + } +}; + +static int __init init_rc_map_alink_dtu_m(void) +{ + return ir_register_map(&alink_dtu_m_map); +} + +static void __exit exit_rc_map_alink_dtu_m(void) +{ + ir_unregister_map(&alink_dtu_m_map); +} + +module_init(init_rc_map_alink_dtu_m) +module_exit(exit_rc_map_alink_dtu_m) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/rc/keymaps/rc-anysee.c b/drivers/media/rc/keymaps/rc-anysee.c new file mode 100644 index 0000000..30d7049 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-anysee.c @@ -0,0 +1,93 @@ +/* + * Anysee remote controller keytable + * + * Copyright (C) 2010 Antti Palosaari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +static struct ir_scancode anysee[] = { + { 0x0800, KEY_0 }, + { 0x0801, KEY_1 }, + { 0x0802, KEY_2 }, + { 0x0803, KEY_3 }, + { 0x0804, KEY_4 }, + { 0x0805, KEY_5 }, + { 0x0806, KEY_6 }, + { 0x0807, KEY_7 }, + { 0x0808, KEY_8 }, + { 0x0809, KEY_9 }, + { 0x080a, KEY_POWER2 }, /* [red power button] */ + { 0x080b, KEY_VIDEO }, /* [*] MODE */ + { 0x080c, KEY_CHANNEL }, /* [symbol counterclockwise arrow] */ + { 0x080d, KEY_NEXT }, /* [>>|] */ + { 0x080e, KEY_MENU }, /* MENU */ + { 0x080f, KEY_EPG }, /* [EPG] */ + { 0x0810, KEY_CLEAR }, /* EXIT */ + { 0x0811, KEY_CHANNELUP }, + { 0x0812, KEY_VOLUMEDOWN }, + { 0x0813, KEY_VOLUMEUP }, + { 0x0814, KEY_CHANNELDOWN }, + { 0x0815, KEY_OK }, + { 0x0816, KEY_RADIO }, /* [symbol TV/radio] */ + { 0x0817, KEY_INFO }, /* [i] */ + { 0x0818, KEY_PREVIOUS }, /* [|<<] */ + { 0x0819, KEY_FAVORITES }, /* FAV. */ + { 0x081a, KEY_SUBTITLE }, /* Subtitle */ + { 0x081b, KEY_CAMERA }, /* [symbol camera] */ + { 0x081c, KEY_YELLOW }, + { 0x081d, KEY_RED }, + { 0x081e, KEY_LANGUAGE }, /* [symbol Second Audio Program] */ + { 0x081f, KEY_GREEN }, + { 0x0820, KEY_SLEEP }, /* Sleep */ + { 0x0821, KEY_SCREEN }, /* 16:9 / 4:3 */ + { 0x0822, KEY_ZOOM }, /* SIZE */ + { 0x0824, KEY_FN }, /* [F1] */ + { 0x0825, KEY_FN }, /* [F2] */ + { 0x0842, KEY_MUTE }, /* symbol mute */ + { 0x0844, KEY_BLUE }, + { 0x0847, KEY_TEXT }, /* TEXT */ + { 0x0848, KEY_STOP }, + { 0x0849, KEY_RECORD }, + { 0x0850, KEY_PLAY }, + { 0x0851, KEY_PAUSE }, +}; + +static struct rc_keymap anysee_map = { + .map = { + .scan = anysee, + .size = ARRAY_SIZE(anysee), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_ANYSEE, + } +}; + +static int __init init_rc_map_anysee(void) +{ + return ir_register_map(&anysee_map); +} + +static void __exit exit_rc_map_anysee(void) +{ + ir_unregister_map(&anysee_map); +} + +module_init(init_rc_map_anysee) +module_exit(exit_rc_map_anysee) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/rc/keymaps/rc-apac-viewcomp.c b/drivers/media/rc/keymaps/rc-apac-viewcomp.c new file mode 100644 index 0000000..0ef2b56 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-apac-viewcomp.c @@ -0,0 +1,80 @@ +/* apac-viewcomp.h - Keytable for apac_viewcomp Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Attila Kondoros */ + +static struct ir_scancode apac_viewcomp[] = { + + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + { 0x00, KEY_0 }, + { 0x17, KEY_LAST }, /* +100 */ + { 0x0a, KEY_LIST }, /* recall */ + + + { 0x1c, KEY_TUNER }, /* TV/FM */ + { 0x15, KEY_SEARCH }, /* scan */ + { 0x12, KEY_POWER }, /* power */ + { 0x1f, KEY_VOLUMEDOWN }, /* vol up */ + { 0x1b, KEY_VOLUMEUP }, /* vol down */ + { 0x1e, KEY_CHANNELDOWN }, /* chn up */ + { 0x1a, KEY_CHANNELUP }, /* chn down */ + + { 0x11, KEY_VIDEO }, /* video */ + { 0x0f, KEY_ZOOM }, /* full screen */ + { 0x13, KEY_MUTE }, /* mute/unmute */ + { 0x10, KEY_TEXT }, /* min */ + + { 0x0d, KEY_STOP }, /* freeze */ + { 0x0e, KEY_RECORD }, /* record */ + { 0x1d, KEY_PLAYPAUSE }, /* stop */ + { 0x19, KEY_PLAY }, /* play */ + + { 0x16, KEY_GOTO }, /* osd */ + { 0x14, KEY_REFRESH }, /* default */ + { 0x0c, KEY_KPPLUS }, /* fine tune >>>> */ + { 0x18, KEY_KPMINUS }, /* fine tune <<<< */ +}; + +static struct rc_keymap apac_viewcomp_map = { + .map = { + .scan = apac_viewcomp, + .size = ARRAY_SIZE(apac_viewcomp), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_APAC_VIEWCOMP, + } +}; + +static int __init init_rc_map_apac_viewcomp(void) +{ + return ir_register_map(&apac_viewcomp_map); +} + +static void __exit exit_rc_map_apac_viewcomp(void) +{ + ir_unregister_map(&apac_viewcomp_map); +} + +module_init(init_rc_map_apac_viewcomp) +module_exit(exit_rc_map_apac_viewcomp) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-asus-pc39.c b/drivers/media/rc/keymaps/rc-asus-pc39.c new file mode 100644 index 0000000..2996e0a --- /dev/null +++ b/drivers/media/rc/keymaps/rc-asus-pc39.c @@ -0,0 +1,91 @@ +/* asus-pc39.h - Keytable for asus_pc39 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * Marc Fargas + * this is the remote control that comes with the asus p7131 + * which has a label saying is "Model PC-39" + */ + +static struct ir_scancode asus_pc39[] = { + /* Keys 0 to 9 */ + { 0x082a, KEY_0 }, + { 0x0816, KEY_1 }, + { 0x0812, KEY_2 }, + { 0x0814, KEY_3 }, + { 0x0836, KEY_4 }, + { 0x0832, KEY_5 }, + { 0x0834, KEY_6 }, + { 0x080e, KEY_7 }, + { 0x080a, KEY_8 }, + { 0x080c, KEY_9 }, + + { 0x0801, KEY_RADIO }, /* radio */ + { 0x083c, KEY_MENU }, /* dvd/menu */ + { 0x0815, KEY_VOLUMEUP }, + { 0x0826, KEY_VOLUMEDOWN }, + { 0x0808, KEY_UP }, + { 0x0804, KEY_DOWN }, + { 0x0818, KEY_LEFT }, + { 0x0810, KEY_RIGHT }, + { 0x081a, KEY_VIDEO }, /* video */ + { 0x0806, KEY_AUDIO }, /* music */ + + { 0x081e, KEY_TV }, /* tv */ + { 0x0822, KEY_EXIT }, /* back */ + { 0x0835, KEY_CHANNELUP }, /* channel / program + */ + { 0x0824, KEY_CHANNELDOWN }, /* channel / program - */ + { 0x0825, KEY_ENTER }, /* enter */ + + { 0x0839, KEY_PAUSE }, /* play/pause */ + { 0x0821, KEY_PREVIOUS }, /* rew */ + { 0x0819, KEY_NEXT }, /* forward */ + { 0x0831, KEY_REWIND }, /* backward << */ + { 0x0805, KEY_FASTFORWARD }, /* forward >> */ + { 0x0809, KEY_STOP }, + { 0x0811, KEY_RECORD }, /* recording */ + { 0x0829, KEY_POWER }, /* the button that reads "close" */ + + { 0x082e, KEY_ZOOM }, /* full screen */ + { 0x082c, KEY_MACRO }, /* recall */ + { 0x081c, KEY_HOME }, /* home */ + { 0x083a, KEY_PVR }, /* picture */ + { 0x0802, KEY_MUTE }, /* mute */ + { 0x083e, KEY_DVD }, /* dvd */ +}; + +static struct rc_keymap asus_pc39_map = { + .map = { + .scan = asus_pc39, + .size = ARRAY_SIZE(asus_pc39), + .ir_type = IR_TYPE_RC5, + .name = RC_MAP_ASUS_PC39, + } +}; + +static int __init init_rc_map_asus_pc39(void) +{ + return ir_register_map(&asus_pc39_map); +} + +static void __exit exit_rc_map_asus_pc39(void) +{ + ir_unregister_map(&asus_pc39_map); +} + +module_init(init_rc_map_asus_pc39) +module_exit(exit_rc_map_asus_pc39) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c b/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c new file mode 100644 index 0000000..8edfd29 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c @@ -0,0 +1,69 @@ +/* ati-tv-wonder-hd-600.h - Keytable for ati_tv_wonder_hd_600 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* ATI TV Wonder HD 600 USB + Devin Heitmueller + */ + +static struct ir_scancode ati_tv_wonder_hd_600[] = { + { 0x00, KEY_RECORD}, /* Row 1 */ + { 0x01, KEY_PLAYPAUSE}, + { 0x02, KEY_STOP}, + { 0x03, KEY_POWER}, + { 0x04, KEY_PREVIOUS}, /* Row 2 */ + { 0x05, KEY_REWIND}, + { 0x06, KEY_FORWARD}, + { 0x07, KEY_NEXT}, + { 0x08, KEY_EPG}, /* Row 3 */ + { 0x09, KEY_HOME}, + { 0x0a, KEY_MENU}, + { 0x0b, KEY_CHANNELUP}, + { 0x0c, KEY_BACK}, /* Row 4 */ + { 0x0d, KEY_UP}, + { 0x0e, KEY_INFO}, + { 0x0f, KEY_CHANNELDOWN}, + { 0x10, KEY_LEFT}, /* Row 5 */ + { 0x11, KEY_SELECT}, + { 0x12, KEY_RIGHT}, + { 0x13, KEY_VOLUMEUP}, + { 0x14, KEY_LAST}, /* Row 6 */ + { 0x15, KEY_DOWN}, + { 0x16, KEY_MUTE}, + { 0x17, KEY_VOLUMEDOWN}, +}; + +static struct rc_keymap ati_tv_wonder_hd_600_map = { + .map = { + .scan = ati_tv_wonder_hd_600, + .size = ARRAY_SIZE(ati_tv_wonder_hd_600), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_ATI_TV_WONDER_HD_600, + } +}; + +static int __init init_rc_map_ati_tv_wonder_hd_600(void) +{ + return ir_register_map(&ati_tv_wonder_hd_600_map); +} + +static void __exit exit_rc_map_ati_tv_wonder_hd_600(void) +{ + ir_unregister_map(&ati_tv_wonder_hd_600_map); +} + +module_init(init_rc_map_ati_tv_wonder_hd_600) +module_exit(exit_rc_map_ati_tv_wonder_hd_600) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-avermedia-a16d.c b/drivers/media/rc/keymaps/rc-avermedia-a16d.c new file mode 100644 index 0000000..12f0435 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-avermedia-a16d.c @@ -0,0 +1,75 @@ +/* avermedia-a16d.h - Keytable for avermedia_a16d Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode avermedia_a16d[] = { + { 0x20, KEY_LIST}, + { 0x00, KEY_POWER}, + { 0x28, KEY_1}, + { 0x18, KEY_2}, + { 0x38, KEY_3}, + { 0x24, KEY_4}, + { 0x14, KEY_5}, + { 0x34, KEY_6}, + { 0x2c, KEY_7}, + { 0x1c, KEY_8}, + { 0x3c, KEY_9}, + { 0x12, KEY_SUBTITLE}, + { 0x22, KEY_0}, + { 0x32, KEY_REWIND}, + { 0x3a, KEY_SHUFFLE}, + { 0x02, KEY_PRINT}, + { 0x11, KEY_CHANNELDOWN}, + { 0x31, KEY_CHANNELUP}, + { 0x0c, KEY_ZOOM}, + { 0x1e, KEY_VOLUMEDOWN}, + { 0x3e, KEY_VOLUMEUP}, + { 0x0a, KEY_MUTE}, + { 0x04, KEY_AUDIO}, + { 0x26, KEY_RECORD}, + { 0x06, KEY_PLAY}, + { 0x36, KEY_STOP}, + { 0x16, KEY_PAUSE}, + { 0x2e, KEY_REWIND}, + { 0x0e, KEY_FASTFORWARD}, + { 0x30, KEY_TEXT}, + { 0x21, KEY_GREEN}, + { 0x01, KEY_BLUE}, + { 0x08, KEY_EPG}, + { 0x2a, KEY_MENU}, +}; + +static struct rc_keymap avermedia_a16d_map = { + .map = { + .scan = avermedia_a16d, + .size = ARRAY_SIZE(avermedia_a16d), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_AVERMEDIA_A16D, + } +}; + +static int __init init_rc_map_avermedia_a16d(void) +{ + return ir_register_map(&avermedia_a16d_map); +} + +static void __exit exit_rc_map_avermedia_a16d(void) +{ + ir_unregister_map(&avermedia_a16d_map); +} + +module_init(init_rc_map_avermedia_a16d) +module_exit(exit_rc_map_avermedia_a16d) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-avermedia-cardbus.c b/drivers/media/rc/keymaps/rc-avermedia-cardbus.c new file mode 100644 index 0000000..2a945b0 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-avermedia-cardbus.c @@ -0,0 +1,97 @@ +/* avermedia-cardbus.h - Keytable for avermedia_cardbus Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Oldrich Jedlicka */ + +static struct ir_scancode avermedia_cardbus[] = { + { 0x00, KEY_POWER }, + { 0x01, KEY_TUNER }, /* TV/FM */ + { 0x03, KEY_TEXT }, /* Teletext */ + { 0x04, KEY_EPG }, + { 0x05, KEY_1 }, + { 0x06, KEY_2 }, + { 0x07, KEY_3 }, + { 0x08, KEY_AUDIO }, + { 0x09, KEY_4 }, + { 0x0a, KEY_5 }, + { 0x0b, KEY_6 }, + { 0x0c, KEY_ZOOM }, /* Full screen */ + { 0x0d, KEY_7 }, + { 0x0e, KEY_8 }, + { 0x0f, KEY_9 }, + { 0x10, KEY_PAGEUP }, /* 16-CH PREV */ + { 0x11, KEY_0 }, + { 0x12, KEY_INFO }, + { 0x13, KEY_AGAIN }, /* CH RTN - channel return */ + { 0x14, KEY_MUTE }, + { 0x15, KEY_EDIT }, /* Autoscan */ + { 0x17, KEY_SAVE }, /* Screenshot */ + { 0x18, KEY_PLAYPAUSE }, + { 0x19, KEY_RECORD }, + { 0x1a, KEY_PLAY }, + { 0x1b, KEY_STOP }, + { 0x1c, KEY_FASTFORWARD }, + { 0x1d, KEY_REWIND }, + { 0x1e, KEY_VOLUMEDOWN }, + { 0x1f, KEY_VOLUMEUP }, + { 0x22, KEY_SLEEP }, /* Sleep */ + { 0x23, KEY_ZOOM }, /* Aspect */ + { 0x26, KEY_SCREEN }, /* Pos */ + { 0x27, KEY_ANGLE }, /* Size */ + { 0x28, KEY_SELECT }, /* Select */ + { 0x29, KEY_BLUE }, /* Blue/Picture */ + { 0x2a, KEY_BACKSPACE }, /* Back */ + { 0x2b, KEY_MEDIA }, /* PIP (Picture-in-picture) */ + { 0x2c, KEY_DOWN }, + { 0x2e, KEY_DOT }, + { 0x2f, KEY_TV }, /* Live TV */ + { 0x32, KEY_LEFT }, + { 0x33, KEY_CLEAR }, /* Clear */ + { 0x35, KEY_RED }, /* Red/TV */ + { 0x36, KEY_UP }, + { 0x37, KEY_HOME }, /* Home */ + { 0x39, KEY_GREEN }, /* Green/Video */ + { 0x3d, KEY_YELLOW }, /* Yellow/Music */ + { 0x3e, KEY_OK }, /* Ok */ + { 0x3f, KEY_RIGHT }, + { 0x40, KEY_NEXT }, /* Next */ + { 0x41, KEY_PREVIOUS }, /* Previous */ + { 0x42, KEY_CHANNELDOWN }, /* Channel down */ + { 0x43, KEY_CHANNELUP }, /* Channel up */ +}; + +static struct rc_keymap avermedia_cardbus_map = { + .map = { + .scan = avermedia_cardbus, + .size = ARRAY_SIZE(avermedia_cardbus), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_AVERMEDIA_CARDBUS, + } +}; + +static int __init init_rc_map_avermedia_cardbus(void) +{ + return ir_register_map(&avermedia_cardbus_map); +} + +static void __exit exit_rc_map_avermedia_cardbus(void) +{ + ir_unregister_map(&avermedia_cardbus_map); +} + +module_init(init_rc_map_avermedia_cardbus) +module_exit(exit_rc_map_avermedia_cardbus) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-avermedia-dvbt.c b/drivers/media/rc/keymaps/rc-avermedia-dvbt.c new file mode 100644 index 0000000..39dde62 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-avermedia-dvbt.c @@ -0,0 +1,78 @@ +/* avermedia-dvbt.h - Keytable for avermedia_dvbt Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Matt Jesson >' */ + { 0x3a, KEY_RECORD }, /* 'capture' */ + { 0x0a, KEY_MUTE }, /* 'mute' */ + { 0x2c, KEY_RECORD }, /* 'record' */ + { 0x1c, KEY_PAUSE }, /* 'pause' */ + { 0x3c, KEY_STOP }, /* 'stop' */ + { 0x0c, KEY_PLAY }, /* 'play' */ + { 0x2e, KEY_RED }, /* 'red' */ + { 0x01, KEY_BLUE }, /* 'blue' / 'cancel' */ + { 0x0e, KEY_YELLOW }, /* 'yellow' / 'ok' */ + { 0x21, KEY_GREEN }, /* 'green' */ + { 0x11, KEY_CHANNELDOWN }, /* 'channel -' */ + { 0x31, KEY_CHANNELUP }, /* 'channel +' */ + { 0x1e, KEY_VOLUMEDOWN }, /* 'volume -' */ + { 0x3e, KEY_VOLUMEUP }, /* 'volume +' */ +}; + +static struct rc_keymap avermedia_dvbt_map = { + .map = { + .scan = avermedia_dvbt, + .size = ARRAY_SIZE(avermedia_dvbt), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_AVERMEDIA_DVBT, + } +}; + +static int __init init_rc_map_avermedia_dvbt(void) +{ + return ir_register_map(&avermedia_dvbt_map); +} + +static void __exit exit_rc_map_avermedia_dvbt(void) +{ + ir_unregister_map(&avermedia_dvbt_map); +} + +module_init(init_rc_map_avermedia_dvbt) +module_exit(exit_rc_map_avermedia_dvbt) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-avermedia-m135a.c b/drivers/media/rc/keymaps/rc-avermedia-m135a.c new file mode 100644 index 0000000..e4471fb --- /dev/null +++ b/drivers/media/rc/keymaps/rc-avermedia-m135a.c @@ -0,0 +1,147 @@ +/* avermedia-m135a.c - Keytable for Avermedia M135A Remote Controllers + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * Copyright (c) 2010 by Herton Ronaldo Krzesinski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * Avermedia M135A with RM-JX and RM-K6 remote controls + * + * On Avermedia M135A with IR model RM-JX, the same codes exist on both + * Positivo (BR) and original IR, initial version and remote control codes + * added by Mauro Carvalho Chehab + * + * Positivo also ships Avermedia M135A with model RM-K6, extra control + * codes added by Herton Ronaldo Krzesinski + */ + +static struct ir_scancode avermedia_m135a[] = { + /* RM-JX */ + { 0x0200, KEY_POWER2 }, + { 0x022e, KEY_DOT }, /* '.' */ + { 0x0201, KEY_MODE }, /* TV/FM or SOURCE */ + + { 0x0205, KEY_1 }, + { 0x0206, KEY_2 }, + { 0x0207, KEY_3 }, + { 0x0209, KEY_4 }, + { 0x020a, KEY_5 }, + { 0x020b, KEY_6 }, + { 0x020d, KEY_7 }, + { 0x020e, KEY_8 }, + { 0x020f, KEY_9 }, + { 0x0211, KEY_0 }, + + { 0x0213, KEY_RIGHT }, /* -> or L */ + { 0x0212, KEY_LEFT }, /* <- or R */ + + { 0x0217, KEY_SLEEP }, /* Capturar Imagem or Snapshot */ + { 0x0210, KEY_SHUFFLE }, /* Amostra or 16 chan prev */ + + { 0x0303, KEY_CHANNELUP }, + { 0x0302, KEY_CHANNELDOWN }, + { 0x021f, KEY_VOLUMEUP }, + { 0x021e, KEY_VOLUMEDOWN }, + { 0x020c, KEY_ENTER }, /* Full Screen */ + + { 0x0214, KEY_MUTE }, + { 0x0208, KEY_AUDIO }, + + { 0x0203, KEY_TEXT }, /* Teletext */ + { 0x0204, KEY_EPG }, + { 0x022b, KEY_TV2 }, /* TV2 or PIP */ + + { 0x021d, KEY_RED }, + { 0x021c, KEY_YELLOW }, + { 0x0301, KEY_GREEN }, + { 0x0300, KEY_BLUE }, + + { 0x021a, KEY_PLAYPAUSE }, + { 0x0219, KEY_RECORD }, + { 0x0218, KEY_PLAY }, + { 0x021b, KEY_STOP }, + + /* RM-K6 */ + { 0x0401, KEY_POWER2 }, + { 0x0406, KEY_MUTE }, + { 0x0408, KEY_MODE }, /* TV/FM */ + + { 0x0409, KEY_1 }, + { 0x040a, KEY_2 }, + { 0x040b, KEY_3 }, + { 0x040c, KEY_4 }, + { 0x040d, KEY_5 }, + { 0x040e, KEY_6 }, + { 0x040f, KEY_7 }, + { 0x0410, KEY_8 }, + { 0x0411, KEY_9 }, + { 0x044c, KEY_DOT }, /* '.' */ + { 0x0412, KEY_0 }, + { 0x0407, KEY_REFRESH }, /* Refresh/Reload */ + + { 0x0413, KEY_AUDIO }, + { 0x0440, KEY_SCREEN }, /* Full Screen toggle */ + { 0x0441, KEY_HOME }, + { 0x0442, KEY_BACK }, + { 0x0447, KEY_UP }, + { 0x0448, KEY_DOWN }, + { 0x0449, KEY_LEFT }, + { 0x044a, KEY_RIGHT }, + { 0x044b, KEY_OK }, + { 0x0404, KEY_VOLUMEUP }, + { 0x0405, KEY_VOLUMEDOWN }, + { 0x0402, KEY_CHANNELUP }, + { 0x0403, KEY_CHANNELDOWN }, + + { 0x0443, KEY_RED }, + { 0x0444, KEY_GREEN }, + { 0x0445, KEY_YELLOW }, + { 0x0446, KEY_BLUE }, + + { 0x0414, KEY_TEXT }, + { 0x0415, KEY_EPG }, + { 0x041a, KEY_TV2 }, /* PIP */ + { 0x041b, KEY_MHP }, /* Snapshot */ + + { 0x0417, KEY_RECORD }, + { 0x0416, KEY_PLAYPAUSE }, + { 0x0418, KEY_STOP }, + { 0x0419, KEY_PAUSE }, + + { 0x041f, KEY_PREVIOUS }, + { 0x041c, KEY_REWIND }, + { 0x041d, KEY_FORWARD }, + { 0x041e, KEY_NEXT }, +}; + +static struct rc_keymap avermedia_m135a_map = { + .map = { + .scan = avermedia_m135a, + .size = ARRAY_SIZE(avermedia_m135a), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_AVERMEDIA_M135A, + } +}; + +static int __init init_rc_map_avermedia_m135a(void) +{ + return ir_register_map(&avermedia_m135a_map); +} + +static void __exit exit_rc_map_avermedia_m135a(void) +{ + ir_unregister_map(&avermedia_m135a_map); +} + +module_init(init_rc_map_avermedia_m135a) +module_exit(exit_rc_map_avermedia_m135a) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c b/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c new file mode 100644 index 0000000..cf8d457 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c @@ -0,0 +1,95 @@ +/* avermedia-m733a-rm-k6.h - Keytable for avermedia_m733a_rm_k6 Remote Controller + * + * Copyright (c) 2010 by Herton Ronaldo Krzesinski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * Avermedia M733A with IR model RM-K6 + * This is the stock remote controller used with Positivo machines with M733A + * Herton Ronaldo Krzesinski + */ + +static struct ir_scancode avermedia_m733a_rm_k6[] = { + { 0x0401, KEY_POWER2 }, + { 0x0406, KEY_MUTE }, + { 0x0408, KEY_MODE }, /* TV/FM */ + + { 0x0409, KEY_1 }, + { 0x040a, KEY_2 }, + { 0x040b, KEY_3 }, + { 0x040c, KEY_4 }, + { 0x040d, KEY_5 }, + { 0x040e, KEY_6 }, + { 0x040f, KEY_7 }, + { 0x0410, KEY_8 }, + { 0x0411, KEY_9 }, + { 0x044c, KEY_DOT }, /* '.' */ + { 0x0412, KEY_0 }, + { 0x0407, KEY_REFRESH }, /* Refresh/Reload */ + + { 0x0413, KEY_AUDIO }, + { 0x0440, KEY_SCREEN }, /* Full Screen toggle */ + { 0x0441, KEY_HOME }, + { 0x0442, KEY_BACK }, + { 0x0447, KEY_UP }, + { 0x0448, KEY_DOWN }, + { 0x0449, KEY_LEFT }, + { 0x044a, KEY_RIGHT }, + { 0x044b, KEY_OK }, + { 0x0404, KEY_VOLUMEUP }, + { 0x0405, KEY_VOLUMEDOWN }, + { 0x0402, KEY_CHANNELUP }, + { 0x0403, KEY_CHANNELDOWN }, + + { 0x0443, KEY_RED }, + { 0x0444, KEY_GREEN }, + { 0x0445, KEY_YELLOW }, + { 0x0446, KEY_BLUE }, + + { 0x0414, KEY_TEXT }, + { 0x0415, KEY_EPG }, + { 0x041a, KEY_TV2 }, /* PIP */ + { 0x041b, KEY_MHP }, /* Snapshot */ + + { 0x0417, KEY_RECORD }, + { 0x0416, KEY_PLAYPAUSE }, + { 0x0418, KEY_STOP }, + { 0x0419, KEY_PAUSE }, + + { 0x041f, KEY_PREVIOUS }, + { 0x041c, KEY_REWIND }, + { 0x041d, KEY_FORWARD }, + { 0x041e, KEY_NEXT }, +}; + +static struct rc_keymap avermedia_m733a_rm_k6_map = { + .map = { + .scan = avermedia_m733a_rm_k6, + .size = ARRAY_SIZE(avermedia_m733a_rm_k6), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_AVERMEDIA_M733A_RM_K6, + } +}; + +static int __init init_rc_map_avermedia_m733a_rm_k6(void) +{ + return ir_register_map(&avermedia_m733a_rm_k6_map); +} + +static void __exit exit_rc_map_avermedia_m733a_rm_k6(void) +{ + ir_unregister_map(&avermedia_m733a_rm_k6_map); +} + +module_init(init_rc_map_avermedia_m733a_rm_k6) +module_exit(exit_rc_map_avermedia_m733a_rm_k6) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c b/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c new file mode 100644 index 0000000..9ee6090 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c @@ -0,0 +1,79 @@ +/* + * AverMedia RM-KS remote controller keytable + * + * Copyright (C) 2010 Antti Palosaari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +/* Initial keytable is from Jose Alberto Reguero + and Felipe Morales Moreno */ +/* FIXME: mappings are not 100% correct? */ +static struct ir_scancode avermedia_rm_ks[] = { + { 0x0501, KEY_POWER2 }, + { 0x0502, KEY_CHANNELUP }, + { 0x0503, KEY_CHANNELDOWN }, + { 0x0504, KEY_VOLUMEUP }, + { 0x0505, KEY_VOLUMEDOWN }, + { 0x0506, KEY_MUTE }, + { 0x0507, KEY_RIGHT }, + { 0x0508, KEY_PROG1 }, + { 0x0509, KEY_1 }, + { 0x050a, KEY_2 }, + { 0x050b, KEY_3 }, + { 0x050c, KEY_4 }, + { 0x050d, KEY_5 }, + { 0x050e, KEY_6 }, + { 0x050f, KEY_7 }, + { 0x0510, KEY_8 }, + { 0x0511, KEY_9 }, + { 0x0512, KEY_0 }, + { 0x0513, KEY_AUDIO }, + { 0x0515, KEY_EPG }, + { 0x0516, KEY_PLAY }, + { 0x0517, KEY_RECORD }, + { 0x0518, KEY_STOP }, + { 0x051c, KEY_BACK }, + { 0x051d, KEY_FORWARD }, + { 0x054d, KEY_LEFT }, + { 0x0556, KEY_ZOOM }, +}; + +static struct rc_keymap avermedia_rm_ks_map = { + .map = { + .scan = avermedia_rm_ks, + .size = ARRAY_SIZE(avermedia_rm_ks), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_AVERMEDIA_RM_KS, + } +}; + +static int __init init_rc_map_avermedia_rm_ks(void) +{ + return ir_register_map(&avermedia_rm_ks_map); +} + +static void __exit exit_rc_map_avermedia_rm_ks(void) +{ + ir_unregister_map(&avermedia_rm_ks_map); +} + +module_init(init_rc_map_avermedia_rm_ks) +module_exit(exit_rc_map_avermedia_rm_ks) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/rc/keymaps/rc-avermedia.c b/drivers/media/rc/keymaps/rc-avermedia.c new file mode 100644 index 0000000..21effd5 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-avermedia.c @@ -0,0 +1,86 @@ +/* avermedia.h - Keytable for avermedia Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Alex Hermann */ + +static struct ir_scancode avermedia[] = { + { 0x28, KEY_1 }, + { 0x18, KEY_2 }, + { 0x38, KEY_3 }, + { 0x24, KEY_4 }, + { 0x14, KEY_5 }, + { 0x34, KEY_6 }, + { 0x2c, KEY_7 }, + { 0x1c, KEY_8 }, + { 0x3c, KEY_9 }, + { 0x22, KEY_0 }, + + { 0x20, KEY_TV }, /* TV/FM */ + { 0x10, KEY_CD }, /* CD */ + { 0x30, KEY_TEXT }, /* TELETEXT */ + { 0x00, KEY_POWER }, /* POWER */ + + { 0x08, KEY_VIDEO }, /* VIDEO */ + { 0x04, KEY_AUDIO }, /* AUDIO */ + { 0x0c, KEY_ZOOM }, /* FULL SCREEN */ + + { 0x12, KEY_SUBTITLE }, /* DISPLAY */ + { 0x32, KEY_REWIND }, /* LOOP */ + { 0x02, KEY_PRINT }, /* PREVIEW */ + + { 0x2a, KEY_SEARCH }, /* AUTOSCAN */ + { 0x1a, KEY_SLEEP }, /* FREEZE */ + { 0x3a, KEY_CAMERA }, /* SNAPSHOT */ + { 0x0a, KEY_MUTE }, /* MUTE */ + + { 0x26, KEY_RECORD }, /* RECORD */ + { 0x16, KEY_PAUSE }, /* PAUSE */ + { 0x36, KEY_STOP }, /* STOP */ + { 0x06, KEY_PLAY }, /* PLAY */ + + { 0x2e, KEY_RED }, /* RED */ + { 0x21, KEY_GREEN }, /* GREEN */ + { 0x0e, KEY_YELLOW }, /* YELLOW */ + { 0x01, KEY_BLUE }, /* BLUE */ + + { 0x1e, KEY_VOLUMEDOWN }, /* VOLUME- */ + { 0x3e, KEY_VOLUMEUP }, /* VOLUME+ */ + { 0x11, KEY_CHANNELDOWN }, /* CHANNEL/PAGE- */ + { 0x31, KEY_CHANNELUP } /* CHANNEL/PAGE+ */ +}; + +static struct rc_keymap avermedia_map = { + .map = { + .scan = avermedia, + .size = ARRAY_SIZE(avermedia), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_AVERMEDIA, + } +}; + +static int __init init_rc_map_avermedia(void) +{ + return ir_register_map(&avermedia_map); +} + +static void __exit exit_rc_map_avermedia(void) +{ + ir_unregister_map(&avermedia_map); +} + +module_init(init_rc_map_avermedia) +module_exit(exit_rc_map_avermedia) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-avertv-303.c b/drivers/media/rc/keymaps/rc-avertv-303.c new file mode 100644 index 0000000..971c59d --- /dev/null +++ b/drivers/media/rc/keymaps/rc-avertv-303.c @@ -0,0 +1,85 @@ +/* avertv-303.h - Keytable for avertv_303 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* AVERTV STUDIO 303 Remote */ + +static struct ir_scancode avertv_303[] = { + { 0x2a, KEY_1 }, + { 0x32, KEY_2 }, + { 0x3a, KEY_3 }, + { 0x4a, KEY_4 }, + { 0x52, KEY_5 }, + { 0x5a, KEY_6 }, + { 0x6a, KEY_7 }, + { 0x72, KEY_8 }, + { 0x7a, KEY_9 }, + { 0x0e, KEY_0 }, + + { 0x02, KEY_POWER }, + { 0x22, KEY_VIDEO }, + { 0x42, KEY_AUDIO }, + { 0x62, KEY_ZOOM }, + { 0x0a, KEY_TV }, + { 0x12, KEY_CD }, + { 0x1a, KEY_TEXT }, + + { 0x16, KEY_SUBTITLE }, + { 0x1e, KEY_REWIND }, + { 0x06, KEY_PRINT }, + + { 0x2e, KEY_SEARCH }, + { 0x36, KEY_SLEEP }, + { 0x3e, KEY_SHUFFLE }, + { 0x26, KEY_MUTE }, + + { 0x4e, KEY_RECORD }, + { 0x56, KEY_PAUSE }, + { 0x5e, KEY_STOP }, + { 0x46, KEY_PLAY }, + + { 0x6e, KEY_RED }, + { 0x0b, KEY_GREEN }, + { 0x66, KEY_YELLOW }, + { 0x03, KEY_BLUE }, + + { 0x76, KEY_LEFT }, + { 0x7e, KEY_RIGHT }, + { 0x13, KEY_DOWN }, + { 0x1b, KEY_UP }, +}; + +static struct rc_keymap avertv_303_map = { + .map = { + .scan = avertv_303, + .size = ARRAY_SIZE(avertv_303), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_AVERTV_303, + } +}; + +static int __init init_rc_map_avertv_303(void) +{ + return ir_register_map(&avertv_303_map); +} + +static void __exit exit_rc_map_avertv_303(void) +{ + ir_unregister_map(&avertv_303_map); +} + +module_init(init_rc_map_avertv_303) +module_exit(exit_rc_map_avertv_303) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c b/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c new file mode 100644 index 0000000..e087614 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c @@ -0,0 +1,102 @@ +/* + * TwinHan AzureWave AD-TU700(704J) remote controller keytable + * + * Copyright (C) 2010 Antti Palosaari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +static struct ir_scancode azurewave_ad_tu700[] = { + { 0x0000, KEY_TAB }, /* Tab */ + { 0x0001, KEY_2 }, + { 0x0002, KEY_CHANNELDOWN }, + { 0x0003, KEY_1 }, + { 0x0004, KEY_MENU }, /* Record List */ + { 0x0005, KEY_CHANNELUP }, + { 0x0006, KEY_3 }, + { 0x0007, KEY_SLEEP }, /* Hibernate */ + { 0x0008, KEY_VIDEO }, /* A/V */ + { 0x0009, KEY_4 }, + { 0x000a, KEY_VOLUMEDOWN }, + { 0x000c, KEY_CANCEL }, /* Cancel */ + { 0x000d, KEY_7 }, + { 0x000e, KEY_AGAIN }, /* Recall */ + { 0x000f, KEY_TEXT }, /* Teletext */ + { 0x0010, KEY_MUTE }, + { 0x0011, KEY_RECORD }, + { 0x0012, KEY_FASTFORWARD }, /* FF >> */ + { 0x0013, KEY_BACK }, /* Back */ + { 0x0014, KEY_PLAY }, + { 0x0015, KEY_0 }, + { 0x0016, KEY_POWER2 }, /* [red power button] */ + { 0x0017, KEY_FAVORITES }, /* Favorite List */ + { 0x0018, KEY_RED }, + { 0x0019, KEY_8 }, + { 0x001a, KEY_STOP }, + { 0x001b, KEY_9 }, + { 0x001c, KEY_EPG }, /* Info/EPG */ + { 0x001d, KEY_5 }, + { 0x001e, KEY_VOLUMEUP }, + { 0x001f, KEY_6 }, + { 0x0040, KEY_REWIND }, /* FR << */ + { 0x0041, KEY_PREVIOUS }, /* Replay */ + { 0x0042, KEY_NEXT }, /* Skip */ + { 0x0043, KEY_SUBTITLE }, /* Subtitle / CC */ + { 0x0045, KEY_KPPLUS }, /* Zoom+ */ + { 0x0046, KEY_KPMINUS }, /* Zoom- */ + { 0x0047, KEY_NEW }, /* PIP */ + { 0x0048, KEY_INFO }, /* Preview */ + { 0x0049, KEY_MODE }, /* L/R */ + { 0x004a, KEY_CLEAR }, /* Clear */ + { 0x004b, KEY_UP }, /* up arrow */ + { 0x004c, KEY_PAUSE }, + { 0x004d, KEY_ZOOM }, /* Full Screen */ + { 0x004e, KEY_LEFT }, /* left arrow */ + { 0x004f, KEY_OK }, /* Enter / ok */ + { 0x0050, KEY_LANGUAGE }, /* SAP */ + { 0x0051, KEY_DOWN }, /* down arrow */ + { 0x0052, KEY_RIGHT }, /* right arrow */ + { 0x0053, KEY_GREEN }, + { 0x0054, KEY_CAMERA }, /* Capture */ + { 0x005e, KEY_YELLOW }, + { 0x005f, KEY_BLUE }, +}; + +static struct rc_keymap azurewave_ad_tu700_map = { + .map = { + .scan = azurewave_ad_tu700, + .size = ARRAY_SIZE(azurewave_ad_tu700), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_AZUREWAVE_AD_TU700, + } +}; + +static int __init init_rc_map_azurewave_ad_tu700(void) +{ + return ir_register_map(&azurewave_ad_tu700_map); +} + +static void __exit exit_rc_map_azurewave_ad_tu700(void) +{ + ir_unregister_map(&azurewave_ad_tu700_map); +} + +module_init(init_rc_map_azurewave_ad_tu700) +module_exit(exit_rc_map_azurewave_ad_tu700) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/rc/keymaps/rc-behold-columbus.c b/drivers/media/rc/keymaps/rc-behold-columbus.c new file mode 100644 index 0000000..9f56c98 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-behold-columbus.c @@ -0,0 +1,108 @@ +/* behold-columbus.h - Keytable for behold_columbus Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Beholder Intl. Ltd. 2008 + * Dmitry Belimov d.belimov@google.com + * Keytable is used by BeholdTV Columbus + * The "ascii-art picture" below (in comments, first row + * is the keycode in hex, and subsequent row(s) shows + * the button labels (several variants when appropriate) + * helps to descide which keycodes to assign to the buttons. + */ + +static struct ir_scancode behold_columbus[] = { + + /* 0x13 0x11 0x1C 0x12 * + * Mute Source TV/FM Power * + * */ + + { 0x13, KEY_MUTE }, + { 0x11, KEY_PROPS }, + { 0x1C, KEY_TUNER }, /* KEY_TV/KEY_RADIO */ + { 0x12, KEY_POWER }, + + /* 0x01 0x02 0x03 0x0D * + * 1 2 3 Stereo * + * * + * 0x04 0x05 0x06 0x19 * + * 4 5 6 Snapshot * + * * + * 0x07 0x08 0x09 0x10 * + * 7 8 9 Zoom * + * */ + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x0D, KEY_SETUP }, /* Setup key */ + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x19, KEY_CAMERA }, /* Snapshot key */ + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + { 0x10, KEY_ZOOM }, + + /* 0x0A 0x00 0x0B 0x0C * + * RECALL 0 ChannelUp VolumeUp * + * */ + { 0x0A, KEY_AGAIN }, + { 0x00, KEY_0 }, + { 0x0B, KEY_CHANNELUP }, + { 0x0C, KEY_VOLUMEUP }, + + /* 0x1B 0x1D 0x15 0x18 * + * Timeshift Record ChannelDown VolumeDown * + * */ + + { 0x1B, KEY_TIME }, + { 0x1D, KEY_RECORD }, + { 0x15, KEY_CHANNELDOWN }, + { 0x18, KEY_VOLUMEDOWN }, + + /* 0x0E 0x1E 0x0F 0x1A * + * Stop Pause Previouse Next * + * */ + + { 0x0E, KEY_STOP }, + { 0x1E, KEY_PAUSE }, + { 0x0F, KEY_PREVIOUS }, + { 0x1A, KEY_NEXT }, + +}; + +static struct rc_keymap behold_columbus_map = { + .map = { + .scan = behold_columbus, + .size = ARRAY_SIZE(behold_columbus), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_BEHOLD_COLUMBUS, + } +}; + +static int __init init_rc_map_behold_columbus(void) +{ + return ir_register_map(&behold_columbus_map); +} + +static void __exit exit_rc_map_behold_columbus(void) +{ + ir_unregister_map(&behold_columbus_map); +} + +module_init(init_rc_map_behold_columbus) +module_exit(exit_rc_map_behold_columbus) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-behold.c b/drivers/media/rc/keymaps/rc-behold.c new file mode 100644 index 0000000..abc140b --- /dev/null +++ b/drivers/media/rc/keymaps/rc-behold.c @@ -0,0 +1,141 @@ +/* behold.h - Keytable for behold Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * Igor Kuznetsov + * Andrey J. Melnikov + * + * Keytable is used by BeholdTV 60x series, M6 series at + * least, and probably other cards too. + * The "ascii-art picture" below (in comments, first row + * is the keycode in hex, and subsequent row(s) shows + * the button labels (several variants when appropriate) + * helps to descide which keycodes to assign to the buttons. + */ + +static struct ir_scancode behold[] = { + + /* 0x1c 0x12 * + * TV/FM POWER * + * */ + { 0x1c, KEY_TUNER }, /* XXX KEY_TV / KEY_RADIO */ + { 0x12, KEY_POWER }, + + /* 0x01 0x02 0x03 * + * 1 2 3 * + * * + * 0x04 0x05 0x06 * + * 4 5 6 * + * * + * 0x07 0x08 0x09 * + * 7 8 9 * + * */ + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + /* 0x0a 0x00 0x17 * + * RECALL 0 MODE * + * */ + { 0x0a, KEY_AGAIN }, + { 0x00, KEY_0 }, + { 0x17, KEY_MODE }, + + /* 0x14 0x10 * + * ASPECT FULLSCREEN * + * */ + { 0x14, KEY_SCREEN }, + { 0x10, KEY_ZOOM }, + + /* 0x0b * + * Up * + * * + * 0x18 0x16 0x0c * + * Left Ok Right * + * * + * 0x015 * + * Down * + * */ + { 0x0b, KEY_CHANNELUP }, + { 0x18, KEY_VOLUMEDOWN }, + { 0x16, KEY_OK }, /* XXX KEY_ENTER */ + { 0x0c, KEY_VOLUMEUP }, + { 0x15, KEY_CHANNELDOWN }, + + /* 0x11 0x0d * + * MUTE INFO * + * */ + { 0x11, KEY_MUTE }, + { 0x0d, KEY_INFO }, + + /* 0x0f 0x1b 0x1a * + * RECORD PLAY/PAUSE STOP * + * * + * 0x0e 0x1f 0x1e * + *TELETEXT AUDIO SOURCE * + * RED YELLOW * + * */ + { 0x0f, KEY_RECORD }, + { 0x1b, KEY_PLAYPAUSE }, + { 0x1a, KEY_STOP }, + { 0x0e, KEY_TEXT }, + { 0x1f, KEY_RED }, /*XXX KEY_AUDIO */ + { 0x1e, KEY_YELLOW }, /*XXX KEY_SOURCE */ + + /* 0x1d 0x13 0x19 * + * SLEEP PREVIEW DVB * + * GREEN BLUE * + * */ + { 0x1d, KEY_SLEEP }, + { 0x13, KEY_GREEN }, + { 0x19, KEY_BLUE }, /* XXX KEY_SAT */ + + /* 0x58 0x5c * + * FREEZE SNAPSHOT * + * */ + { 0x58, KEY_SLOW }, + { 0x5c, KEY_CAMERA }, + +}; + +static struct rc_keymap behold_map = { + .map = { + .scan = behold, + .size = ARRAY_SIZE(behold), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_BEHOLD, + } +}; + +static int __init init_rc_map_behold(void) +{ + return ir_register_map(&behold_map); +} + +static void __exit exit_rc_map_behold(void) +{ + ir_unregister_map(&behold_map); +} + +module_init(init_rc_map_behold) +module_exit(exit_rc_map_behold) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-budget-ci-old.c b/drivers/media/rc/keymaps/rc-budget-ci-old.c new file mode 100644 index 0000000..64c2ac9 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-budget-ci-old.c @@ -0,0 +1,92 @@ +/* budget-ci-old.h - Keytable for budget_ci_old Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* From reading the following remotes: + * Zenith Universal 7 / TV Mode 807 / VCR Mode 837 + * Hauppauge (from NOVA-CI-s box product) + * This is a "middle of the road" approach, differences are noted + */ + +static struct ir_scancode budget_ci_old[] = { + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + { 0x0a, KEY_ENTER }, + { 0x0b, KEY_RED }, + { 0x0c, KEY_POWER }, /* RADIO on Hauppauge */ + { 0x0d, KEY_MUTE }, + { 0x0f, KEY_A }, /* TV on Hauppauge */ + { 0x10, KEY_VOLUMEUP }, + { 0x11, KEY_VOLUMEDOWN }, + { 0x14, KEY_B }, + { 0x1c, KEY_UP }, + { 0x1d, KEY_DOWN }, + { 0x1e, KEY_OPTION }, /* RESERVED on Hauppauge */ + { 0x1f, KEY_BREAK }, + { 0x20, KEY_CHANNELUP }, + { 0x21, KEY_CHANNELDOWN }, + { 0x22, KEY_PREVIOUS }, /* Prev Ch on Zenith, SOURCE on Hauppauge */ + { 0x24, KEY_RESTART }, + { 0x25, KEY_OK }, + { 0x26, KEY_CYCLEWINDOWS }, /* MINIMIZE on Hauppauge */ + { 0x28, KEY_ENTER }, /* VCR mode on Zenith */ + { 0x29, KEY_PAUSE }, + { 0x2b, KEY_RIGHT }, + { 0x2c, KEY_LEFT }, + { 0x2e, KEY_MENU }, /* FULL SCREEN on Hauppauge */ + { 0x30, KEY_SLOW }, + { 0x31, KEY_PREVIOUS }, /* VCR mode on Zenith */ + { 0x32, KEY_REWIND }, + { 0x34, KEY_FASTFORWARD }, + { 0x35, KEY_PLAY }, + { 0x36, KEY_STOP }, + { 0x37, KEY_RECORD }, + { 0x38, KEY_TUNER }, /* TV/VCR on Zenith */ + { 0x3a, KEY_C }, + { 0x3c, KEY_EXIT }, + { 0x3d, KEY_POWER2 }, + { 0x3e, KEY_TUNER }, +}; + +static struct rc_keymap budget_ci_old_map = { + .map = { + .scan = budget_ci_old, + .size = ARRAY_SIZE(budget_ci_old), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_BUDGET_CI_OLD, + } +}; + +static int __init init_rc_map_budget_ci_old(void) +{ + return ir_register_map(&budget_ci_old_map); +} + +static void __exit exit_rc_map_budget_ci_old(void) +{ + ir_unregister_map(&budget_ci_old_map); +} + +module_init(init_rc_map_budget_ci_old) +module_exit(exit_rc_map_budget_ci_old) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-cinergy-1400.c b/drivers/media/rc/keymaps/rc-cinergy-1400.c new file mode 100644 index 0000000..074f2c2 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-cinergy-1400.c @@ -0,0 +1,84 @@ +/* cinergy-1400.h - Keytable for cinergy_1400 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Cinergy 1400 DVB-T */ + +static struct ir_scancode cinergy_1400[] = { + { 0x01, KEY_POWER }, + { 0x02, KEY_1 }, + { 0x03, KEY_2 }, + { 0x04, KEY_3 }, + { 0x05, KEY_4 }, + { 0x06, KEY_5 }, + { 0x07, KEY_6 }, + { 0x08, KEY_7 }, + { 0x09, KEY_8 }, + { 0x0a, KEY_9 }, + { 0x0c, KEY_0 }, + + { 0x0b, KEY_VIDEO }, + { 0x0d, KEY_REFRESH }, + { 0x0e, KEY_SELECT }, + { 0x0f, KEY_EPG }, + { 0x10, KEY_UP }, + { 0x11, KEY_LEFT }, + { 0x12, KEY_OK }, + { 0x13, KEY_RIGHT }, + { 0x14, KEY_DOWN }, + { 0x15, KEY_TEXT }, + { 0x16, KEY_INFO }, + + { 0x17, KEY_RED }, + { 0x18, KEY_GREEN }, + { 0x19, KEY_YELLOW }, + { 0x1a, KEY_BLUE }, + + { 0x1b, KEY_CHANNELUP }, + { 0x1c, KEY_VOLUMEUP }, + { 0x1d, KEY_MUTE }, + { 0x1e, KEY_VOLUMEDOWN }, + { 0x1f, KEY_CHANNELDOWN }, + + { 0x40, KEY_PAUSE }, + { 0x4c, KEY_PLAY }, + { 0x58, KEY_RECORD }, + { 0x54, KEY_PREVIOUS }, + { 0x48, KEY_STOP }, + { 0x5c, KEY_NEXT }, +}; + +static struct rc_keymap cinergy_1400_map = { + .map = { + .scan = cinergy_1400, + .size = ARRAY_SIZE(cinergy_1400), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_CINERGY_1400, + } +}; + +static int __init init_rc_map_cinergy_1400(void) +{ + return ir_register_map(&cinergy_1400_map); +} + +static void __exit exit_rc_map_cinergy_1400(void) +{ + ir_unregister_map(&cinergy_1400_map); +} + +module_init(init_rc_map_cinergy_1400) +module_exit(exit_rc_map_cinergy_1400) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-cinergy.c b/drivers/media/rc/keymaps/rc-cinergy.c new file mode 100644 index 0000000..cf84c3d --- /dev/null +++ b/drivers/media/rc/keymaps/rc-cinergy.c @@ -0,0 +1,78 @@ +/* cinergy.h - Keytable for cinergy Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode cinergy[] = { + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x0a, KEY_POWER }, + { 0x0b, KEY_PROG1 }, /* app */ + { 0x0c, KEY_ZOOM }, /* zoom/fullscreen */ + { 0x0d, KEY_CHANNELUP }, /* channel */ + { 0x0e, KEY_CHANNELDOWN }, /* channel- */ + { 0x0f, KEY_VOLUMEUP }, + { 0x10, KEY_VOLUMEDOWN }, + { 0x11, KEY_TUNER }, /* AV */ + { 0x12, KEY_NUMLOCK }, /* -/-- */ + { 0x13, KEY_AUDIO }, /* audio */ + { 0x14, KEY_MUTE }, + { 0x15, KEY_UP }, + { 0x16, KEY_DOWN }, + { 0x17, KEY_LEFT }, + { 0x18, KEY_RIGHT }, + { 0x19, BTN_LEFT, }, + { 0x1a, BTN_RIGHT, }, + { 0x1b, KEY_WWW }, /* text */ + { 0x1c, KEY_REWIND }, + { 0x1d, KEY_FORWARD }, + { 0x1e, KEY_RECORD }, + { 0x1f, KEY_PLAY }, + { 0x20, KEY_PREVIOUSSONG }, + { 0x21, KEY_NEXTSONG }, + { 0x22, KEY_PAUSE }, + { 0x23, KEY_STOP }, +}; + +static struct rc_keymap cinergy_map = { + .map = { + .scan = cinergy, + .size = ARRAY_SIZE(cinergy), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_CINERGY, + } +}; + +static int __init init_rc_map_cinergy(void) +{ + return ir_register_map(&cinergy_map); +} + +static void __exit exit_rc_map_cinergy(void) +{ + ir_unregister_map(&cinergy_map); +} + +module_init(init_rc_map_cinergy) +module_exit(exit_rc_map_cinergy) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-dib0700-nec.c b/drivers/media/rc/keymaps/rc-dib0700-nec.c new file mode 100644 index 0000000..ae18320 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-dib0700-nec.c @@ -0,0 +1,124 @@ +/* rc-dvb0700-big.c - Keytable for devices in dvb0700 + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * TODO: This table is a real mess, as it merges RC codes from several + * devices into a big table. It also has both RC-5 and NEC codes inside. + * It should be broken into small tables, and the protocols should properly + * be indentificated. + * + * The table were imported from dib0700_devices.c. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode dib0700_nec_table[] = { + /* Key codes for the Pixelview SBTVD remote */ + { 0x8613, KEY_MUTE }, + { 0x8612, KEY_POWER }, + { 0x8601, KEY_1 }, + { 0x8602, KEY_2 }, + { 0x8603, KEY_3 }, + { 0x8604, KEY_4 }, + { 0x8605, KEY_5 }, + { 0x8606, KEY_6 }, + { 0x8607, KEY_7 }, + { 0x8608, KEY_8 }, + { 0x8609, KEY_9 }, + { 0x8600, KEY_0 }, + { 0x860d, KEY_CHANNELUP }, + { 0x8619, KEY_CHANNELDOWN }, + { 0x8610, KEY_VOLUMEUP }, + { 0x860c, KEY_VOLUMEDOWN }, + + { 0x860a, KEY_CAMERA }, + { 0x860b, KEY_ZOOM }, + { 0x861b, KEY_BACKSPACE }, + { 0x8615, KEY_ENTER }, + + { 0x861d, KEY_UP }, + { 0x861e, KEY_DOWN }, + { 0x860e, KEY_LEFT }, + { 0x860f, KEY_RIGHT }, + + { 0x8618, KEY_RECORD }, + { 0x861a, KEY_STOP }, + + /* Key codes for the EvolutePC TVWay+ remote */ + { 0x7a00, KEY_MENU }, + { 0x7a01, KEY_RECORD }, + { 0x7a02, KEY_PLAY }, + { 0x7a03, KEY_STOP }, + { 0x7a10, KEY_CHANNELUP }, + { 0x7a11, KEY_CHANNELDOWN }, + { 0x7a12, KEY_VOLUMEUP }, + { 0x7a13, KEY_VOLUMEDOWN }, + { 0x7a40, KEY_POWER }, + { 0x7a41, KEY_MUTE }, + + /* Key codes for the Elgato EyeTV Diversity silver remote */ + { 0x4501, KEY_POWER }, + { 0x4502, KEY_MUTE }, + { 0x4503, KEY_1 }, + { 0x4504, KEY_2 }, + { 0x4505, KEY_3 }, + { 0x4506, KEY_4 }, + { 0x4507, KEY_5 }, + { 0x4508, KEY_6 }, + { 0x4509, KEY_7 }, + { 0x450a, KEY_8 }, + { 0x450b, KEY_9 }, + { 0x450c, KEY_LAST }, + { 0x450d, KEY_0 }, + { 0x450e, KEY_ENTER }, + { 0x450f, KEY_RED }, + { 0x4510, KEY_CHANNELUP }, + { 0x4511, KEY_GREEN }, + { 0x4512, KEY_VOLUMEDOWN }, + { 0x4513, KEY_OK }, + { 0x4514, KEY_VOLUMEUP }, + { 0x4515, KEY_YELLOW }, + { 0x4516, KEY_CHANNELDOWN }, + { 0x4517, KEY_BLUE }, + { 0x4518, KEY_LEFT }, /* Skip backwards */ + { 0x4519, KEY_PLAYPAUSE }, + { 0x451a, KEY_RIGHT }, /* Skip forward */ + { 0x451b, KEY_REWIND }, + { 0x451c, KEY_L }, /* Live */ + { 0x451d, KEY_FASTFORWARD }, + { 0x451e, KEY_STOP }, /* 'Reveal' for Teletext */ + { 0x451f, KEY_MENU }, /* KEY_TEXT for Teletext */ + { 0x4540, KEY_RECORD }, /* Font 'Size' for Teletext */ + { 0x4541, KEY_SCREEN }, /* Full screen toggle, 'Hold' for Teletext */ + { 0x4542, KEY_SELECT }, /* Select video input, 'Select' for Teletext */ +}; + +static struct rc_keymap dib0700_nec_map = { + .map = { + .scan = dib0700_nec_table, + .size = ARRAY_SIZE(dib0700_nec_table), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_DIB0700_NEC_TABLE, + } +}; + +static int __init init_rc_map(void) +{ + return ir_register_map(&dib0700_nec_map); +} + +static void __exit exit_rc_map(void) +{ + ir_unregister_map(&dib0700_nec_map); +} + +module_init(init_rc_map) +module_exit(exit_rc_map) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-dib0700-rc5.c b/drivers/media/rc/keymaps/rc-dib0700-rc5.c new file mode 100644 index 0000000..4a4797c --- /dev/null +++ b/drivers/media/rc/keymaps/rc-dib0700-rc5.c @@ -0,0 +1,235 @@ +/* rc-dvb0700-big.c - Keytable for devices in dvb0700 + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * TODO: This table is a real mess, as it merges RC codes from several + * devices into a big table. It also has both RC-5 and NEC codes inside. + * It should be broken into small tables, and the protocols should properly + * be indentificated. + * + * The table were imported from dib0700_devices.c. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode dib0700_rc5_table[] = { + /* Key codes for the tiny Pinnacle remote*/ + { 0x0700, KEY_MUTE }, + { 0x0701, KEY_MENU }, /* Pinnacle logo */ + { 0x0739, KEY_POWER }, + { 0x0703, KEY_VOLUMEUP }, + { 0x0709, KEY_VOLUMEDOWN }, + { 0x0706, KEY_CHANNELUP }, + { 0x070c, KEY_CHANNELDOWN }, + { 0x070f, KEY_1 }, + { 0x0715, KEY_2 }, + { 0x0710, KEY_3 }, + { 0x0718, KEY_4 }, + { 0x071b, KEY_5 }, + { 0x071e, KEY_6 }, + { 0x0711, KEY_7 }, + { 0x0721, KEY_8 }, + { 0x0712, KEY_9 }, + { 0x0727, KEY_0 }, + { 0x0724, KEY_SCREEN }, /* 'Square' key */ + { 0x072a, KEY_TEXT }, /* 'T' key */ + { 0x072d, KEY_REWIND }, + { 0x0730, KEY_PLAY }, + { 0x0733, KEY_FASTFORWARD }, + { 0x0736, KEY_RECORD }, + { 0x073c, KEY_STOP }, + { 0x073f, KEY_CANCEL }, /* '?' key */ + + /* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */ + { 0xeb01, KEY_POWER }, + { 0xeb02, KEY_1 }, + { 0xeb03, KEY_2 }, + { 0xeb04, KEY_3 }, + { 0xeb05, KEY_4 }, + { 0xeb06, KEY_5 }, + { 0xeb07, KEY_6 }, + { 0xeb08, KEY_7 }, + { 0xeb09, KEY_8 }, + { 0xeb0a, KEY_9 }, + { 0xeb0b, KEY_VIDEO }, + { 0xeb0c, KEY_0 }, + { 0xeb0d, KEY_REFRESH }, + { 0xeb0f, KEY_EPG }, + { 0xeb10, KEY_UP }, + { 0xeb11, KEY_LEFT }, + { 0xeb12, KEY_OK }, + { 0xeb13, KEY_RIGHT }, + { 0xeb14, KEY_DOWN }, + { 0xeb16, KEY_INFO }, + { 0xeb17, KEY_RED }, + { 0xeb18, KEY_GREEN }, + { 0xeb19, KEY_YELLOW }, + { 0xeb1a, KEY_BLUE }, + { 0xeb1b, KEY_CHANNELUP }, + { 0xeb1c, KEY_VOLUMEUP }, + { 0xeb1d, KEY_MUTE }, + { 0xeb1e, KEY_VOLUMEDOWN }, + { 0xeb1f, KEY_CHANNELDOWN }, + { 0xeb40, KEY_PAUSE }, + { 0xeb41, KEY_HOME }, + { 0xeb42, KEY_MENU }, /* DVD Menu */ + { 0xeb43, KEY_SUBTITLE }, + { 0xeb44, KEY_TEXT }, /* Teletext */ + { 0xeb45, KEY_DELETE }, + { 0xeb46, KEY_TV }, + { 0xeb47, KEY_DVD }, + { 0xeb48, KEY_STOP }, + { 0xeb49, KEY_VIDEO }, + { 0xeb4a, KEY_AUDIO }, /* Music */ + { 0xeb4b, KEY_SCREEN }, /* Pic */ + { 0xeb4c, KEY_PLAY }, + { 0xeb4d, KEY_BACK }, + { 0xeb4e, KEY_REWIND }, + { 0xeb4f, KEY_FASTFORWARD }, + { 0xeb54, KEY_PREVIOUS }, + { 0xeb58, KEY_RECORD }, + { 0xeb5c, KEY_NEXT }, + + /* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */ + { 0x1e00, KEY_0 }, + { 0x1e01, KEY_1 }, + { 0x1e02, KEY_2 }, + { 0x1e03, KEY_3 }, + { 0x1e04, KEY_4 }, + { 0x1e05, KEY_5 }, + { 0x1e06, KEY_6 }, + { 0x1e07, KEY_7 }, + { 0x1e08, KEY_8 }, + { 0x1e09, KEY_9 }, + { 0x1e0a, KEY_KPASTERISK }, + { 0x1e0b, KEY_RED }, + { 0x1e0c, KEY_RADIO }, + { 0x1e0d, KEY_MENU }, + { 0x1e0e, KEY_GRAVE }, /* # */ + { 0x1e0f, KEY_MUTE }, + { 0x1e10, KEY_VOLUMEUP }, + { 0x1e11, KEY_VOLUMEDOWN }, + { 0x1e12, KEY_CHANNEL }, + { 0x1e14, KEY_UP }, + { 0x1e15, KEY_DOWN }, + { 0x1e16, KEY_LEFT }, + { 0x1e17, KEY_RIGHT }, + { 0x1e18, KEY_VIDEO }, + { 0x1e19, KEY_AUDIO }, + { 0x1e1a, KEY_MEDIA }, + { 0x1e1b, KEY_EPG }, + { 0x1e1c, KEY_TV }, + { 0x1e1e, KEY_NEXT }, + { 0x1e1f, KEY_BACK }, + { 0x1e20, KEY_CHANNELUP }, + { 0x1e21, KEY_CHANNELDOWN }, + { 0x1e24, KEY_LAST }, /* Skip backwards */ + { 0x1e25, KEY_OK }, + { 0x1e29, KEY_BLUE}, + { 0x1e2e, KEY_GREEN }, + { 0x1e30, KEY_PAUSE }, + { 0x1e32, KEY_REWIND }, + { 0x1e34, KEY_FASTFORWARD }, + { 0x1e35, KEY_PLAY }, + { 0x1e36, KEY_STOP }, + { 0x1e37, KEY_RECORD }, + { 0x1e38, KEY_YELLOW }, + { 0x1e3b, KEY_GOTO }, + { 0x1e3d, KEY_POWER }, + + /* Key codes for the Leadtek Winfast DTV Dongle */ + { 0x0042, KEY_POWER }, + { 0x077c, KEY_TUNER }, + { 0x0f4e, KEY_PRINT }, /* PREVIEW */ + { 0x0840, KEY_SCREEN }, /* full screen toggle*/ + { 0x0f71, KEY_DOT }, /* frequency */ + { 0x0743, KEY_0 }, + { 0x0c41, KEY_1 }, + { 0x0443, KEY_2 }, + { 0x0b7f, KEY_3 }, + { 0x0e41, KEY_4 }, + { 0x0643, KEY_5 }, + { 0x097f, KEY_6 }, + { 0x0d7e, KEY_7 }, + { 0x057c, KEY_8 }, + { 0x0a40, KEY_9 }, + { 0x0e4e, KEY_CLEAR }, + { 0x047c, KEY_CHANNEL }, /* show channel number */ + { 0x0f41, KEY_LAST }, /* recall */ + { 0x0342, KEY_MUTE }, + { 0x064c, KEY_RESERVED }, /* PIP button*/ + { 0x0172, KEY_SHUFFLE }, /* SNAPSHOT */ + { 0x0c4e, KEY_PLAYPAUSE }, /* TIMESHIFT */ + { 0x0b70, KEY_RECORD }, + { 0x037d, KEY_VOLUMEUP }, + { 0x017d, KEY_VOLUMEDOWN }, + { 0x0242, KEY_CHANNELUP }, + { 0x007d, KEY_CHANNELDOWN }, + + /* Key codes for Nova-TD "credit card" remote control. */ + { 0x1d00, KEY_0 }, + { 0x1d01, KEY_1 }, + { 0x1d02, KEY_2 }, + { 0x1d03, KEY_3 }, + { 0x1d04, KEY_4 }, + { 0x1d05, KEY_5 }, + { 0x1d06, KEY_6 }, + { 0x1d07, KEY_7 }, + { 0x1d08, KEY_8 }, + { 0x1d09, KEY_9 }, + { 0x1d0a, KEY_TEXT }, + { 0x1d0d, KEY_MENU }, + { 0x1d0f, KEY_MUTE }, + { 0x1d10, KEY_VOLUMEUP }, + { 0x1d11, KEY_VOLUMEDOWN }, + { 0x1d12, KEY_CHANNEL }, + { 0x1d14, KEY_UP }, + { 0x1d15, KEY_DOWN }, + { 0x1d16, KEY_LEFT }, + { 0x1d17, KEY_RIGHT }, + { 0x1d1c, KEY_TV }, + { 0x1d1e, KEY_NEXT }, + { 0x1d1f, KEY_BACK }, + { 0x1d20, KEY_CHANNELUP }, + { 0x1d21, KEY_CHANNELDOWN }, + { 0x1d24, KEY_LAST }, + { 0x1d25, KEY_OK }, + { 0x1d30, KEY_PAUSE }, + { 0x1d32, KEY_REWIND }, + { 0x1d34, KEY_FASTFORWARD }, + { 0x1d35, KEY_PLAY }, + { 0x1d36, KEY_STOP }, + { 0x1d37, KEY_RECORD }, + { 0x1d3b, KEY_GOTO }, + { 0x1d3d, KEY_POWER }, +}; + +static struct rc_keymap dib0700_rc5_map = { + .map = { + .scan = dib0700_rc5_table, + .size = ARRAY_SIZE(dib0700_rc5_table), + .ir_type = IR_TYPE_RC5, + .name = RC_MAP_DIB0700_RC5_TABLE, + } +}; + +static int __init init_rc_map(void) +{ + return ir_register_map(&dib0700_rc5_map); +} + +static void __exit exit_rc_map(void) +{ + ir_unregister_map(&dib0700_rc5_map); +} + +module_init(init_rc_map) +module_exit(exit_rc_map) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c b/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c new file mode 100644 index 0000000..63e469e --- /dev/null +++ b/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c @@ -0,0 +1,98 @@ +/* + * DigitalNow TinyTwin remote controller keytable + * + * Copyright (C) 2010 Antti Palosaari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +static struct ir_scancode digitalnow_tinytwin[] = { + { 0x0000, KEY_MUTE }, /* [symbol speaker] */ + { 0x0001, KEY_VOLUMEUP }, + { 0x0002, KEY_POWER2 }, /* TV [power button] */ + { 0x0003, KEY_2 }, + { 0x0004, KEY_3 }, + { 0x0005, KEY_4 }, + { 0x0006, KEY_6 }, + { 0x0007, KEY_7 }, + { 0x0008, KEY_8 }, + { 0x0009, KEY_NUMERIC_STAR }, /* [*] */ + { 0x000a, KEY_0 }, + { 0x000b, KEY_NUMERIC_POUND }, /* [#] */ + { 0x000c, KEY_RIGHT }, /* [right arrow] */ + { 0x000d, KEY_HOMEPAGE }, /* [symbol home] Start */ + { 0x000e, KEY_RED }, /* [red] Videos */ + { 0x0010, KEY_POWER }, /* PC [power button] */ + { 0x0011, KEY_YELLOW }, /* [yellow] Pictures */ + { 0x0012, KEY_DOWN }, /* [down arrow] */ + { 0x0013, KEY_GREEN }, /* [green] Music */ + { 0x0014, KEY_CYCLEWINDOWS }, /* BACK */ + { 0x0015, KEY_FAVORITES }, /* MORE */ + { 0x0016, KEY_UP }, /* [up arrow] */ + { 0x0017, KEY_LEFT }, /* [left arrow] */ + { 0x0018, KEY_OK }, /* OK */ + { 0x0019, KEY_BLUE }, /* [blue] MyTV */ + { 0x001a, KEY_REWIND }, /* REW [<<] */ + { 0x001b, KEY_PLAY }, /* PLAY */ + { 0x001c, KEY_5 }, + { 0x001d, KEY_9 }, + { 0x001e, KEY_VOLUMEDOWN }, + { 0x001f, KEY_1 }, + { 0x0040, KEY_STOP }, /* STOP */ + { 0x0042, KEY_PAUSE }, /* PAUSE */ + { 0x0043, KEY_SCREEN }, /* Aspect */ + { 0x0044, KEY_FORWARD }, /* FWD [>>] */ + { 0x0045, KEY_NEXT }, /* SKIP */ + { 0x0048, KEY_RECORD }, /* RECORD */ + { 0x0049, KEY_VIDEO }, /* RTV */ + { 0x004a, KEY_EPG }, /* Guide */ + { 0x004b, KEY_CHANNELUP }, + { 0x004c, KEY_HELP }, /* Help */ + { 0x004d, KEY_RADIO }, /* Radio */ + { 0x004f, KEY_CHANNELDOWN }, + { 0x0050, KEY_DVD }, /* DVD */ + { 0x0051, KEY_AUDIO }, /* Audio */ + { 0x0052, KEY_TITLE }, /* Title */ + { 0x0053, KEY_NEW }, /* [symbol PIP?] */ + { 0x0057, KEY_MENU }, /* Mouse */ + { 0x005a, KEY_PREVIOUS }, /* REPLAY */ +}; + +static struct rc_keymap digitalnow_tinytwin_map = { + .map = { + .scan = digitalnow_tinytwin, + .size = ARRAY_SIZE(digitalnow_tinytwin), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_DIGITALNOW_TINYTWIN, + } +}; + +static int __init init_rc_map_digitalnow_tinytwin(void) +{ + return ir_register_map(&digitalnow_tinytwin_map); +} + +static void __exit exit_rc_map_digitalnow_tinytwin(void) +{ + ir_unregister_map(&digitalnow_tinytwin_map); +} + +module_init(init_rc_map_digitalnow_tinytwin) +module_exit(exit_rc_map_digitalnow_tinytwin) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/rc/keymaps/rc-digittrade.c b/drivers/media/rc/keymaps/rc-digittrade.c new file mode 100644 index 0000000..5dece78 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-digittrade.c @@ -0,0 +1,82 @@ +/* + * Digittrade DVB-T USB Stick remote controller keytable + * + * Copyright (C) 2010 Antti Palosaari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +/* Digittrade DVB-T USB Stick remote controller. */ +/* Imported from af9015.h. + Initial keytable was from Alain Kalker */ + +/* Digittrade DVB-T USB Stick */ +static struct ir_scancode digittrade[] = { + { 0x0000, KEY_9 }, + { 0x0001, KEY_EPG }, /* EPG */ + { 0x0002, KEY_VOLUMEDOWN }, /* Vol Dn */ + { 0x0003, KEY_TEXT }, /* TELETEXT */ + { 0x0004, KEY_8 }, + { 0x0005, KEY_MUTE }, /* MUTE */ + { 0x0006, KEY_POWER2 }, /* POWER */ + { 0x0009, KEY_ZOOM }, /* FULLSCREEN */ + { 0x000a, KEY_RECORD }, /* RECORD */ + { 0x000d, KEY_SUBTITLE }, /* SUBTITLE */ + { 0x000e, KEY_STOP }, /* STOP */ + { 0x0010, KEY_OK }, /* RETURN */ + { 0x0011, KEY_2 }, + { 0x0012, KEY_4 }, + { 0x0015, KEY_3 }, + { 0x0016, KEY_5 }, + { 0x0017, KEY_CHANNELDOWN }, /* Ch Dn */ + { 0x0019, KEY_CHANNELUP }, /* CH Up */ + { 0x001a, KEY_PAUSE }, /* PAUSE */ + { 0x001b, KEY_1 }, + { 0x001d, KEY_AUDIO }, /* DUAL SOUND */ + { 0x001e, KEY_PLAY }, /* PLAY */ + { 0x001f, KEY_CAMERA }, /* SNAPSHOT */ + { 0x0040, KEY_VOLUMEUP }, /* Vol Up */ + { 0x0048, KEY_7 }, + { 0x004c, KEY_6 }, + { 0x004d, KEY_PLAYPAUSE }, /* TIMESHIFT */ + { 0x0054, KEY_0 }, +}; + +static struct rc_keymap digittrade_map = { + .map = { + .scan = digittrade, + .size = ARRAY_SIZE(digittrade), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_DIGITTRADE, + } +}; + +static int __init init_rc_map_digittrade(void) +{ + return ir_register_map(&digittrade_map); +} + +static void __exit exit_rc_map_digittrade(void) +{ + ir_unregister_map(&digittrade_map); +} + +module_init(init_rc_map_digittrade) +module_exit(exit_rc_map_digittrade) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/rc/keymaps/rc-dm1105-nec.c b/drivers/media/rc/keymaps/rc-dm1105-nec.c new file mode 100644 index 0000000..90684d0 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-dm1105-nec.c @@ -0,0 +1,76 @@ +/* dm1105-nec.h - Keytable for dm1105_nec Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* DVBWorld remotes + Igor M. Liplianin + */ + +static struct ir_scancode dm1105_nec[] = { + { 0x0a, KEY_POWER2}, /* power */ + { 0x0c, KEY_MUTE}, /* mute */ + { 0x11, KEY_1}, + { 0x12, KEY_2}, + { 0x13, KEY_3}, + { 0x14, KEY_4}, + { 0x15, KEY_5}, + { 0x16, KEY_6}, + { 0x17, KEY_7}, + { 0x18, KEY_8}, + { 0x19, KEY_9}, + { 0x10, KEY_0}, + { 0x1c, KEY_CHANNELUP}, /* ch+ */ + { 0x0f, KEY_CHANNELDOWN}, /* ch- */ + { 0x1a, KEY_VOLUMEUP}, /* vol+ */ + { 0x0e, KEY_VOLUMEDOWN}, /* vol- */ + { 0x04, KEY_RECORD}, /* rec */ + { 0x09, KEY_CHANNEL}, /* fav */ + { 0x08, KEY_BACKSPACE}, /* rewind */ + { 0x07, KEY_FASTFORWARD}, /* fast */ + { 0x0b, KEY_PAUSE}, /* pause */ + { 0x02, KEY_ESC}, /* cancel */ + { 0x03, KEY_TAB}, /* tab */ + { 0x00, KEY_UP}, /* up */ + { 0x1f, KEY_ENTER}, /* ok */ + { 0x01, KEY_DOWN}, /* down */ + { 0x05, KEY_RECORD}, /* cap */ + { 0x06, KEY_STOP}, /* stop */ + { 0x40, KEY_ZOOM}, /* full */ + { 0x1e, KEY_TV}, /* tvmode */ + { 0x1b, KEY_B}, /* recall */ +}; + +static struct rc_keymap dm1105_nec_map = { + .map = { + .scan = dm1105_nec, + .size = ARRAY_SIZE(dm1105_nec), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_DM1105_NEC, + } +}; + +static int __init init_rc_map_dm1105_nec(void) +{ + return ir_register_map(&dm1105_nec_map); +} + +static void __exit exit_rc_map_dm1105_nec(void) +{ + ir_unregister_map(&dm1105_nec_map); +} + +module_init(init_rc_map_dm1105_nec) +module_exit(exit_rc_map_dm1105_nec) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c b/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c new file mode 100644 index 0000000..8a4027a --- /dev/null +++ b/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c @@ -0,0 +1,78 @@ +/* dntv-live-dvb-t.h - Keytable for dntv_live_dvb_t Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* DigitalNow DNTV Live DVB-T Remote */ + +static struct ir_scancode dntv_live_dvb_t[] = { + { 0x00, KEY_ESC }, /* 'go up a level?' */ + /* Keys 0 to 9 */ + { 0x0a, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x0b, KEY_TUNER }, /* tv/fm */ + { 0x0c, KEY_SEARCH }, /* scan */ + { 0x0d, KEY_STOP }, + { 0x0e, KEY_PAUSE }, + { 0x0f, KEY_LIST }, /* source */ + + { 0x10, KEY_MUTE }, + { 0x11, KEY_REWIND }, /* backward << */ + { 0x12, KEY_POWER }, + { 0x13, KEY_CAMERA }, /* snap */ + { 0x14, KEY_AUDIO }, /* stereo */ + { 0x15, KEY_CLEAR }, /* reset */ + { 0x16, KEY_PLAY }, + { 0x17, KEY_ENTER }, + { 0x18, KEY_ZOOM }, /* full screen */ + { 0x19, KEY_FASTFORWARD }, /* forward >> */ + { 0x1a, KEY_CHANNELUP }, + { 0x1b, KEY_VOLUMEUP }, + { 0x1c, KEY_INFO }, /* preview */ + { 0x1d, KEY_RECORD }, /* record */ + { 0x1e, KEY_CHANNELDOWN }, + { 0x1f, KEY_VOLUMEDOWN }, +}; + +static struct rc_keymap dntv_live_dvb_t_map = { + .map = { + .scan = dntv_live_dvb_t, + .size = ARRAY_SIZE(dntv_live_dvb_t), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_DNTV_LIVE_DVB_T, + } +}; + +static int __init init_rc_map_dntv_live_dvb_t(void) +{ + return ir_register_map(&dntv_live_dvb_t_map); +} + +static void __exit exit_rc_map_dntv_live_dvb_t(void) +{ + ir_unregister_map(&dntv_live_dvb_t_map); +} + +module_init(init_rc_map_dntv_live_dvb_t) +module_exit(exit_rc_map_dntv_live_dvb_t) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c b/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c new file mode 100644 index 0000000..6f4d607 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c @@ -0,0 +1,97 @@ +/* dntv-live-dvbt-pro.h - Keytable for dntv_live_dvbt_pro Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* DigitalNow DNTV Live! DVB-T Pro Remote */ + +static struct ir_scancode dntv_live_dvbt_pro[] = { + { 0x16, KEY_POWER }, + { 0x5b, KEY_HOME }, + + { 0x55, KEY_TV }, /* live tv */ + { 0x58, KEY_TUNER }, /* digital Radio */ + { 0x5a, KEY_RADIO }, /* FM radio */ + { 0x59, KEY_DVD }, /* dvd menu */ + { 0x03, KEY_1 }, + { 0x01, KEY_2 }, + { 0x06, KEY_3 }, + { 0x09, KEY_4 }, + { 0x1d, KEY_5 }, + { 0x1f, KEY_6 }, + { 0x0d, KEY_7 }, + { 0x19, KEY_8 }, + { 0x1b, KEY_9 }, + { 0x0c, KEY_CANCEL }, + { 0x15, KEY_0 }, + { 0x4a, KEY_CLEAR }, + { 0x13, KEY_BACK }, + { 0x00, KEY_TAB }, + { 0x4b, KEY_UP }, + { 0x4e, KEY_LEFT }, + { 0x4f, KEY_OK }, + { 0x52, KEY_RIGHT }, + { 0x51, KEY_DOWN }, + { 0x1e, KEY_VOLUMEUP }, + { 0x0a, KEY_VOLUMEDOWN }, + { 0x02, KEY_CHANNELDOWN }, + { 0x05, KEY_CHANNELUP }, + { 0x11, KEY_RECORD }, + { 0x14, KEY_PLAY }, + { 0x4c, KEY_PAUSE }, + { 0x1a, KEY_STOP }, + { 0x40, KEY_REWIND }, + { 0x12, KEY_FASTFORWARD }, + { 0x41, KEY_PREVIOUSSONG }, /* replay |< */ + { 0x42, KEY_NEXTSONG }, /* skip >| */ + { 0x54, KEY_CAMERA }, /* capture */ + { 0x50, KEY_LANGUAGE }, /* sap */ + { 0x47, KEY_TV2 }, /* pip */ + { 0x4d, KEY_SCREEN }, + { 0x43, KEY_SUBTITLE }, + { 0x10, KEY_MUTE }, + { 0x49, KEY_AUDIO }, /* l/r */ + { 0x07, KEY_SLEEP }, + { 0x08, KEY_VIDEO }, /* a/v */ + { 0x0e, KEY_PREVIOUS }, /* recall */ + { 0x45, KEY_ZOOM }, /* zoom + */ + { 0x46, KEY_ANGLE }, /* zoom - */ + { 0x56, KEY_RED }, + { 0x57, KEY_GREEN }, + { 0x5c, KEY_YELLOW }, + { 0x5d, KEY_BLUE }, +}; + +static struct rc_keymap dntv_live_dvbt_pro_map = { + .map = { + .scan = dntv_live_dvbt_pro, + .size = ARRAY_SIZE(dntv_live_dvbt_pro), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_DNTV_LIVE_DVBT_PRO, + } +}; + +static int __init init_rc_map_dntv_live_dvbt_pro(void) +{ + return ir_register_map(&dntv_live_dvbt_pro_map); +} + +static void __exit exit_rc_map_dntv_live_dvbt_pro(void) +{ + ir_unregister_map(&dntv_live_dvbt_pro_map); +} + +module_init(init_rc_map_dntv_live_dvbt_pro) +module_exit(exit_rc_map_dntv_live_dvbt_pro) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-em-terratec.c b/drivers/media/rc/keymaps/rc-em-terratec.c new file mode 100644 index 0000000..3130c9c --- /dev/null +++ b/drivers/media/rc/keymaps/rc-em-terratec.c @@ -0,0 +1,69 @@ +/* em-terratec.h - Keytable for em_terratec Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode em_terratec[] = { + { 0x01, KEY_CHANNEL }, + { 0x02, KEY_SELECT }, + { 0x03, KEY_MUTE }, + { 0x04, KEY_POWER }, + { 0x05, KEY_1 }, + { 0x06, KEY_2 }, + { 0x07, KEY_3 }, + { 0x08, KEY_CHANNELUP }, + { 0x09, KEY_4 }, + { 0x0a, KEY_5 }, + { 0x0b, KEY_6 }, + { 0x0c, KEY_CHANNELDOWN }, + { 0x0d, KEY_7 }, + { 0x0e, KEY_8 }, + { 0x0f, KEY_9 }, + { 0x10, KEY_VOLUMEUP }, + { 0x11, KEY_0 }, + { 0x12, KEY_MENU }, + { 0x13, KEY_PRINT }, + { 0x14, KEY_VOLUMEDOWN }, + { 0x16, KEY_PAUSE }, + { 0x18, KEY_RECORD }, + { 0x19, KEY_REWIND }, + { 0x1a, KEY_PLAY }, + { 0x1b, KEY_FORWARD }, + { 0x1c, KEY_BACKSPACE }, + { 0x1e, KEY_STOP }, + { 0x40, KEY_ZOOM }, +}; + +static struct rc_keymap em_terratec_map = { + .map = { + .scan = em_terratec, + .size = ARRAY_SIZE(em_terratec), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_EM_TERRATEC, + } +}; + +static int __init init_rc_map_em_terratec(void) +{ + return ir_register_map(&em_terratec_map); +} + +static void __exit exit_rc_map_em_terratec(void) +{ + ir_unregister_map(&em_terratec_map); +} + +module_init(init_rc_map_em_terratec) +module_exit(exit_rc_map_em_terratec) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c b/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c new file mode 100644 index 0000000..4b81696 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c @@ -0,0 +1,81 @@ +/* encore-enltv-fm53.h - Keytable for encore_enltv_fm53 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Encore ENLTV-FM v5.3 + Mauro Carvalho Chehab + */ + +static struct ir_scancode encore_enltv_fm53[] = { + { 0x10, KEY_POWER2}, + { 0x06, KEY_MUTE}, + + { 0x09, KEY_1}, + { 0x1d, KEY_2}, + { 0x1f, KEY_3}, + { 0x19, KEY_4}, + { 0x1b, KEY_5}, + { 0x11, KEY_6}, + { 0x17, KEY_7}, + { 0x12, KEY_8}, + { 0x16, KEY_9}, + { 0x48, KEY_0}, + + { 0x04, KEY_LIST}, /* -/-- */ + { 0x40, KEY_LAST}, /* recall */ + + { 0x02, KEY_MODE}, /* TV/AV */ + { 0x05, KEY_CAMERA}, /* SNAPSHOT */ + + { 0x4c, KEY_CHANNELUP}, /* UP */ + { 0x00, KEY_CHANNELDOWN}, /* DOWN */ + { 0x0d, KEY_VOLUMEUP}, /* RIGHT */ + { 0x15, KEY_VOLUMEDOWN}, /* LEFT */ + { 0x49, KEY_ENTER}, /* OK */ + + { 0x54, KEY_RECORD}, + { 0x4d, KEY_PLAY}, /* pause */ + + { 0x1e, KEY_MENU}, /* video setting */ + { 0x0e, KEY_RIGHT}, /* <- */ + { 0x1a, KEY_LEFT}, /* -> */ + + { 0x0a, KEY_CLEAR}, /* video default */ + { 0x0c, KEY_ZOOM}, /* hide pannel */ + { 0x47, KEY_SLEEP}, /* shutdown */ +}; + +static struct rc_keymap encore_enltv_fm53_map = { + .map = { + .scan = encore_enltv_fm53, + .size = ARRAY_SIZE(encore_enltv_fm53), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_ENCORE_ENLTV_FM53, + } +}; + +static int __init init_rc_map_encore_enltv_fm53(void) +{ + return ir_register_map(&encore_enltv_fm53_map); +} + +static void __exit exit_rc_map_encore_enltv_fm53(void) +{ + ir_unregister_map(&encore_enltv_fm53_map); +} + +module_init(init_rc_map_encore_enltv_fm53) +module_exit(exit_rc_map_encore_enltv_fm53) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-encore-enltv.c b/drivers/media/rc/keymaps/rc-encore-enltv.c new file mode 100644 index 0000000..9fabffd --- /dev/null +++ b/drivers/media/rc/keymaps/rc-encore-enltv.c @@ -0,0 +1,112 @@ +/* encore-enltv.h - Keytable for encore_enltv Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Encore ENLTV-FM - black plastic, white front cover with white glowing buttons + Juan Pablo Sormani */ + +static struct ir_scancode encore_enltv[] = { + + /* Power button does nothing, neither in Windows app, + although it sends data (used for BIOS wakeup?) */ + { 0x0d, KEY_MUTE }, + + { 0x1e, KEY_TV }, + { 0x00, KEY_VIDEO }, + { 0x01, KEY_AUDIO }, /* music */ + { 0x02, KEY_MHP }, /* picture */ + + { 0x1f, KEY_1 }, + { 0x03, KEY_2 }, + { 0x04, KEY_3 }, + { 0x05, KEY_4 }, + { 0x1c, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x1d, KEY_9 }, + { 0x0a, KEY_0 }, + + { 0x09, KEY_LIST }, /* -/-- */ + { 0x0b, KEY_LAST }, /* recall */ + + { 0x14, KEY_HOME }, /* win start menu */ + { 0x15, KEY_EXIT }, /* exit */ + { 0x16, KEY_CHANNELUP }, /* UP */ + { 0x12, KEY_CHANNELDOWN }, /* DOWN */ + { 0x0c, KEY_VOLUMEUP }, /* RIGHT */ + { 0x17, KEY_VOLUMEDOWN }, /* LEFT */ + + { 0x18, KEY_ENTER }, /* OK */ + + { 0x0e, KEY_ESC }, + { 0x13, KEY_CYCLEWINDOWS }, /* desktop */ + { 0x11, KEY_TAB }, + { 0x19, KEY_SWITCHVIDEOMODE }, /* switch */ + + { 0x1a, KEY_MENU }, + { 0x1b, KEY_ZOOM }, /* fullscreen */ + { 0x44, KEY_TIME }, /* time shift */ + { 0x40, KEY_MODE }, /* source */ + + { 0x5a, KEY_RECORD }, + { 0x42, KEY_PLAY }, /* play/pause */ + { 0x45, KEY_STOP }, + { 0x43, KEY_CAMERA }, /* camera icon */ + + { 0x48, KEY_REWIND }, + { 0x4a, KEY_FASTFORWARD }, + { 0x49, KEY_PREVIOUS }, + { 0x4b, KEY_NEXT }, + + { 0x4c, KEY_FAVORITES }, /* tv wall */ + { 0x4d, KEY_SOUND }, /* DVD sound */ + { 0x4e, KEY_LANGUAGE }, /* DVD lang */ + { 0x4f, KEY_TEXT }, /* DVD text */ + + { 0x50, KEY_SLEEP }, /* shutdown */ + { 0x51, KEY_MODE }, /* stereo > main */ + { 0x52, KEY_SELECT }, /* stereo > sap */ + { 0x53, KEY_PROG1 }, /* teletext */ + + + { 0x59, KEY_RED }, /* AP1 */ + { 0x41, KEY_GREEN }, /* AP2 */ + { 0x47, KEY_YELLOW }, /* AP3 */ + { 0x57, KEY_BLUE }, /* AP4 */ +}; + +static struct rc_keymap encore_enltv_map = { + .map = { + .scan = encore_enltv, + .size = ARRAY_SIZE(encore_enltv), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_ENCORE_ENLTV, + } +}; + +static int __init init_rc_map_encore_enltv(void) +{ + return ir_register_map(&encore_enltv_map); +} + +static void __exit exit_rc_map_encore_enltv(void) +{ + ir_unregister_map(&encore_enltv_map); +} + +module_init(init_rc_map_encore_enltv) +module_exit(exit_rc_map_encore_enltv) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-encore-enltv2.c b/drivers/media/rc/keymaps/rc-encore-enltv2.c new file mode 100644 index 0000000..efefd51 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-encore-enltv2.c @@ -0,0 +1,90 @@ +/* encore-enltv2.h - Keytable for encore_enltv2 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Encore ENLTV2-FM - silver plastic - "Wand Media" written at the botton + Mauro Carvalho Chehab */ + +static struct ir_scancode encore_enltv2[] = { + { 0x4c, KEY_POWER2 }, + { 0x4a, KEY_TUNER }, + { 0x40, KEY_1 }, + { 0x60, KEY_2 }, + { 0x50, KEY_3 }, + { 0x70, KEY_4 }, + { 0x48, KEY_5 }, + { 0x68, KEY_6 }, + { 0x58, KEY_7 }, + { 0x78, KEY_8 }, + { 0x44, KEY_9 }, + { 0x54, KEY_0 }, + + { 0x64, KEY_LAST }, /* +100 */ + { 0x4e, KEY_AGAIN }, /* Recall */ + + { 0x6c, KEY_SWITCHVIDEOMODE }, /* Video Source */ + { 0x5e, KEY_MENU }, + { 0x56, KEY_SCREEN }, + { 0x7a, KEY_SETUP }, + + { 0x46, KEY_MUTE }, + { 0x5c, KEY_MODE }, /* Stereo */ + { 0x74, KEY_INFO }, + { 0x7c, KEY_CLEAR }, + + { 0x55, KEY_UP }, + { 0x49, KEY_DOWN }, + { 0x7e, KEY_LEFT }, + { 0x59, KEY_RIGHT }, + { 0x6a, KEY_ENTER }, + + { 0x42, KEY_VOLUMEUP }, + { 0x62, KEY_VOLUMEDOWN }, + { 0x52, KEY_CHANNELUP }, + { 0x72, KEY_CHANNELDOWN }, + + { 0x41, KEY_RECORD }, + { 0x51, KEY_CAMERA }, /* Snapshot */ + { 0x75, KEY_TIME }, /* Timeshift */ + { 0x71, KEY_TV2 }, /* PIP */ + + { 0x45, KEY_REWIND }, + { 0x6f, KEY_PAUSE }, + { 0x7d, KEY_FORWARD }, + { 0x79, KEY_STOP }, +}; + +static struct rc_keymap encore_enltv2_map = { + .map = { + .scan = encore_enltv2, + .size = ARRAY_SIZE(encore_enltv2), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_ENCORE_ENLTV2, + } +}; + +static int __init init_rc_map_encore_enltv2(void) +{ + return ir_register_map(&encore_enltv2_map); +} + +static void __exit exit_rc_map_encore_enltv2(void) +{ + ir_unregister_map(&encore_enltv2_map); +} + +module_init(init_rc_map_encore_enltv2) +module_exit(exit_rc_map_encore_enltv2) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-evga-indtube.c b/drivers/media/rc/keymaps/rc-evga-indtube.c new file mode 100644 index 0000000..3f3fb13 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-evga-indtube.c @@ -0,0 +1,61 @@ +/* evga-indtube.h - Keytable for evga_indtube Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* EVGA inDtube + Devin Heitmueller + */ + +static struct ir_scancode evga_indtube[] = { + { 0x12, KEY_POWER}, + { 0x02, KEY_MODE}, /* TV */ + { 0x14, KEY_MUTE}, + { 0x1a, KEY_CHANNELUP}, + { 0x16, KEY_TV2}, /* PIP */ + { 0x1d, KEY_VOLUMEUP}, + { 0x05, KEY_CHANNELDOWN}, + { 0x0f, KEY_PLAYPAUSE}, + { 0x19, KEY_VOLUMEDOWN}, + { 0x1c, KEY_REWIND}, + { 0x0d, KEY_RECORD}, + { 0x18, KEY_FORWARD}, + { 0x1e, KEY_PREVIOUS}, + { 0x1b, KEY_STOP}, + { 0x1f, KEY_NEXT}, + { 0x13, KEY_CAMERA}, +}; + +static struct rc_keymap evga_indtube_map = { + .map = { + .scan = evga_indtube, + .size = ARRAY_SIZE(evga_indtube), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_EVGA_INDTUBE, + } +}; + +static int __init init_rc_map_evga_indtube(void) +{ + return ir_register_map(&evga_indtube_map); +} + +static void __exit exit_rc_map_evga_indtube(void) +{ + ir_unregister_map(&evga_indtube_map); +} + +module_init(init_rc_map_evga_indtube) +module_exit(exit_rc_map_evga_indtube) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-eztv.c b/drivers/media/rc/keymaps/rc-eztv.c new file mode 100644 index 0000000..660907a --- /dev/null +++ b/drivers/media/rc/keymaps/rc-eztv.c @@ -0,0 +1,96 @@ +/* eztv.h - Keytable for eztv Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Alfons Geser + * updates from Job D. R. Borges */ + +static struct ir_scancode eztv[] = { + { 0x12, KEY_POWER }, + { 0x01, KEY_TV }, /* DVR */ + { 0x15, KEY_DVD }, /* DVD */ + { 0x17, KEY_AUDIO }, /* music */ + /* DVR mode / DVD mode / music mode */ + + { 0x1b, KEY_MUTE }, /* mute */ + { 0x02, KEY_LANGUAGE }, /* MTS/SAP / audio / autoseek */ + { 0x1e, KEY_SUBTITLE }, /* closed captioning / subtitle / seek */ + { 0x16, KEY_ZOOM }, /* full screen */ + { 0x1c, KEY_VIDEO }, /* video source / eject / delall */ + { 0x1d, KEY_RESTART }, /* playback / angle / del */ + { 0x2f, KEY_SEARCH }, /* scan / menu / playlist */ + { 0x30, KEY_CHANNEL }, /* CH surfing / bookmark / memo */ + + { 0x31, KEY_HELP }, /* help */ + { 0x32, KEY_MODE }, /* num/memo */ + { 0x33, KEY_ESC }, /* cancel */ + + { 0x0c, KEY_UP }, /* up */ + { 0x10, KEY_DOWN }, /* down */ + { 0x08, KEY_LEFT }, /* left */ + { 0x04, KEY_RIGHT }, /* right */ + { 0x03, KEY_SELECT }, /* select */ + + { 0x1f, KEY_REWIND }, /* rewind */ + { 0x20, KEY_PLAYPAUSE },/* play/pause */ + { 0x29, KEY_FORWARD }, /* forward */ + { 0x14, KEY_AGAIN }, /* repeat */ + { 0x2b, KEY_RECORD }, /* recording */ + { 0x2c, KEY_STOP }, /* stop */ + { 0x2d, KEY_PLAY }, /* play */ + { 0x2e, KEY_CAMERA }, /* snapshot / shuffle */ + + { 0x00, KEY_0 }, + { 0x05, KEY_1 }, + { 0x06, KEY_2 }, + { 0x07, KEY_3 }, + { 0x09, KEY_4 }, + { 0x0a, KEY_5 }, + { 0x0b, KEY_6 }, + { 0x0d, KEY_7 }, + { 0x0e, KEY_8 }, + { 0x0f, KEY_9 }, + + { 0x2a, KEY_VOLUMEUP }, + { 0x11, KEY_VOLUMEDOWN }, + { 0x18, KEY_CHANNELUP },/* CH.tracking up */ + { 0x19, KEY_CHANNELDOWN },/* CH.tracking down */ + + { 0x13, KEY_ENTER }, /* enter */ + { 0x21, KEY_DOT }, /* . (decimal dot) */ +}; + +static struct rc_keymap eztv_map = { + .map = { + .scan = eztv, + .size = ARRAY_SIZE(eztv), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_EZTV, + } +}; + +static int __init init_rc_map_eztv(void) +{ + return ir_register_map(&eztv_map); +} + +static void __exit exit_rc_map_eztv(void) +{ + ir_unregister_map(&eztv_map); +} + +module_init(init_rc_map_eztv) +module_exit(exit_rc_map_eztv) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-flydvb.c b/drivers/media/rc/keymaps/rc-flydvb.c new file mode 100644 index 0000000..a173c81 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-flydvb.c @@ -0,0 +1,77 @@ +/* flydvb.h - Keytable for flydvb Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode flydvb[] = { + { 0x01, KEY_ZOOM }, /* Full Screen */ + { 0x00, KEY_POWER }, /* Power */ + + { 0x03, KEY_1 }, + { 0x04, KEY_2 }, + { 0x05, KEY_3 }, + { 0x07, KEY_4 }, + { 0x08, KEY_5 }, + { 0x09, KEY_6 }, + { 0x0b, KEY_7 }, + { 0x0c, KEY_8 }, + { 0x0d, KEY_9 }, + { 0x06, KEY_AGAIN }, /* Recall */ + { 0x0f, KEY_0 }, + { 0x10, KEY_MUTE }, /* Mute */ + { 0x02, KEY_RADIO }, /* TV/Radio */ + { 0x1b, KEY_LANGUAGE }, /* SAP (Second Audio Program) */ + + { 0x14, KEY_VOLUMEUP }, /* VOL+ */ + { 0x17, KEY_VOLUMEDOWN }, /* VOL- */ + { 0x12, KEY_CHANNELUP }, /* CH+ */ + { 0x13, KEY_CHANNELDOWN }, /* CH- */ + { 0x1d, KEY_ENTER }, /* Enter */ + + { 0x1a, KEY_MODE }, /* PIP */ + { 0x18, KEY_TUNER }, /* Source */ + + { 0x1e, KEY_RECORD }, /* Record/Pause */ + { 0x15, KEY_ANGLE }, /* Swap (no label on key) */ + { 0x1c, KEY_PAUSE }, /* Timeshift/Pause */ + { 0x19, KEY_BACK }, /* Rewind << */ + { 0x0a, KEY_PLAYPAUSE }, /* Play/Pause */ + { 0x1f, KEY_FORWARD }, /* Forward >> */ + { 0x16, KEY_PREVIOUS }, /* Back |<< */ + { 0x11, KEY_STOP }, /* Stop */ + { 0x0e, KEY_NEXT }, /* End >>| */ +}; + +static struct rc_keymap flydvb_map = { + .map = { + .scan = flydvb, + .size = ARRAY_SIZE(flydvb), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_FLYDVB, + } +}; + +static int __init init_rc_map_flydvb(void) +{ + return ir_register_map(&flydvb_map); +} + +static void __exit exit_rc_map_flydvb(void) +{ + ir_unregister_map(&flydvb_map); +} + +module_init(init_rc_map_flydvb) +module_exit(exit_rc_map_flydvb) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-flyvideo.c b/drivers/media/rc/keymaps/rc-flyvideo.c new file mode 100644 index 0000000..9c73043 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-flyvideo.c @@ -0,0 +1,70 @@ +/* flyvideo.h - Keytable for flyvideo Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode flyvideo[] = { + { 0x0f, KEY_0 }, + { 0x03, KEY_1 }, + { 0x04, KEY_2 }, + { 0x05, KEY_3 }, + { 0x07, KEY_4 }, + { 0x08, KEY_5 }, + { 0x09, KEY_6 }, + { 0x0b, KEY_7 }, + { 0x0c, KEY_8 }, + { 0x0d, KEY_9 }, + + { 0x0e, KEY_MODE }, /* Air/Cable */ + { 0x11, KEY_VIDEO }, /* Video */ + { 0x15, KEY_AUDIO }, /* Audio */ + { 0x00, KEY_POWER }, /* Power */ + { 0x18, KEY_TUNER }, /* AV Source */ + { 0x02, KEY_ZOOM }, /* Fullscreen */ + { 0x1a, KEY_LANGUAGE }, /* Stereo */ + { 0x1b, KEY_MUTE }, /* Mute */ + { 0x14, KEY_VOLUMEUP }, /* Volume + */ + { 0x17, KEY_VOLUMEDOWN },/* Volume - */ + { 0x12, KEY_CHANNELUP },/* Channel + */ + { 0x13, KEY_CHANNELDOWN },/* Channel - */ + { 0x06, KEY_AGAIN }, /* Recall */ + { 0x10, KEY_ENTER }, /* Enter */ + + { 0x19, KEY_BACK }, /* Rewind ( <<< ) */ + { 0x1f, KEY_FORWARD }, /* Forward ( >>> ) */ + { 0x0a, KEY_ANGLE }, /* no label, may be used as the PAUSE button */ +}; + +static struct rc_keymap flyvideo_map = { + .map = { + .scan = flyvideo, + .size = ARRAY_SIZE(flyvideo), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_FLYVIDEO, + } +}; + +static int __init init_rc_map_flyvideo(void) +{ + return ir_register_map(&flyvideo_map); +} + +static void __exit exit_rc_map_flyvideo(void) +{ + ir_unregister_map(&flyvideo_map); +} + +module_init(init_rc_map_flyvideo) +module_exit(exit_rc_map_flyvideo) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c b/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c new file mode 100644 index 0000000..cdb1038 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c @@ -0,0 +1,98 @@ +/* fusionhdtv-mce.h - Keytable for fusionhdtv_mce Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* DViCO FUSION HDTV MCE remote */ + +static struct ir_scancode fusionhdtv_mce[] = { + + { 0x0b, KEY_1 }, + { 0x17, KEY_2 }, + { 0x1b, KEY_3 }, + { 0x07, KEY_4 }, + { 0x50, KEY_5 }, + { 0x54, KEY_6 }, + { 0x48, KEY_7 }, + { 0x4c, KEY_8 }, + { 0x58, KEY_9 }, + { 0x03, KEY_0 }, + + { 0x5e, KEY_OK }, + { 0x51, KEY_UP }, + { 0x53, KEY_DOWN }, + { 0x5b, KEY_LEFT }, + { 0x5f, KEY_RIGHT }, + + { 0x02, KEY_TV }, /* Labeled DTV on remote */ + { 0x0e, KEY_MP3 }, + { 0x1a, KEY_DVD }, + { 0x1e, KEY_FAVORITES }, /* Labeled CPF on remote */ + { 0x16, KEY_SETUP }, + { 0x46, KEY_POWER2 }, /* TV On/Off button on remote */ + { 0x0a, KEY_EPG }, /* Labeled Guide on remote */ + + { 0x49, KEY_BACK }, + { 0x59, KEY_INFO }, /* Labeled MORE on remote */ + { 0x4d, KEY_MENU }, /* Labeled DVDMENU on remote */ + { 0x55, KEY_CYCLEWINDOWS }, /* Labeled ALT-TAB on remote */ + + { 0x0f, KEY_PREVIOUSSONG }, /* Labeled |<< REPLAY on remote */ + { 0x12, KEY_NEXTSONG }, /* Labeled >>| SKIP on remote */ + { 0x42, KEY_ENTER }, /* Labeled START with a green + MS windows logo on remote */ + + { 0x15, KEY_VOLUMEUP }, + { 0x05, KEY_VOLUMEDOWN }, + { 0x11, KEY_CHANNELUP }, + { 0x09, KEY_CHANNELDOWN }, + + { 0x52, KEY_CAMERA }, + { 0x5a, KEY_TUNER }, + { 0x19, KEY_OPEN }, + + { 0x13, KEY_MODE }, /* 4:3 16:9 select */ + { 0x1f, KEY_ZOOM }, + + { 0x43, KEY_REWIND }, + { 0x47, KEY_PLAYPAUSE }, + { 0x4f, KEY_FASTFORWARD }, + { 0x57, KEY_MUTE }, + { 0x0d, KEY_STOP }, + { 0x01, KEY_RECORD }, + { 0x4e, KEY_POWER }, +}; + +static struct rc_keymap fusionhdtv_mce_map = { + .map = { + .scan = fusionhdtv_mce, + .size = ARRAY_SIZE(fusionhdtv_mce), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_FUSIONHDTV_MCE, + } +}; + +static int __init init_rc_map_fusionhdtv_mce(void) +{ + return ir_register_map(&fusionhdtv_mce_map); +} + +static void __exit exit_rc_map_fusionhdtv_mce(void) +{ + ir_unregister_map(&fusionhdtv_mce_map); +} + +module_init(init_rc_map_fusionhdtv_mce) +module_exit(exit_rc_map_fusionhdtv_mce) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-gadmei-rm008z.c b/drivers/media/rc/keymaps/rc-gadmei-rm008z.c new file mode 100644 index 0000000..c16c0d1 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-gadmei-rm008z.c @@ -0,0 +1,81 @@ +/* gadmei-rm008z.h - Keytable for gadmei_rm008z Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* GADMEI UTV330+ RM008Z remote + Shine Liu + */ + +static struct ir_scancode gadmei_rm008z[] = { + { 0x14, KEY_POWER2}, /* POWER OFF */ + { 0x0c, KEY_MUTE}, /* MUTE */ + + { 0x18, KEY_TV}, /* TV */ + { 0x0e, KEY_VIDEO}, /* AV */ + { 0x0b, KEY_AUDIO}, /* SV */ + { 0x0f, KEY_RADIO}, /* FM */ + + { 0x00, KEY_1}, + { 0x01, KEY_2}, + { 0x02, KEY_3}, + { 0x03, KEY_4}, + { 0x04, KEY_5}, + { 0x05, KEY_6}, + { 0x06, KEY_7}, + { 0x07, KEY_8}, + { 0x08, KEY_9}, + { 0x09, KEY_0}, + { 0x0a, KEY_INFO}, /* OSD */ + { 0x1c, KEY_BACKSPACE}, /* LAST */ + + { 0x0d, KEY_PLAY}, /* PLAY */ + { 0x1e, KEY_CAMERA}, /* SNAPSHOT */ + { 0x1a, KEY_RECORD}, /* RECORD */ + { 0x17, KEY_STOP}, /* STOP */ + + { 0x1f, KEY_UP}, /* UP */ + { 0x44, KEY_DOWN}, /* DOWN */ + { 0x46, KEY_TAB}, /* BACK */ + { 0x4a, KEY_ZOOM}, /* FULLSECREEN */ + + { 0x10, KEY_VOLUMEUP}, /* VOLUMEUP */ + { 0x11, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */ + { 0x12, KEY_CHANNELUP}, /* CHANNELUP */ + { 0x13, KEY_CHANNELDOWN}, /* CHANNELDOWN */ + { 0x15, KEY_ENTER}, /* OK */ +}; + +static struct rc_keymap gadmei_rm008z_map = { + .map = { + .scan = gadmei_rm008z, + .size = ARRAY_SIZE(gadmei_rm008z), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_GADMEI_RM008Z, + } +}; + +static int __init init_rc_map_gadmei_rm008z(void) +{ + return ir_register_map(&gadmei_rm008z_map); +} + +static void __exit exit_rc_map_gadmei_rm008z(void) +{ + ir_unregister_map(&gadmei_rm008z_map); +} + +module_init(init_rc_map_gadmei_rm008z) +module_exit(exit_rc_map_gadmei_rm008z) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c b/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c new file mode 100644 index 0000000..89f8e38 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c @@ -0,0 +1,84 @@ +/* genius-tvgo-a11mce.h - Keytable for genius_tvgo_a11mce Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * Remote control for the Genius TVGO A11MCE + * Adrian Pardini + */ + +static struct ir_scancode genius_tvgo_a11mce[] = { + /* Keys 0 to 9 */ + { 0x48, KEY_0 }, + { 0x09, KEY_1 }, + { 0x1d, KEY_2 }, + { 0x1f, KEY_3 }, + { 0x19, KEY_4 }, + { 0x1b, KEY_5 }, + { 0x11, KEY_6 }, + { 0x17, KEY_7 }, + { 0x12, KEY_8 }, + { 0x16, KEY_9 }, + + { 0x54, KEY_RECORD }, /* recording */ + { 0x06, KEY_MUTE }, /* mute */ + { 0x10, KEY_POWER }, + { 0x40, KEY_LAST }, /* recall */ + { 0x4c, KEY_CHANNELUP }, /* channel / program + */ + { 0x00, KEY_CHANNELDOWN }, /* channel / program - */ + { 0x0d, KEY_VOLUMEUP }, + { 0x15, KEY_VOLUMEDOWN }, + { 0x4d, KEY_OK }, /* also labeled as Pause */ + { 0x1c, KEY_ZOOM }, /* full screen and Stop*/ + { 0x02, KEY_MODE }, /* AV Source or Rewind*/ + { 0x04, KEY_LIST }, /* -/-- */ + /* small arrows above numbers */ + { 0x1a, KEY_NEXT }, /* also Fast Forward */ + { 0x0e, KEY_PREVIOUS }, /* also Rewind */ + /* these are in a rather non standard layout and have + an alternate name written */ + { 0x1e, KEY_UP }, /* Video Setting */ + { 0x0a, KEY_DOWN }, /* Video Default */ + { 0x05, KEY_CAMERA }, /* Snapshot */ + { 0x0c, KEY_RIGHT }, /* Hide Panel */ + /* Four buttons without label */ + { 0x49, KEY_RED }, + { 0x0b, KEY_GREEN }, + { 0x13, KEY_YELLOW }, + { 0x50, KEY_BLUE }, +}; + +static struct rc_keymap genius_tvgo_a11mce_map = { + .map = { + .scan = genius_tvgo_a11mce, + .size = ARRAY_SIZE(genius_tvgo_a11mce), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_GENIUS_TVGO_A11MCE, + } +}; + +static int __init init_rc_map_genius_tvgo_a11mce(void) +{ + return ir_register_map(&genius_tvgo_a11mce_map); +} + +static void __exit exit_rc_map_genius_tvgo_a11mce(void) +{ + ir_unregister_map(&genius_tvgo_a11mce_map); +} + +module_init(init_rc_map_genius_tvgo_a11mce) +module_exit(exit_rc_map_genius_tvgo_a11mce) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-gotview7135.c b/drivers/media/rc/keymaps/rc-gotview7135.c new file mode 100644 index 0000000..52f025b --- /dev/null +++ b/drivers/media/rc/keymaps/rc-gotview7135.c @@ -0,0 +1,79 @@ +/* gotview7135.h - Keytable for gotview7135 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Mike Baikov */ + +static struct ir_scancode gotview7135[] = { + + { 0x11, KEY_POWER }, + { 0x35, KEY_TV }, + { 0x1b, KEY_0 }, + { 0x29, KEY_1 }, + { 0x19, KEY_2 }, + { 0x39, KEY_3 }, + { 0x1f, KEY_4 }, + { 0x2c, KEY_5 }, + { 0x21, KEY_6 }, + { 0x24, KEY_7 }, + { 0x18, KEY_8 }, + { 0x2b, KEY_9 }, + { 0x3b, KEY_AGAIN }, /* LOOP */ + { 0x06, KEY_AUDIO }, + { 0x31, KEY_PRINT }, /* PREVIEW */ + { 0x3e, KEY_VIDEO }, + { 0x10, KEY_CHANNELUP }, + { 0x20, KEY_CHANNELDOWN }, + { 0x0c, KEY_VOLUMEDOWN }, + { 0x28, KEY_VOLUMEUP }, + { 0x08, KEY_MUTE }, + { 0x26, KEY_SEARCH }, /* SCAN */ + { 0x3f, KEY_CAMERA }, /* SNAPSHOT */ + { 0x12, KEY_RECORD }, + { 0x32, KEY_STOP }, + { 0x3c, KEY_PLAY }, + { 0x1d, KEY_REWIND }, + { 0x2d, KEY_PAUSE }, + { 0x0d, KEY_FORWARD }, + { 0x05, KEY_ZOOM }, /*FULL*/ + + { 0x2a, KEY_F21 }, /* LIVE TIMESHIFT */ + { 0x0e, KEY_F22 }, /* MIN TIMESHIFT */ + { 0x1e, KEY_TIME }, /* TIMESHIFT */ + { 0x38, KEY_F24 }, /* NORMAL TIMESHIFT */ +}; + +static struct rc_keymap gotview7135_map = { + .map = { + .scan = gotview7135, + .size = ARRAY_SIZE(gotview7135), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_GOTVIEW7135, + } +}; + +static int __init init_rc_map_gotview7135(void) +{ + return ir_register_map(&gotview7135_map); +} + +static void __exit exit_rc_map_gotview7135(void) +{ + ir_unregister_map(&gotview7135_map); +} + +module_init(init_rc_map_gotview7135) +module_exit(exit_rc_map_gotview7135) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-hauppauge-new.c b/drivers/media/rc/keymaps/rc-hauppauge-new.c new file mode 100644 index 0000000..c6f8cd7 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-hauppauge-new.c @@ -0,0 +1,100 @@ +/* hauppauge-new.h - Keytable for hauppauge_new Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Hauppauge: the newer, gray remotes (seems there are multiple + * slightly different versions), shipped with cx88+ivtv cards. + * almost rc5 coding, but some non-standard keys */ + +static struct ir_scancode hauppauge_new[] = { + /* Keys 0 to 9 */ + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x0a, KEY_TEXT }, /* keypad asterisk as well */ + { 0x0b, KEY_RED }, /* red button */ + { 0x0c, KEY_RADIO }, + { 0x0d, KEY_MENU }, + { 0x0e, KEY_SUBTITLE }, /* also the # key */ + { 0x0f, KEY_MUTE }, + { 0x10, KEY_VOLUMEUP }, + { 0x11, KEY_VOLUMEDOWN }, + { 0x12, KEY_PREVIOUS }, /* previous channel */ + { 0x14, KEY_UP }, + { 0x15, KEY_DOWN }, + { 0x16, KEY_LEFT }, + { 0x17, KEY_RIGHT }, + { 0x18, KEY_VIDEO }, /* Videos */ + { 0x19, KEY_AUDIO }, /* Music */ + /* 0x1a: Pictures - presume this means + "Multimedia Home Platform" - + no "PICTURES" key in input.h + */ + { 0x1a, KEY_MHP }, + + { 0x1b, KEY_EPG }, /* Guide */ + { 0x1c, KEY_TV }, + { 0x1e, KEY_NEXTSONG }, /* skip >| */ + { 0x1f, KEY_EXIT }, /* back/exit */ + { 0x20, KEY_CHANNELUP }, /* channel / program + */ + { 0x21, KEY_CHANNELDOWN }, /* channel / program - */ + { 0x22, KEY_CHANNEL }, /* source (old black remote) */ + { 0x24, KEY_PREVIOUSSONG }, /* replay |< */ + { 0x25, KEY_ENTER }, /* OK */ + { 0x26, KEY_SLEEP }, /* minimize (old black remote) */ + { 0x29, KEY_BLUE }, /* blue key */ + { 0x2e, KEY_GREEN }, /* green button */ + { 0x30, KEY_PAUSE }, /* pause */ + { 0x32, KEY_REWIND }, /* backward << */ + { 0x34, KEY_FASTFORWARD }, /* forward >> */ + { 0x35, KEY_PLAY }, + { 0x36, KEY_STOP }, + { 0x37, KEY_RECORD }, /* recording */ + { 0x38, KEY_YELLOW }, /* yellow key */ + { 0x3b, KEY_SELECT }, /* top right button */ + { 0x3c, KEY_ZOOM }, /* full */ + { 0x3d, KEY_POWER }, /* system power (green button) */ +}; + +static struct rc_keymap hauppauge_new_map = { + .map = { + .scan = hauppauge_new, + .size = ARRAY_SIZE(hauppauge_new), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_HAUPPAUGE_NEW, + } +}; + +static int __init init_rc_map_hauppauge_new(void) +{ + return ir_register_map(&hauppauge_new_map); +} + +static void __exit exit_rc_map_hauppauge_new(void) +{ + ir_unregister_map(&hauppauge_new_map); +} + +module_init(init_rc_map_hauppauge_new) +module_exit(exit_rc_map_hauppauge_new) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-imon-mce.c b/drivers/media/rc/keymaps/rc-imon-mce.c new file mode 100644 index 0000000..e49f350 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-imon-mce.c @@ -0,0 +1,142 @@ +/* rc5-imon-mce.c - Keytable for Windows Media Center RC-6 remotes for use + * with the SoundGraph iMON/Antec Veris hardware IR decoder + * + * Copyright (c) 2010 by Jarod Wilson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* mce-mode imon mce remote key table */ +static struct ir_scancode imon_mce[] = { + /* keys sorted mostly by frequency of use to optimize lookups */ + { 0x800ff415, KEY_REWIND }, + { 0x800ff414, KEY_FASTFORWARD }, + { 0x800ff41b, KEY_PREVIOUS }, + { 0x800ff41a, KEY_NEXT }, + + { 0x800ff416, KEY_PLAY }, + { 0x800ff418, KEY_PAUSE }, + { 0x800ff419, KEY_STOP }, + { 0x800ff417, KEY_RECORD }, + + { 0x02000052, KEY_UP }, + { 0x02000051, KEY_DOWN }, + { 0x02000050, KEY_LEFT }, + { 0x0200004f, KEY_RIGHT }, + + { 0x800ff41e, KEY_UP }, + { 0x800ff41f, KEY_DOWN }, + { 0x800ff420, KEY_LEFT }, + { 0x800ff421, KEY_RIGHT }, + + /* 0x800ff40b also KEY_NUMERIC_POUND on some receivers */ + { 0x800ff40b, KEY_ENTER }, + { 0x02000028, KEY_ENTER }, +/* the OK and Enter buttons decode to the same value on some remotes + { 0x02000028, KEY_OK }, */ + { 0x800ff422, KEY_OK }, + { 0x0200002a, KEY_EXIT }, + { 0x800ff423, KEY_EXIT }, + { 0x02000029, KEY_DELETE }, + /* 0x800ff40a also KEY_NUMERIC_STAR on some receivers */ + { 0x800ff40a, KEY_DELETE }, + + { 0x800ff40e, KEY_MUTE }, + { 0x800ff410, KEY_VOLUMEUP }, + { 0x800ff411, KEY_VOLUMEDOWN }, + { 0x800ff412, KEY_CHANNELUP }, + { 0x800ff413, KEY_CHANNELDOWN }, + + { 0x0200001e, KEY_NUMERIC_1 }, + { 0x0200001f, KEY_NUMERIC_2 }, + { 0x02000020, KEY_NUMERIC_3 }, + { 0x02000021, KEY_NUMERIC_4 }, + { 0x02000022, KEY_NUMERIC_5 }, + { 0x02000023, KEY_NUMERIC_6 }, + { 0x02000024, KEY_NUMERIC_7 }, + { 0x02000025, KEY_NUMERIC_8 }, + { 0x02000026, KEY_NUMERIC_9 }, + { 0x02000027, KEY_NUMERIC_0 }, + + { 0x800ff401, KEY_NUMERIC_1 }, + { 0x800ff402, KEY_NUMERIC_2 }, + { 0x800ff403, KEY_NUMERIC_3 }, + { 0x800ff404, KEY_NUMERIC_4 }, + { 0x800ff405, KEY_NUMERIC_5 }, + { 0x800ff406, KEY_NUMERIC_6 }, + { 0x800ff407, KEY_NUMERIC_7 }, + { 0x800ff408, KEY_NUMERIC_8 }, + { 0x800ff409, KEY_NUMERIC_9 }, + { 0x800ff400, KEY_NUMERIC_0 }, + + { 0x02200025, KEY_NUMERIC_STAR }, + { 0x02200020, KEY_NUMERIC_POUND }, + /* 0x800ff41d also KEY_BLUE on some receivers */ + { 0x800ff41d, KEY_NUMERIC_STAR }, + /* 0x800ff41c also KEY_PREVIOUS on some receivers */ + { 0x800ff41c, KEY_NUMERIC_POUND }, + + { 0x800ff446, KEY_TV }, + { 0x800ff447, KEY_AUDIO }, /* My Music */ + { 0x800ff448, KEY_PVR }, /* RecordedTV */ + { 0x800ff449, KEY_CAMERA }, + { 0x800ff44a, KEY_VIDEO }, + /* 0x800ff424 also KEY_MENU on some receivers */ + { 0x800ff424, KEY_DVD }, + /* 0x800ff425 also KEY_GREEN on some receivers */ + { 0x800ff425, KEY_TUNER }, /* LiveTV */ + { 0x800ff450, KEY_RADIO }, + + { 0x800ff44c, KEY_LANGUAGE }, + { 0x800ff427, KEY_ZOOM }, /* Aspect */ + + { 0x800ff45b, KEY_RED }, + { 0x800ff45c, KEY_GREEN }, + { 0x800ff45d, KEY_YELLOW }, + { 0x800ff45e, KEY_BLUE }, + + { 0x800ff466, KEY_RED }, + /* { 0x800ff425, KEY_GREEN }, */ + { 0x800ff468, KEY_YELLOW }, + /* { 0x800ff41d, KEY_BLUE }, */ + + { 0x800ff40f, KEY_INFO }, + { 0x800ff426, KEY_EPG }, /* Guide */ + { 0x800ff45a, KEY_SUBTITLE }, /* Caption/Teletext */ + { 0x800ff44d, KEY_TITLE }, + + { 0x800ff40c, KEY_POWER }, + { 0x800ff40d, KEY_PROG1 }, /* Windows MCE button */ + +}; + +static struct rc_keymap imon_mce_map = { + .map = { + .scan = imon_mce, + .size = ARRAY_SIZE(imon_mce), + /* its RC6, but w/a hardware decoder */ + .ir_type = IR_TYPE_RC6, + .name = RC_MAP_IMON_MCE, + } +}; + +static int __init init_rc_map_imon_mce(void) +{ + return ir_register_map(&imon_mce_map); +} + +static void __exit exit_rc_map_imon_mce(void) +{ + ir_unregister_map(&imon_mce_map); +} + +module_init(init_rc_map_imon_mce) +module_exit(exit_rc_map_imon_mce) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jarod Wilson "); diff --git a/drivers/media/rc/keymaps/rc-imon-pad.c b/drivers/media/rc/keymaps/rc-imon-pad.c new file mode 100644 index 0000000..bc4db72 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-imon-pad.c @@ -0,0 +1,156 @@ +/* rc5-imon-pad.c - Keytable for SoundGraph iMON PAD and Antec Veris + * RM-200 Remote Control + * + * Copyright (c) 2010 by Jarod Wilson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * standard imon remote key table, which isn't really entirely + * "standard", as different receivers decode the same key on the + * same remote to different hex codes, and the silkscreened names + * vary a bit between the SoundGraph and Antec remotes... ugh. + */ +static struct ir_scancode imon_pad[] = { + /* keys sorted mostly by frequency of use to optimize lookups */ + { 0x2a8195b7, KEY_REWIND }, + { 0x298315b7, KEY_REWIND }, + { 0x2b8115b7, KEY_FASTFORWARD }, + { 0x2b8315b7, KEY_FASTFORWARD }, + { 0x2b9115b7, KEY_PREVIOUS }, + { 0x298195b7, KEY_NEXT }, + + { 0x2a8115b7, KEY_PLAY }, + { 0x2a8315b7, KEY_PLAY }, + { 0x2a9115b7, KEY_PAUSE }, + { 0x2b9715b7, KEY_STOP }, + { 0x298115b7, KEY_RECORD }, + + { 0x01008000, KEY_UP }, + { 0x01007f00, KEY_DOWN }, + { 0x01000080, KEY_LEFT }, + { 0x0100007f, KEY_RIGHT }, + + { 0x2aa515b7, KEY_UP }, + { 0x289515b7, KEY_DOWN }, + { 0x29a515b7, KEY_LEFT }, + { 0x2ba515b7, KEY_RIGHT }, + + { 0x0200002c, KEY_SPACE }, /* Select/Space */ + { 0x2a9315b7, KEY_SPACE }, /* Select/Space */ + { 0x02000028, KEY_ENTER }, + { 0x28a195b7, KEY_ENTER }, + { 0x288195b7, KEY_EXIT }, + { 0x02000029, KEY_ESC }, + { 0x2bb715b7, KEY_ESC }, + { 0x0200002a, KEY_BACKSPACE }, + { 0x28a115b7, KEY_BACKSPACE }, + + { 0x2b9595b7, KEY_MUTE }, + { 0x28a395b7, KEY_VOLUMEUP }, + { 0x28a595b7, KEY_VOLUMEDOWN }, + { 0x289395b7, KEY_CHANNELUP }, + { 0x288795b7, KEY_CHANNELDOWN }, + + { 0x0200001e, KEY_NUMERIC_1 }, + { 0x0200001f, KEY_NUMERIC_2 }, + { 0x02000020, KEY_NUMERIC_3 }, + { 0x02000021, KEY_NUMERIC_4 }, + { 0x02000022, KEY_NUMERIC_5 }, + { 0x02000023, KEY_NUMERIC_6 }, + { 0x02000024, KEY_NUMERIC_7 }, + { 0x02000025, KEY_NUMERIC_8 }, + { 0x02000026, KEY_NUMERIC_9 }, + { 0x02000027, KEY_NUMERIC_0 }, + + { 0x28b595b7, KEY_NUMERIC_1 }, + { 0x2bb195b7, KEY_NUMERIC_2 }, + { 0x28b195b7, KEY_NUMERIC_3 }, + { 0x2a8595b7, KEY_NUMERIC_4 }, + { 0x299595b7, KEY_NUMERIC_5 }, + { 0x2aa595b7, KEY_NUMERIC_6 }, + { 0x2b9395b7, KEY_NUMERIC_7 }, + { 0x2a8515b7, KEY_NUMERIC_8 }, + { 0x2aa115b7, KEY_NUMERIC_9 }, + { 0x2ba595b7, KEY_NUMERIC_0 }, + + { 0x02200025, KEY_NUMERIC_STAR }, + { 0x28b515b7, KEY_NUMERIC_STAR }, + { 0x02200020, KEY_NUMERIC_POUND }, + { 0x29a115b7, KEY_NUMERIC_POUND }, + + { 0x2b8515b7, KEY_VIDEO }, + { 0x299195b7, KEY_AUDIO }, + { 0x2ba115b7, KEY_CAMERA }, + { 0x28a515b7, KEY_TV }, + { 0x29a395b7, KEY_DVD }, + { 0x29a295b7, KEY_DVD }, + + /* the Menu key between DVD and Subtitle on the RM-200... */ + { 0x2ba385b7, KEY_MENU }, + { 0x2ba395b7, KEY_MENU }, + + { 0x288515b7, KEY_BOOKMARKS }, + { 0x2ab715b7, KEY_MEDIA }, /* Thumbnail */ + { 0x298595b7, KEY_SUBTITLE }, + { 0x2b8595b7, KEY_LANGUAGE }, + + { 0x29a595b7, KEY_ZOOM }, + { 0x2aa395b7, KEY_SCREEN }, /* FullScreen */ + + { 0x299115b7, KEY_KEYBOARD }, + { 0x299135b7, KEY_KEYBOARD }, + + { 0x01010000, BTN_LEFT }, + { 0x01020000, BTN_RIGHT }, + { 0x01010080, BTN_LEFT }, + { 0x01020080, BTN_RIGHT }, + { 0x688301b7, BTN_LEFT }, + { 0x688481b7, BTN_RIGHT }, + + { 0x2a9395b7, KEY_CYCLEWINDOWS }, /* TaskSwitcher */ + { 0x2b8395b7, KEY_TIME }, /* Timer */ + + { 0x289115b7, KEY_POWER }, + { 0x29b195b7, KEY_EJECTCD }, /* the one next to play */ + { 0x299395b7, KEY_EJECTCLOSECD }, /* eject (by TaskSw) */ + + { 0x02800000, KEY_CONTEXT_MENU }, /* Left Menu */ + { 0x2b8195b7, KEY_CONTEXT_MENU }, /* Left Menu*/ + { 0x02000065, KEY_COMPOSE }, /* RightMenu */ + { 0x28b715b7, KEY_COMPOSE }, /* RightMenu */ + { 0x2ab195b7, KEY_PROG1 }, /* Go or MultiMon */ + { 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */ +}; + +static struct rc_keymap imon_pad_map = { + .map = { + .scan = imon_pad, + .size = ARRAY_SIZE(imon_pad), + /* actual protocol details unknown, hardware decoder */ + .ir_type = IR_TYPE_OTHER, + .name = RC_MAP_IMON_PAD, + } +}; + +static int __init init_rc_map_imon_pad(void) +{ + return ir_register_map(&imon_pad_map); +} + +static void __exit exit_rc_map_imon_pad(void) +{ + ir_unregister_map(&imon_pad_map); +} + +module_init(init_rc_map_imon_pad) +module_exit(exit_rc_map_imon_pad) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jarod Wilson "); diff --git a/drivers/media/rc/keymaps/rc-iodata-bctv7e.c b/drivers/media/rc/keymaps/rc-iodata-bctv7e.c new file mode 100644 index 0000000..ef66002 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-iodata-bctv7e.c @@ -0,0 +1,88 @@ +/* iodata-bctv7e.h - Keytable for iodata_bctv7e Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* IO-DATA BCTV7E Remote */ + +static struct ir_scancode iodata_bctv7e[] = { + { 0x40, KEY_TV }, + { 0x20, KEY_RADIO }, /* FM */ + { 0x60, KEY_EPG }, + { 0x00, KEY_POWER }, + + /* Keys 0 to 9 */ + { 0x44, KEY_0 }, /* 10 */ + { 0x50, KEY_1 }, + { 0x30, KEY_2 }, + { 0x70, KEY_3 }, + { 0x48, KEY_4 }, + { 0x28, KEY_5 }, + { 0x68, KEY_6 }, + { 0x58, KEY_7 }, + { 0x38, KEY_8 }, + { 0x78, KEY_9 }, + + { 0x10, KEY_L }, /* Live */ + { 0x08, KEY_TIME }, /* Time Shift */ + + { 0x18, KEY_PLAYPAUSE }, /* Play */ + + { 0x24, KEY_ENTER }, /* 11 */ + { 0x64, KEY_ESC }, /* 12 */ + { 0x04, KEY_M }, /* Multi */ + + { 0x54, KEY_VIDEO }, + { 0x34, KEY_CHANNELUP }, + { 0x74, KEY_VOLUMEUP }, + { 0x14, KEY_MUTE }, + + { 0x4c, KEY_VCR }, /* SVIDEO */ + { 0x2c, KEY_CHANNELDOWN }, + { 0x6c, KEY_VOLUMEDOWN }, + { 0x0c, KEY_ZOOM }, + + { 0x5c, KEY_PAUSE }, + { 0x3c, KEY_RED }, /* || (red) */ + { 0x7c, KEY_RECORD }, /* recording */ + { 0x1c, KEY_STOP }, + + { 0x41, KEY_REWIND }, /* backward << */ + { 0x21, KEY_PLAY }, + { 0x61, KEY_FASTFORWARD }, /* forward >> */ + { 0x01, KEY_NEXT }, /* skip >| */ +}; + +static struct rc_keymap iodata_bctv7e_map = { + .map = { + .scan = iodata_bctv7e, + .size = ARRAY_SIZE(iodata_bctv7e), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_IODATA_BCTV7E, + } +}; + +static int __init init_rc_map_iodata_bctv7e(void) +{ + return ir_register_map(&iodata_bctv7e_map); +} + +static void __exit exit_rc_map_iodata_bctv7e(void) +{ + ir_unregister_map(&iodata_bctv7e_map); +} + +module_init(init_rc_map_iodata_bctv7e) +module_exit(exit_rc_map_iodata_bctv7e) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-kaiomy.c b/drivers/media/rc/keymaps/rc-kaiomy.c new file mode 100644 index 0000000..4c7883b --- /dev/null +++ b/drivers/media/rc/keymaps/rc-kaiomy.c @@ -0,0 +1,87 @@ +/* kaiomy.h - Keytable for kaiomy Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Kaiomy TVnPC U2 + Mauro Carvalho Chehab + */ + +static struct ir_scancode kaiomy[] = { + { 0x43, KEY_POWER2}, + { 0x01, KEY_LIST}, + { 0x0b, KEY_ZOOM}, + { 0x03, KEY_POWER}, + + { 0x04, KEY_1}, + { 0x08, KEY_2}, + { 0x02, KEY_3}, + + { 0x0f, KEY_4}, + { 0x05, KEY_5}, + { 0x06, KEY_6}, + + { 0x0c, KEY_7}, + { 0x0d, KEY_8}, + { 0x0a, KEY_9}, + + { 0x11, KEY_0}, + + { 0x09, KEY_CHANNELUP}, + { 0x07, KEY_CHANNELDOWN}, + + { 0x0e, KEY_VOLUMEUP}, + { 0x13, KEY_VOLUMEDOWN}, + + { 0x10, KEY_HOME}, + { 0x12, KEY_ENTER}, + + { 0x14, KEY_RECORD}, + { 0x15, KEY_STOP}, + { 0x16, KEY_PLAY}, + { 0x17, KEY_MUTE}, + + { 0x18, KEY_UP}, + { 0x19, KEY_DOWN}, + { 0x1a, KEY_LEFT}, + { 0x1b, KEY_RIGHT}, + + { 0x1c, KEY_RED}, + { 0x1d, KEY_GREEN}, + { 0x1e, KEY_YELLOW}, + { 0x1f, KEY_BLUE}, +}; + +static struct rc_keymap kaiomy_map = { + .map = { + .scan = kaiomy, + .size = ARRAY_SIZE(kaiomy), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_KAIOMY, + } +}; + +static int __init init_rc_map_kaiomy(void) +{ + return ir_register_map(&kaiomy_map); +} + +static void __exit exit_rc_map_kaiomy(void) +{ + ir_unregister_map(&kaiomy_map); +} + +module_init(init_rc_map_kaiomy) +module_exit(exit_rc_map_kaiomy) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-kworld-315u.c b/drivers/media/rc/keymaps/rc-kworld-315u.c new file mode 100644 index 0000000..618c817 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-kworld-315u.c @@ -0,0 +1,83 @@ +/* kworld-315u.h - Keytable for kworld_315u Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Kworld 315U + */ + +static struct ir_scancode kworld_315u[] = { + { 0x6143, KEY_POWER }, + { 0x6101, KEY_TUNER }, /* source */ + { 0x610b, KEY_ZOOM }, + { 0x6103, KEY_POWER2 }, /* shutdown */ + + { 0x6104, KEY_1 }, + { 0x6108, KEY_2 }, + { 0x6102, KEY_3 }, + { 0x6109, KEY_CHANNELUP }, + + { 0x610f, KEY_4 }, + { 0x6105, KEY_5 }, + { 0x6106, KEY_6 }, + { 0x6107, KEY_CHANNELDOWN }, + + { 0x610c, KEY_7 }, + { 0x610d, KEY_8 }, + { 0x610a, KEY_9 }, + { 0x610e, KEY_VOLUMEUP }, + + { 0x6110, KEY_LAST }, + { 0x6111, KEY_0 }, + { 0x6112, KEY_ENTER }, + { 0x6113, KEY_VOLUMEDOWN }, + + { 0x6114, KEY_RECORD }, + { 0x6115, KEY_STOP }, + { 0x6116, KEY_PLAY }, + { 0x6117, KEY_MUTE }, + + { 0x6118, KEY_UP }, + { 0x6119, KEY_DOWN }, + { 0x611a, KEY_LEFT }, + { 0x611b, KEY_RIGHT }, + + { 0x611c, KEY_RED }, + { 0x611d, KEY_GREEN }, + { 0x611e, KEY_YELLOW }, + { 0x611f, KEY_BLUE }, +}; + +static struct rc_keymap kworld_315u_map = { + .map = { + .scan = kworld_315u, + .size = ARRAY_SIZE(kworld_315u), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_KWORLD_315U, + } +}; + +static int __init init_rc_map_kworld_315u(void) +{ + return ir_register_map(&kworld_315u_map); +} + +static void __exit exit_rc_map_kworld_315u(void) +{ + ir_unregister_map(&kworld_315u_map); +} + +module_init(init_rc_map_kworld_315u) +module_exit(exit_rc_map_kworld_315u) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c new file mode 100644 index 0000000..366732f --- /dev/null +++ b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c @@ -0,0 +1,99 @@ +/* kworld-plus-tv-analog.h - Keytable for kworld_plus_tv_analog Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Kworld Plus TV Analog Lite PCI IR + Mauro Carvalho Chehab + */ + +static struct ir_scancode kworld_plus_tv_analog[] = { + { 0x0c, KEY_PROG1 }, /* Kworld key */ + { 0x16, KEY_CLOSECD }, /* -> ) */ + { 0x1d, KEY_POWER2 }, + + { 0x00, KEY_1 }, + { 0x01, KEY_2 }, + { 0x02, KEY_3 }, /* Two keys have the same code: 3 and left */ + { 0x03, KEY_4 }, /* Two keys have the same code: 3 and right */ + { 0x04, KEY_5 }, + { 0x05, KEY_6 }, + { 0x06, KEY_7 }, + { 0x07, KEY_8 }, + { 0x08, KEY_9 }, + { 0x0a, KEY_0 }, + + { 0x09, KEY_AGAIN }, + { 0x14, KEY_MUTE }, + + { 0x20, KEY_UP }, + { 0x21, KEY_DOWN }, + { 0x0b, KEY_ENTER }, + + { 0x10, KEY_CHANNELUP }, + { 0x11, KEY_CHANNELDOWN }, + + /* Couldn't map key left/key right since those + conflict with '3' and '4' scancodes + I dunno what the original driver does + */ + + { 0x13, KEY_VOLUMEUP }, + { 0x12, KEY_VOLUMEDOWN }, + + /* The lower part of the IR + There are several duplicated keycodes there. + Most of them conflict with digits. + Add mappings just to the unused scancodes. + Somehow, the original driver has a way to know, + but this doesn't seem to be on some GPIO. + Also, it is not related to the time between keyup + and keydown. + */ + { 0x19, KEY_TIME}, /* Timeshift */ + { 0x1a, KEY_STOP}, + { 0x1b, KEY_RECORD}, + + { 0x22, KEY_TEXT}, + + { 0x15, KEY_AUDIO}, /* ((*)) */ + { 0x0f, KEY_ZOOM}, + { 0x1c, KEY_CAMERA}, /* snapshot */ + + { 0x18, KEY_RED}, /* B */ + { 0x23, KEY_GREEN}, /* C */ +}; + +static struct rc_keymap kworld_plus_tv_analog_map = { + .map = { + .scan = kworld_plus_tv_analog, + .size = ARRAY_SIZE(kworld_plus_tv_analog), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_KWORLD_PLUS_TV_ANALOG, + } +}; + +static int __init init_rc_map_kworld_plus_tv_analog(void) +{ + return ir_register_map(&kworld_plus_tv_analog_map); +} + +static void __exit exit_rc_map_kworld_plus_tv_analog(void) +{ + ir_unregister_map(&kworld_plus_tv_analog_map); +} + +module_init(init_rc_map_kworld_plus_tv_analog) +module_exit(exit_rc_map_kworld_plus_tv_analog) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c b/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c new file mode 100644 index 0000000..7521315 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c @@ -0,0 +1,99 @@ +/* + * LeadTek Y04G0051 remote controller keytable + * + * Copyright (C) 2010 Antti Palosaari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +static struct ir_scancode leadtek_y04g0051[] = { + { 0x0300, KEY_POWER2 }, + { 0x0303, KEY_SCREEN }, + { 0x0304, KEY_RIGHT }, + { 0x0305, KEY_1 }, + { 0x0306, KEY_2 }, + { 0x0307, KEY_3 }, + { 0x0308, KEY_LEFT }, + { 0x0309, KEY_4 }, + { 0x030a, KEY_5 }, + { 0x030b, KEY_6 }, + { 0x030c, KEY_UP }, + { 0x030d, KEY_7 }, + { 0x030e, KEY_8 }, + { 0x030f, KEY_9 }, + { 0x0310, KEY_DOWN }, + { 0x0311, KEY_AGAIN }, + { 0x0312, KEY_0 }, + { 0x0313, KEY_OK }, /* 1st ok */ + { 0x0314, KEY_MUTE }, + { 0x0316, KEY_OK }, /* 2nd ok */ + { 0x031e, KEY_VIDEO }, /* 2nd video */ + { 0x031b, KEY_AUDIO }, + { 0x031f, KEY_TEXT }, + { 0x0340, KEY_SLEEP }, + { 0x0341, KEY_DOT }, + { 0x0342, KEY_REWIND }, + { 0x0343, KEY_PLAY }, + { 0x0344, KEY_FASTFORWARD }, + { 0x0345, KEY_TIME }, + { 0x0346, KEY_STOP }, /* 2nd stop */ + { 0x0347, KEY_RECORD }, + { 0x0348, KEY_CAMERA }, + { 0x0349, KEY_ESC }, + { 0x034a, KEY_NEW }, + { 0x034b, KEY_RED }, + { 0x034c, KEY_GREEN }, + { 0x034d, KEY_YELLOW }, + { 0x034e, KEY_BLUE }, + { 0x034f, KEY_MENU }, + { 0x0350, KEY_STOP }, /* 1st stop */ + { 0x0351, KEY_CHANNEL }, + { 0x0352, KEY_VIDEO }, /* 1st video */ + { 0x0353, KEY_EPG }, + { 0x0354, KEY_PREVIOUS }, + { 0x0355, KEY_NEXT }, + { 0x0356, KEY_TV }, + { 0x035a, KEY_VOLUMEDOWN }, + { 0x035b, KEY_CHANNELUP }, + { 0x035e, KEY_VOLUMEUP }, + { 0x035f, KEY_CHANNELDOWN }, +}; + +static struct rc_keymap leadtek_y04g0051_map = { + .map = { + .scan = leadtek_y04g0051, + .size = ARRAY_SIZE(leadtek_y04g0051), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_LEADTEK_Y04G0051, + } +}; + +static int __init init_rc_map_leadtek_y04g0051(void) +{ + return ir_register_map(&leadtek_y04g0051_map); +} + +static void __exit exit_rc_map_leadtek_y04g0051(void) +{ + ir_unregister_map(&leadtek_y04g0051_map); +} + +module_init(init_rc_map_leadtek_y04g0051) +module_exit(exit_rc_map_leadtek_y04g0051) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/rc/keymaps/rc-lirc.c b/drivers/media/rc/keymaps/rc-lirc.c new file mode 100644 index 0000000..43fcf90 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-lirc.c @@ -0,0 +1,41 @@ +/* rc-lirc.c - Empty dummy keytable, for use when its preferred to pass + * all raw IR data to the lirc userspace decoder. + * + * Copyright (c) 2010 by Jarod Wilson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode lirc[] = { + { }, +}; + +static struct rc_keymap lirc_map = { + .map = { + .scan = lirc, + .size = ARRAY_SIZE(lirc), + .ir_type = IR_TYPE_LIRC, + .name = RC_MAP_LIRC, + } +}; + +static int __init init_rc_map_lirc(void) +{ + return ir_register_map(&lirc_map); +} + +static void __exit exit_rc_map_lirc(void) +{ + ir_unregister_map(&lirc_map); +} + +module_init(init_rc_map_lirc) +module_exit(exit_rc_map_lirc) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jarod Wilson "); diff --git a/drivers/media/rc/keymaps/rc-lme2510.c b/drivers/media/rc/keymaps/rc-lme2510.c new file mode 100644 index 0000000..40dcf0b --- /dev/null +++ b/drivers/media/rc/keymaps/rc-lme2510.c @@ -0,0 +1,68 @@ +/* LME2510 remote control + * + * + * Copyright (C) 2010 Malcolm Priestley (tvboxspy@gmail.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + + +static struct ir_scancode lme2510_rc[] = { + { 0xba45, KEY_0 }, + { 0xa05f, KEY_1 }, + { 0xaf50, KEY_2 }, + { 0xa25d, KEY_3 }, + { 0xbe41, KEY_4 }, + { 0xf50a, KEY_5 }, + { 0xbd42, KEY_6 }, + { 0xb847, KEY_7 }, + { 0xb649, KEY_8 }, + { 0xfa05, KEY_9 }, + { 0xbc43, KEY_POWER }, + { 0xb946, KEY_SUBTITLE }, + { 0xf906, KEY_PAUSE }, + { 0xfc03, KEY_MEDIA_REPEAT}, + { 0xfd02, KEY_PAUSE }, + { 0xa15e, KEY_VOLUMEUP }, + { 0xa35c, KEY_VOLUMEDOWN }, + { 0xf609, KEY_CHANNELUP }, + { 0xe51a, KEY_CHANNELDOWN }, + { 0xe11e, KEY_PLAY }, + { 0xe41b, KEY_ZOOM }, + { 0xa659, KEY_MUTE }, + { 0xa55a, KEY_TV }, + { 0xe718, KEY_RECORD }, + { 0xf807, KEY_EPG }, + { 0xfe01, KEY_STOP }, + +}; + +static struct rc_keymap lme2510_map = { + .map = { + .scan = lme2510_rc, + .size = ARRAY_SIZE(lme2510_rc), + .ir_type = IR_TYPE_UNKNOWN, + .name = RC_MAP_LME2510, + } +}; + +static int __init init_rc_lme2510_map(void) +{ + return ir_register_map(&lme2510_map); +} + +static void __exit exit_rc_lme2510_map(void) +{ + ir_unregister_map(&lme2510_map); +} + +module_init(init_rc_lme2510_map) +module_exit(exit_rc_lme2510_map) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com"); diff --git a/drivers/media/rc/keymaps/rc-manli.c b/drivers/media/rc/keymaps/rc-manli.c new file mode 100644 index 0000000..0f590b3 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-manli.c @@ -0,0 +1,134 @@ +/* manli.h - Keytable for manli Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Michael Tokarev + keytable is used by MANLI MTV00[0x0c] and BeholdTV 40[13] at + least, and probably other cards too. + The "ascii-art picture" below (in comments, first row + is the keycode in hex, and subsequent row(s) shows + the button labels (several variants when appropriate) + helps to descide which keycodes to assign to the buttons. + */ + +static struct ir_scancode manli[] = { + + /* 0x1c 0x12 * + * FUNCTION POWER * + * FM (|) * + * */ + { 0x1c, KEY_RADIO }, /*XXX*/ + { 0x12, KEY_POWER }, + + /* 0x01 0x02 0x03 * + * 1 2 3 * + * * + * 0x04 0x05 0x06 * + * 4 5 6 * + * * + * 0x07 0x08 0x09 * + * 7 8 9 * + * */ + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + /* 0x0a 0x00 0x17 * + * RECALL 0 +100 * + * PLUS * + * */ + { 0x0a, KEY_AGAIN }, /*XXX KEY_REWIND? */ + { 0x00, KEY_0 }, + { 0x17, KEY_DIGITS }, /*XXX*/ + + /* 0x14 0x10 * + * MENU INFO * + * OSD */ + { 0x14, KEY_MENU }, + { 0x10, KEY_INFO }, + + /* 0x0b * + * Up * + * * + * 0x18 0x16 0x0c * + * Left Ok Right * + * * + * 0x015 * + * Down * + * */ + { 0x0b, KEY_UP }, + { 0x18, KEY_LEFT }, + { 0x16, KEY_OK }, /*XXX KEY_SELECT? KEY_ENTER? */ + { 0x0c, KEY_RIGHT }, + { 0x15, KEY_DOWN }, + + /* 0x11 0x0d * + * TV/AV MODE * + * SOURCE STEREO * + * */ + { 0x11, KEY_TV }, /*XXX*/ + { 0x0d, KEY_MODE }, /*XXX there's no KEY_STEREO */ + + /* 0x0f 0x1b 0x1a * + * AUDIO Vol+ Chan+ * + * TIMESHIFT??? * + * * + * 0x0e 0x1f 0x1e * + * SLEEP Vol- Chan- * + * */ + { 0x0f, KEY_AUDIO }, + { 0x1b, KEY_VOLUMEUP }, + { 0x1a, KEY_CHANNELUP }, + { 0x0e, KEY_TIME }, + { 0x1f, KEY_VOLUMEDOWN }, + { 0x1e, KEY_CHANNELDOWN }, + + /* 0x13 0x19 * + * MUTE SNAPSHOT* + * */ + { 0x13, KEY_MUTE }, + { 0x19, KEY_CAMERA }, + + /* 0x1d unused ? */ +}; + +static struct rc_keymap manli_map = { + .map = { + .scan = manli, + .size = ARRAY_SIZE(manli), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_MANLI, + } +}; + +static int __init init_rc_map_manli(void) +{ + return ir_register_map(&manli_map); +} + +static void __exit exit_rc_map_manli(void) +{ + ir_unregister_map(&manli_map); +} + +module_init(init_rc_map_manli) +module_exit(exit_rc_map_manli) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-msi-digivox-ii.c b/drivers/media/rc/keymaps/rc-msi-digivox-ii.c new file mode 100644 index 0000000..67237fb --- /dev/null +++ b/drivers/media/rc/keymaps/rc-msi-digivox-ii.c @@ -0,0 +1,67 @@ +/* + * MSI DIGIVOX mini II remote controller keytable + * + * Copyright (C) 2010 Antti Palosaari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +static struct ir_scancode msi_digivox_ii[] = { + { 0x0002, KEY_2 }, + { 0x0003, KEY_UP }, /* up */ + { 0x0004, KEY_3 }, + { 0x0005, KEY_CHANNELDOWN }, + { 0x0008, KEY_5 }, + { 0x0009, KEY_0 }, + { 0x000b, KEY_8 }, + { 0x000d, KEY_DOWN }, /* down */ + { 0x0010, KEY_9 }, + { 0x0011, KEY_7 }, + { 0x0014, KEY_VOLUMEUP }, + { 0x0015, KEY_CHANNELUP }, + { 0x0016, KEY_OK }, + { 0x0017, KEY_POWER2 }, + { 0x001a, KEY_1 }, + { 0x001c, KEY_4 }, + { 0x001d, KEY_6 }, + { 0x001f, KEY_VOLUMEDOWN }, +}; + +static struct rc_keymap msi_digivox_ii_map = { + .map = { + .scan = msi_digivox_ii, + .size = ARRAY_SIZE(msi_digivox_ii), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_MSI_DIGIVOX_II, + } +}; + +static int __init init_rc_map_msi_digivox_ii(void) +{ + return ir_register_map(&msi_digivox_ii_map); +} + +static void __exit exit_rc_map_msi_digivox_ii(void) +{ + ir_unregister_map(&msi_digivox_ii_map); +} + +module_init(init_rc_map_msi_digivox_ii) +module_exit(exit_rc_map_msi_digivox_ii) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/rc/keymaps/rc-msi-digivox-iii.c b/drivers/media/rc/keymaps/rc-msi-digivox-iii.c new file mode 100644 index 0000000..882056e --- /dev/null +++ b/drivers/media/rc/keymaps/rc-msi-digivox-iii.c @@ -0,0 +1,85 @@ +/* + * MSI DIGIVOX mini III remote controller keytable + * + * Copyright (C) 2010 Antti Palosaari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +/* MSI DIGIVOX mini III */ +/* Uses NEC extended 0x61d6. */ +/* This remote seems to be same as rc-kworld-315u.c. Anyhow, add new remote + since rc-kworld-315u.c lacks NEC extended address byte. */ +static struct ir_scancode msi_digivox_iii[] = { + { 0x61d601, KEY_VIDEO }, /* Source */ + { 0x61d602, KEY_3 }, + { 0x61d603, KEY_POWER }, /* ShutDown */ + { 0x61d604, KEY_1 }, + { 0x61d605, KEY_5 }, + { 0x61d606, KEY_6 }, + { 0x61d607, KEY_CHANNELDOWN }, /* CH- */ + { 0x61d608, KEY_2 }, + { 0x61d609, KEY_CHANNELUP }, /* CH+ */ + { 0x61d60a, KEY_9 }, + { 0x61d60b, KEY_ZOOM }, /* Zoom */ + { 0x61d60c, KEY_7 }, + { 0x61d60d, KEY_8 }, + { 0x61d60e, KEY_VOLUMEUP }, /* Vol+ */ + { 0x61d60f, KEY_4 }, + { 0x61d610, KEY_ESC }, /* [back up arrow] */ + { 0x61d611, KEY_0 }, + { 0x61d612, KEY_OK }, /* [enter arrow] */ + { 0x61d613, KEY_VOLUMEDOWN }, /* Vol- */ + { 0x61d614, KEY_RECORD }, /* Rec */ + { 0x61d615, KEY_STOP }, /* Stop */ + { 0x61d616, KEY_PLAY }, /* Play */ + { 0x61d617, KEY_MUTE }, /* Mute */ + { 0x61d618, KEY_UP }, + { 0x61d619, KEY_DOWN }, + { 0x61d61a, KEY_LEFT }, + { 0x61d61b, KEY_RIGHT }, + { 0x61d61c, KEY_RED }, + { 0x61d61d, KEY_GREEN }, + { 0x61d61e, KEY_YELLOW }, + { 0x61d61f, KEY_BLUE }, + { 0x61d643, KEY_POWER2 }, /* [red power button] */ +}; + +static struct rc_keymap msi_digivox_iii_map = { + .map = { + .scan = msi_digivox_iii, + .size = ARRAY_SIZE(msi_digivox_iii), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_MSI_DIGIVOX_III, + } +}; + +static int __init init_rc_map_msi_digivox_iii(void) +{ + return ir_register_map(&msi_digivox_iii_map); +} + +static void __exit exit_rc_map_msi_digivox_iii(void) +{ + ir_unregister_map(&msi_digivox_iii_map); +} + +module_init(init_rc_map_msi_digivox_iii) +module_exit(exit_rc_map_msi_digivox_iii) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c b/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c new file mode 100644 index 0000000..eb8e42c --- /dev/null +++ b/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c @@ -0,0 +1,123 @@ +/* msi-tvanywhere-plus.h - Keytable for msi_tvanywhere_plus Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + Keycodes for remote on the MSI TV@nywhere Plus. The controller IC on the card + is marked "KS003". The controller is I2C at address 0x30, but does not seem + to respond to probes until a read is performed from a valid device. + I don't know why... + + Note: This remote may be of similar or identical design to the + Pixelview remote (?). The raw codes and duplicate button codes + appear to be the same. + + Henry Wong + Some changes to formatting and keycodes by Mark Schultz +*/ + +static struct ir_scancode msi_tvanywhere_plus[] = { + +/* ---- Remote Button Layout ---- + + POWER SOURCE SCAN MUTE + TV/FM 1 2 3 + |> 4 5 6 + <| 7 8 9 + ^^UP 0 + RECALL + vvDN RECORD STOP PLAY + + MINIMIZE ZOOM + + CH+ + VOL- VOL+ + CH- + + SNAPSHOT MTS + + << FUNC >> RESET +*/ + + { 0x01, KEY_1 }, /* 1 */ + { 0x0b, KEY_2 }, /* 2 */ + { 0x1b, KEY_3 }, /* 3 */ + { 0x05, KEY_4 }, /* 4 */ + { 0x09, KEY_5 }, /* 5 */ + { 0x15, KEY_6 }, /* 6 */ + { 0x06, KEY_7 }, /* 7 */ + { 0x0a, KEY_8 }, /* 8 */ + { 0x12, KEY_9 }, /* 9 */ + { 0x02, KEY_0 }, /* 0 */ + { 0x10, KEY_KPPLUS }, /* + */ + { 0x13, KEY_AGAIN }, /* Recall */ + + { 0x1e, KEY_POWER }, /* Power */ + { 0x07, KEY_TUNER }, /* Source */ + { 0x1c, KEY_SEARCH }, /* Scan */ + { 0x18, KEY_MUTE }, /* Mute */ + + { 0x03, KEY_RADIO }, /* TV/FM */ + /* The next four keys are duplicates that appear to send the + same IR code as Ch+, Ch-, >>, and << . The raw code assigned + to them is the actual code + 0x20 - they will never be + detected as such unless some way is discovered to distinguish + these buttons from those that have the same code. */ + { 0x3f, KEY_RIGHT }, /* |> and Ch+ */ + { 0x37, KEY_LEFT }, /* <| and Ch- */ + { 0x2c, KEY_UP }, /* ^^Up and >> */ + { 0x24, KEY_DOWN }, /* vvDn and << */ + + { 0x00, KEY_RECORD }, /* Record */ + { 0x08, KEY_STOP }, /* Stop */ + { 0x11, KEY_PLAY }, /* Play */ + + { 0x0f, KEY_CLOSE }, /* Minimize */ + { 0x19, KEY_ZOOM }, /* Zoom */ + { 0x1a, KEY_CAMERA }, /* Snapshot */ + { 0x0d, KEY_LANGUAGE }, /* MTS */ + + { 0x14, KEY_VOLUMEDOWN }, /* Vol- */ + { 0x16, KEY_VOLUMEUP }, /* Vol+ */ + { 0x17, KEY_CHANNELDOWN }, /* Ch- */ + { 0x1f, KEY_CHANNELUP }, /* Ch+ */ + + { 0x04, KEY_REWIND }, /* << */ + { 0x0e, KEY_MENU }, /* Function */ + { 0x0c, KEY_FASTFORWARD }, /* >> */ + { 0x1d, KEY_RESTART }, /* Reset */ +}; + +static struct rc_keymap msi_tvanywhere_plus_map = { + .map = { + .scan = msi_tvanywhere_plus, + .size = ARRAY_SIZE(msi_tvanywhere_plus), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_MSI_TVANYWHERE_PLUS, + } +}; + +static int __init init_rc_map_msi_tvanywhere_plus(void) +{ + return ir_register_map(&msi_tvanywhere_plus_map); +} + +static void __exit exit_rc_map_msi_tvanywhere_plus(void) +{ + ir_unregister_map(&msi_tvanywhere_plus_map); +} + +module_init(init_rc_map_msi_tvanywhere_plus) +module_exit(exit_rc_map_msi_tvanywhere_plus) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-msi-tvanywhere.c b/drivers/media/rc/keymaps/rc-msi-tvanywhere.c new file mode 100644 index 0000000..ef41185 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-msi-tvanywhere.c @@ -0,0 +1,69 @@ +/* msi-tvanywhere.h - Keytable for msi_tvanywhere Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* MSI TV@nywhere MASTER remote */ + +static struct ir_scancode msi_tvanywhere[] = { + /* Keys 0 to 9 */ + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x0c, KEY_MUTE }, + { 0x0f, KEY_SCREEN }, /* Full Screen */ + { 0x10, KEY_FN }, /* Funtion */ + { 0x11, KEY_TIME }, /* Time shift */ + { 0x12, KEY_POWER }, + { 0x13, KEY_MEDIA }, /* MTS */ + { 0x14, KEY_SLOW }, + { 0x16, KEY_REWIND }, /* backward << */ + { 0x17, KEY_ENTER }, /* Return */ + { 0x18, KEY_FASTFORWARD }, /* forward >> */ + { 0x1a, KEY_CHANNELUP }, + { 0x1b, KEY_VOLUMEUP }, + { 0x1e, KEY_CHANNELDOWN }, + { 0x1f, KEY_VOLUMEDOWN }, +}; + +static struct rc_keymap msi_tvanywhere_map = { + .map = { + .scan = msi_tvanywhere, + .size = ARRAY_SIZE(msi_tvanywhere), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_MSI_TVANYWHERE, + } +}; + +static int __init init_rc_map_msi_tvanywhere(void) +{ + return ir_register_map(&msi_tvanywhere_map); +} + +static void __exit exit_rc_map_msi_tvanywhere(void) +{ + ir_unregister_map(&msi_tvanywhere_map); +} + +module_init(init_rc_map_msi_tvanywhere) +module_exit(exit_rc_map_msi_tvanywhere) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-nebula.c b/drivers/media/rc/keymaps/rc-nebula.c new file mode 100644 index 0000000..ccc50eb --- /dev/null +++ b/drivers/media/rc/keymaps/rc-nebula.c @@ -0,0 +1,96 @@ +/* nebula.h - Keytable for nebula Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode nebula[] = { + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + { 0x0a, KEY_TV }, + { 0x0b, KEY_AUX }, + { 0x0c, KEY_DVD }, + { 0x0d, KEY_POWER }, + { 0x0e, KEY_MHP }, /* labelled 'Picture' */ + { 0x0f, KEY_AUDIO }, + { 0x10, KEY_INFO }, + { 0x11, KEY_F13 }, /* 16:9 */ + { 0x12, KEY_F14 }, /* 14:9 */ + { 0x13, KEY_EPG }, + { 0x14, KEY_EXIT }, + { 0x15, KEY_MENU }, + { 0x16, KEY_UP }, + { 0x17, KEY_DOWN }, + { 0x18, KEY_LEFT }, + { 0x19, KEY_RIGHT }, + { 0x1a, KEY_ENTER }, + { 0x1b, KEY_CHANNELUP }, + { 0x1c, KEY_CHANNELDOWN }, + { 0x1d, KEY_VOLUMEUP }, + { 0x1e, KEY_VOLUMEDOWN }, + { 0x1f, KEY_RED }, + { 0x20, KEY_GREEN }, + { 0x21, KEY_YELLOW }, + { 0x22, KEY_BLUE }, + { 0x23, KEY_SUBTITLE }, + { 0x24, KEY_F15 }, /* AD */ + { 0x25, KEY_TEXT }, + { 0x26, KEY_MUTE }, + { 0x27, KEY_REWIND }, + { 0x28, KEY_STOP }, + { 0x29, KEY_PLAY }, + { 0x2a, KEY_FASTFORWARD }, + { 0x2b, KEY_F16 }, /* chapter */ + { 0x2c, KEY_PAUSE }, + { 0x2d, KEY_PLAY }, + { 0x2e, KEY_RECORD }, + { 0x2f, KEY_F17 }, /* picture in picture */ + { 0x30, KEY_KPPLUS }, /* zoom in */ + { 0x31, KEY_KPMINUS }, /* zoom out */ + { 0x32, KEY_F18 }, /* capture */ + { 0x33, KEY_F19 }, /* web */ + { 0x34, KEY_EMAIL }, + { 0x35, KEY_PHONE }, + { 0x36, KEY_PC }, +}; + +static struct rc_keymap nebula_map = { + .map = { + .scan = nebula, + .size = ARRAY_SIZE(nebula), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_NEBULA, + } +}; + +static int __init init_rc_map_nebula(void) +{ + return ir_register_map(&nebula_map); +} + +static void __exit exit_rc_map_nebula(void) +{ + ir_unregister_map(&nebula_map); +} + +module_init(init_rc_map_nebula) +module_exit(exit_rc_map_nebula) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c b/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c new file mode 100644 index 0000000..e1b54d2 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c @@ -0,0 +1,105 @@ +/* nec-terratec-cinergy-xs.h - Keytable for nec_terratec_cinergy_xs Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Terratec Cinergy Hybrid T USB XS FM + Mauro Carvalho Chehab + */ + +static struct ir_scancode nec_terratec_cinergy_xs[] = { + { 0x1441, KEY_HOME}, + { 0x1401, KEY_POWER2}, + + { 0x1442, KEY_MENU}, /* DVD menu */ + { 0x1443, KEY_SUBTITLE}, + { 0x1444, KEY_TEXT}, /* Teletext */ + { 0x1445, KEY_DELETE}, + + { 0x1402, KEY_1}, + { 0x1403, KEY_2}, + { 0x1404, KEY_3}, + { 0x1405, KEY_4}, + { 0x1406, KEY_5}, + { 0x1407, KEY_6}, + { 0x1408, KEY_7}, + { 0x1409, KEY_8}, + { 0x140a, KEY_9}, + { 0x140c, KEY_0}, + + { 0x140b, KEY_TUNER}, /* AV */ + { 0x140d, KEY_MODE}, /* A.B */ + + { 0x1446, KEY_TV}, + { 0x1447, KEY_DVD}, + { 0x1449, KEY_VIDEO}, + { 0x144a, KEY_RADIO}, /* Music */ + { 0x144b, KEY_CAMERA}, /* PIC */ + + { 0x1410, KEY_UP}, + { 0x1411, KEY_LEFT}, + { 0x1412, KEY_OK}, + { 0x1413, KEY_RIGHT}, + { 0x1414, KEY_DOWN}, + + { 0x140f, KEY_EPG}, + { 0x1416, KEY_INFO}, + { 0x144d, KEY_BACKSPACE}, + + { 0x141c, KEY_VOLUMEUP}, + { 0x141e, KEY_VOLUMEDOWN}, + + { 0x144c, KEY_PLAY}, + { 0x141d, KEY_MUTE}, + + { 0x141b, KEY_CHANNELUP}, + { 0x141f, KEY_CHANNELDOWN}, + + { 0x1417, KEY_RED}, + { 0x1418, KEY_GREEN}, + { 0x1419, KEY_YELLOW}, + { 0x141a, KEY_BLUE}, + + { 0x1458, KEY_RECORD}, + { 0x1448, KEY_STOP}, + { 0x1440, KEY_PAUSE}, + + { 0x1454, KEY_LAST}, + { 0x144e, KEY_REWIND}, + { 0x144f, KEY_FASTFORWARD}, + { 0x145c, KEY_NEXT}, +}; + +static struct rc_keymap nec_terratec_cinergy_xs_map = { + .map = { + .scan = nec_terratec_cinergy_xs, + .size = ARRAY_SIZE(nec_terratec_cinergy_xs), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_NEC_TERRATEC_CINERGY_XS, + } +}; + +static int __init init_rc_map_nec_terratec_cinergy_xs(void) +{ + return ir_register_map(&nec_terratec_cinergy_xs_map); +} + +static void __exit exit_rc_map_nec_terratec_cinergy_xs(void) +{ + ir_unregister_map(&nec_terratec_cinergy_xs_map); +} + +module_init(init_rc_map_nec_terratec_cinergy_xs) +module_exit(exit_rc_map_nec_terratec_cinergy_xs) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-norwood.c b/drivers/media/rc/keymaps/rc-norwood.c new file mode 100644 index 0000000..e5849a6 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-norwood.c @@ -0,0 +1,85 @@ +/* norwood.h - Keytable for norwood Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Norwood Micro (non-Pro) TV Tuner + By Peter Naulls + Key comments are the functions given in the manual */ + +static struct ir_scancode norwood[] = { + /* Keys 0 to 9 */ + { 0x20, KEY_0 }, + { 0x21, KEY_1 }, + { 0x22, KEY_2 }, + { 0x23, KEY_3 }, + { 0x24, KEY_4 }, + { 0x25, KEY_5 }, + { 0x26, KEY_6 }, + { 0x27, KEY_7 }, + { 0x28, KEY_8 }, + { 0x29, KEY_9 }, + + { 0x78, KEY_TUNER }, /* Video Source */ + { 0x2c, KEY_EXIT }, /* Open/Close software */ + { 0x2a, KEY_SELECT }, /* 2 Digit Select */ + { 0x69, KEY_AGAIN }, /* Recall */ + + { 0x32, KEY_BRIGHTNESSUP }, /* Brightness increase */ + { 0x33, KEY_BRIGHTNESSDOWN }, /* Brightness decrease */ + { 0x6b, KEY_KPPLUS }, /* (not named >>>>>) */ + { 0x6c, KEY_KPMINUS }, /* (not named <<<<<) */ + + { 0x2d, KEY_MUTE }, /* Mute */ + { 0x30, KEY_VOLUMEUP }, /* Volume up */ + { 0x31, KEY_VOLUMEDOWN }, /* Volume down */ + { 0x60, KEY_CHANNELUP }, /* Channel up */ + { 0x61, KEY_CHANNELDOWN }, /* Channel down */ + + { 0x3f, KEY_RECORD }, /* Record */ + { 0x37, KEY_PLAY }, /* Play */ + { 0x36, KEY_PAUSE }, /* Pause */ + { 0x2b, KEY_STOP }, /* Stop */ + { 0x67, KEY_FASTFORWARD }, /* Foward */ + { 0x66, KEY_REWIND }, /* Rewind */ + { 0x3e, KEY_SEARCH }, /* Auto Scan */ + { 0x2e, KEY_CAMERA }, /* Capture Video */ + { 0x6d, KEY_MENU }, /* Show/Hide Control */ + { 0x2f, KEY_ZOOM }, /* Full Screen */ + { 0x34, KEY_RADIO }, /* FM */ + { 0x65, KEY_POWER }, /* Computer power */ +}; + +static struct rc_keymap norwood_map = { + .map = { + .scan = norwood, + .size = ARRAY_SIZE(norwood), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_NORWOOD, + } +}; + +static int __init init_rc_map_norwood(void) +{ + return ir_register_map(&norwood_map); +} + +static void __exit exit_rc_map_norwood(void) +{ + ir_unregister_map(&norwood_map); +} + +module_init(init_rc_map_norwood) +module_exit(exit_rc_map_norwood) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-npgtech.c b/drivers/media/rc/keymaps/rc-npgtech.c new file mode 100644 index 0000000..b9ece1e --- /dev/null +++ b/drivers/media/rc/keymaps/rc-npgtech.c @@ -0,0 +1,80 @@ +/* npgtech.h - Keytable for npgtech Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode npgtech[] = { + { 0x1d, KEY_SWITCHVIDEOMODE }, /* switch inputs */ + { 0x2a, KEY_FRONT }, + + { 0x3e, KEY_1 }, + { 0x02, KEY_2 }, + { 0x06, KEY_3 }, + { 0x0a, KEY_4 }, + { 0x0e, KEY_5 }, + { 0x12, KEY_6 }, + { 0x16, KEY_7 }, + { 0x1a, KEY_8 }, + { 0x1e, KEY_9 }, + { 0x3a, KEY_0 }, + { 0x22, KEY_NUMLOCK }, /* -/-- */ + { 0x20, KEY_REFRESH }, + + { 0x03, KEY_BRIGHTNESSDOWN }, + { 0x28, KEY_AUDIO }, + { 0x3c, KEY_CHANNELUP }, + { 0x3f, KEY_VOLUMEDOWN }, + { 0x2e, KEY_MUTE }, + { 0x3b, KEY_VOLUMEUP }, + { 0x00, KEY_CHANNELDOWN }, + { 0x07, KEY_BRIGHTNESSUP }, + { 0x2c, KEY_TEXT }, + + { 0x37, KEY_RECORD }, + { 0x17, KEY_PLAY }, + { 0x13, KEY_PAUSE }, + { 0x26, KEY_STOP }, + { 0x18, KEY_FASTFORWARD }, + { 0x14, KEY_REWIND }, + { 0x33, KEY_ZOOM }, + { 0x32, KEY_KEYBOARD }, + { 0x30, KEY_GOTO }, /* Pointing arrow */ + { 0x36, KEY_MACRO }, /* Maximize/Minimize (yellow) */ + { 0x0b, KEY_RADIO }, + { 0x10, KEY_POWER }, + +}; + +static struct rc_keymap npgtech_map = { + .map = { + .scan = npgtech, + .size = ARRAY_SIZE(npgtech), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_NPGTECH, + } +}; + +static int __init init_rc_map_npgtech(void) +{ + return ir_register_map(&npgtech_map); +} + +static void __exit exit_rc_map_npgtech(void) +{ + ir_unregister_map(&npgtech_map); +} + +module_init(init_rc_map_npgtech) +module_exit(exit_rc_map_npgtech) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-pctv-sedna.c b/drivers/media/rc/keymaps/rc-pctv-sedna.c new file mode 100644 index 0000000..4129bb4 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-pctv-sedna.c @@ -0,0 +1,80 @@ +/* pctv-sedna.h - Keytable for pctv_sedna Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Mapping for the 28 key remote control as seen at + http://www.sednacomputer.com/photo/cardbus-tv.jpg + Pavel Mihaylov + Also for the remote bundled with Kozumi KTV-01C card */ + +static struct ir_scancode pctv_sedna[] = { + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x0a, KEY_AGAIN }, /* Recall */ + { 0x0b, KEY_CHANNELUP }, + { 0x0c, KEY_VOLUMEUP }, + { 0x0d, KEY_MODE }, /* Stereo */ + { 0x0e, KEY_STOP }, + { 0x0f, KEY_PREVIOUSSONG }, + { 0x10, KEY_ZOOM }, + { 0x11, KEY_TUNER }, /* Source */ + { 0x12, KEY_POWER }, + { 0x13, KEY_MUTE }, + { 0x15, KEY_CHANNELDOWN }, + { 0x18, KEY_VOLUMEDOWN }, + { 0x19, KEY_CAMERA }, /* Snapshot */ + { 0x1a, KEY_NEXTSONG }, + { 0x1b, KEY_TIME }, /* Time Shift */ + { 0x1c, KEY_RADIO }, /* FM Radio */ + { 0x1d, KEY_RECORD }, + { 0x1e, KEY_PAUSE }, + /* additional codes for Kozumi's remote */ + { 0x14, KEY_INFO }, /* OSD */ + { 0x16, KEY_OK }, /* OK */ + { 0x17, KEY_DIGITS }, /* Plus */ + { 0x1f, KEY_PLAY }, /* Play */ +}; + +static struct rc_keymap pctv_sedna_map = { + .map = { + .scan = pctv_sedna, + .size = ARRAY_SIZE(pctv_sedna), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_PCTV_SEDNA, + } +}; + +static int __init init_rc_map_pctv_sedna(void) +{ + return ir_register_map(&pctv_sedna_map); +} + +static void __exit exit_rc_map_pctv_sedna(void) +{ + ir_unregister_map(&pctv_sedna_map); +} + +module_init(init_rc_map_pctv_sedna) +module_exit(exit_rc_map_pctv_sedna) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-pinnacle-color.c b/drivers/media/rc/keymaps/rc-pinnacle-color.c new file mode 100644 index 0000000..326e023 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-pinnacle-color.c @@ -0,0 +1,94 @@ +/* pinnacle-color.h - Keytable for pinnacle_color Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode pinnacle_color[] = { + { 0x59, KEY_MUTE }, + { 0x4a, KEY_POWER }, + + { 0x18, KEY_TEXT }, + { 0x26, KEY_TV }, + { 0x3d, KEY_PRINT }, + + { 0x48, KEY_RED }, + { 0x04, KEY_GREEN }, + { 0x11, KEY_YELLOW }, + { 0x00, KEY_BLUE }, + + { 0x2d, KEY_VOLUMEUP }, + { 0x1e, KEY_VOLUMEDOWN }, + + { 0x49, KEY_MENU }, + + { 0x16, KEY_CHANNELUP }, + { 0x17, KEY_CHANNELDOWN }, + + { 0x20, KEY_UP }, + { 0x21, KEY_DOWN }, + { 0x22, KEY_LEFT }, + { 0x23, KEY_RIGHT }, + { 0x0d, KEY_SELECT }, + + { 0x08, KEY_BACK }, + { 0x07, KEY_REFRESH }, + + { 0x2f, KEY_ZOOM }, + { 0x29, KEY_RECORD }, + + { 0x4b, KEY_PAUSE }, + { 0x4d, KEY_REWIND }, + { 0x2e, KEY_PLAY }, + { 0x4e, KEY_FORWARD }, + { 0x53, KEY_PREVIOUS }, + { 0x4c, KEY_STOP }, + { 0x54, KEY_NEXT }, + + { 0x69, KEY_0 }, + { 0x6a, KEY_1 }, + { 0x6b, KEY_2 }, + { 0x6c, KEY_3 }, + { 0x6d, KEY_4 }, + { 0x6e, KEY_5 }, + { 0x6f, KEY_6 }, + { 0x70, KEY_7 }, + { 0x71, KEY_8 }, + { 0x72, KEY_9 }, + + { 0x74, KEY_CHANNEL }, + { 0x0a, KEY_BACKSPACE }, +}; + +static struct rc_keymap pinnacle_color_map = { + .map = { + .scan = pinnacle_color, + .size = ARRAY_SIZE(pinnacle_color), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_PINNACLE_COLOR, + } +}; + +static int __init init_rc_map_pinnacle_color(void) +{ + return ir_register_map(&pinnacle_color_map); +} + +static void __exit exit_rc_map_pinnacle_color(void) +{ + ir_unregister_map(&pinnacle_color_map); +} + +module_init(init_rc_map_pinnacle_color) +module_exit(exit_rc_map_pinnacle_color) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-pinnacle-grey.c b/drivers/media/rc/keymaps/rc-pinnacle-grey.c new file mode 100644 index 0000000..14cb772 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-pinnacle-grey.c @@ -0,0 +1,89 @@ +/* pinnacle-grey.h - Keytable for pinnacle_grey Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode pinnacle_grey[] = { + { 0x3a, KEY_0 }, + { 0x31, KEY_1 }, + { 0x32, KEY_2 }, + { 0x33, KEY_3 }, + { 0x34, KEY_4 }, + { 0x35, KEY_5 }, + { 0x36, KEY_6 }, + { 0x37, KEY_7 }, + { 0x38, KEY_8 }, + { 0x39, KEY_9 }, + + { 0x2f, KEY_POWER }, + + { 0x2e, KEY_P }, + { 0x1f, KEY_L }, + { 0x2b, KEY_I }, + + { 0x2d, KEY_SCREEN }, + { 0x1e, KEY_ZOOM }, + { 0x1b, KEY_VOLUMEUP }, + { 0x0f, KEY_VOLUMEDOWN }, + { 0x17, KEY_CHANNELUP }, + { 0x1c, KEY_CHANNELDOWN }, + { 0x25, KEY_INFO }, + + { 0x3c, KEY_MUTE }, + + { 0x3d, KEY_LEFT }, + { 0x3b, KEY_RIGHT }, + + { 0x3f, KEY_UP }, + { 0x3e, KEY_DOWN }, + { 0x1a, KEY_ENTER }, + + { 0x1d, KEY_MENU }, + { 0x19, KEY_AGAIN }, + { 0x16, KEY_PREVIOUSSONG }, + { 0x13, KEY_NEXTSONG }, + { 0x15, KEY_PAUSE }, + { 0x0e, KEY_REWIND }, + { 0x0d, KEY_PLAY }, + { 0x0b, KEY_STOP }, + { 0x07, KEY_FORWARD }, + { 0x27, KEY_RECORD }, + { 0x26, KEY_TUNER }, + { 0x29, KEY_TEXT }, + { 0x2a, KEY_MEDIA }, + { 0x18, KEY_EPG }, +}; + +static struct rc_keymap pinnacle_grey_map = { + .map = { + .scan = pinnacle_grey, + .size = ARRAY_SIZE(pinnacle_grey), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_PINNACLE_GREY, + } +}; + +static int __init init_rc_map_pinnacle_grey(void) +{ + return ir_register_map(&pinnacle_grey_map); +} + +static void __exit exit_rc_map_pinnacle_grey(void) +{ + ir_unregister_map(&pinnacle_grey_map); +} + +module_init(init_rc_map_pinnacle_grey) +module_exit(exit_rc_map_pinnacle_grey) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c new file mode 100644 index 0000000..835bf4e --- /dev/null +++ b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c @@ -0,0 +1,73 @@ +/* pinnacle-pctv-hd.h - Keytable for pinnacle_pctv_hd Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Pinnacle PCTV HD 800i mini remote */ + +static struct ir_scancode pinnacle_pctv_hd[] = { + + { 0x0f, KEY_1 }, + { 0x15, KEY_2 }, + { 0x10, KEY_3 }, + { 0x18, KEY_4 }, + { 0x1b, KEY_5 }, + { 0x1e, KEY_6 }, + { 0x11, KEY_7 }, + { 0x21, KEY_8 }, + { 0x12, KEY_9 }, + { 0x27, KEY_0 }, + + { 0x24, KEY_ZOOM }, + { 0x2a, KEY_SUBTITLE }, + + { 0x00, KEY_MUTE }, + { 0x01, KEY_ENTER }, /* Pinnacle Logo */ + { 0x39, KEY_POWER }, + + { 0x03, KEY_VOLUMEUP }, + { 0x09, KEY_VOLUMEDOWN }, + { 0x06, KEY_CHANNELUP }, + { 0x0c, KEY_CHANNELDOWN }, + + { 0x2d, KEY_REWIND }, + { 0x30, KEY_PLAYPAUSE }, + { 0x33, KEY_FASTFORWARD }, + { 0x3c, KEY_STOP }, + { 0x36, KEY_RECORD }, + { 0x3f, KEY_EPG }, /* Labeled "?" */ +}; + +static struct rc_keymap pinnacle_pctv_hd_map = { + .map = { + .scan = pinnacle_pctv_hd, + .size = ARRAY_SIZE(pinnacle_pctv_hd), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_PINNACLE_PCTV_HD, + } +}; + +static int __init init_rc_map_pinnacle_pctv_hd(void) +{ + return ir_register_map(&pinnacle_pctv_hd_map); +} + +static void __exit exit_rc_map_pinnacle_pctv_hd(void) +{ + ir_unregister_map(&pinnacle_pctv_hd_map); +} + +module_init(init_rc_map_pinnacle_pctv_hd) +module_exit(exit_rc_map_pinnacle_pctv_hd) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-pixelview-mk12.c b/drivers/media/rc/keymaps/rc-pixelview-mk12.c new file mode 100644 index 0000000..5a735d5 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-pixelview-mk12.c @@ -0,0 +1,83 @@ +/* rc-pixelview-mk12.h - Keytable for pixelview Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * Keytable for MK-F12 IR remote provided together with Pixelview + * Ultra Pro Remote Controller. Uses NEC extended format. + */ +static struct ir_scancode pixelview_mk12[] = { + { 0x866b03, KEY_TUNER }, /* Timeshift */ + { 0x866b1e, KEY_POWER2 }, /* power */ + + { 0x866b01, KEY_1 }, + { 0x866b0b, KEY_2 }, + { 0x866b1b, KEY_3 }, + { 0x866b05, KEY_4 }, + { 0x866b09, KEY_5 }, + { 0x866b15, KEY_6 }, + { 0x866b06, KEY_7 }, + { 0x866b0a, KEY_8 }, + { 0x866b12, KEY_9 }, + { 0x866b02, KEY_0 }, + + { 0x866b13, KEY_AGAIN }, /* loop */ + { 0x866b10, KEY_DIGITS }, /* +100 */ + + { 0x866b00, KEY_MEDIA }, /* source */ + { 0x866b18, KEY_MUTE }, /* mute */ + { 0x866b19, KEY_CAMERA }, /* snapshot */ + { 0x866b1a, KEY_SEARCH }, /* scan */ + + { 0x866b16, KEY_CHANNELUP }, /* chn + */ + { 0x866b14, KEY_CHANNELDOWN }, /* chn - */ + { 0x866b1f, KEY_VOLUMEUP }, /* vol + */ + { 0x866b17, KEY_VOLUMEDOWN }, /* vol - */ + { 0x866b1c, KEY_ZOOM }, /* zoom */ + + { 0x866b04, KEY_REWIND }, + { 0x866b0e, KEY_RECORD }, + { 0x866b0c, KEY_FORWARD }, + + { 0x866b1d, KEY_STOP }, + { 0x866b08, KEY_PLAY }, + { 0x866b0f, KEY_PAUSE }, + + { 0x866b0d, KEY_TV }, + { 0x866b07, KEY_RADIO }, /* FM */ +}; + +static struct rc_keymap pixelview_map = { + .map = { + .scan = pixelview_mk12, + .size = ARRAY_SIZE(pixelview_mk12), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_PIXELVIEW_MK12, + } +}; + +static int __init init_rc_map_pixelview(void) +{ + return ir_register_map(&pixelview_map); +} + +static void __exit exit_rc_map_pixelview(void) +{ + ir_unregister_map(&pixelview_map); +} + +module_init(init_rc_map_pixelview) +module_exit(exit_rc_map_pixelview) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-pixelview-new.c b/drivers/media/rc/keymaps/rc-pixelview-new.c new file mode 100644 index 0000000..7bbbbf5 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-pixelview-new.c @@ -0,0 +1,83 @@ +/* pixelview-new.h - Keytable for pixelview_new Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + Mauro Carvalho Chehab + present on PV MPEG 8000GT + */ + +static struct ir_scancode pixelview_new[] = { + { 0x3c, KEY_TIME }, /* Timeshift */ + { 0x12, KEY_POWER }, + + { 0x3d, KEY_1 }, + { 0x38, KEY_2 }, + { 0x18, KEY_3 }, + { 0x35, KEY_4 }, + { 0x39, KEY_5 }, + { 0x15, KEY_6 }, + { 0x36, KEY_7 }, + { 0x3a, KEY_8 }, + { 0x1e, KEY_9 }, + { 0x3e, KEY_0 }, + + { 0x1c, KEY_AGAIN }, /* LOOP */ + { 0x3f, KEY_MEDIA }, /* Source */ + { 0x1f, KEY_LAST }, /* +100 */ + { 0x1b, KEY_MUTE }, + + { 0x17, KEY_CHANNELDOWN }, + { 0x16, KEY_CHANNELUP }, + { 0x10, KEY_VOLUMEUP }, + { 0x14, KEY_VOLUMEDOWN }, + { 0x13, KEY_ZOOM }, + + { 0x19, KEY_CAMERA }, /* SNAPSHOT */ + { 0x1a, KEY_SEARCH }, /* scan */ + + { 0x37, KEY_REWIND }, /* << */ + { 0x32, KEY_RECORD }, /* o (red) */ + { 0x33, KEY_FORWARD }, /* >> */ + { 0x11, KEY_STOP }, /* square */ + { 0x3b, KEY_PLAY }, /* > */ + { 0x30, KEY_PLAYPAUSE }, /* || */ + + { 0x31, KEY_TV }, + { 0x34, KEY_RADIO }, +}; + +static struct rc_keymap pixelview_new_map = { + .map = { + .scan = pixelview_new, + .size = ARRAY_SIZE(pixelview_new), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_PIXELVIEW_NEW, + } +}; + +static int __init init_rc_map_pixelview_new(void) +{ + return ir_register_map(&pixelview_new_map); +} + +static void __exit exit_rc_map_pixelview_new(void) +{ + ir_unregister_map(&pixelview_new_map); +} + +module_init(init_rc_map_pixelview_new) +module_exit(exit_rc_map_pixelview_new) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-pixelview.c b/drivers/media/rc/keymaps/rc-pixelview.c new file mode 100644 index 0000000..82ff12e --- /dev/null +++ b/drivers/media/rc/keymaps/rc-pixelview.c @@ -0,0 +1,82 @@ +/* pixelview.h - Keytable for pixelview Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode pixelview[] = { + + { 0x1e, KEY_POWER }, /* power */ + { 0x07, KEY_MEDIA }, /* source */ + { 0x1c, KEY_SEARCH }, /* scan */ + + + { 0x03, KEY_TUNER }, /* TV/FM */ + + { 0x00, KEY_RECORD }, + { 0x08, KEY_STOP }, + { 0x11, KEY_PLAY }, + + { 0x1a, KEY_PLAYPAUSE }, /* freeze */ + { 0x19, KEY_ZOOM }, /* zoom */ + { 0x0f, KEY_TEXT }, /* min */ + + { 0x01, KEY_1 }, + { 0x0b, KEY_2 }, + { 0x1b, KEY_3 }, + { 0x05, KEY_4 }, + { 0x09, KEY_5 }, + { 0x15, KEY_6 }, + { 0x06, KEY_7 }, + { 0x0a, KEY_8 }, + { 0x12, KEY_9 }, + { 0x02, KEY_0 }, + { 0x10, KEY_LAST }, /* +100 */ + { 0x13, KEY_LIST }, /* recall */ + + { 0x1f, KEY_CHANNELUP }, /* chn down */ + { 0x17, KEY_CHANNELDOWN }, /* chn up */ + { 0x16, KEY_VOLUMEUP }, /* vol down */ + { 0x14, KEY_VOLUMEDOWN }, /* vol up */ + + { 0x04, KEY_KPMINUS }, /* <<< */ + { 0x0e, KEY_SETUP }, /* function */ + { 0x0c, KEY_KPPLUS }, /* >>> */ + + { 0x0d, KEY_GOTO }, /* mts */ + { 0x1d, KEY_REFRESH }, /* reset */ + { 0x18, KEY_MUTE }, /* mute/unmute */ +}; + +static struct rc_keymap pixelview_map = { + .map = { + .scan = pixelview, + .size = ARRAY_SIZE(pixelview), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_PIXELVIEW, + } +}; + +static int __init init_rc_map_pixelview(void) +{ + return ir_register_map(&pixelview_map); +} + +static void __exit exit_rc_map_pixelview(void) +{ + ir_unregister_map(&pixelview_map); +} + +module_init(init_rc_map_pixelview) +module_exit(exit_rc_map_pixelview) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-powercolor-real-angel.c b/drivers/media/rc/keymaps/rc-powercolor-real-angel.c new file mode 100644 index 0000000..7cef819 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-powercolor-real-angel.c @@ -0,0 +1,81 @@ +/* powercolor-real-angel.h - Keytable for powercolor_real_angel Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * Remote control for Powercolor Real Angel 330 + * Daniel Fraga + */ + +static struct ir_scancode powercolor_real_angel[] = { + { 0x38, KEY_SWITCHVIDEOMODE }, /* switch inputs */ + { 0x0c, KEY_MEDIA }, /* Turn ON/OFF App */ + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + { 0x0a, KEY_DIGITS }, /* single, double, tripple digit */ + { 0x29, KEY_PREVIOUS }, /* previous channel */ + { 0x12, KEY_BRIGHTNESSUP }, + { 0x13, KEY_BRIGHTNESSDOWN }, + { 0x2b, KEY_MODE }, /* stereo/mono */ + { 0x2c, KEY_TEXT }, /* teletext */ + { 0x20, KEY_CHANNELUP }, /* channel up */ + { 0x21, KEY_CHANNELDOWN }, /* channel down */ + { 0x10, KEY_VOLUMEUP }, /* volume up */ + { 0x11, KEY_VOLUMEDOWN }, /* volume down */ + { 0x0d, KEY_MUTE }, + { 0x1f, KEY_RECORD }, + { 0x17, KEY_PLAY }, + { 0x16, KEY_PAUSE }, + { 0x0b, KEY_STOP }, + { 0x27, KEY_FASTFORWARD }, + { 0x26, KEY_REWIND }, + { 0x1e, KEY_SEARCH }, /* autoscan */ + { 0x0e, KEY_CAMERA }, /* snapshot */ + { 0x2d, KEY_SETUP }, + { 0x0f, KEY_SCREEN }, /* full screen */ + { 0x14, KEY_RADIO }, /* FM radio */ + { 0x25, KEY_POWER }, /* power */ +}; + +static struct rc_keymap powercolor_real_angel_map = { + .map = { + .scan = powercolor_real_angel, + .size = ARRAY_SIZE(powercolor_real_angel), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_POWERCOLOR_REAL_ANGEL, + } +}; + +static int __init init_rc_map_powercolor_real_angel(void) +{ + return ir_register_map(&powercolor_real_angel_map); +} + +static void __exit exit_rc_map_powercolor_real_angel(void) +{ + ir_unregister_map(&powercolor_real_angel_map); +} + +module_init(init_rc_map_powercolor_real_angel) +module_exit(exit_rc_map_powercolor_real_angel) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-proteus-2309.c b/drivers/media/rc/keymaps/rc-proteus-2309.c new file mode 100644 index 0000000..22e92d3 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-proteus-2309.c @@ -0,0 +1,69 @@ +/* proteus-2309.h - Keytable for proteus_2309 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Michal Majchrowicz */ + +static struct ir_scancode proteus_2309[] = { + /* numeric */ + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x5c, KEY_POWER }, /* power */ + { 0x20, KEY_ZOOM }, /* full screen */ + { 0x0f, KEY_BACKSPACE }, /* recall */ + { 0x1b, KEY_ENTER }, /* mute */ + { 0x41, KEY_RECORD }, /* record */ + { 0x43, KEY_STOP }, /* stop */ + { 0x16, KEY_S }, + { 0x1a, KEY_POWER2 }, /* off */ + { 0x2e, KEY_RED }, + { 0x1f, KEY_CHANNELDOWN }, /* channel - */ + { 0x1c, KEY_CHANNELUP }, /* channel + */ + { 0x10, KEY_VOLUMEDOWN }, /* volume - */ + { 0x1e, KEY_VOLUMEUP }, /* volume + */ + { 0x14, KEY_F1 }, +}; + +static struct rc_keymap proteus_2309_map = { + .map = { + .scan = proteus_2309, + .size = ARRAY_SIZE(proteus_2309), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_PROTEUS_2309, + } +}; + +static int __init init_rc_map_proteus_2309(void) +{ + return ir_register_map(&proteus_2309_map); +} + +static void __exit exit_rc_map_proteus_2309(void) +{ + ir_unregister_map(&proteus_2309_map); +} + +module_init(init_rc_map_proteus_2309) +module_exit(exit_rc_map_proteus_2309) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-purpletv.c b/drivers/media/rc/keymaps/rc-purpletv.c new file mode 100644 index 0000000..4e20fc2 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-purpletv.c @@ -0,0 +1,81 @@ +/* purpletv.h - Keytable for purpletv Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode purpletv[] = { + { 0x03, KEY_POWER }, + { 0x6f, KEY_MUTE }, + { 0x10, KEY_BACKSPACE }, /* Recall */ + + { 0x11, KEY_0 }, + { 0x04, KEY_1 }, + { 0x05, KEY_2 }, + { 0x06, KEY_3 }, + { 0x08, KEY_4 }, + { 0x09, KEY_5 }, + { 0x0a, KEY_6 }, + { 0x0c, KEY_7 }, + { 0x0d, KEY_8 }, + { 0x0e, KEY_9 }, + { 0x12, KEY_DOT }, /* 100+ */ + + { 0x07, KEY_VOLUMEUP }, + { 0x0b, KEY_VOLUMEDOWN }, + { 0x1a, KEY_KPPLUS }, + { 0x18, KEY_KPMINUS }, + { 0x15, KEY_UP }, + { 0x1d, KEY_DOWN }, + { 0x0f, KEY_CHANNELUP }, + { 0x13, KEY_CHANNELDOWN }, + { 0x48, KEY_ZOOM }, + + { 0x1b, KEY_VIDEO }, /* Video source */ + { 0x1f, KEY_CAMERA }, /* Snapshot */ + { 0x49, KEY_LANGUAGE }, /* MTS Select */ + { 0x19, KEY_SEARCH }, /* Auto Scan */ + + { 0x4b, KEY_RECORD }, + { 0x46, KEY_PLAY }, + { 0x45, KEY_PAUSE }, /* Pause */ + { 0x44, KEY_STOP }, + { 0x43, KEY_TIME }, /* Time Shift */ + { 0x17, KEY_CHANNEL }, /* SURF CH */ + { 0x40, KEY_FORWARD }, /* Forward ? */ + { 0x42, KEY_REWIND }, /* Backward ? */ + +}; + +static struct rc_keymap purpletv_map = { + .map = { + .scan = purpletv, + .size = ARRAY_SIZE(purpletv), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_PURPLETV, + } +}; + +static int __init init_rc_map_purpletv(void) +{ + return ir_register_map(&purpletv_map); +} + +static void __exit exit_rc_map_purpletv(void) +{ + ir_unregister_map(&purpletv_map); +} + +module_init(init_rc_map_purpletv) +module_exit(exit_rc_map_purpletv) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-pv951.c b/drivers/media/rc/keymaps/rc-pv951.c new file mode 100644 index 0000000..36679e7 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-pv951.c @@ -0,0 +1,78 @@ +/* pv951.h - Keytable for pv951 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Mark Phalan */ + +static struct ir_scancode pv951[] = { + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x12, KEY_POWER }, + { 0x10, KEY_MUTE }, + { 0x1f, KEY_VOLUMEDOWN }, + { 0x1b, KEY_VOLUMEUP }, + { 0x1a, KEY_CHANNELUP }, + { 0x1e, KEY_CHANNELDOWN }, + { 0x0e, KEY_PAGEUP }, + { 0x1d, KEY_PAGEDOWN }, + { 0x13, KEY_SOUND }, + + { 0x18, KEY_KPPLUSMINUS }, /* CH +/- */ + { 0x16, KEY_SUBTITLE }, /* CC */ + { 0x0d, KEY_TEXT }, /* TTX */ + { 0x0b, KEY_TV }, /* AIR/CBL */ + { 0x11, KEY_PC }, /* PC/TV */ + { 0x17, KEY_OK }, /* CH RTN */ + { 0x19, KEY_MODE }, /* FUNC */ + { 0x0c, KEY_SEARCH }, /* AUTOSCAN */ + + /* Not sure what to do with these ones! */ + { 0x0f, KEY_SELECT }, /* SOURCE */ + { 0x0a, KEY_KPPLUS }, /* +100 */ + { 0x14, KEY_EQUAL }, /* SYNC */ + { 0x1c, KEY_MEDIA }, /* PC/TV */ +}; + +static struct rc_keymap pv951_map = { + .map = { + .scan = pv951, + .size = ARRAY_SIZE(pv951), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_PV951, + } +}; + +static int __init init_rc_map_pv951(void) +{ + return ir_register_map(&pv951_map); +} + +static void __exit exit_rc_map_pv951(void) +{ + ir_unregister_map(&pv951_map); +} + +module_init(init_rc_map_pv951) +module_exit(exit_rc_map_pv951) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c b/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c new file mode 100644 index 0000000..cc6b8f5 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c @@ -0,0 +1,103 @@ +/* rc5-hauppauge-new.h - Keytable for rc5_hauppauge_new Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * Hauppauge:the newer, gray remotes (seems there are multiple + * slightly different versions), shipped with cx88+ivtv cards. + * + * This table contains the complete RC5 code, instead of just the data part + */ + +static struct ir_scancode rc5_hauppauge_new[] = { + /* Keys 0 to 9 */ + { 0x1e00, KEY_0 }, + { 0x1e01, KEY_1 }, + { 0x1e02, KEY_2 }, + { 0x1e03, KEY_3 }, + { 0x1e04, KEY_4 }, + { 0x1e05, KEY_5 }, + { 0x1e06, KEY_6 }, + { 0x1e07, KEY_7 }, + { 0x1e08, KEY_8 }, + { 0x1e09, KEY_9 }, + + { 0x1e0a, KEY_TEXT }, /* keypad asterisk as well */ + { 0x1e0b, KEY_RED }, /* red button */ + { 0x1e0c, KEY_RADIO }, + { 0x1e0d, KEY_MENU }, + { 0x1e0e, KEY_SUBTITLE }, /* also the # key */ + { 0x1e0f, KEY_MUTE }, + { 0x1e10, KEY_VOLUMEUP }, + { 0x1e11, KEY_VOLUMEDOWN }, + { 0x1e12, KEY_PREVIOUS }, /* previous channel */ + { 0x1e14, KEY_UP }, + { 0x1e15, KEY_DOWN }, + { 0x1e16, KEY_LEFT }, + { 0x1e17, KEY_RIGHT }, + { 0x1e18, KEY_VIDEO }, /* Videos */ + { 0x1e19, KEY_AUDIO }, /* Music */ + /* 0x1e1a: Pictures - presume this means + "Multimedia Home Platform" - + no "PICTURES" key in input.h + */ + { 0x1e1a, KEY_MHP }, + + { 0x1e1b, KEY_EPG }, /* Guide */ + { 0x1e1c, KEY_TV }, + { 0x1e1e, KEY_NEXTSONG }, /* skip >| */ + { 0x1e1f, KEY_EXIT }, /* back/exit */ + { 0x1e20, KEY_CHANNELUP }, /* channel / program + */ + { 0x1e21, KEY_CHANNELDOWN }, /* channel / program - */ + { 0x1e22, KEY_CHANNEL }, /* source (old black remote) */ + { 0x1e24, KEY_PREVIOUSSONG }, /* replay |< */ + { 0x1e25, KEY_ENTER }, /* OK */ + { 0x1e26, KEY_SLEEP }, /* minimize (old black remote) */ + { 0x1e29, KEY_BLUE }, /* blue key */ + { 0x1e2e, KEY_GREEN }, /* green button */ + { 0x1e30, KEY_PAUSE }, /* pause */ + { 0x1e32, KEY_REWIND }, /* backward << */ + { 0x1e34, KEY_FASTFORWARD }, /* forward >> */ + { 0x1e35, KEY_PLAY }, + { 0x1e36, KEY_STOP }, + { 0x1e37, KEY_RECORD }, /* recording */ + { 0x1e38, KEY_YELLOW }, /* yellow key */ + { 0x1e3b, KEY_SELECT }, /* top right button */ + { 0x1e3c, KEY_ZOOM }, /* full */ + { 0x1e3d, KEY_POWER }, /* system power (green button) */ +}; + +static struct rc_keymap rc5_hauppauge_new_map = { + .map = { + .scan = rc5_hauppauge_new, + .size = ARRAY_SIZE(rc5_hauppauge_new), + .ir_type = IR_TYPE_RC5, + .name = RC_MAP_RC5_HAUPPAUGE_NEW, + } +}; + +static int __init init_rc_map_rc5_hauppauge_new(void) +{ + return ir_register_map(&rc5_hauppauge_new_map); +} + +static void __exit exit_rc_map_rc5_hauppauge_new(void) +{ + ir_unregister_map(&rc5_hauppauge_new_map); +} + +module_init(init_rc_map_rc5_hauppauge_new) +module_exit(exit_rc_map_rc5_hauppauge_new) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-rc5-tv.c b/drivers/media/rc/keymaps/rc-rc5-tv.c new file mode 100644 index 0000000..73cce2f --- /dev/null +++ b/drivers/media/rc/keymaps/rc-rc5-tv.c @@ -0,0 +1,81 @@ +/* rc5-tv.h - Keytable for rc5_tv Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* generic RC5 keytable */ +/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ +/* used by old (black) Hauppauge remotes */ + +static struct ir_scancode rc5_tv[] = { + /* Keys 0 to 9 */ + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x0b, KEY_CHANNEL }, /* channel / program (japan: 11) */ + { 0x0c, KEY_POWER }, /* standby */ + { 0x0d, KEY_MUTE }, /* mute / demute */ + { 0x0f, KEY_TV }, /* display */ + { 0x10, KEY_VOLUMEUP }, + { 0x11, KEY_VOLUMEDOWN }, + { 0x12, KEY_BRIGHTNESSUP }, + { 0x13, KEY_BRIGHTNESSDOWN }, + { 0x1e, KEY_SEARCH }, /* search + */ + { 0x20, KEY_CHANNELUP }, /* channel / program + */ + { 0x21, KEY_CHANNELDOWN }, /* channel / program - */ + { 0x22, KEY_CHANNEL }, /* alt / channel */ + { 0x23, KEY_LANGUAGE }, /* 1st / 2nd language */ + { 0x26, KEY_SLEEP }, /* sleeptimer */ + { 0x2e, KEY_MENU }, /* 2nd controls (USA: menu) */ + { 0x30, KEY_PAUSE }, + { 0x32, KEY_REWIND }, + { 0x33, KEY_GOTO }, + { 0x35, KEY_PLAY }, + { 0x36, KEY_STOP }, + { 0x37, KEY_RECORD }, /* recording */ + { 0x3c, KEY_TEXT }, /* teletext submode (Japan: 12) */ + { 0x3d, KEY_SUSPEND }, /* system standby */ + +}; + +static struct rc_keymap rc5_tv_map = { + .map = { + .scan = rc5_tv, + .size = ARRAY_SIZE(rc5_tv), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_RC5_TV, + } +}; + +static int __init init_rc_map_rc5_tv(void) +{ + return ir_register_map(&rc5_tv_map); +} + +static void __exit exit_rc_map_rc5_tv(void) +{ + ir_unregister_map(&rc5_tv_map); +} + +module_init(init_rc_map_rc5_tv) +module_exit(exit_rc_map_rc5_tv) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-rc6-mce.c b/drivers/media/rc/keymaps/rc-rc6-mce.c new file mode 100644 index 0000000..6da955d --- /dev/null +++ b/drivers/media/rc/keymaps/rc-rc6-mce.c @@ -0,0 +1,113 @@ +/* rc-rc6-mce.c - Keytable for Windows Media Center RC-6 remotes for use + * with the Media Center Edition eHome Infrared Transceiver. + * + * Copyright (c) 2010 by Jarod Wilson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode rc6_mce[] = { + + { 0x800f0400, KEY_NUMERIC_0 }, + { 0x800f0401, KEY_NUMERIC_1 }, + { 0x800f0402, KEY_NUMERIC_2 }, + { 0x800f0403, KEY_NUMERIC_3 }, + { 0x800f0404, KEY_NUMERIC_4 }, + { 0x800f0405, KEY_NUMERIC_5 }, + { 0x800f0406, KEY_NUMERIC_6 }, + { 0x800f0407, KEY_NUMERIC_7 }, + { 0x800f0408, KEY_NUMERIC_8 }, + { 0x800f0409, KEY_NUMERIC_9 }, + + { 0x800f040a, KEY_DELETE }, + { 0x800f040b, KEY_ENTER }, + { 0x800f040c, KEY_POWER }, /* PC Power */ + { 0x800f040d, KEY_PROG1 }, /* Windows MCE button */ + { 0x800f040e, KEY_MUTE }, + { 0x800f040f, KEY_INFO }, + + { 0x800f0410, KEY_VOLUMEUP }, + { 0x800f0411, KEY_VOLUMEDOWN }, + { 0x800f0412, KEY_CHANNELUP }, + { 0x800f0413, KEY_CHANNELDOWN }, + + { 0x800f0414, KEY_FASTFORWARD }, + { 0x800f0415, KEY_REWIND }, + { 0x800f0416, KEY_PLAY }, + { 0x800f0417, KEY_RECORD }, + { 0x800f0418, KEY_PAUSE }, + { 0x800f046e, KEY_PLAYPAUSE }, + { 0x800f0419, KEY_STOP }, + { 0x800f041a, KEY_NEXT }, + { 0x800f041b, KEY_PREVIOUS }, + { 0x800f041c, KEY_NUMERIC_POUND }, + { 0x800f041d, KEY_NUMERIC_STAR }, + + { 0x800f041e, KEY_UP }, + { 0x800f041f, KEY_DOWN }, + { 0x800f0420, KEY_LEFT }, + { 0x800f0421, KEY_RIGHT }, + + { 0x800f0422, KEY_OK }, + { 0x800f0423, KEY_EXIT }, + { 0x800f0424, KEY_DVD }, + { 0x800f0425, KEY_TUNER }, /* LiveTV */ + { 0x800f0426, KEY_EPG }, /* Guide */ + { 0x800f0427, KEY_ZOOM }, /* Aspect */ + + { 0x800f043a, KEY_BRIGHTNESSUP }, + + { 0x800f0446, KEY_TV }, + { 0x800f0447, KEY_AUDIO }, /* My Music */ + { 0x800f0448, KEY_PVR }, /* RecordedTV */ + { 0x800f0449, KEY_CAMERA }, + { 0x800f044a, KEY_VIDEO }, + { 0x800f044c, KEY_LANGUAGE }, + { 0x800f044d, KEY_TITLE }, + { 0x800f044e, KEY_PRINT }, /* Print - HP OEM version of remote */ + + { 0x800f0450, KEY_RADIO }, + + { 0x800f045a, KEY_SUBTITLE }, /* Caption/Teletext */ + { 0x800f045b, KEY_RED }, + { 0x800f045c, KEY_GREEN }, + { 0x800f045d, KEY_YELLOW }, + { 0x800f045e, KEY_BLUE }, + + { 0x800f0465, KEY_POWER2 }, /* TV Power */ + { 0x800f046e, KEY_PLAYPAUSE }, + { 0x800f046f, KEY_MEDIA }, /* Start media application (NEW) */ + + { 0x800f0480, KEY_BRIGHTNESSDOWN }, + { 0x800f0481, KEY_PLAYPAUSE }, +}; + +static struct rc_keymap rc6_mce_map = { + .map = { + .scan = rc6_mce, + .size = ARRAY_SIZE(rc6_mce), + .ir_type = IR_TYPE_RC6, + .name = RC_MAP_RC6_MCE, + } +}; + +static int __init init_rc_map_rc6_mce(void) +{ + return ir_register_map(&rc6_mce_map); +} + +static void __exit exit_rc_map_rc6_mce(void) +{ + ir_unregister_map(&rc6_mce_map); +} + +module_init(init_rc_map_rc6_mce) +module_exit(exit_rc_map_rc6_mce) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jarod Wilson "); diff --git a/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c b/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c new file mode 100644 index 0000000..ab1a6d2 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c @@ -0,0 +1,78 @@ +/* real-audio-220-32-keys.h - Keytable for real_audio_220_32_keys Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Zogis Real Audio 220 - 32 keys IR */ + +static struct ir_scancode real_audio_220_32_keys[] = { + { 0x1c, KEY_RADIO}, + { 0x12, KEY_POWER2}, + + { 0x01, KEY_1}, + { 0x02, KEY_2}, + { 0x03, KEY_3}, + { 0x04, KEY_4}, + { 0x05, KEY_5}, + { 0x06, KEY_6}, + { 0x07, KEY_7}, + { 0x08, KEY_8}, + { 0x09, KEY_9}, + { 0x00, KEY_0}, + + { 0x0c, KEY_VOLUMEUP}, + { 0x18, KEY_VOLUMEDOWN}, + { 0x0b, KEY_CHANNELUP}, + { 0x15, KEY_CHANNELDOWN}, + { 0x16, KEY_ENTER}, + + { 0x11, KEY_LIST}, /* Source */ + { 0x0d, KEY_AUDIO}, /* stereo */ + + { 0x0f, KEY_PREVIOUS}, /* Prev */ + { 0x1b, KEY_TIME}, /* Timeshift */ + { 0x1a, KEY_NEXT}, /* Next */ + + { 0x0e, KEY_STOP}, + { 0x1f, KEY_PLAY}, + { 0x1e, KEY_PLAYPAUSE}, /* Pause */ + + { 0x1d, KEY_RECORD}, + { 0x13, KEY_MUTE}, + { 0x19, KEY_CAMERA}, /* Snapshot */ + +}; + +static struct rc_keymap real_audio_220_32_keys_map = { + .map = { + .scan = real_audio_220_32_keys, + .size = ARRAY_SIZE(real_audio_220_32_keys), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_REAL_AUDIO_220_32_KEYS, + } +}; + +static int __init init_rc_map_real_audio_220_32_keys(void) +{ + return ir_register_map(&real_audio_220_32_keys_map); +} + +static void __exit exit_rc_map_real_audio_220_32_keys(void) +{ + ir_unregister_map(&real_audio_220_32_keys_map); +} + +module_init(init_rc_map_real_audio_220_32_keys) +module_exit(exit_rc_map_real_audio_220_32_keys) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-streamzap.c b/drivers/media/rc/keymaps/rc-streamzap.c new file mode 100644 index 0000000..df32013 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-streamzap.c @@ -0,0 +1,82 @@ +/* rc-streamzap.c - Keytable for Streamzap PC Remote, for use + * with the Streamzap PC Remote IR Receiver. + * + * Copyright (c) 2010 by Jarod Wilson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode streamzap[] = { +/* + * The Streamzap remote is almost, but not quite, RC-5, as it has an extra + * bit in it, which throws the in-kernel RC-5 decoder for a loop. Currently, + * an additional RC-5-sz decoder is being deployed to support it, but it + * may be possible to merge it back with the standard RC-5 decoder. + */ + { 0x28c0, KEY_NUMERIC_0 }, + { 0x28c1, KEY_NUMERIC_1 }, + { 0x28c2, KEY_NUMERIC_2 }, + { 0x28c3, KEY_NUMERIC_3 }, + { 0x28c4, KEY_NUMERIC_4 }, + { 0x28c5, KEY_NUMERIC_5 }, + { 0x28c6, KEY_NUMERIC_6 }, + { 0x28c7, KEY_NUMERIC_7 }, + { 0x28c8, KEY_NUMERIC_8 }, + { 0x28c9, KEY_NUMERIC_9 }, + { 0x28ca, KEY_POWER }, + { 0x28cb, KEY_MUTE }, + { 0x28cc, KEY_CHANNELUP }, + { 0x28cd, KEY_VOLUMEUP }, + { 0x28ce, KEY_CHANNELDOWN }, + { 0x28cf, KEY_VOLUMEDOWN }, + { 0x28d0, KEY_UP }, + { 0x28d1, KEY_LEFT }, + { 0x28d2, KEY_OK }, + { 0x28d3, KEY_RIGHT }, + { 0x28d4, KEY_DOWN }, + { 0x28d5, KEY_MENU }, + { 0x28d6, KEY_EXIT }, + { 0x28d7, KEY_PLAY }, + { 0x28d8, KEY_PAUSE }, + { 0x28d9, KEY_STOP }, + { 0x28da, KEY_BACK }, + { 0x28db, KEY_FORWARD }, + { 0x28dc, KEY_RECORD }, + { 0x28dd, KEY_REWIND }, + { 0x28de, KEY_FASTFORWARD }, + { 0x28e0, KEY_RED }, + { 0x28e1, KEY_GREEN }, + { 0x28e2, KEY_YELLOW }, + { 0x28e3, KEY_BLUE }, + +}; + +static struct rc_keymap streamzap_map = { + .map = { + .scan = streamzap, + .size = ARRAY_SIZE(streamzap), + .ir_type = IR_TYPE_RC5_SZ, + .name = RC_MAP_STREAMZAP, + } +}; + +static int __init init_rc_map_streamzap(void) +{ + return ir_register_map(&streamzap_map); +} + +static void __exit exit_rc_map_streamzap(void) +{ + ir_unregister_map(&streamzap_map); +} + +module_init(init_rc_map_streamzap) +module_exit(exit_rc_map_streamzap) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jarod Wilson "); diff --git a/drivers/media/rc/keymaps/rc-tbs-nec.c b/drivers/media/rc/keymaps/rc-tbs-nec.c new file mode 100644 index 0000000..3309631 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-tbs-nec.c @@ -0,0 +1,73 @@ +/* tbs-nec.h - Keytable for tbs_nec Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode tbs_nec[] = { + { 0x04, KEY_POWER2}, /*power*/ + { 0x14, KEY_MUTE}, /*mute*/ + { 0x07, KEY_1}, + { 0x06, KEY_2}, + { 0x05, KEY_3}, + { 0x0b, KEY_4}, + { 0x0a, KEY_5}, + { 0x09, KEY_6}, + { 0x0f, KEY_7}, + { 0x0e, KEY_8}, + { 0x0d, KEY_9}, + { 0x12, KEY_0}, + { 0x16, KEY_CHANNELUP}, /*ch+*/ + { 0x11, KEY_CHANNELDOWN},/*ch-*/ + { 0x13, KEY_VOLUMEUP}, /*vol+*/ + { 0x0c, KEY_VOLUMEDOWN},/*vol-*/ + { 0x03, KEY_RECORD}, /*rec*/ + { 0x18, KEY_PAUSE}, /*pause*/ + { 0x19, KEY_OK}, /*ok*/ + { 0x1a, KEY_CAMERA}, /* snapshot */ + { 0x01, KEY_UP}, + { 0x10, KEY_LEFT}, + { 0x02, KEY_RIGHT}, + { 0x08, KEY_DOWN}, + { 0x15, KEY_FAVORITES}, + { 0x17, KEY_SUBTITLE}, + { 0x1d, KEY_ZOOM}, + { 0x1f, KEY_EXIT}, + { 0x1e, KEY_MENU}, + { 0x1c, KEY_EPG}, + { 0x00, KEY_PREVIOUS}, + { 0x1b, KEY_MODE}, +}; + +static struct rc_keymap tbs_nec_map = { + .map = { + .scan = tbs_nec, + .size = ARRAY_SIZE(tbs_nec), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_TBS_NEC, + } +}; + +static int __init init_rc_map_tbs_nec(void) +{ + return ir_register_map(&tbs_nec_map); +} + +static void __exit exit_rc_map_tbs_nec(void) +{ + ir_unregister_map(&tbs_nec_map); +} + +module_init(init_rc_map_tbs_nec) +module_exit(exit_rc_map_tbs_nec) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c b/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c new file mode 100644 index 0000000..5326a0b --- /dev/null +++ b/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c @@ -0,0 +1,92 @@ +/* terratec-cinergy-xs.h - Keytable for terratec_cinergy_xs Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Terratec Cinergy Hybrid T USB XS + Devin Heitmueller + */ + +static struct ir_scancode terratec_cinergy_xs[] = { + { 0x41, KEY_HOME}, + { 0x01, KEY_POWER}, + { 0x42, KEY_MENU}, + { 0x02, KEY_1}, + { 0x03, KEY_2}, + { 0x04, KEY_3}, + { 0x43, KEY_SUBTITLE}, + { 0x05, KEY_4}, + { 0x06, KEY_5}, + { 0x07, KEY_6}, + { 0x44, KEY_TEXT}, + { 0x08, KEY_7}, + { 0x09, KEY_8}, + { 0x0a, KEY_9}, + { 0x45, KEY_DELETE}, + { 0x0b, KEY_TUNER}, + { 0x0c, KEY_0}, + { 0x0d, KEY_MODE}, + { 0x46, KEY_TV}, + { 0x47, KEY_DVD}, + { 0x49, KEY_VIDEO}, + { 0x4b, KEY_AUX}, + { 0x10, KEY_UP}, + { 0x11, KEY_LEFT}, + { 0x12, KEY_OK}, + { 0x13, KEY_RIGHT}, + { 0x14, KEY_DOWN}, + { 0x0f, KEY_EPG}, + { 0x16, KEY_INFO}, + { 0x4d, KEY_BACKSPACE}, + { 0x1c, KEY_VOLUMEUP}, + { 0x4c, KEY_PLAY}, + { 0x1b, KEY_CHANNELUP}, + { 0x1e, KEY_VOLUMEDOWN}, + { 0x1d, KEY_MUTE}, + { 0x1f, KEY_CHANNELDOWN}, + { 0x17, KEY_RED}, + { 0x18, KEY_GREEN}, + { 0x19, KEY_YELLOW}, + { 0x1a, KEY_BLUE}, + { 0x58, KEY_RECORD}, + { 0x48, KEY_STOP}, + { 0x40, KEY_PAUSE}, + { 0x54, KEY_LAST}, + { 0x4e, KEY_REWIND}, + { 0x4f, KEY_FASTFORWARD}, + { 0x5c, KEY_NEXT}, +}; + +static struct rc_keymap terratec_cinergy_xs_map = { + .map = { + .scan = terratec_cinergy_xs, + .size = ARRAY_SIZE(terratec_cinergy_xs), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_TERRATEC_CINERGY_XS, + } +}; + +static int __init init_rc_map_terratec_cinergy_xs(void) +{ + return ir_register_map(&terratec_cinergy_xs_map); +} + +static void __exit exit_rc_map_terratec_cinergy_xs(void) +{ + ir_unregister_map(&terratec_cinergy_xs_map); +} + +module_init(init_rc_map_terratec_cinergy_xs) +module_exit(exit_rc_map_terratec_cinergy_xs) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-terratec-slim.c b/drivers/media/rc/keymaps/rc-terratec-slim.c new file mode 100644 index 0000000..10dee4c --- /dev/null +++ b/drivers/media/rc/keymaps/rc-terratec-slim.c @@ -0,0 +1,79 @@ +/* + * TerraTec remote controller keytable + * + * Copyright (C) 2010 Antti Palosaari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +/* TerraTec slim remote, 7 rows, 4 columns. */ +/* Uses NEC extended 0x02bd. */ +static struct ir_scancode terratec_slim[] = { + { 0x02bd00, KEY_1 }, + { 0x02bd01, KEY_2 }, + { 0x02bd02, KEY_3 }, + { 0x02bd03, KEY_4 }, + { 0x02bd04, KEY_5 }, + { 0x02bd05, KEY_6 }, + { 0x02bd06, KEY_7 }, + { 0x02bd07, KEY_8 }, + { 0x02bd08, KEY_9 }, + { 0x02bd09, KEY_0 }, + { 0x02bd0a, KEY_MUTE }, + { 0x02bd0b, KEY_NEW }, /* symbol: PIP */ + { 0x02bd0e, KEY_VOLUMEDOWN }, + { 0x02bd0f, KEY_PLAYPAUSE }, + { 0x02bd10, KEY_RIGHT }, + { 0x02bd11, KEY_LEFT }, + { 0x02bd12, KEY_UP }, + { 0x02bd13, KEY_DOWN }, + { 0x02bd15, KEY_OK }, + { 0x02bd16, KEY_STOP }, + { 0x02bd17, KEY_CAMERA }, /* snapshot */ + { 0x02bd18, KEY_CHANNELUP }, + { 0x02bd19, KEY_RECORD }, + { 0x02bd1a, KEY_CHANNELDOWN }, + { 0x02bd1c, KEY_ESC }, + { 0x02bd1f, KEY_VOLUMEUP }, + { 0x02bd44, KEY_EPG }, + { 0x02bd45, KEY_POWER2 }, /* [red power button] */ +}; + +static struct rc_keymap terratec_slim_map = { + .map = { + .scan = terratec_slim, + .size = ARRAY_SIZE(terratec_slim), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_TERRATEC_SLIM, + } +}; + +static int __init init_rc_map_terratec_slim(void) +{ + return ir_register_map(&terratec_slim_map); +} + +static void __exit exit_rc_map_terratec_slim(void) +{ + ir_unregister_map(&terratec_slim_map); +} + +module_init(init_rc_map_terratec_slim) +module_exit(exit_rc_map_terratec_slim) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/rc/keymaps/rc-tevii-nec.c b/drivers/media/rc/keymaps/rc-tevii-nec.c new file mode 100644 index 0000000..e30d411 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-tevii-nec.c @@ -0,0 +1,88 @@ +/* tevii-nec.h - Keytable for tevii_nec Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode tevii_nec[] = { + { 0x0a, KEY_POWER2}, + { 0x0c, KEY_MUTE}, + { 0x11, KEY_1}, + { 0x12, KEY_2}, + { 0x13, KEY_3}, + { 0x14, KEY_4}, + { 0x15, KEY_5}, + { 0x16, KEY_6}, + { 0x17, KEY_7}, + { 0x18, KEY_8}, + { 0x19, KEY_9}, + { 0x10, KEY_0}, + { 0x1c, KEY_MENU}, + { 0x0f, KEY_VOLUMEDOWN}, + { 0x1a, KEY_LAST}, + { 0x0e, KEY_OPEN}, + { 0x04, KEY_RECORD}, + { 0x09, KEY_VOLUMEUP}, + { 0x08, KEY_CHANNELUP}, + { 0x07, KEY_PVR}, + { 0x0b, KEY_TIME}, + { 0x02, KEY_RIGHT}, + { 0x03, KEY_LEFT}, + { 0x00, KEY_UP}, + { 0x1f, KEY_OK}, + { 0x01, KEY_DOWN}, + { 0x05, KEY_TUNER}, + { 0x06, KEY_CHANNELDOWN}, + { 0x40, KEY_PLAYPAUSE}, + { 0x1e, KEY_REWIND}, + { 0x1b, KEY_FAVORITES}, + { 0x1d, KEY_BACK}, + { 0x4d, KEY_FASTFORWARD}, + { 0x44, KEY_EPG}, + { 0x4c, KEY_INFO}, + { 0x41, KEY_AB}, + { 0x43, KEY_AUDIO}, + { 0x45, KEY_SUBTITLE}, + { 0x4a, KEY_LIST}, + { 0x46, KEY_F1}, + { 0x47, KEY_F2}, + { 0x5e, KEY_F3}, + { 0x5c, KEY_F4}, + { 0x52, KEY_F5}, + { 0x5a, KEY_F6}, + { 0x56, KEY_MODE}, + { 0x58, KEY_SWITCHVIDEOMODE}, +}; + +static struct rc_keymap tevii_nec_map = { + .map = { + .scan = tevii_nec, + .size = ARRAY_SIZE(tevii_nec), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_TEVII_NEC, + } +}; + +static int __init init_rc_map_tevii_nec(void) +{ + return ir_register_map(&tevii_nec_map); +} + +static void __exit exit_rc_map_tevii_nec(void) +{ + ir_unregister_map(&tevii_nec_map); +} + +module_init(init_rc_map_tevii_nec) +module_exit(exit_rc_map_tevii_nec) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-total-media-in-hand.c b/drivers/media/rc/keymaps/rc-total-media-in-hand.c new file mode 100644 index 0000000..fd19857 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-total-media-in-hand.c @@ -0,0 +1,85 @@ +/* + * Total Media In Hand remote controller keytable + * + * Copyright (C) 2010 Antti Palosaari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +/* Uses NEC extended 0x02bd */ +static struct ir_scancode total_media_in_hand[] = { + { 0x02bd00, KEY_1 }, + { 0x02bd01, KEY_2 }, + { 0x02bd02, KEY_3 }, + { 0x02bd03, KEY_4 }, + { 0x02bd04, KEY_5 }, + { 0x02bd05, KEY_6 }, + { 0x02bd06, KEY_7 }, + { 0x02bd07, KEY_8 }, + { 0x02bd08, KEY_9 }, + { 0x02bd09, KEY_0 }, + { 0x02bd0a, KEY_MUTE }, + { 0x02bd0b, KEY_CYCLEWINDOWS }, /* yellow, [min / max] */ + { 0x02bd0c, KEY_VIDEO }, /* TV / AV */ + { 0x02bd0e, KEY_VOLUMEDOWN }, + { 0x02bd0f, KEY_TIME }, /* TimeShift */ + { 0x02bd10, KEY_RIGHT }, /* right arrow */ + { 0x02bd11, KEY_LEFT }, /* left arrow */ + { 0x02bd12, KEY_UP }, /* up arrow */ + { 0x02bd13, KEY_DOWN }, /* down arrow */ + { 0x02bd14, KEY_POWER2 }, /* [red] */ + { 0x02bd15, KEY_OK }, /* OK */ + { 0x02bd16, KEY_STOP }, + { 0x02bd17, KEY_CAMERA }, /* Snapshot */ + { 0x02bd18, KEY_CHANNELUP }, + { 0x02bd19, KEY_RECORD }, + { 0x02bd1a, KEY_CHANNELDOWN }, + { 0x02bd1c, KEY_ESC }, /* Esc */ + { 0x02bd1e, KEY_PLAY }, + { 0x02bd1f, KEY_VOLUMEUP }, + { 0x02bd40, KEY_PAUSE }, + { 0x02bd41, KEY_FASTFORWARD }, /* FF >> */ + { 0x02bd42, KEY_REWIND }, /* FR << */ + { 0x02bd43, KEY_ZOOM }, /* [window + mouse pointer] */ + { 0x02bd44, KEY_SHUFFLE }, /* Shuffle */ + { 0x02bd45, KEY_INFO }, /* [red (I)] */ +}; + +static struct rc_keymap total_media_in_hand_map = { + .map = { + .scan = total_media_in_hand, + .size = ARRAY_SIZE(total_media_in_hand), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_TOTAL_MEDIA_IN_HAND, + } +}; + +static int __init init_rc_map_total_media_in_hand(void) +{ + return ir_register_map(&total_media_in_hand_map); +} + +static void __exit exit_rc_map_total_media_in_hand(void) +{ + ir_unregister_map(&total_media_in_hand_map); +} + +module_init(init_rc_map_total_media_in_hand) +module_exit(exit_rc_map_total_media_in_hand) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/rc/keymaps/rc-trekstor.c b/drivers/media/rc/keymaps/rc-trekstor.c new file mode 100644 index 0000000..91092ca --- /dev/null +++ b/drivers/media/rc/keymaps/rc-trekstor.c @@ -0,0 +1,80 @@ +/* + * TrekStor remote controller keytable + * + * Copyright (C) 2010 Antti Palosaari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +/* TrekStor DVB-T USB Stick remote controller. */ +/* Imported from af9015.h. + Initial keytable was from Marc Schneider */ +static struct ir_scancode trekstor[] = { + { 0x0084, KEY_0 }, + { 0x0085, KEY_MUTE }, /* Mute */ + { 0x0086, KEY_HOMEPAGE }, /* Home */ + { 0x0087, KEY_UP }, /* Up */ + { 0x0088, KEY_OK }, /* OK */ + { 0x0089, KEY_RIGHT }, /* Right */ + { 0x008a, KEY_FASTFORWARD }, /* Fast forward */ + { 0x008b, KEY_VOLUMEUP }, /* Volume + */ + { 0x008c, KEY_DOWN }, /* Down */ + { 0x008d, KEY_PLAY }, /* Play/Pause */ + { 0x008e, KEY_STOP }, /* Stop */ + { 0x008f, KEY_EPG }, /* Info/EPG */ + { 0x0090, KEY_7 }, + { 0x0091, KEY_4 }, + { 0x0092, KEY_1 }, + { 0x0093, KEY_CHANNELDOWN }, /* Channel - */ + { 0x0094, KEY_8 }, + { 0x0095, KEY_5 }, + { 0x0096, KEY_2 }, + { 0x0097, KEY_CHANNELUP }, /* Channel + */ + { 0x0098, KEY_9 }, + { 0x0099, KEY_6 }, + { 0x009a, KEY_3 }, + { 0x009b, KEY_VOLUMEDOWN }, /* Volume - */ + { 0x009c, KEY_TV }, /* TV */ + { 0x009d, KEY_RECORD }, /* Record */ + { 0x009e, KEY_REWIND }, /* Rewind */ + { 0x009f, KEY_LEFT }, /* Left */ +}; + +static struct rc_keymap trekstor_map = { + .map = { + .scan = trekstor, + .size = ARRAY_SIZE(trekstor), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_TREKSTOR, + } +}; + +static int __init init_rc_map_trekstor(void) +{ + return ir_register_map(&trekstor_map); +} + +static void __exit exit_rc_map_trekstor(void) +{ + ir_unregister_map(&trekstor_map); +} + +module_init(init_rc_map_trekstor) +module_exit(exit_rc_map_trekstor) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Antti Palosaari "); diff --git a/drivers/media/rc/keymaps/rc-tt-1500.c b/drivers/media/rc/keymaps/rc-tt-1500.c new file mode 100644 index 0000000..bc88de0 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-tt-1500.c @@ -0,0 +1,82 @@ +/* tt-1500.h - Keytable for tt_1500 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* for the Technotrend 1500 bundled remotes (grey and black): */ + +static struct ir_scancode tt_1500[] = { + { 0x01, KEY_POWER }, + { 0x02, KEY_SHUFFLE }, /* ? double-arrow key */ + { 0x03, KEY_1 }, + { 0x04, KEY_2 }, + { 0x05, KEY_3 }, + { 0x06, KEY_4 }, + { 0x07, KEY_5 }, + { 0x08, KEY_6 }, + { 0x09, KEY_7 }, + { 0x0a, KEY_8 }, + { 0x0b, KEY_9 }, + { 0x0c, KEY_0 }, + { 0x0d, KEY_UP }, + { 0x0e, KEY_LEFT }, + { 0x0f, KEY_OK }, + { 0x10, KEY_RIGHT }, + { 0x11, KEY_DOWN }, + { 0x12, KEY_INFO }, + { 0x13, KEY_EXIT }, + { 0x14, KEY_RED }, + { 0x15, KEY_GREEN }, + { 0x16, KEY_YELLOW }, + { 0x17, KEY_BLUE }, + { 0x18, KEY_MUTE }, + { 0x19, KEY_TEXT }, + { 0x1a, KEY_MODE }, /* ? TV/Radio */ + { 0x21, KEY_OPTION }, + { 0x22, KEY_EPG }, + { 0x23, KEY_CHANNELUP }, + { 0x24, KEY_CHANNELDOWN }, + { 0x25, KEY_VOLUMEUP }, + { 0x26, KEY_VOLUMEDOWN }, + { 0x27, KEY_SETUP }, + { 0x3a, KEY_RECORD }, /* these keys are only in the black remote */ + { 0x3b, KEY_PLAY }, + { 0x3c, KEY_STOP }, + { 0x3d, KEY_REWIND }, + { 0x3e, KEY_PAUSE }, + { 0x3f, KEY_FORWARD }, +}; + +static struct rc_keymap tt_1500_map = { + .map = { + .scan = tt_1500, + .size = ARRAY_SIZE(tt_1500), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_TT_1500, + } +}; + +static int __init init_rc_map_tt_1500(void) +{ + return ir_register_map(&tt_1500_map); +} + +static void __exit exit_rc_map_tt_1500(void) +{ + ir_unregister_map(&tt_1500_map); +} + +module_init(init_rc_map_tt_1500) +module_exit(exit_rc_map_tt_1500) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-twinhan1027.c b/drivers/media/rc/keymaps/rc-twinhan1027.c new file mode 100644 index 0000000..0b5d356 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-twinhan1027.c @@ -0,0 +1,87 @@ +#include + +static struct ir_scancode twinhan_vp1027[] = { + { 0x16, KEY_POWER2 }, + { 0x17, KEY_FAVORITES }, + { 0x0f, KEY_TEXT }, + { 0x48, KEY_INFO}, + { 0x1c, KEY_EPG }, + { 0x04, KEY_LIST }, + + { 0x03, KEY_1 }, + { 0x01, KEY_2 }, + { 0x06, KEY_3 }, + { 0x09, KEY_4 }, + { 0x1d, KEY_5 }, + { 0x1f, KEY_6 }, + { 0x0d, KEY_7 }, + { 0x19, KEY_8 }, + { 0x1b, KEY_9 }, + { 0x15, KEY_0 }, + + { 0x0c, KEY_CANCEL }, + { 0x4a, KEY_CLEAR }, + { 0x13, KEY_BACKSPACE }, + { 0x00, KEY_TAB }, + + { 0x4b, KEY_UP }, + { 0x51, KEY_DOWN }, + { 0x4e, KEY_LEFT }, + { 0x52, KEY_RIGHT }, + { 0x4f, KEY_ENTER }, + + { 0x1e, KEY_VOLUMEUP }, + { 0x0a, KEY_VOLUMEDOWN }, + { 0x02, KEY_CHANNELDOWN }, + { 0x05, KEY_CHANNELUP }, + { 0x11, KEY_RECORD }, + + { 0x14, KEY_PLAY }, + { 0x4c, KEY_PAUSE }, + { 0x1a, KEY_STOP }, + { 0x40, KEY_REWIND }, + { 0x12, KEY_FASTFORWARD }, + { 0x41, KEY_PREVIOUSSONG }, + { 0x42, KEY_NEXTSONG }, + { 0x54, KEY_SAVE }, + { 0x50, KEY_LANGUAGE }, + { 0x47, KEY_MEDIA }, + { 0x4d, KEY_SCREEN }, + { 0x43, KEY_SUBTITLE }, + { 0x10, KEY_MUTE }, + { 0x49, KEY_AUDIO }, + { 0x07, KEY_SLEEP }, + { 0x08, KEY_VIDEO }, + { 0x0e, KEY_AGAIN }, + { 0x45, KEY_EQUAL }, + { 0x46, KEY_MINUS }, + { 0x18, KEY_RED }, + { 0x53, KEY_GREEN }, + { 0x5e, KEY_YELLOW }, + { 0x5f, KEY_BLUE }, +}; + +static struct rc_keymap twinhan_vp1027_map = { + .map = { + .scan = twinhan_vp1027, + .size = ARRAY_SIZE(twinhan_vp1027), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_TWINHAN_VP1027_DVBS, + } +}; + +static int __init init_rc_map_twinhan_vp1027(void) +{ + return ir_register_map(&twinhan_vp1027_map); +} + +static void __exit exit_rc_map_twinhan_vp1027(void) +{ + ir_unregister_map(&twinhan_vp1027_map); +} + +module_init(init_rc_map_twinhan_vp1027) +module_exit(exit_rc_map_twinhan_vp1027) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Sergey Ivanov <123kash@gmail.com>"); diff --git a/drivers/media/rc/keymaps/rc-videomate-s350.c b/drivers/media/rc/keymaps/rc-videomate-s350.c new file mode 100644 index 0000000..4df7fcd --- /dev/null +++ b/drivers/media/rc/keymaps/rc-videomate-s350.c @@ -0,0 +1,85 @@ +/* videomate-s350.h - Keytable for videomate_s350 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode videomate_s350[] = { + { 0x00, KEY_TV}, + { 0x01, KEY_DVD}, + { 0x04, KEY_RECORD}, + { 0x05, KEY_VIDEO}, /* TV/Video */ + { 0x07, KEY_STOP}, + { 0x08, KEY_PLAYPAUSE}, + { 0x0a, KEY_REWIND}, + { 0x0f, KEY_FASTFORWARD}, + { 0x10, KEY_CHANNELUP}, + { 0x12, KEY_VOLUMEUP}, + { 0x13, KEY_CHANNELDOWN}, + { 0x14, KEY_MUTE}, + { 0x15, KEY_VOLUMEDOWN}, + { 0x16, KEY_1}, + { 0x17, KEY_2}, + { 0x18, KEY_3}, + { 0x19, KEY_4}, + { 0x1a, KEY_5}, + { 0x1b, KEY_6}, + { 0x1c, KEY_7}, + { 0x1d, KEY_8}, + { 0x1e, KEY_9}, + { 0x1f, KEY_0}, + { 0x21, KEY_SLEEP}, + { 0x24, KEY_ZOOM}, + { 0x25, KEY_LAST}, /* Recall */ + { 0x26, KEY_SUBTITLE}, /* CC */ + { 0x27, KEY_LANGUAGE}, /* MTS */ + { 0x29, KEY_CHANNEL}, /* SURF */ + { 0x2b, KEY_A}, + { 0x2c, KEY_B}, + { 0x2f, KEY_CAMERA}, /* Snapshot */ + { 0x23, KEY_RADIO}, + { 0x02, KEY_PREVIOUSSONG}, + { 0x06, KEY_NEXTSONG}, + { 0x03, KEY_EPG}, + { 0x09, KEY_SETUP}, + { 0x22, KEY_BACKSPACE}, + { 0x0c, KEY_UP}, + { 0x0e, KEY_DOWN}, + { 0x0b, KEY_LEFT}, + { 0x0d, KEY_RIGHT}, + { 0x11, KEY_ENTER}, + { 0x20, KEY_TEXT}, +}; + +static struct rc_keymap videomate_s350_map = { + .map = { + .scan = videomate_s350, + .size = ARRAY_SIZE(videomate_s350), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_VIDEOMATE_S350, + } +}; + +static int __init init_rc_map_videomate_s350(void) +{ + return ir_register_map(&videomate_s350_map); +} + +static void __exit exit_rc_map_videomate_s350(void) +{ + ir_unregister_map(&videomate_s350_map); +} + +module_init(init_rc_map_videomate_s350) +module_exit(exit_rc_map_videomate_s350) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c b/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c new file mode 100644 index 0000000..776b0a6 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c @@ -0,0 +1,87 @@ +/* videomate-tv-pvr.h - Keytable for videomate_tv_pvr Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode videomate_tv_pvr[] = { + { 0x14, KEY_MUTE }, + { 0x24, KEY_ZOOM }, + + { 0x01, KEY_DVD }, + { 0x23, KEY_RADIO }, + { 0x00, KEY_TV }, + + { 0x0a, KEY_REWIND }, + { 0x08, KEY_PLAYPAUSE }, + { 0x0f, KEY_FORWARD }, + + { 0x02, KEY_PREVIOUS }, + { 0x07, KEY_STOP }, + { 0x06, KEY_NEXT }, + + { 0x0c, KEY_UP }, + { 0x0e, KEY_DOWN }, + { 0x0b, KEY_LEFT }, + { 0x0d, KEY_RIGHT }, + { 0x11, KEY_OK }, + + { 0x03, KEY_MENU }, + { 0x09, KEY_SETUP }, + { 0x05, KEY_VIDEO }, + { 0x22, KEY_CHANNEL }, + + { 0x12, KEY_VOLUMEUP }, + { 0x15, KEY_VOLUMEDOWN }, + { 0x10, KEY_CHANNELUP }, + { 0x13, KEY_CHANNELDOWN }, + + { 0x04, KEY_RECORD }, + + { 0x16, KEY_1 }, + { 0x17, KEY_2 }, + { 0x18, KEY_3 }, + { 0x19, KEY_4 }, + { 0x1a, KEY_5 }, + { 0x1b, KEY_6 }, + { 0x1c, KEY_7 }, + { 0x1d, KEY_8 }, + { 0x1e, KEY_9 }, + { 0x1f, KEY_0 }, + + { 0x20, KEY_LANGUAGE }, + { 0x21, KEY_SLEEP }, +}; + +static struct rc_keymap videomate_tv_pvr_map = { + .map = { + .scan = videomate_tv_pvr, + .size = ARRAY_SIZE(videomate_tv_pvr), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_VIDEOMATE_TV_PVR, + } +}; + +static int __init init_rc_map_videomate_tv_pvr(void) +{ + return ir_register_map(&videomate_tv_pvr_map); +} + +static void __exit exit_rc_map_videomate_tv_pvr(void) +{ + ir_unregister_map(&videomate_tv_pvr_map); +} + +module_init(init_rc_map_videomate_tv_pvr) +module_exit(exit_rc_map_videomate_tv_pvr) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c b/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c new file mode 100644 index 0000000..9d2d550 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c @@ -0,0 +1,82 @@ +/* winfast-usbii-deluxe.h - Keytable for winfast_usbii_deluxe Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Leadtek Winfast TV USB II Deluxe remote + Magnus Alm + */ + +static struct ir_scancode winfast_usbii_deluxe[] = { + { 0x62, KEY_0}, + { 0x75, KEY_1}, + { 0x76, KEY_2}, + { 0x77, KEY_3}, + { 0x79, KEY_4}, + { 0x7a, KEY_5}, + { 0x7b, KEY_6}, + { 0x7d, KEY_7}, + { 0x7e, KEY_8}, + { 0x7f, KEY_9}, + + { 0x38, KEY_CAMERA}, /* SNAPSHOT */ + { 0x37, KEY_RECORD}, /* RECORD */ + { 0x35, KEY_TIME}, /* TIMESHIFT */ + + { 0x74, KEY_VOLUMEUP}, /* VOLUMEUP */ + { 0x78, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */ + { 0x64, KEY_MUTE}, /* MUTE */ + + { 0x21, KEY_CHANNEL}, /* SURF */ + { 0x7c, KEY_CHANNELUP}, /* CHANNELUP */ + { 0x60, KEY_CHANNELDOWN}, /* CHANNELDOWN */ + { 0x61, KEY_LAST}, /* LAST CHANNEL (RECALL) */ + + { 0x72, KEY_VIDEO}, /* INPUT MODES (TV/FM) */ + + { 0x70, KEY_POWER2}, /* TV ON/OFF */ + + { 0x39, KEY_CYCLEWINDOWS}, /* MINIMIZE (BOSS) */ + { 0x3a, KEY_NEW}, /* PIP */ + { 0x73, KEY_ZOOM}, /* FULLSECREEN */ + + { 0x66, KEY_INFO}, /* OSD (DISPLAY) */ + + { 0x31, KEY_DOT}, /* '.' */ + { 0x63, KEY_ENTER}, /* ENTER */ + +}; + +static struct rc_keymap winfast_usbii_deluxe_map = { + .map = { + .scan = winfast_usbii_deluxe, + .size = ARRAY_SIZE(winfast_usbii_deluxe), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_WINFAST_USBII_DELUXE, + } +}; + +static int __init init_rc_map_winfast_usbii_deluxe(void) +{ + return ir_register_map(&winfast_usbii_deluxe_map); +} + +static void __exit exit_rc_map_winfast_usbii_deluxe(void) +{ + ir_unregister_map(&winfast_usbii_deluxe_map); +} + +module_init(init_rc_map_winfast_usbii_deluxe) +module_exit(exit_rc_map_winfast_usbii_deluxe) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/keymaps/rc-winfast.c b/drivers/media/rc/keymaps/rc-winfast.c new file mode 100644 index 0000000..0e90a3b --- /dev/null +++ b/drivers/media/rc/keymaps/rc-winfast.c @@ -0,0 +1,102 @@ +/* winfast.h - Keytable for winfast Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ + +static struct ir_scancode winfast[] = { + /* Keys 0 to 9 */ + { 0x12, KEY_0 }, + { 0x05, KEY_1 }, + { 0x06, KEY_2 }, + { 0x07, KEY_3 }, + { 0x09, KEY_4 }, + { 0x0a, KEY_5 }, + { 0x0b, KEY_6 }, + { 0x0d, KEY_7 }, + { 0x0e, KEY_8 }, + { 0x0f, KEY_9 }, + + { 0x00, KEY_POWER }, + { 0x1b, KEY_AUDIO }, /* Audio Source */ + { 0x02, KEY_TUNER }, /* TV/FM, not on Y0400052 */ + { 0x1e, KEY_VIDEO }, /* Video Source */ + { 0x16, KEY_INFO }, /* Display information */ + { 0x04, KEY_VOLUMEUP }, + { 0x08, KEY_VOLUMEDOWN }, + { 0x0c, KEY_CHANNELUP }, + { 0x10, KEY_CHANNELDOWN }, + { 0x03, KEY_ZOOM }, /* fullscreen */ + { 0x1f, KEY_TEXT }, /* closed caption/teletext */ + { 0x20, KEY_SLEEP }, + { 0x29, KEY_CLEAR }, /* boss key */ + { 0x14, KEY_MUTE }, + { 0x2b, KEY_RED }, + { 0x2c, KEY_GREEN }, + { 0x2d, KEY_YELLOW }, + { 0x2e, KEY_BLUE }, + { 0x18, KEY_KPPLUS }, /* fine tune + , not on Y040052 */ + { 0x19, KEY_KPMINUS }, /* fine tune - , not on Y040052 */ + { 0x2a, KEY_MEDIA }, /* PIP (Picture in picture */ + { 0x21, KEY_DOT }, + { 0x13, KEY_ENTER }, + { 0x11, KEY_LAST }, /* Recall (last channel */ + { 0x22, KEY_PREVIOUS }, + { 0x23, KEY_PLAYPAUSE }, + { 0x24, KEY_NEXT }, + { 0x25, KEY_TIME }, /* Time Shifting */ + { 0x26, KEY_STOP }, + { 0x27, KEY_RECORD }, + { 0x28, KEY_SAVE }, /* Screenshot */ + { 0x2f, KEY_MENU }, + { 0x30, KEY_CANCEL }, + { 0x31, KEY_CHANNEL }, /* Channel Surf */ + { 0x32, KEY_SUBTITLE }, + { 0x33, KEY_LANGUAGE }, + { 0x34, KEY_REWIND }, + { 0x35, KEY_FASTFORWARD }, + { 0x36, KEY_TV }, + { 0x37, KEY_RADIO }, /* FM */ + { 0x38, KEY_DVD }, + + { 0x1a, KEY_MODE}, /* change to MCE mode on Y04G0051 */ + { 0x3e, KEY_F21 }, /* MCE +VOL, on Y04G0033 */ + { 0x3a, KEY_F22 }, /* MCE -VOL, on Y04G0033 */ + { 0x3b, KEY_F23 }, /* MCE +CH, on Y04G0033 */ + { 0x3f, KEY_F24 } /* MCE -CH, on Y04G0033 */ +}; + +static struct rc_keymap winfast_map = { + .map = { + .scan = winfast, + .size = ARRAY_SIZE(winfast), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_WINFAST, + } +}; + +static int __init init_rc_map_winfast(void) +{ + return ir_register_map(&winfast_map); +} + +static void __exit exit_rc_map_winfast(void) +{ + ir_unregister_map(&winfast_map); +} + +module_init(init_rc_map_winfast) +module_exit(exit_rc_map_winfast) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c new file mode 100644 index 0000000..756656e --- /dev/null +++ b/drivers/media/rc/lirc_dev.c @@ -0,0 +1,814 @@ +/* + * LIRC base driver + * + * by Artur Lipowski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static int debug; + +#define IRCTL_DEV_NAME "BaseRemoteCtl" +#define NOPLUG -1 +#define LOGHEAD "lirc_dev (%s[%d]): " + +static dev_t lirc_base_dev; + +struct irctl { + struct lirc_driver d; + int attached; + int open; + + struct mutex irctl_lock; + struct lirc_buffer *buf; + unsigned int chunk_size; + + struct task_struct *task; + long jiffies_to_wait; +}; + +static DEFINE_MUTEX(lirc_dev_lock); + +static struct irctl *irctls[MAX_IRCTL_DEVICES]; +static struct cdev cdevs[MAX_IRCTL_DEVICES]; + +/* Only used for sysfs but defined to void otherwise */ +static struct class *lirc_class; + +/* helper function + * initializes the irctl structure + */ +static void lirc_irctl_init(struct irctl *ir) +{ + mutex_init(&ir->irctl_lock); + ir->d.minor = NOPLUG; +} + +static void lirc_irctl_cleanup(struct irctl *ir) +{ + dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor); + + device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor)); + + if (ir->buf != ir->d.rbuf) { + lirc_buffer_free(ir->buf); + kfree(ir->buf); + } + ir->buf = NULL; +} + +/* helper function + * reads key codes from driver and puts them into buffer + * returns 0 on success + */ +static int lirc_add_to_buf(struct irctl *ir) +{ + if (ir->d.add_to_buf) { + int res = -ENODATA; + int got_data = 0; + + /* + * service the device as long as it is returning + * data and we have space + */ +get_data: + res = ir->d.add_to_buf(ir->d.data, ir->buf); + if (res == 0) { + got_data++; + goto get_data; + } + + if (res == -ENODEV) + kthread_stop(ir->task); + + return got_data ? 0 : res; + } + + return 0; +} + +/* main function of the polling thread + */ +static int lirc_thread(void *irctl) +{ + struct irctl *ir = irctl; + + dev_dbg(ir->d.dev, LOGHEAD "poll thread started\n", + ir->d.name, ir->d.minor); + + do { + if (ir->open) { + if (ir->jiffies_to_wait) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(ir->jiffies_to_wait); + } + if (kthread_should_stop()) + break; + if (!lirc_add_to_buf(ir)) + wake_up_interruptible(&ir->buf->wait_poll); + } else { + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + } + } while (!kthread_should_stop()); + + dev_dbg(ir->d.dev, LOGHEAD "poll thread ended\n", + ir->d.name, ir->d.minor); + + return 0; +} + + +static struct file_operations lirc_dev_fops = { + .owner = THIS_MODULE, + .read = lirc_dev_fop_read, + .write = lirc_dev_fop_write, + .poll = lirc_dev_fop_poll, + .unlocked_ioctl = lirc_dev_fop_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = lirc_dev_fop_ioctl, +#endif + .open = lirc_dev_fop_open, + .release = lirc_dev_fop_close, + .llseek = noop_llseek, +}; + +static int lirc_cdev_add(struct irctl *ir) +{ + int retval; + struct lirc_driver *d = &ir->d; + struct cdev *cdev = &cdevs[d->minor]; + + if (d->fops) { + cdev_init(cdev, d->fops); + cdev->owner = d->owner; + } else { + cdev_init(cdev, &lirc_dev_fops); + cdev->owner = THIS_MODULE; + } + kobject_set_name(&cdev->kobj, "lirc%d", d->minor); + + retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1); + if (retval) + kobject_put(&cdev->kobj); + + return retval; +} + +int lirc_register_driver(struct lirc_driver *d) +{ + struct irctl *ir; + int minor; + int bytes_in_key; + unsigned int chunk_size; + unsigned int buffer_size; + int err; + + if (!d) { + printk(KERN_ERR "lirc_dev: lirc_register_driver: " + "driver pointer must be not NULL!\n"); + err = -EBADRQC; + goto out; + } + + if (!d->dev) { + printk(KERN_ERR "%s: dev pointer not filled in!\n", __func__); + err = -EINVAL; + goto out; + } + + if (MAX_IRCTL_DEVICES <= d->minor) { + dev_err(d->dev, "lirc_dev: lirc_register_driver: " + "\"minor\" must be between 0 and %d (%d)!\n", + MAX_IRCTL_DEVICES-1, d->minor); + err = -EBADRQC; + goto out; + } + + if (1 > d->code_length || (BUFLEN * 8) < d->code_length) { + dev_err(d->dev, "lirc_dev: lirc_register_driver: " + "code length in bits for minor (%d) " + "must be less than %d!\n", + d->minor, BUFLEN * 8); + err = -EBADRQC; + goto out; + } + + dev_dbg(d->dev, "lirc_dev: lirc_register_driver: sample_rate: %d\n", + d->sample_rate); + if (d->sample_rate) { + if (2 > d->sample_rate || HZ < d->sample_rate) { + dev_err(d->dev, "lirc_dev: lirc_register_driver: " + "sample_rate must be between 2 and %d!\n", HZ); + err = -EBADRQC; + goto out; + } + if (!d->add_to_buf) { + dev_err(d->dev, "lirc_dev: lirc_register_driver: " + "add_to_buf cannot be NULL when " + "sample_rate is set\n"); + err = -EBADRQC; + goto out; + } + } else if (!(d->fops && d->fops->read) && !d->rbuf) { + dev_err(d->dev, "lirc_dev: lirc_register_driver: " + "fops->read and rbuf cannot all be NULL!\n"); + err = -EBADRQC; + goto out; + } else if (!d->rbuf) { + if (!(d->fops && d->fops->read && d->fops->poll && + d->fops->unlocked_ioctl)) { + dev_err(d->dev, "lirc_dev: lirc_register_driver: " + "neither read, poll nor unlocked_ioctl can be NULL!\n"); + err = -EBADRQC; + goto out; + } + } + + mutex_lock(&lirc_dev_lock); + + minor = d->minor; + + if (minor < 0) { + /* find first free slot for driver */ + for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++) + if (!irctls[minor]) + break; + if (MAX_IRCTL_DEVICES == minor) { + dev_err(d->dev, "lirc_dev: lirc_register_driver: " + "no free slots for drivers!\n"); + err = -ENOMEM; + goto out_lock; + } + } else if (irctls[minor]) { + dev_err(d->dev, "lirc_dev: lirc_register_driver: " + "minor (%d) just registered!\n", minor); + err = -EBUSY; + goto out_lock; + } + + ir = kzalloc(sizeof(struct irctl), GFP_KERNEL); + if (!ir) { + err = -ENOMEM; + goto out_lock; + } + lirc_irctl_init(ir); + irctls[minor] = ir; + d->minor = minor; + + if (d->sample_rate) { + ir->jiffies_to_wait = HZ / d->sample_rate; + } else { + /* it means - wait for external event in task queue */ + ir->jiffies_to_wait = 0; + } + + /* some safety check 8-) */ + d->name[sizeof(d->name)-1] = '\0'; + + bytes_in_key = BITS_TO_LONGS(d->code_length) + + (d->code_length % 8 ? 1 : 0); + buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key; + chunk_size = d->chunk_size ? d->chunk_size : bytes_in_key; + + if (d->rbuf) { + ir->buf = d->rbuf; + } else { + ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + if (!ir->buf) { + err = -ENOMEM; + goto out_lock; + } + err = lirc_buffer_init(ir->buf, chunk_size, buffer_size); + if (err) { + kfree(ir->buf); + goto out_lock; + } + } + ir->chunk_size = ir->buf->chunk_size; + + if (d->features == 0) + d->features = LIRC_CAN_REC_LIRCCODE; + + ir->d = *d; + + device_create(lirc_class, ir->d.dev, + MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL, + "lirc%u", ir->d.minor); + + if (d->sample_rate) { + /* try to fire up polling thread */ + ir->task = kthread_run(lirc_thread, (void *)ir, "lirc_dev"); + if (IS_ERR(ir->task)) { + dev_err(d->dev, "lirc_dev: lirc_register_driver: " + "cannot run poll thread for minor = %d\n", + d->minor); + err = -ECHILD; + goto out_sysfs; + } + } + + err = lirc_cdev_add(ir); + if (err) + goto out_sysfs; + + ir->attached = 1; + mutex_unlock(&lirc_dev_lock); + + dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n", + ir->d.name, ir->d.minor); + return minor; + +out_sysfs: + device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor)); +out_lock: + mutex_unlock(&lirc_dev_lock); +out: + return err; +} +EXPORT_SYMBOL(lirc_register_driver); + +int lirc_unregister_driver(int minor) +{ + struct irctl *ir; + struct cdev *cdev; + + if (minor < 0 || minor >= MAX_IRCTL_DEVICES) { + printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between " + "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES-1); + return -EBADRQC; + } + + ir = irctls[minor]; + if (!ir) { + printk(KERN_ERR "lirc_dev: %s: failed to get irctl struct " + "for minor %d!\n", __func__, minor); + return -ENOENT; + } + + cdev = &cdevs[minor]; + + mutex_lock(&lirc_dev_lock); + + if (ir->d.minor != minor) { + printk(KERN_ERR "lirc_dev: %s: minor (%d) device not " + "registered!\n", __func__, minor); + mutex_unlock(&lirc_dev_lock); + return -ENOENT; + } + + /* end up polling thread */ + if (ir->task) + kthread_stop(ir->task); + + dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n", + ir->d.name, ir->d.minor); + + ir->attached = 0; + if (ir->open) { + dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n", + ir->d.name, ir->d.minor); + wake_up_interruptible(&ir->buf->wait_poll); + mutex_lock(&ir->irctl_lock); + ir->d.set_use_dec(ir->d.data); + module_put(cdev->owner); + mutex_unlock(&ir->irctl_lock); + } else { + lirc_irctl_cleanup(ir); + cdev_del(cdev); + kfree(ir); + irctls[minor] = NULL; + } + + mutex_unlock(&lirc_dev_lock); + + return 0; +} +EXPORT_SYMBOL(lirc_unregister_driver); + +int lirc_dev_fop_open(struct inode *inode, struct file *file) +{ + struct irctl *ir; + struct cdev *cdev; + int retval = 0; + + if (iminor(inode) >= MAX_IRCTL_DEVICES) { + printk(KERN_WARNING "lirc_dev [%d]: open result = -ENODEV\n", + iminor(inode)); + return -ENODEV; + } + + if (mutex_lock_interruptible(&lirc_dev_lock)) + return -ERESTARTSYS; + + ir = irctls[iminor(inode)]; + if (!ir) { + retval = -ENODEV; + goto error; + } + + dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor); + + if (ir->d.minor == NOPLUG) { + retval = -ENODEV; + goto error; + } + + if (ir->open) { + retval = -EBUSY; + goto error; + } + + cdev = &cdevs[iminor(inode)]; + if (try_module_get(cdev->owner)) { + ir->open++; + retval = ir->d.set_use_inc(ir->d.data); + + if (retval) { + module_put(cdev->owner); + ir->open--; + } else { + lirc_buffer_clear(ir->buf); + } + if (ir->task) + wake_up_process(ir->task); + } + +error: + if (ir) + dev_dbg(ir->d.dev, LOGHEAD "open result = %d\n", + ir->d.name, ir->d.minor, retval); + + mutex_unlock(&lirc_dev_lock); + + nonseekable_open(inode, file); + + return retval; +} +EXPORT_SYMBOL(lirc_dev_fop_open); + +int lirc_dev_fop_close(struct inode *inode, struct file *file) +{ + struct irctl *ir = irctls[iminor(inode)]; + struct cdev *cdev = &cdevs[iminor(inode)]; + + if (!ir) { + printk(KERN_ERR "%s: called with invalid irctl\n", __func__); + return -EINVAL; + } + + dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor); + + WARN_ON(mutex_lock_killable(&lirc_dev_lock)); + + ir->open--; + if (ir->attached) { + ir->d.set_use_dec(ir->d.data); + module_put(cdev->owner); + } else { + lirc_irctl_cleanup(ir); + cdev_del(cdev); + irctls[ir->d.minor] = NULL; + kfree(ir); + } + + mutex_unlock(&lirc_dev_lock); + + return 0; +} +EXPORT_SYMBOL(lirc_dev_fop_close); + +unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait) +{ + struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; + unsigned int ret; + + if (!ir) { + printk(KERN_ERR "%s: called with invalid irctl\n", __func__); + return POLLERR; + } + + dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor); + + if (!ir->attached) + return POLLERR; + + poll_wait(file, &ir->buf->wait_poll, wait); + + if (ir->buf) + if (lirc_buffer_empty(ir->buf)) + ret = 0; + else + ret = POLLIN | POLLRDNORM; + else + ret = POLLERR; + + dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n", + ir->d.name, ir->d.minor, ret); + + return ret; +} +EXPORT_SYMBOL(lirc_dev_fop_poll); + +long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + __u32 mode; + int result = 0; + struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; + + if (!ir) { + printk(KERN_ERR "lirc_dev: %s: no irctl found!\n", __func__); + return -ENODEV; + } + + dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n", + ir->d.name, ir->d.minor, cmd); + + if (ir->d.minor == NOPLUG || !ir->attached) { + dev_dbg(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n", + ir->d.name, ir->d.minor); + return -ENODEV; + } + + mutex_lock(&ir->irctl_lock); + + switch (cmd) { + case LIRC_GET_FEATURES: + result = put_user(ir->d.features, (__u32 *)arg); + break; + case LIRC_GET_REC_MODE: + if (!(ir->d.features & LIRC_CAN_REC_MASK)) { + result = -ENOSYS; + break; + } + + result = put_user(LIRC_REC2MODE + (ir->d.features & LIRC_CAN_REC_MASK), + (__u32 *)arg); + break; + case LIRC_SET_REC_MODE: + if (!(ir->d.features & LIRC_CAN_REC_MASK)) { + result = -ENOSYS; + break; + } + + result = get_user(mode, (__u32 *)arg); + if (!result && !(LIRC_MODE2REC(mode) & ir->d.features)) + result = -EINVAL; + /* + * FIXME: We should actually set the mode somehow but + * for now, lirc_serial doesn't support mode changing either + */ + break; + case LIRC_GET_LENGTH: + result = put_user(ir->d.code_length, (__u32 *)arg); + break; + case LIRC_GET_MIN_TIMEOUT: + if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || + ir->d.min_timeout == 0) { + result = -ENOSYS; + break; + } + + result = put_user(ir->d.min_timeout, (__u32 *)arg); + break; + case LIRC_GET_MAX_TIMEOUT: + if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || + ir->d.max_timeout == 0) { + result = -ENOSYS; + break; + } + + result = put_user(ir->d.max_timeout, (__u32 *)arg); + break; + default: + result = -EINVAL; + } + + dev_dbg(ir->d.dev, LOGHEAD "ioctl result = %d\n", + ir->d.name, ir->d.minor, result); + + mutex_unlock(&ir->irctl_lock); + + return result; +} +EXPORT_SYMBOL(lirc_dev_fop_ioctl); + +ssize_t lirc_dev_fop_read(struct file *file, + char *buffer, + size_t length, + loff_t *ppos) +{ + struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; + unsigned char *buf; + int ret = 0, written = 0; + DECLARE_WAITQUEUE(wait, current); + + if (!ir) { + printk(KERN_ERR "%s: called with invalid irctl\n", __func__); + return -ENODEV; + } + + dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor); + + buf = kzalloc(ir->chunk_size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + if (mutex_lock_interruptible(&ir->irctl_lock)) { + ret = -ERESTARTSYS; + goto out_unlocked; + } + if (!ir->attached) { + ret = -ENODEV; + goto out_locked; + } + + if (length % ir->chunk_size) { + ret = -EINVAL; + goto out_locked; + } + + /* + * we add ourselves to the task queue before buffer check + * to avoid losing scan code (in case when queue is awaken somewhere + * between while condition checking and scheduling) + */ + add_wait_queue(&ir->buf->wait_poll, &wait); + set_current_state(TASK_INTERRUPTIBLE); + + /* + * while we didn't provide 'length' bytes, device is opened in blocking + * mode and 'copy_to_user' is happy, wait for data. + */ + while (written < length && ret == 0) { + if (lirc_buffer_empty(ir->buf)) { + /* According to the read(2) man page, 'written' can be + * returned as less than 'length', instead of blocking + * again, returning -EWOULDBLOCK, or returning + * -ERESTARTSYS */ + if (written) + break; + if (file->f_flags & O_NONBLOCK) { + ret = -EWOULDBLOCK; + break; + } + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + + mutex_unlock(&ir->irctl_lock); + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + + if (mutex_lock_interruptible(&ir->irctl_lock)) { + ret = -ERESTARTSYS; + remove_wait_queue(&ir->buf->wait_poll, &wait); + set_current_state(TASK_RUNNING); + goto out_unlocked; + } + + if (!ir->attached) { + ret = -ENODEV; + break; + } + } else { + lirc_buffer_read(ir->buf, buf); + ret = copy_to_user((void *)buffer+written, buf, + ir->buf->chunk_size); + if (!ret) + written += ir->buf->chunk_size; + else + ret = -EFAULT; + } + } + + remove_wait_queue(&ir->buf->wait_poll, &wait); + set_current_state(TASK_RUNNING); + +out_locked: + mutex_unlock(&ir->irctl_lock); + +out_unlocked: + kfree(buf); + dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n", + ir->d.name, ir->d.minor, ret ? "" : "", ret); + + return ret ? ret : written; +} +EXPORT_SYMBOL(lirc_dev_fop_read); + +void *lirc_get_pdata(struct file *file) +{ + void *data = NULL; + + if (file && file->f_dentry && file->f_dentry->d_inode && + file->f_dentry->d_inode->i_rdev) { + struct irctl *ir; + ir = irctls[iminor(file->f_dentry->d_inode)]; + data = ir->d.data; + } + + return data; +} +EXPORT_SYMBOL(lirc_get_pdata); + + +ssize_t lirc_dev_fop_write(struct file *file, const char *buffer, + size_t length, loff_t *ppos) +{ + struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; + + if (!ir) { + printk(KERN_ERR "%s: called with invalid irctl\n", __func__); + return -ENODEV; + } + + dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor); + + if (!ir->attached) + return -ENODEV; + + return -EINVAL; +} +EXPORT_SYMBOL(lirc_dev_fop_write); + + +static int __init lirc_dev_init(void) +{ + int retval; + + lirc_class = class_create(THIS_MODULE, "lirc"); + if (IS_ERR(lirc_class)) { + retval = PTR_ERR(lirc_class); + printk(KERN_ERR "lirc_dev: class_create failed\n"); + goto error; + } + + retval = alloc_chrdev_region(&lirc_base_dev, 0, MAX_IRCTL_DEVICES, + IRCTL_DEV_NAME); + if (retval) { + class_destroy(lirc_class); + printk(KERN_ERR "lirc_dev: alloc_chrdev_region failed\n"); + goto error; + } + + + printk(KERN_INFO "lirc_dev: IR Remote Control driver registered, " + "major %d \n", MAJOR(lirc_base_dev)); + +error: + return retval; +} + + + +static void __exit lirc_dev_exit(void) +{ + class_destroy(lirc_class); + unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES); + printk(KERN_INFO "lirc_dev: module unloaded\n"); +} + +module_init(lirc_dev_init); +module_exit(lirc_dev_exit); + +MODULE_DESCRIPTION("LIRC base driver module"); +MODULE_AUTHOR("Artur Lipowski"); +MODULE_LICENSE("GPL"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable debugging messages"); diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c new file mode 100644 index 0000000..392ca24 --- /dev/null +++ b/drivers/media/rc/mceusb.c @@ -0,0 +1,1333 @@ +/* + * Driver for USB Windows Media Center Ed. eHome Infrared Transceivers + * + * Copyright (c) 2010 by Jarod Wilson + * + * Based on the original lirc_mceusb and lirc_mceusb2 drivers, by Dan + * Conti, Martin Blatter and Daniel Melander, the latter of which was + * in turn also based on the lirc_atiusb driver by Paul Miller. The + * two mce drivers were merged into one by Jarod Wilson, with transmit + * support for the 1st-gen device added primarily by Patrick Calhoun, + * with a bit of tweaks by Jarod. Debugging improvements and proper + * support for what appears to be 3rd-gen hardware added by Jarod. + * Initial port from lirc driver to ir-core drivery by Jarod, based + * partially on a port to an earlier proposed IR infrastructure by + * Jon Smirl, which included enhancements and simplifications to the + * incoming IR buffer parsing routines. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_VERSION "1.91" +#define DRIVER_AUTHOR "Jarod Wilson " +#define DRIVER_DESC "Windows Media Center Ed. eHome Infrared Transceiver " \ + "device driver" +#define DRIVER_NAME "mceusb" + +#define USB_BUFLEN 32 /* USB reception buffer length */ +#define USB_CTRL_MSG_SZ 2 /* Size of usb ctrl msg on gen1 hw */ +#define MCE_G1_INIT_MSGS 40 /* Init messages on gen1 hw to throw out */ +#define MS_TO_NS(msec) ((msec) * 1000) + +/* MCE constants */ +#define MCE_CMDBUF_SIZE 384 /* MCE Command buffer length */ +#define MCE_TIME_UNIT 50 /* Approx 50us resolution */ +#define MCE_CODE_LENGTH 5 /* Normal length of packet (with header) */ +#define MCE_PACKET_SIZE 4 /* Normal length of packet (without header) */ +#define MCE_IRDATA_HEADER 0x84 /* Actual header format is 0x80 + num_bytes */ +#define MCE_IRDATA_TRAILER 0x80 /* End of IR data */ +#define MCE_TX_HEADER_LENGTH 3 /* # of bytes in the initializing tx header */ +#define MCE_MAX_CHANNELS 2 /* Two transmitters, hardware dependent? */ +#define MCE_DEFAULT_TX_MASK 0x03 /* Vals: TX1=0x01, TX2=0x02, ALL=0x03 */ +#define MCE_PULSE_BIT 0x80 /* Pulse bit, MSB set == PULSE else SPACE */ +#define MCE_PULSE_MASK 0x7f /* Pulse mask */ +#define MCE_MAX_PULSE_LENGTH 0x7f /* Longest transmittable pulse symbol */ + +#define MCE_HW_CMD_HEADER 0xff /* MCE hardware command header */ +#define MCE_COMMAND_HEADER 0x9f /* MCE command header */ +#define MCE_COMMAND_MASK 0xe0 /* Mask out command bits */ +#define MCE_COMMAND_NULL 0x00 /* These show up various places... */ +/* if buf[i] & MCE_COMMAND_MASK == 0x80 and buf[i] != MCE_COMMAND_HEADER, + * then we're looking at a raw IR data sample */ +#define MCE_COMMAND_IRDATA 0x80 +#define MCE_PACKET_LENGTH_MASK 0x1f /* Packet length mask */ + +/* Sub-commands, which follow MCE_COMMAND_HEADER or MCE_HW_CMD_HEADER */ +#define MCE_CMD_SIG_END 0x01 /* End of signal */ +#define MCE_CMD_PING 0x03 /* Ping device */ +#define MCE_CMD_UNKNOWN 0x04 /* Unknown */ +#define MCE_CMD_UNKNOWN2 0x05 /* Unknown */ +#define MCE_CMD_S_CARRIER 0x06 /* Set TX carrier frequency */ +#define MCE_CMD_G_CARRIER 0x07 /* Get TX carrier frequency */ +#define MCE_CMD_S_TXMASK 0x08 /* Set TX port bitmask */ +#define MCE_CMD_UNKNOWN3 0x09 /* Unknown */ +#define MCE_CMD_UNKNOWN4 0x0a /* Unknown */ +#define MCE_CMD_G_REVISION 0x0b /* Get hw/sw revision */ +#define MCE_CMD_S_TIMEOUT 0x0c /* Set RX timeout value */ +#define MCE_CMD_G_TIMEOUT 0x0d /* Get RX timeout value */ +#define MCE_CMD_UNKNOWN5 0x0e /* Unknown */ +#define MCE_CMD_UNKNOWN6 0x0f /* Unknown */ +#define MCE_CMD_G_RXPORTSTS 0x11 /* Get RX port status */ +#define MCE_CMD_G_TXMASK 0x13 /* Set TX port bitmask */ +#define MCE_CMD_S_RXSENSOR 0x14 /* Set RX sensor (std/learning) */ +#define MCE_CMD_G_RXSENSOR 0x15 /* Get RX sensor (std/learning) */ +#define MCE_RSP_PULSE_COUNT 0x15 /* RX pulse count (only if learning) */ +#define MCE_CMD_TX_PORTS 0x16 /* Get number of TX ports */ +#define MCE_CMD_G_WAKESRC 0x17 /* Get wake source */ +#define MCE_CMD_UNKNOWN7 0x18 /* Unknown */ +#define MCE_CMD_UNKNOWN8 0x19 /* Unknown */ +#define MCE_CMD_UNKNOWN9 0x1b /* Unknown */ +#define MCE_CMD_DEVICE_RESET 0xaa /* Reset the hardware */ +#define MCE_RSP_CMD_INVALID 0xfe /* Invalid command issued */ + + +/* module parameters */ +#ifdef CONFIG_USB_DEBUG +static int debug = 1; +#else +static int debug; +#endif + +/* general constants */ +#define SEND_FLAG_IN_PROGRESS 1 +#define SEND_FLAG_COMPLETE 2 +#define RECV_FLAG_IN_PROGRESS 3 +#define RECV_FLAG_COMPLETE 4 + +#define MCEUSB_RX 1 +#define MCEUSB_TX 2 + +#define VENDOR_PHILIPS 0x0471 +#define VENDOR_SMK 0x0609 +#define VENDOR_TATUNG 0x1460 +#define VENDOR_GATEWAY 0x107b +#define VENDOR_SHUTTLE 0x1308 +#define VENDOR_SHUTTLE2 0x051c +#define VENDOR_MITSUMI 0x03ee +#define VENDOR_TOPSEED 0x1784 +#define VENDOR_RICAVISION 0x179d +#define VENDOR_ITRON 0x195d +#define VENDOR_FIC 0x1509 +#define VENDOR_LG 0x043e +#define VENDOR_MICROSOFT 0x045e +#define VENDOR_FORMOSA 0x147a +#define VENDOR_FINTEK 0x1934 +#define VENDOR_PINNACLE 0x2304 +#define VENDOR_ECS 0x1019 +#define VENDOR_WISTRON 0x0fb8 +#define VENDOR_COMPRO 0x185b +#define VENDOR_NORTHSTAR 0x04eb +#define VENDOR_REALTEK 0x0bda +#define VENDOR_TIVO 0x105a +#define VENDOR_CONEXANT 0x0572 + +enum mceusb_model_type { + MCE_GEN2 = 0, /* Most boards */ + MCE_GEN1, + MCE_GEN3, + MCE_GEN2_TX_INV, + POLARIS_EVK, + CX_HYBRID_TV, +}; + +struct mceusb_model { + u32 mce_gen1:1; + u32 mce_gen2:1; + u32 mce_gen3:1; + u32 tx_mask_normal:1; + u32 is_polaris:1; + u32 no_tx:1; + + const char *rc_map; /* Allow specify a per-board map */ + const char *name; /* per-board name */ +}; + +static const struct mceusb_model mceusb_model[] = { + [MCE_GEN1] = { + .mce_gen1 = 1, + .tx_mask_normal = 1, + }, + [MCE_GEN2] = { + .mce_gen2 = 1, + }, + [MCE_GEN2_TX_INV] = { + .mce_gen2 = 1, + .tx_mask_normal = 1, + }, + [MCE_GEN3] = { + .mce_gen3 = 1, + .tx_mask_normal = 1, + }, + [POLARIS_EVK] = { + .is_polaris = 1, + /* + * In fact, the EVK is shipped without + * remotes, but we should have something handy, + * to allow testing it + */ + .rc_map = RC_MAP_RC5_HAUPPAUGE_NEW, + .name = "Conexant Hybrid TV (cx231xx) MCE IR", + }, + [CX_HYBRID_TV] = { + .is_polaris = 1, + .no_tx = 1, /* tx isn't wired up at all */ + .name = "Conexant Hybrid TV (cx231xx) MCE IR", + }, +}; + +static struct usb_device_id mceusb_dev_table[] = { + /* Original Microsoft MCE IR Transceiver (often HP-branded) */ + { USB_DEVICE(VENDOR_MICROSOFT, 0x006d), + .driver_info = MCE_GEN1 }, + /* Philips Infrared Transceiver - Sahara branded */ + { USB_DEVICE(VENDOR_PHILIPS, 0x0608) }, + /* Philips Infrared Transceiver - HP branded */ + { USB_DEVICE(VENDOR_PHILIPS, 0x060c), + .driver_info = MCE_GEN2_TX_INV }, + /* Philips SRM5100 */ + { USB_DEVICE(VENDOR_PHILIPS, 0x060d) }, + /* Philips Infrared Transceiver - Omaura */ + { USB_DEVICE(VENDOR_PHILIPS, 0x060f) }, + /* Philips Infrared Transceiver - Spinel plus */ + { USB_DEVICE(VENDOR_PHILIPS, 0x0613) }, + /* Philips eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_PHILIPS, 0x0815) }, + /* Philips/Spinel plus IR transceiver for ASUS */ + { USB_DEVICE(VENDOR_PHILIPS, 0x206c) }, + /* Philips/Spinel plus IR transceiver for ASUS */ + { USB_DEVICE(VENDOR_PHILIPS, 0x2088) }, + /* Realtek MCE IR Receiver */ + { USB_DEVICE(VENDOR_REALTEK, 0x0161) }, + /* SMK/Toshiba G83C0004D410 */ + { USB_DEVICE(VENDOR_SMK, 0x031d), + .driver_info = MCE_GEN2_TX_INV }, + /* SMK eHome Infrared Transceiver (Sony VAIO) */ + { USB_DEVICE(VENDOR_SMK, 0x0322), + .driver_info = MCE_GEN2_TX_INV }, + /* bundled with Hauppauge PVR-150 */ + { USB_DEVICE(VENDOR_SMK, 0x0334), + .driver_info = MCE_GEN2_TX_INV }, + /* SMK eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_SMK, 0x0338) }, + /* Tatung eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_TATUNG, 0x9150) }, + /* Shuttle eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_SHUTTLE, 0xc001) }, + /* Shuttle eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_SHUTTLE2, 0xc001) }, + /* Gateway eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_GATEWAY, 0x3009) }, + /* Mitsumi */ + { USB_DEVICE(VENDOR_MITSUMI, 0x2501) }, + /* Topseed eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_TOPSEED, 0x0001), + .driver_info = MCE_GEN2_TX_INV }, + /* Topseed HP eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_TOPSEED, 0x0006), + .driver_info = MCE_GEN2_TX_INV }, + /* Topseed eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_TOPSEED, 0x0007), + .driver_info = MCE_GEN2_TX_INV }, + /* Topseed eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_TOPSEED, 0x0008), + .driver_info = MCE_GEN3 }, + /* Topseed eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_TOPSEED, 0x000a), + .driver_info = MCE_GEN2_TX_INV }, + /* Topseed eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_TOPSEED, 0x0011), + .driver_info = MCE_GEN2_TX_INV }, + /* Ricavision internal Infrared Transceiver */ + { USB_DEVICE(VENDOR_RICAVISION, 0x0010) }, + /* Itron ione Libra Q-11 */ + { USB_DEVICE(VENDOR_ITRON, 0x7002) }, + /* FIC eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_FIC, 0x9242) }, + /* LG eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_LG, 0x9803) }, + /* Microsoft MCE Infrared Transceiver */ + { USB_DEVICE(VENDOR_MICROSOFT, 0x00a0) }, + /* Formosa eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_FORMOSA, 0xe015) }, + /* Formosa21 / eHome Infrared Receiver */ + { USB_DEVICE(VENDOR_FORMOSA, 0xe016) }, + /* Formosa aim / Trust MCE Infrared Receiver */ + { USB_DEVICE(VENDOR_FORMOSA, 0xe017) }, + /* Formosa Industrial Computing / Beanbag Emulation Device */ + { USB_DEVICE(VENDOR_FORMOSA, 0xe018) }, + /* Formosa21 / eHome Infrared Receiver */ + { USB_DEVICE(VENDOR_FORMOSA, 0xe03a) }, + /* Formosa Industrial Computing AIM IR605/A */ + { USB_DEVICE(VENDOR_FORMOSA, 0xe03c) }, + /* Formosa Industrial Computing */ + { USB_DEVICE(VENDOR_FORMOSA, 0xe03e) }, + /* Fintek eHome Infrared Transceiver (HP branded) */ + { USB_DEVICE(VENDOR_FINTEK, 0x5168) }, + /* Fintek eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_FINTEK, 0x0602) }, + /* Fintek eHome Infrared Transceiver (in the AOpen MP45) */ + { USB_DEVICE(VENDOR_FINTEK, 0x0702) }, + /* Pinnacle Remote Kit */ + { USB_DEVICE(VENDOR_PINNACLE, 0x0225), + .driver_info = MCE_GEN3 }, + /* Elitegroup Computer Systems IR */ + { USB_DEVICE(VENDOR_ECS, 0x0f38) }, + /* Wistron Corp. eHome Infrared Receiver */ + { USB_DEVICE(VENDOR_WISTRON, 0x0002) }, + /* Compro K100 */ + { USB_DEVICE(VENDOR_COMPRO, 0x3020) }, + /* Compro K100 v2 */ + { USB_DEVICE(VENDOR_COMPRO, 0x3082) }, + /* Northstar Systems, Inc. eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) }, + /* TiVo PC IR Receiver */ + { USB_DEVICE(VENDOR_TIVO, 0x2000) }, + /* Conexant Hybrid TV "Shelby" Polaris SDK */ + { USB_DEVICE(VENDOR_CONEXANT, 0x58a1), + .driver_info = POLARIS_EVK }, + /* Conexant Hybrid TV RDU253S Polaris */ + { USB_DEVICE(VENDOR_CONEXANT, 0x58a5), + .driver_info = CX_HYBRID_TV }, + /* Terminating entry */ + { } +}; + +/* data structure for each usb transceiver */ +struct mceusb_dev { + /* ir-core bits */ + struct ir_dev_props *props; + + /* optional features we can enable */ + bool carrier_report_enabled; + bool learning_enabled; + + /* core device bits */ + struct device *dev; + struct input_dev *idev; + + /* usb */ + struct usb_device *usbdev; + struct urb *urb_in; + struct usb_endpoint_descriptor *usb_ep_in; + struct usb_endpoint_descriptor *usb_ep_out; + + /* buffers and dma */ + unsigned char *buf_in; + unsigned int len_in; + dma_addr_t dma_in; + dma_addr_t dma_out; + + enum { + CMD_HEADER = 0, + SUBCMD, + CMD_DATA, + PARSE_IRDATA, + } parser_state; + + u8 cmd, rem; /* Remaining IR data bytes in packet */ + + struct { + u32 connected:1; + u32 tx_mask_normal:1; + u32 microsoft_gen1:1; + u32 no_tx:1; + } flags; + + /* transmit support */ + int send_flags; + u32 carrier; + unsigned char tx_mask; + + char name[128]; + char phys[64]; + enum mceusb_model_type model; +}; + +/* + * MCE Device Command Strings + * Device command responses vary from device to device... + * - DEVICE_RESET resets the hardware to its default state + * - GET_REVISION fetches the hardware/software revision, common + * replies are ff 0b 45 ff 1b 08 and ff 0b 50 ff 1b 42 + * - GET_CARRIER_FREQ gets the carrier mode and frequency of the + * device, with replies in the form of 9f 06 MM FF, where MM is 0-3, + * meaning clk of 10000000, 2500000, 625000 or 156250, and FF is + * ((clk / frequency) - 1) + * - GET_RX_TIMEOUT fetches the receiver timeout in units of 50us, + * response in the form of 9f 0c msb lsb + * - GET_TX_BITMASK fetches the transmitter bitmask, replies in + * the form of 9f 08 bm, where bm is the bitmask + * - GET_RX_SENSOR fetches the RX sensor setting -- long-range + * general use one or short-range learning one, in the form of + * 9f 14 ss, where ss is either 01 for long-range or 02 for short + * - SET_CARRIER_FREQ sets a new carrier mode and frequency + * - SET_TX_BITMASK sets the transmitter bitmask + * - SET_RX_TIMEOUT sets the receiver timeout + * - SET_RX_SENSOR sets which receiver sensor to use + */ +static char DEVICE_RESET[] = {MCE_COMMAND_NULL, MCE_HW_CMD_HEADER, + MCE_CMD_DEVICE_RESET}; +static char GET_REVISION[] = {MCE_HW_CMD_HEADER, MCE_CMD_G_REVISION}; +static char GET_UNKNOWN[] = {MCE_HW_CMD_HEADER, MCE_CMD_UNKNOWN7}; +static char GET_UNKNOWN2[] = {MCE_COMMAND_HEADER, MCE_CMD_UNKNOWN2}; +static char GET_CARRIER_FREQ[] = {MCE_COMMAND_HEADER, MCE_CMD_G_CARRIER}; +static char GET_RX_TIMEOUT[] = {MCE_COMMAND_HEADER, MCE_CMD_G_TIMEOUT}; +static char GET_TX_BITMASK[] = {MCE_COMMAND_HEADER, MCE_CMD_G_TXMASK}; +static char GET_RX_SENSOR[] = {MCE_COMMAND_HEADER, MCE_CMD_G_RXSENSOR}; +/* sub in desired values in lower byte or bytes for full command */ +/* FIXME: make use of these for transmit. +static char SET_CARRIER_FREQ[] = {MCE_COMMAND_HEADER, + MCE_CMD_S_CARRIER, 0x00, 0x00}; +static char SET_TX_BITMASK[] = {MCE_COMMAND_HEADER, MCE_CMD_S_TXMASK, 0x00}; +static char SET_RX_TIMEOUT[] = {MCE_COMMAND_HEADER, + MCE_CMD_S_TIMEOUT, 0x00, 0x00}; +static char SET_RX_SENSOR[] = {MCE_COMMAND_HEADER, + MCE_CMD_S_RXSENSOR, 0x00}; +*/ + +static int mceusb_cmdsize(u8 cmd, u8 subcmd) +{ + int datasize = 0; + + switch (cmd) { + case MCE_COMMAND_NULL: + if (subcmd == MCE_HW_CMD_HEADER) + datasize = 1; + break; + case MCE_HW_CMD_HEADER: + switch (subcmd) { + case MCE_CMD_G_REVISION: + datasize = 2; + break; + } + case MCE_COMMAND_HEADER: + switch (subcmd) { + case MCE_CMD_UNKNOWN: + case MCE_CMD_S_CARRIER: + case MCE_CMD_S_TIMEOUT: + case MCE_RSP_PULSE_COUNT: + datasize = 2; + break; + case MCE_CMD_SIG_END: + case MCE_CMD_S_TXMASK: + case MCE_CMD_S_RXSENSOR: + datasize = 1; + break; + } + } + return datasize; +} + +static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, + int offset, int len, bool out) +{ + char codes[USB_BUFLEN * 3 + 1]; + char inout[9]; + u8 cmd, subcmd, data1, data2; + struct device *dev = ir->dev; + int i, start, skip = 0; + + if (!debug) + return; + + /* skip meaningless 0xb1 0x60 header bytes on orig receiver */ + if (ir->flags.microsoft_gen1 && !out && !offset) + skip = 2; + + if (len <= skip) + return; + + for (i = 0; i < len && i < USB_BUFLEN; i++) + snprintf(codes + i * 3, 4, "%02x ", buf[i + offset] & 0xff); + + dev_info(dev, "%sx data: %s(length=%d)\n", + (out ? "t" : "r"), codes, len); + + if (out) + strcpy(inout, "Request\0"); + else + strcpy(inout, "Got\0"); + + start = offset + skip; + cmd = buf[start] & 0xff; + subcmd = buf[start + 1] & 0xff; + data1 = buf[start + 2] & 0xff; + data2 = buf[start + 3] & 0xff; + + switch (cmd) { + case MCE_COMMAND_NULL: + if ((subcmd == MCE_HW_CMD_HEADER) && + (data1 == MCE_CMD_DEVICE_RESET)) + dev_info(dev, "Device reset requested\n"); + else + dev_info(dev, "Unknown command 0x%02x 0x%02x\n", + cmd, subcmd); + break; + case MCE_HW_CMD_HEADER: + switch (subcmd) { + case MCE_CMD_G_REVISION: + if (len == 2) + dev_info(dev, "Get hw/sw rev?\n"); + else + dev_info(dev, "hw/sw rev 0x%02x 0x%02x " + "0x%02x 0x%02x\n", data1, data2, + buf[start + 4], buf[start + 5]); + break; + case MCE_CMD_DEVICE_RESET: + dev_info(dev, "Device reset requested\n"); + break; + case MCE_RSP_CMD_INVALID: + dev_info(dev, "Previous command not supported\n"); + break; + case MCE_CMD_UNKNOWN7: + case MCE_CMD_UNKNOWN9: + default: + dev_info(dev, "Unknown command 0x%02x 0x%02x\n", + cmd, subcmd); + break; + } + break; + case MCE_COMMAND_HEADER: + switch (subcmd) { + case MCE_CMD_SIG_END: + dev_info(dev, "End of signal\n"); + break; + case MCE_CMD_PING: + dev_info(dev, "Ping\n"); + break; + case MCE_CMD_UNKNOWN: + dev_info(dev, "Resp to 9f 05 of 0x%02x 0x%02x\n", + data1, data2); + break; + case MCE_CMD_S_CARRIER: + dev_info(dev, "%s carrier mode and freq of " + "0x%02x 0x%02x\n", inout, data1, data2); + break; + case MCE_CMD_G_CARRIER: + dev_info(dev, "Get carrier mode and freq\n"); + break; + case MCE_CMD_S_TXMASK: + dev_info(dev, "%s transmit blaster mask of 0x%02x\n", + inout, data1); + break; + case MCE_CMD_S_TIMEOUT: + /* value is in units of 50us, so x*50/100 or x/2 ms */ + dev_info(dev, "%s receive timeout of %d ms\n", + inout, ((data1 << 8) | data2) / 2); + break; + case MCE_CMD_G_TIMEOUT: + dev_info(dev, "Get receive timeout\n"); + break; + case MCE_CMD_G_TXMASK: + dev_info(dev, "Get transmit blaster mask\n"); + break; + case MCE_CMD_S_RXSENSOR: + dev_info(dev, "%s %s-range receive sensor in use\n", + inout, data1 == 0x02 ? "short" : "long"); + break; + case MCE_CMD_G_RXSENSOR: + /* aka MCE_RSP_PULSE_COUNT */ + if (out) + dev_info(dev, "Get receive sensor\n"); + else if (ir->learning_enabled) + dev_info(dev, "RX pulse count: %d\n", + ((data1 << 8) | data2)); + break; + case MCE_RSP_CMD_INVALID: + dev_info(dev, "Error! Hardware is likely wedged...\n"); + break; + case MCE_CMD_UNKNOWN2: + case MCE_CMD_UNKNOWN3: + case MCE_CMD_UNKNOWN5: + default: + dev_info(dev, "Unknown command 0x%02x 0x%02x\n", + cmd, subcmd); + break; + } + break; + default: + break; + } + + if (cmd == MCE_IRDATA_TRAILER) + dev_info(dev, "End of raw IR data\n"); + else if ((cmd != MCE_COMMAND_HEADER) && + ((cmd & MCE_COMMAND_MASK) == MCE_COMMAND_IRDATA)) + dev_info(dev, "Raw IR data, %d pulse/space samples\n", ir->rem); +} + +static void mce_async_callback(struct urb *urb, struct pt_regs *regs) +{ + struct mceusb_dev *ir; + int len; + + if (!urb) + return; + + ir = urb->context; + if (ir) { + len = urb->actual_length; + + dev_dbg(ir->dev, "callback called (status=%d len=%d)\n", + urb->status, len); + + mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true); + } + +} + +/* request incoming or send outgoing usb packet - used to initialize remote */ +static void mce_request_packet(struct mceusb_dev *ir, + struct usb_endpoint_descriptor *ep, + unsigned char *data, int size, int urb_type) +{ + int res; + struct urb *async_urb; + struct device *dev = ir->dev; + unsigned char *async_buf; + + if (urb_type == MCEUSB_TX) { + async_urb = usb_alloc_urb(0, GFP_KERNEL); + if (unlikely(!async_urb)) { + dev_err(dev, "Error, couldn't allocate urb!\n"); + return; + } + + async_buf = kzalloc(size, GFP_KERNEL); + if (!async_buf) { + dev_err(dev, "Error, couldn't allocate buf!\n"); + usb_free_urb(async_urb); + return; + } + + /* outbound data */ + usb_fill_int_urb(async_urb, ir->usbdev, + usb_sndintpipe(ir->usbdev, ep->bEndpointAddress), + async_buf, size, (usb_complete_t)mce_async_callback, + ir, ep->bInterval); + memcpy(async_buf, data, size); + + } else if (urb_type == MCEUSB_RX) { + /* standard request */ + async_urb = ir->urb_in; + ir->send_flags = RECV_FLAG_IN_PROGRESS; + + } else { + dev_err(dev, "Error! Unknown urb type %d\n", urb_type); + return; + } + + dev_dbg(dev, "receive request called (size=%#x)\n", size); + + async_urb->transfer_buffer_length = size; + async_urb->dev = ir->usbdev; + + res = usb_submit_urb(async_urb, GFP_ATOMIC); + if (res) { + dev_dbg(dev, "receive request FAILED! (res=%d)\n", res); + return; + } + dev_dbg(dev, "receive request complete (res=%d)\n", res); +} + +static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size) +{ + mce_request_packet(ir, ir->usb_ep_out, data, size, MCEUSB_TX); +} + +static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size) +{ + mce_request_packet(ir, ir->usb_ep_in, data, size, MCEUSB_RX); +} + +/* Send data out the IR blaster port(s) */ +static int mceusb_tx_ir(void *priv, int *txbuf, u32 n) +{ + struct mceusb_dev *ir = priv; + int i, ret = 0; + int count, cmdcount = 0; + unsigned char *cmdbuf; /* MCE command buffer */ + long signal_duration = 0; /* Singnal length in us */ + struct timeval start_time, end_time; + + do_gettimeofday(&start_time); + + count = n / sizeof(int); + + cmdbuf = kzalloc(sizeof(int) * MCE_CMDBUF_SIZE, GFP_KERNEL); + if (!cmdbuf) + return -ENOMEM; + + /* MCE tx init header */ + cmdbuf[cmdcount++] = MCE_COMMAND_HEADER; + cmdbuf[cmdcount++] = MCE_CMD_S_TXMASK; + cmdbuf[cmdcount++] = ir->tx_mask; + + /* Generate mce packet data */ + for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) { + signal_duration += txbuf[i]; + txbuf[i] = txbuf[i] / MCE_TIME_UNIT; + + do { /* loop to support long pulses/spaces > 127*50us=6.35ms */ + + /* Insert mce packet header every 4th entry */ + if ((cmdcount < MCE_CMDBUF_SIZE) && + (cmdcount - MCE_TX_HEADER_LENGTH) % + MCE_CODE_LENGTH == 0) + cmdbuf[cmdcount++] = MCE_IRDATA_HEADER; + + /* Insert mce packet data */ + if (cmdcount < MCE_CMDBUF_SIZE) + cmdbuf[cmdcount++] = + (txbuf[i] < MCE_PULSE_BIT ? + txbuf[i] : MCE_MAX_PULSE_LENGTH) | + (i & 1 ? 0x00 : MCE_PULSE_BIT); + else { + ret = -EINVAL; + goto out; + } + + } while ((txbuf[i] > MCE_MAX_PULSE_LENGTH) && + (txbuf[i] -= MCE_MAX_PULSE_LENGTH)); + } + + /* Fix packet length in last header */ + cmdbuf[cmdcount - (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH] = + MCE_COMMAND_IRDATA + (cmdcount - MCE_TX_HEADER_LENGTH) % + MCE_CODE_LENGTH - 1; + + /* Check if we have room for the empty packet at the end */ + if (cmdcount >= MCE_CMDBUF_SIZE) { + ret = -EINVAL; + goto out; + } + + /* All mce commands end with an empty packet (0x80) */ + cmdbuf[cmdcount++] = MCE_IRDATA_TRAILER; + + /* Transmit the command to the mce device */ + mce_async_out(ir, cmdbuf, cmdcount); + + /* + * The lircd gap calculation expects the write function to + * wait the time it takes for the ircommand to be sent before + * it returns. + */ + do_gettimeofday(&end_time); + signal_duration -= (end_time.tv_usec - start_time.tv_usec) + + (end_time.tv_sec - start_time.tv_sec) * 1000000; + + /* delay with the closest number of ticks */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(usecs_to_jiffies(signal_duration)); + +out: + kfree(cmdbuf); + return ret ? ret : n; +} + +/* Sets active IR outputs -- mce devices typically have two */ +static int mceusb_set_tx_mask(void *priv, u32 mask) +{ + struct mceusb_dev *ir = priv; + + if (ir->flags.tx_mask_normal) + ir->tx_mask = mask; + else + ir->tx_mask = (mask != MCE_DEFAULT_TX_MASK ? + mask ^ MCE_DEFAULT_TX_MASK : mask) << 1; + + return 0; +} + +/* Sets the send carrier frequency and mode */ +static int mceusb_set_tx_carrier(void *priv, u32 carrier) +{ + struct mceusb_dev *ir = priv; + int clk = 10000000; + int prescaler = 0, divisor = 0; + unsigned char cmdbuf[4] = { MCE_COMMAND_HEADER, + MCE_CMD_S_CARRIER, 0x00, 0x00 }; + + /* Carrier has changed */ + if (ir->carrier != carrier) { + + if (carrier == 0) { + ir->carrier = carrier; + cmdbuf[2] = MCE_CMD_SIG_END; + cmdbuf[3] = MCE_IRDATA_TRAILER; + dev_dbg(ir->dev, "%s: disabling carrier " + "modulation\n", __func__); + mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); + return carrier; + } + + for (prescaler = 0; prescaler < 4; ++prescaler) { + divisor = (clk >> (2 * prescaler)) / carrier; + if (divisor <= 0xff) { + ir->carrier = carrier; + cmdbuf[2] = prescaler; + cmdbuf[3] = divisor; + dev_dbg(ir->dev, "%s: requesting %u HZ " + "carrier\n", __func__, carrier); + + /* Transmit new carrier to mce device */ + mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); + return carrier; + } + } + + return -EINVAL; + + } + + return carrier; +} + +/* + * We don't do anything but print debug spew for many of the command bits + * we receive from the hardware, but some of them are useful information + * we want to store so that we can use them. + */ +static void mceusb_handle_command(struct mceusb_dev *ir, int index) +{ + u8 hi = ir->buf_in[index + 1] & 0xff; + u8 lo = ir->buf_in[index + 2] & 0xff; + + switch (ir->buf_in[index]) { + /* 2-byte return value commands */ + case MCE_CMD_S_TIMEOUT: + ir->props->timeout = MS_TO_NS((hi << 8 | lo) / 2); + break; + + /* 1-byte return value commands */ + case MCE_CMD_S_TXMASK: + ir->tx_mask = hi; + break; + case MCE_CMD_S_RXSENSOR: + ir->learning_enabled = (hi == 0x02); + break; + default: + break; + } +} + +static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) +{ + DEFINE_IR_RAW_EVENT(rawir); + int i = 0; + + /* skip meaningless 0xb1 0x60 header bytes on orig receiver */ + if (ir->flags.microsoft_gen1) + i = 2; + + /* if there's no data, just return now */ + if (buf_len <= i) + return; + + for (; i < buf_len; i++) { + switch (ir->parser_state) { + case SUBCMD: + ir->rem = mceusb_cmdsize(ir->cmd, ir->buf_in[i]); + mceusb_dev_printdata(ir, ir->buf_in, i - 1, + ir->rem + 2, false); + mceusb_handle_command(ir, i); + ir->parser_state = CMD_DATA; + break; + case PARSE_IRDATA: + ir->rem--; + rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0); + rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK) + * MS_TO_NS(MCE_TIME_UNIT); + + dev_dbg(ir->dev, "Storing %s with duration %d\n", + rawir.pulse ? "pulse" : "space", + rawir.duration); + + ir_raw_event_store_with_filter(ir->idev, &rawir); + break; + case CMD_DATA: + ir->rem--; + break; + case CMD_HEADER: + /* decode mce packets of the form (84),AA,BB,CC,DD */ + /* IR data packets can span USB messages - rem */ + ir->cmd = ir->buf_in[i]; + if ((ir->cmd == MCE_COMMAND_HEADER) || + ((ir->cmd & MCE_COMMAND_MASK) != + MCE_COMMAND_IRDATA)) { + ir->parser_state = SUBCMD; + continue; + } + ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK); + mceusb_dev_printdata(ir, ir->buf_in, + i, ir->rem + 1, false); + if (ir->rem) + ir->parser_state = PARSE_IRDATA; + break; + } + + if (ir->parser_state != CMD_HEADER && !ir->rem) + ir->parser_state = CMD_HEADER; + } + dev_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n"); + ir_raw_event_handle(ir->idev); +} + +static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs) +{ + struct mceusb_dev *ir; + int buf_len; + + if (!urb) + return; + + ir = urb->context; + if (!ir) { + usb_unlink_urb(urb); + return; + } + + buf_len = urb->actual_length; + + if (ir->send_flags == RECV_FLAG_IN_PROGRESS) { + ir->send_flags = SEND_FLAG_COMPLETE; + dev_dbg(ir->dev, "setup answer received %d bytes\n", + buf_len); + } + + switch (urb->status) { + /* success */ + case 0: + mceusb_process_ir_data(ir, buf_len); + break; + + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + usb_unlink_urb(urb); + return; + + case -EPIPE: + default: + dev_dbg(ir->dev, "Error: urb status = %d\n", urb->status); + break; + } + + usb_submit_urb(urb, GFP_ATOMIC); +} + +static void mceusb_gen1_init(struct mceusb_dev *ir) +{ + int ret; + int maxp = ir->len_in; + struct device *dev = ir->dev; + char *data; + + data = kzalloc(USB_CTRL_MSG_SZ, GFP_KERNEL); + if (!data) { + dev_err(dev, "%s: memory allocation failed!\n", __func__); + return; + } + + /* + * This is a strange one. Windows issues a set address to the device + * on the receive control pipe and expect a certain value pair back + */ + ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), + USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0, + data, USB_CTRL_MSG_SZ, HZ * 3); + dev_dbg(dev, "%s - ret = %d\n", __func__, ret); + dev_dbg(dev, "%s - data[0] = %d, data[1] = %d\n", + __func__, data[0], data[1]); + + /* set feature: bit rate 38400 bps */ + ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), + USB_REQ_SET_FEATURE, USB_TYPE_VENDOR, + 0xc04e, 0x0000, NULL, 0, HZ * 3); + + dev_dbg(dev, "%s - ret = %d\n", __func__, ret); + + /* bRequest 4: set char length to 8 bits */ + ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), + 4, USB_TYPE_VENDOR, + 0x0808, 0x0000, NULL, 0, HZ * 3); + dev_dbg(dev, "%s - retB = %d\n", __func__, ret); + + /* bRequest 2: set handshaking to use DTR/DSR */ + ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), + 2, USB_TYPE_VENDOR, + 0x0000, 0x0100, NULL, 0, HZ * 3); + dev_dbg(dev, "%s - retC = %d\n", __func__, ret); + + /* device reset */ + mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET)); + mce_sync_in(ir, NULL, maxp); + + /* get hw/sw revision? */ + mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION)); + mce_sync_in(ir, NULL, maxp); + + kfree(data); +}; + +static void mceusb_gen2_init(struct mceusb_dev *ir) +{ + int maxp = ir->len_in; + + /* device reset */ + mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET)); + mce_sync_in(ir, NULL, maxp); + + /* get hw/sw revision? */ + mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION)); + mce_sync_in(ir, NULL, maxp); + + /* unknown what the next two actually return... */ + mce_async_out(ir, GET_UNKNOWN, sizeof(GET_UNKNOWN)); + mce_sync_in(ir, NULL, maxp); + mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2)); + mce_sync_in(ir, NULL, maxp); +} + +static void mceusb_get_parameters(struct mceusb_dev *ir) +{ + int maxp = ir->len_in; + + /* get the carrier and frequency */ + mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ)); + mce_sync_in(ir, NULL, maxp); + + if (!ir->flags.no_tx) { + /* get the transmitter bitmask */ + mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK)); + mce_sync_in(ir, NULL, maxp); + } + + /* get receiver timeout value */ + mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT)); + mce_sync_in(ir, NULL, maxp); + + /* get receiver sensor setting */ + mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR)); + mce_sync_in(ir, NULL, maxp); +} + +static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir) +{ + struct input_dev *idev; + struct ir_dev_props *props; + struct device *dev = ir->dev; + const char *rc_map = RC_MAP_RC6_MCE; + const char *name = "Media Center Ed. eHome Infrared Remote Transceiver"; + int ret = -ENODEV; + + idev = input_allocate_device(); + if (!idev) { + dev_err(dev, "remote input dev allocation failed\n"); + goto idev_alloc_failed; + } + + ret = -ENOMEM; + props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); + if (!props) { + dev_err(dev, "remote ir dev props allocation failed\n"); + goto props_alloc_failed; + } + + if (mceusb_model[ir->model].name) + name = mceusb_model[ir->model].name; + + snprintf(ir->name, sizeof(ir->name), "%s (%04x:%04x)", + name, + le16_to_cpu(ir->usbdev->descriptor.idVendor), + le16_to_cpu(ir->usbdev->descriptor.idProduct)); + + idev->name = ir->name; + usb_make_path(ir->usbdev, ir->phys, sizeof(ir->phys)); + strlcat(ir->phys, "/input0", sizeof(ir->phys)); + idev->phys = ir->phys; + + props->priv = ir; + props->driver_type = RC_DRIVER_IR_RAW; + props->allowed_protos = IR_TYPE_ALL; + props->timeout = MS_TO_NS(1000); + if (!ir->flags.no_tx) { + props->s_tx_mask = mceusb_set_tx_mask; + props->s_tx_carrier = mceusb_set_tx_carrier; + props->tx_ir = mceusb_tx_ir; + } + + ir->props = props; + + usb_to_input_id(ir->usbdev, &idev->id); + idev->dev.parent = ir->dev; + + if (mceusb_model[ir->model].rc_map) + rc_map = mceusb_model[ir->model].rc_map; + + ret = ir_input_register(idev, rc_map, props, DRIVER_NAME); + if (ret < 0) { + dev_err(dev, "remote input device register failed\n"); + goto irdev_failed; + } + + return idev; + +irdev_failed: + kfree(props); +props_alloc_failed: + input_free_device(idev); +idev_alloc_failed: + return NULL; +} + +static int __devinit mceusb_dev_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct usb_host_interface *idesc; + struct usb_endpoint_descriptor *ep = NULL; + struct usb_endpoint_descriptor *ep_in = NULL; + struct usb_endpoint_descriptor *ep_out = NULL; + struct mceusb_dev *ir = NULL; + int pipe, maxp, i; + char buf[63], name[128] = ""; + enum mceusb_model_type model = id->driver_info; + bool is_gen3; + bool is_microsoft_gen1; + bool tx_mask_normal; + bool is_polaris; + + dev_dbg(&intf->dev, "%s called\n", __func__); + + idesc = intf->cur_altsetting; + + is_gen3 = mceusb_model[model].mce_gen3; + is_microsoft_gen1 = mceusb_model[model].mce_gen1; + tx_mask_normal = mceusb_model[model].tx_mask_normal; + is_polaris = mceusb_model[model].is_polaris; + + if (is_polaris) { + /* Interface 0 is IR */ + if (idesc->desc.bInterfaceNumber) + return -ENODEV; + } + + /* step through the endpoints to find first bulk in and out endpoint */ + for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { + ep = &idesc->endpoint[i].desc; + + if ((ep_in == NULL) + && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + == USB_DIR_IN) + && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_BULK) + || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_INT))) { + + ep_in = ep; + ep_in->bmAttributes = USB_ENDPOINT_XFER_INT; + ep_in->bInterval = 1; + dev_dbg(&intf->dev, "acceptable inbound endpoint " + "found\n"); + } + + if ((ep_out == NULL) + && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + == USB_DIR_OUT) + && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_BULK) + || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_INT))) { + + ep_out = ep; + ep_out->bmAttributes = USB_ENDPOINT_XFER_INT; + ep_out->bInterval = 1; + dev_dbg(&intf->dev, "acceptable outbound endpoint " + "found\n"); + } + } + if (ep_in == NULL) { + dev_dbg(&intf->dev, "inbound and/or endpoint not found\n"); + return -ENODEV; + } + + pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress); + maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + + ir = kzalloc(sizeof(struct mceusb_dev), GFP_KERNEL); + if (!ir) + goto mem_alloc_fail; + + ir->buf_in = usb_alloc_coherent(dev, maxp, GFP_ATOMIC, &ir->dma_in); + if (!ir->buf_in) + goto buf_in_alloc_fail; + + ir->urb_in = usb_alloc_urb(0, GFP_KERNEL); + if (!ir->urb_in) + goto urb_in_alloc_fail; + + ir->usbdev = dev; + ir->dev = &intf->dev; + ir->len_in = maxp; + ir->flags.microsoft_gen1 = is_microsoft_gen1; + ir->flags.tx_mask_normal = tx_mask_normal; + ir->flags.no_tx = mceusb_model[model].no_tx; + ir->model = model; + + /* Saving usb interface data for use by the transmitter routine */ + ir->usb_ep_in = ep_in; + ir->usb_ep_out = ep_out; + + if (dev->descriptor.iManufacturer + && usb_string(dev, dev->descriptor.iManufacturer, + buf, sizeof(buf)) > 0) + strlcpy(name, buf, sizeof(name)); + if (dev->descriptor.iProduct + && usb_string(dev, dev->descriptor.iProduct, + buf, sizeof(buf)) > 0) + snprintf(name + strlen(name), sizeof(name) - strlen(name), + " %s", buf); + + ir->idev = mceusb_init_input_dev(ir); + if (!ir->idev) + goto input_dev_fail; + + /* flush buffers on the device */ + mce_sync_in(ir, NULL, maxp); + mce_sync_in(ir, NULL, maxp); + + /* wire up inbound data handler */ + usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, + maxp, (usb_complete_t) mceusb_dev_recv, ir, ep_in->bInterval); + ir->urb_in->transfer_dma = ir->dma_in; + ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + /* initialize device */ + if (ir->flags.microsoft_gen1) + mceusb_gen1_init(ir); + else if (!is_gen3) + mceusb_gen2_init(ir); + + mceusb_get_parameters(ir); + + if (!ir->flags.no_tx) + mceusb_set_tx_mask(ir, MCE_DEFAULT_TX_MASK); + + usb_set_intfdata(intf, ir); + + dev_info(&intf->dev, "Registered %s on usb%d:%d\n", name, + dev->bus->busnum, dev->devnum); + + return 0; + + /* Error-handling path */ +input_dev_fail: + usb_free_urb(ir->urb_in); +urb_in_alloc_fail: + usb_free_coherent(dev, maxp, ir->buf_in, ir->dma_in); +buf_in_alloc_fail: + kfree(ir); +mem_alloc_fail: + dev_err(&intf->dev, "%s: device setup failed!\n", __func__); + + return -ENOMEM; +} + + +static void __devexit mceusb_dev_disconnect(struct usb_interface *intf) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct mceusb_dev *ir = usb_get_intfdata(intf); + + usb_set_intfdata(intf, NULL); + + if (!ir) + return; + + ir->usbdev = NULL; + ir_input_unregister(ir->idev); + usb_kill_urb(ir->urb_in); + usb_free_urb(ir->urb_in); + usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in); + + kfree(ir); +} + +static int mceusb_dev_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct mceusb_dev *ir = usb_get_intfdata(intf); + dev_info(ir->dev, "suspend\n"); + usb_kill_urb(ir->urb_in); + return 0; +} + +static int mceusb_dev_resume(struct usb_interface *intf) +{ + struct mceusb_dev *ir = usb_get_intfdata(intf); + dev_info(ir->dev, "resume\n"); + if (usb_submit_urb(ir->urb_in, GFP_ATOMIC)) + return -EIO; + return 0; +} + +static struct usb_driver mceusb_dev_driver = { + .name = DRIVER_NAME, + .probe = mceusb_dev_probe, + .disconnect = mceusb_dev_disconnect, + .suspend = mceusb_dev_suspend, + .resume = mceusb_dev_resume, + .reset_resume = mceusb_dev_resume, + .id_table = mceusb_dev_table +}; + +static int __init mceusb_dev_init(void) +{ + int ret; + + ret = usb_register(&mceusb_dev_driver); + if (ret < 0) + printk(KERN_ERR DRIVER_NAME + ": usb register failed, result = %d\n", ret); + + return ret; +} + +static void __exit mceusb_dev_exit(void) +{ + usb_deregister(&mceusb_dev_driver); +} + +module_init(mceusb_dev_init); +module_exit(mceusb_dev_exit); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(usb, mceusb_dev_table); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug enabled or not"); diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c new file mode 100644 index 0000000..acc729c --- /dev/null +++ b/drivers/media/rc/nuvoton-cir.c @@ -0,0 +1,1252 @@ +/* + * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR + * + * Copyright (C) 2010 Jarod Wilson + * Copyright (C) 2009 Nuvoton PS Team + * + * Special thanks to Nuvoton for providing hardware, spec sheets and + * sample code upon which portions of this driver are based. Indirect + * thanks also to Maxim Levitsky, whose ene_ir driver this driver is + * modeled after. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nuvoton-cir.h" + +static char *chip_id = "w836x7hg"; + +/* write val to config reg */ +static inline void nvt_cr_write(struct nvt_dev *nvt, u8 val, u8 reg) +{ + outb(reg, nvt->cr_efir); + outb(val, nvt->cr_efdr); +} + +/* read val from config reg */ +static inline u8 nvt_cr_read(struct nvt_dev *nvt, u8 reg) +{ + outb(reg, nvt->cr_efir); + return inb(nvt->cr_efdr); +} + +/* update config register bit without changing other bits */ +static inline void nvt_set_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg) +{ + u8 tmp = nvt_cr_read(nvt, reg) | val; + nvt_cr_write(nvt, tmp, reg); +} + +/* clear config register bit without changing other bits */ +static inline void nvt_clear_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg) +{ + u8 tmp = nvt_cr_read(nvt, reg) & ~val; + nvt_cr_write(nvt, tmp, reg); +} + +/* enter extended function mode */ +static inline void nvt_efm_enable(struct nvt_dev *nvt) +{ + /* Enabling Extended Function Mode explicitly requires writing 2x */ + outb(EFER_EFM_ENABLE, nvt->cr_efir); + outb(EFER_EFM_ENABLE, nvt->cr_efir); +} + +/* exit extended function mode */ +static inline void nvt_efm_disable(struct nvt_dev *nvt) +{ + outb(EFER_EFM_DISABLE, nvt->cr_efir); +} + +/* + * When you want to address a specific logical device, write its logical + * device number to CR_LOGICAL_DEV_SEL, then enable/disable by writing + * 0x1/0x0 respectively to CR_LOGICAL_DEV_EN. + */ +static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev) +{ + outb(CR_LOGICAL_DEV_SEL, nvt->cr_efir); + outb(ldev, nvt->cr_efdr); +} + +/* write val to cir config register */ +static inline void nvt_cir_reg_write(struct nvt_dev *nvt, u8 val, u8 offset) +{ + outb(val, nvt->cir_addr + offset); +} + +/* read val from cir config register */ +static u8 nvt_cir_reg_read(struct nvt_dev *nvt, u8 offset) +{ + u8 val; + + val = inb(nvt->cir_addr + offset); + + return val; +} + +/* write val to cir wake register */ +static inline void nvt_cir_wake_reg_write(struct nvt_dev *nvt, + u8 val, u8 offset) +{ + outb(val, nvt->cir_wake_addr + offset); +} + +/* read val from cir wake config register */ +static u8 nvt_cir_wake_reg_read(struct nvt_dev *nvt, u8 offset) +{ + u8 val; + + val = inb(nvt->cir_wake_addr + offset); + + return val; +} + +#define pr_reg(text, ...) \ + printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__) + +/* dump current cir register contents */ +static void cir_dump_regs(struct nvt_dev *nvt) +{ + nvt_efm_enable(nvt); + nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); + + pr_reg("%s: Dump CIR logical device registers:\n", NVT_DRIVER_NAME); + pr_reg(" * CR CIR ACTIVE : 0x%x\n", + nvt_cr_read(nvt, CR_LOGICAL_DEV_EN)); + pr_reg(" * CR CIR BASE ADDR: 0x%x\n", + (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) | + nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO)); + pr_reg(" * CR CIR IRQ NUM: 0x%x\n", + nvt_cr_read(nvt, CR_CIR_IRQ_RSRC)); + + nvt_efm_disable(nvt); + + pr_reg("%s: Dump CIR registers:\n", NVT_DRIVER_NAME); + pr_reg(" * IRCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRCON)); + pr_reg(" * IRSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRSTS)); + pr_reg(" * IREN: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IREN)); + pr_reg(" * RXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_RXFCONT)); + pr_reg(" * CP: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CP)); + pr_reg(" * CC: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CC)); + pr_reg(" * SLCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCH)); + pr_reg(" * SLCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCL)); + pr_reg(" * FIFOCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FIFOCON)); + pr_reg(" * IRFIFOSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFIFOSTS)); + pr_reg(" * SRXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SRXFIFO)); + pr_reg(" * TXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_TXFCONT)); + pr_reg(" * STXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_STXFIFO)); + pr_reg(" * FCCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCH)); + pr_reg(" * FCCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCL)); + pr_reg(" * IRFSM: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFSM)); +} + +/* dump current cir wake register contents */ +static void cir_wake_dump_regs(struct nvt_dev *nvt) +{ + u8 i, fifo_len; + + nvt_efm_enable(nvt); + nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); + + pr_reg("%s: Dump CIR WAKE logical device registers:\n", + NVT_DRIVER_NAME); + pr_reg(" * CR CIR WAKE ACTIVE : 0x%x\n", + nvt_cr_read(nvt, CR_LOGICAL_DEV_EN)); + pr_reg(" * CR CIR WAKE BASE ADDR: 0x%x\n", + (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) | + nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO)); + pr_reg(" * CR CIR WAKE IRQ NUM: 0x%x\n", + nvt_cr_read(nvt, CR_CIR_IRQ_RSRC)); + + nvt_efm_disable(nvt); + + pr_reg("%s: Dump CIR WAKE registers\n", NVT_DRIVER_NAME); + pr_reg(" * IRCON: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON)); + pr_reg(" * IRSTS: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS)); + pr_reg(" * IREN: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN)); + pr_reg(" * FIFO CMP DEEP: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_DEEP)); + pr_reg(" * FIFO CMP TOL: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_TOL)); + pr_reg(" * FIFO COUNT: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT)); + pr_reg(" * SLCH: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCH)); + pr_reg(" * SLCL: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCL)); + pr_reg(" * FIFOCON: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON)); + pr_reg(" * SRXFSTS: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_SRXFSTS)); + pr_reg(" * SAMPLE RX FIFO: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_SAMPLE_RX_FIFO)); + pr_reg(" * WR FIFO DATA: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_WR_FIFO_DATA)); + pr_reg(" * RD FIFO ONLY: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY)); + pr_reg(" * RD FIFO ONLY IDX: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)); + pr_reg(" * FIFO IGNORE: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_IGNORE)); + pr_reg(" * IRFSM: 0x%x\n", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRFSM)); + + fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT); + pr_reg("%s: Dump CIR WAKE FIFO (len %d)\n", NVT_DRIVER_NAME, fifo_len); + pr_reg("* Contents = "); + for (i = 0; i < fifo_len; i++) + printk(KERN_CONT "%02x ", + nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY)); + printk(KERN_CONT "\n"); +} + +/* detect hardware features */ +static int nvt_hw_detect(struct nvt_dev *nvt) +{ + unsigned long flags; + u8 chip_major, chip_minor; + int ret = 0; + + nvt_efm_enable(nvt); + + /* Check if we're wired for the alternate EFER setup */ + chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); + if (chip_major == 0xff) { + nvt->cr_efir = CR_EFIR2; + nvt->cr_efdr = CR_EFDR2; + nvt_efm_enable(nvt); + chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); + } + + chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO); + nvt_dbg("%s: chip id: 0x%02x 0x%02x", chip_id, chip_major, chip_minor); + + if (chip_major != CHIP_ID_HIGH && + (chip_minor != CHIP_ID_LOW || chip_minor != CHIP_ID_LOW2)) + ret = -ENODEV; + + nvt_efm_disable(nvt); + + spin_lock_irqsave(&nvt->nvt_lock, flags); + nvt->chip_major = chip_major; + nvt->chip_minor = chip_minor; + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + + return ret; +} + +static void nvt_cir_ldev_init(struct nvt_dev *nvt) +{ + u8 val; + + /* output pin selection (Pin95=CIRRX, Pin96=CIRTX1, WB enabled */ + val = nvt_cr_read(nvt, CR_OUTPUT_PIN_SEL); + val &= OUTPUT_PIN_SEL_MASK; + val |= (OUTPUT_ENABLE_CIR | OUTPUT_ENABLE_CIRWB); + nvt_cr_write(nvt, val, CR_OUTPUT_PIN_SEL); + + /* Select CIR logical device and enable */ + nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); + nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); + + nvt_cr_write(nvt, nvt->cir_addr >> 8, CR_CIR_BASE_ADDR_HI); + nvt_cr_write(nvt, nvt->cir_addr & 0xff, CR_CIR_BASE_ADDR_LO); + + nvt_cr_write(nvt, nvt->cir_irq, CR_CIR_IRQ_RSRC); + + nvt_dbg("CIR initialized, base io port address: 0x%lx, irq: %d", + nvt->cir_addr, nvt->cir_irq); +} + +static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt) +{ + /* Select ACPI logical device, enable it and CIR Wake */ + nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI); + nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); + + /* Enable CIR Wake via PSOUT# (Pin60) */ + nvt_set_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE); + + /* enable cir interrupt of mouse/keyboard IRQ event */ + nvt_set_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS); + + /* enable pme interrupt of cir wakeup event */ + nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2); + + /* Select CIR Wake logical device and enable */ + nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); + nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); + + nvt_cr_write(nvt, nvt->cir_wake_addr >> 8, CR_CIR_BASE_ADDR_HI); + nvt_cr_write(nvt, nvt->cir_wake_addr & 0xff, CR_CIR_BASE_ADDR_LO); + + nvt_cr_write(nvt, nvt->cir_wake_irq, CR_CIR_IRQ_RSRC); + + nvt_dbg("CIR Wake initialized, base io port address: 0x%lx, irq: %d", + nvt->cir_wake_addr, nvt->cir_wake_irq); +} + +/* clear out the hardware's cir rx fifo */ +static void nvt_clear_cir_fifo(struct nvt_dev *nvt) +{ + u8 val; + + val = nvt_cir_reg_read(nvt, CIR_FIFOCON); + nvt_cir_reg_write(nvt, val | CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON); +} + +/* clear out the hardware's cir wake rx fifo */ +static void nvt_clear_cir_wake_fifo(struct nvt_dev *nvt) +{ + u8 val; + + val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON); + nvt_cir_wake_reg_write(nvt, val | CIR_WAKE_FIFOCON_RXFIFOCLR, + CIR_WAKE_FIFOCON); +} + +/* clear out the hardware's cir tx fifo */ +static void nvt_clear_tx_fifo(struct nvt_dev *nvt) +{ + u8 val; + + val = nvt_cir_reg_read(nvt, CIR_FIFOCON); + nvt_cir_reg_write(nvt, val | CIR_FIFOCON_TXFIFOCLR, CIR_FIFOCON); +} + +/* enable RX Trigger Level Reach and Packet End interrupts */ +static void nvt_set_cir_iren(struct nvt_dev *nvt) +{ + u8 iren; + + iren = CIR_IREN_RTR | CIR_IREN_PE; + nvt_cir_reg_write(nvt, iren, CIR_IREN); +} + +static void nvt_cir_regs_init(struct nvt_dev *nvt) +{ + /* set sample limit count (PE interrupt raised when reached) */ + nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_SLCH); + nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_SLCL); + + /* set fifo irq trigger levels */ + nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV | + CIR_FIFOCON_RX_TRIGGER_LEV, CIR_FIFOCON); + + /* + * Enable TX and RX, specify carrier on = low, off = high, and set + * sample period (currently 50us) + */ + nvt_cir_reg_write(nvt, + CIR_IRCON_TXEN | CIR_IRCON_RXEN | + CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, + CIR_IRCON); + + /* clear hardware rx and tx fifos */ + nvt_clear_cir_fifo(nvt); + nvt_clear_tx_fifo(nvt); + + /* clear any and all stray interrupts */ + nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); + + /* and finally, enable interrupts */ + nvt_set_cir_iren(nvt); +} + +static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) +{ + /* set number of bytes needed for wake key comparison (default 67) */ + nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFO_LEN, CIR_WAKE_FIFO_CMP_DEEP); + + /* set tolerance/variance allowed per byte during wake compare */ + nvt_cir_wake_reg_write(nvt, CIR_WAKE_CMP_TOLERANCE, + CIR_WAKE_FIFO_CMP_TOL); + + /* set sample limit count (PE interrupt raised when reached) */ + nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_WAKE_SLCH); + nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_WAKE_SLCL); + + /* set cir wake fifo rx trigger level (currently 67) */ + nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFOCON_RX_TRIGGER_LEV, + CIR_WAKE_FIFOCON); + + /* + * Enable TX and RX, specific carrier on = low, off = high, and set + * sample period (currently 50us) + */ + nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | + CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | + CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, + CIR_WAKE_IRCON); + + /* clear cir wake rx fifo */ + nvt_clear_cir_wake_fifo(nvt); + + /* clear any and all stray interrupts */ + nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); +} + +static void nvt_enable_wake(struct nvt_dev *nvt) +{ + nvt_efm_enable(nvt); + + nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI); + nvt_set_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE); + nvt_set_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS); + nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2); + + nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); + nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); + + nvt_efm_disable(nvt); + + nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | + CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | + CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, + CIR_WAKE_IRCON); + nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); + nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN); +} + +/* rx carrier detect only works in learning mode, must be called w/nvt_lock */ +static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt) +{ + u32 count, carrier, duration = 0; + int i; + + count = nvt_cir_reg_read(nvt, CIR_FCCL) | + nvt_cir_reg_read(nvt, CIR_FCCH) << 8; + + for (i = 0; i < nvt->pkts; i++) { + if (nvt->buf[i] & BUF_PULSE_BIT) + duration += nvt->buf[i] & BUF_LEN_MASK; + } + + duration *= SAMPLE_PERIOD; + + if (!count || !duration) { + nvt_pr(KERN_NOTICE, "Unable to determine carrier! (c:%u, d:%u)", + count, duration); + return 0; + } + + carrier = (count * 1000000) / duration; + + if ((carrier > MAX_CARRIER) || (carrier < MIN_CARRIER)) + nvt_dbg("WTF? Carrier frequency out of range!"); + + nvt_dbg("Carrier frequency: %u (count %u, duration %u)", + carrier, count, duration); + + return carrier; +} + +/* + * set carrier frequency + * + * set carrier on 2 registers: CP & CC + * always set CP as 0x81 + * set CC by SPEC, CC = 3MHz/carrier - 1 + */ +static int nvt_set_tx_carrier(void *data, u32 carrier) +{ + struct nvt_dev *nvt = data; + u16 val; + + nvt_cir_reg_write(nvt, 1, CIR_CP); + val = 3000000 / (carrier) - 1; + nvt_cir_reg_write(nvt, val & 0xff, CIR_CC); + + nvt_dbg("cp: 0x%x cc: 0x%x\n", + nvt_cir_reg_read(nvt, CIR_CP), nvt_cir_reg_read(nvt, CIR_CC)); + + return 0; +} + +/* + * nvt_tx_ir + * + * 1) clean TX fifo first (handled by AP) + * 2) copy data from user space + * 3) disable RX interrupts, enable TX interrupts: TTR & TFU + * 4) send 9 packets to TX FIFO to open TTR + * in interrupt_handler: + * 5) send all data out + * go back to write(): + * 6) disable TX interrupts, re-enable RX interupts + * + * The key problem of this function is user space data may larger than + * driver's data buf length. So nvt_tx_ir() will only copy TX_BUF_LEN data to + * buf, and keep current copied data buf num in cur_buf_num. But driver's buf + * number may larger than TXFCONT (0xff). So in interrupt_handler, it has to + * set TXFCONT as 0xff, until buf_count less than 0xff. + */ +static int nvt_tx_ir(void *priv, int *txbuf, u32 n) +{ + struct nvt_dev *nvt = priv; + unsigned long flags; + size_t cur_count; + unsigned int i; + u8 iren; + int ret; + + spin_lock_irqsave(&nvt->tx.lock, flags); + + if (n >= TX_BUF_LEN) { + nvt->tx.buf_count = cur_count = TX_BUF_LEN; + ret = TX_BUF_LEN; + } else { + nvt->tx.buf_count = cur_count = n; + ret = n; + } + + memcpy(nvt->tx.buf, txbuf, nvt->tx.buf_count); + + nvt->tx.cur_buf_num = 0; + + /* save currently enabled interrupts */ + iren = nvt_cir_reg_read(nvt, CIR_IREN); + + /* now disable all interrupts, save TFU & TTR */ + nvt_cir_reg_write(nvt, CIR_IREN_TFU | CIR_IREN_TTR, CIR_IREN); + + nvt->tx.tx_state = ST_TX_REPLY; + + nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV_8 | + CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON); + + /* trigger TTR interrupt by writing out ones, (yes, it's ugly) */ + for (i = 0; i < 9; i++) + nvt_cir_reg_write(nvt, 0x01, CIR_STXFIFO); + + spin_unlock_irqrestore(&nvt->tx.lock, flags); + + wait_event(nvt->tx.queue, nvt->tx.tx_state == ST_TX_REQUEST); + + spin_lock_irqsave(&nvt->tx.lock, flags); + nvt->tx.tx_state = ST_TX_NONE; + spin_unlock_irqrestore(&nvt->tx.lock, flags); + + /* restore enabled interrupts to prior state */ + nvt_cir_reg_write(nvt, iren, CIR_IREN); + + return ret; +} + +/* dump contents of the last rx buffer we got from the hw rx fifo */ +static void nvt_dump_rx_buf(struct nvt_dev *nvt) +{ + int i; + + printk(KERN_DEBUG "%s (len %d): ", __func__, nvt->pkts); + for (i = 0; (i < nvt->pkts) && (i < RX_BUF_LEN); i++) + printk(KERN_CONT "0x%02x ", nvt->buf[i]); + printk(KERN_CONT "\n"); +} + +/* + * Process raw data in rx driver buffer, store it in raw IR event kfifo, + * trigger decode when appropriate. + * + * We get IR data samples one byte at a time. If the msb is set, its a pulse, + * otherwise its a space. The lower 7 bits are the count of SAMPLE_PERIOD + * (default 50us) intervals for that pulse/space. A discrete signal is + * followed by a series of 0x7f packets, then either 0x7 or 0x80 + * to signal more IR coming (repeats) or end of IR, respectively. We store + * sample data in the raw event kfifo until we see 0x7 (except f) + * or 0x80, at which time, we trigger a decode operation. + */ +static void nvt_process_rx_ir_data(struct nvt_dev *nvt) +{ + DEFINE_IR_RAW_EVENT(rawir); + unsigned int count; + u32 carrier; + u8 sample; + int i; + + nvt_dbg_verbose("%s firing", __func__); + + if (debug) + nvt_dump_rx_buf(nvt); + + if (nvt->carrier_detect_enabled) + carrier = nvt_rx_carrier_detect(nvt); + + count = nvt->pkts; + nvt_dbg_verbose("Processing buffer of len %d", count); + + init_ir_raw_event(&rawir); + + for (i = 0; i < count; i++) { + nvt->pkts--; + sample = nvt->buf[i]; + + rawir.pulse = ((sample & BUF_PULSE_BIT) != 0); + rawir.duration = (sample & BUF_LEN_MASK) + * SAMPLE_PERIOD * 1000; + + if ((sample & BUF_LEN_MASK) == BUF_LEN_MASK) { + if (nvt->rawir.pulse == rawir.pulse) + nvt->rawir.duration += rawir.duration; + else { + nvt->rawir.duration = rawir.duration; + nvt->rawir.pulse = rawir.pulse; + } + continue; + } + + rawir.duration += nvt->rawir.duration; + + init_ir_raw_event(&nvt->rawir); + nvt->rawir.duration = 0; + nvt->rawir.pulse = rawir.pulse; + + if (sample == BUF_PULSE_BIT) + rawir.pulse = false; + + if (rawir.duration) { + nvt_dbg("Storing %s with duration %d", + rawir.pulse ? "pulse" : "space", + rawir.duration); + + ir_raw_event_store(nvt->rdev, &rawir); + } + + /* + * BUF_PULSE_BIT indicates end of IR data, BUF_REPEAT_BYTE + * indicates end of IR signal, but new data incoming. In both + * cases, it means we're ready to call ir_raw_event_handle + */ + if ((sample == BUF_PULSE_BIT) && nvt->pkts) { + nvt_dbg("Calling ir_raw_event_handle (signal end)\n"); + ir_raw_event_handle(nvt->rdev); + } + } + + nvt_dbg("Calling ir_raw_event_handle (buffer empty)\n"); + ir_raw_event_handle(nvt->rdev); + + if (nvt->pkts) { + nvt_dbg("Odd, pkts should be 0 now... (its %u)", nvt->pkts); + nvt->pkts = 0; + } + + nvt_dbg_verbose("%s done", __func__); +} + +static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt) +{ + nvt_pr(KERN_WARNING, "RX FIFO overrun detected, flushing data!"); + + nvt->pkts = 0; + nvt_clear_cir_fifo(nvt); + ir_raw_event_reset(nvt->rdev); +} + +/* copy data from hardware rx fifo into driver buffer */ +static void nvt_get_rx_ir_data(struct nvt_dev *nvt) +{ + unsigned long flags; + u8 fifocount, val; + unsigned int b_idx; + bool overrun = false; + int i; + + /* Get count of how many bytes to read from RX FIFO */ + fifocount = nvt_cir_reg_read(nvt, CIR_RXFCONT); + /* if we get 0xff, probably means the logical dev is disabled */ + if (fifocount == 0xff) + return; + /* watch out for a fifo overrun condition */ + else if (fifocount > RX_BUF_LEN) { + overrun = true; + fifocount = RX_BUF_LEN; + } + + nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount); + + spin_lock_irqsave(&nvt->nvt_lock, flags); + + b_idx = nvt->pkts; + + /* This should never happen, but lets check anyway... */ + if (b_idx + fifocount > RX_BUF_LEN) { + nvt_process_rx_ir_data(nvt); + b_idx = 0; + } + + /* Read fifocount bytes from CIR Sample RX FIFO register */ + for (i = 0; i < fifocount; i++) { + val = nvt_cir_reg_read(nvt, CIR_SRXFIFO); + nvt->buf[b_idx + i] = val; + } + + nvt->pkts += fifocount; + nvt_dbg("%s: pkts now %d", __func__, nvt->pkts); + + nvt_process_rx_ir_data(nvt); + + if (overrun) + nvt_handle_rx_fifo_overrun(nvt); + + spin_unlock_irqrestore(&nvt->nvt_lock, flags); +} + +static void nvt_cir_log_irqs(u8 status, u8 iren) +{ + nvt_pr(KERN_INFO, "IRQ 0x%02x (IREN 0x%02x) :%s%s%s%s%s%s%s%s%s", + status, iren, + status & CIR_IRSTS_RDR ? " RDR" : "", + status & CIR_IRSTS_RTR ? " RTR" : "", + status & CIR_IRSTS_PE ? " PE" : "", + status & CIR_IRSTS_RFO ? " RFO" : "", + status & CIR_IRSTS_TE ? " TE" : "", + status & CIR_IRSTS_TTR ? " TTR" : "", + status & CIR_IRSTS_TFU ? " TFU" : "", + status & CIR_IRSTS_GH ? " GH" : "", + status & ~(CIR_IRSTS_RDR | CIR_IRSTS_RTR | CIR_IRSTS_PE | + CIR_IRSTS_RFO | CIR_IRSTS_TE | CIR_IRSTS_TTR | + CIR_IRSTS_TFU | CIR_IRSTS_GH) ? " ?" : ""); +} + +static bool nvt_cir_tx_inactive(struct nvt_dev *nvt) +{ + unsigned long flags; + bool tx_inactive; + u8 tx_state; + + spin_lock_irqsave(&nvt->tx.lock, flags); + tx_state = nvt->tx.tx_state; + spin_unlock_irqrestore(&nvt->tx.lock, flags); + + tx_inactive = (tx_state == ST_TX_NONE); + + return tx_inactive; +} + +/* interrupt service routine for incoming and outgoing CIR data */ +static irqreturn_t nvt_cir_isr(int irq, void *data) +{ + struct nvt_dev *nvt = data; + u8 status, iren, cur_state; + unsigned long flags; + + nvt_dbg_verbose("%s firing", __func__); + + nvt_efm_enable(nvt); + nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); + nvt_efm_disable(nvt); + + /* + * Get IR Status register contents. Write 1 to ack/clear + * + * bit: reg name - description + * 7: CIR_IRSTS_RDR - RX Data Ready + * 6: CIR_IRSTS_RTR - RX FIFO Trigger Level Reach + * 5: CIR_IRSTS_PE - Packet End + * 4: CIR_IRSTS_RFO - RX FIFO Overrun (RDR will also be set) + * 3: CIR_IRSTS_TE - TX FIFO Empty + * 2: CIR_IRSTS_TTR - TX FIFO Trigger Level Reach + * 1: CIR_IRSTS_TFU - TX FIFO Underrun + * 0: CIR_IRSTS_GH - Min Length Detected + */ + status = nvt_cir_reg_read(nvt, CIR_IRSTS); + if (!status) { + nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__); + nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); + return IRQ_RETVAL(IRQ_NONE); + } + + /* ack/clear all irq flags we've got */ + nvt_cir_reg_write(nvt, status, CIR_IRSTS); + nvt_cir_reg_write(nvt, 0, CIR_IRSTS); + + /* Interrupt may be shared with CIR Wake, bail if CIR not enabled */ + iren = nvt_cir_reg_read(nvt, CIR_IREN); + if (!iren) { + nvt_dbg_verbose("%s exiting, CIR not enabled", __func__); + return IRQ_RETVAL(IRQ_NONE); + } + + if (debug) + nvt_cir_log_irqs(status, iren); + + if (status & CIR_IRSTS_RTR) { + /* FIXME: add code for study/learn mode */ + /* We only do rx if not tx'ing */ + if (nvt_cir_tx_inactive(nvt)) + nvt_get_rx_ir_data(nvt); + } + + if (status & CIR_IRSTS_PE) { + if (nvt_cir_tx_inactive(nvt)) + nvt_get_rx_ir_data(nvt); + + spin_lock_irqsave(&nvt->nvt_lock, flags); + + cur_state = nvt->study_state; + + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + + if (cur_state == ST_STUDY_NONE) + nvt_clear_cir_fifo(nvt); + } + + if (status & CIR_IRSTS_TE) + nvt_clear_tx_fifo(nvt); + + if (status & CIR_IRSTS_TTR) { + unsigned int pos, count; + u8 tmp; + + spin_lock_irqsave(&nvt->tx.lock, flags); + + pos = nvt->tx.cur_buf_num; + count = nvt->tx.buf_count; + + /* Write data into the hardware tx fifo while pos < count */ + if (pos < count) { + nvt_cir_reg_write(nvt, nvt->tx.buf[pos], CIR_STXFIFO); + nvt->tx.cur_buf_num++; + /* Disable TX FIFO Trigger Level Reach (TTR) interrupt */ + } else { + tmp = nvt_cir_reg_read(nvt, CIR_IREN); + nvt_cir_reg_write(nvt, tmp & ~CIR_IREN_TTR, CIR_IREN); + } + + spin_unlock_irqrestore(&nvt->tx.lock, flags); + + } + + if (status & CIR_IRSTS_TFU) { + spin_lock_irqsave(&nvt->tx.lock, flags); + if (nvt->tx.tx_state == ST_TX_REPLY) { + nvt->tx.tx_state = ST_TX_REQUEST; + wake_up(&nvt->tx.queue); + } + spin_unlock_irqrestore(&nvt->tx.lock, flags); + } + + nvt_dbg_verbose("%s done", __func__); + return IRQ_RETVAL(IRQ_HANDLED); +} + +/* Interrupt service routine for CIR Wake */ +static irqreturn_t nvt_cir_wake_isr(int irq, void *data) +{ + u8 status, iren, val; + struct nvt_dev *nvt = data; + unsigned long flags; + + nvt_dbg_wake("%s firing", __func__); + + status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS); + if (!status) + return IRQ_RETVAL(IRQ_NONE); + + if (status & CIR_WAKE_IRSTS_IR_PENDING) + nvt_clear_cir_wake_fifo(nvt); + + nvt_cir_wake_reg_write(nvt, status, CIR_WAKE_IRSTS); + nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IRSTS); + + /* Interrupt may be shared with CIR, bail if Wake not enabled */ + iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN); + if (!iren) { + nvt_dbg_wake("%s exiting, wake not enabled", __func__); + return IRQ_RETVAL(IRQ_HANDLED); + } + + if ((status & CIR_WAKE_IRSTS_PE) && + (nvt->wake_state == ST_WAKE_START)) { + while (nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)) { + val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY); + nvt_dbg("setting wake up key: 0x%x", val); + } + + nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN); + spin_lock_irqsave(&nvt->nvt_lock, flags); + nvt->wake_state = ST_WAKE_FINISH; + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + } + + nvt_dbg_wake("%s done", __func__); + return IRQ_RETVAL(IRQ_HANDLED); +} + +static void nvt_enable_cir(struct nvt_dev *nvt) +{ + /* set function enable flags */ + nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN | + CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, + CIR_IRCON); + + nvt_efm_enable(nvt); + + /* enable the CIR logical device */ + nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); + nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); + + nvt_efm_disable(nvt); + + /* clear all pending interrupts */ + nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); + + /* enable interrupts */ + nvt_set_cir_iren(nvt); +} + +static void nvt_disable_cir(struct nvt_dev *nvt) +{ + /* disable CIR interrupts */ + nvt_cir_reg_write(nvt, 0, CIR_IREN); + + /* clear any and all pending interrupts */ + nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); + + /* clear all function enable flags */ + nvt_cir_reg_write(nvt, 0, CIR_IRCON); + + /* clear hardware rx and tx fifos */ + nvt_clear_cir_fifo(nvt); + nvt_clear_tx_fifo(nvt); + + nvt_efm_enable(nvt); + + /* disable the CIR logical device */ + nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); + nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); + + nvt_efm_disable(nvt); +} + +static int nvt_open(void *data) +{ + struct nvt_dev *nvt = (struct nvt_dev *)data; + unsigned long flags; + + spin_lock_irqsave(&nvt->nvt_lock, flags); + nvt->in_use = true; + nvt_enable_cir(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + + return 0; +} + +static void nvt_close(void *data) +{ + struct nvt_dev *nvt = (struct nvt_dev *)data; + unsigned long flags; + + spin_lock_irqsave(&nvt->nvt_lock, flags); + nvt->in_use = false; + nvt_disable_cir(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); +} + +/* Allocate memory, probe hardware, and initialize everything */ +static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) +{ + struct nvt_dev *nvt = NULL; + struct input_dev *rdev = NULL; + struct ir_dev_props *props = NULL; + int ret = -ENOMEM; + + nvt = kzalloc(sizeof(struct nvt_dev), GFP_KERNEL); + if (!nvt) + return ret; + + props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); + if (!props) + goto failure; + + /* input device for IR remote (and tx) */ + rdev = input_allocate_device(); + if (!rdev) + goto failure; + + ret = -ENODEV; + /* validate pnp resources */ + if (!pnp_port_valid(pdev, 0) || + pnp_port_len(pdev, 0) < CIR_IOREG_LENGTH) { + dev_err(&pdev->dev, "IR PNP Port not valid!\n"); + goto failure; + } + + if (!pnp_irq_valid(pdev, 0)) { + dev_err(&pdev->dev, "PNP IRQ not valid!\n"); + goto failure; + } + + if (!pnp_port_valid(pdev, 1) || + pnp_port_len(pdev, 1) < CIR_IOREG_LENGTH) { + dev_err(&pdev->dev, "Wake PNP Port not valid!\n"); + goto failure; + } + + nvt->cir_addr = pnp_port_start(pdev, 0); + nvt->cir_irq = pnp_irq(pdev, 0); + + nvt->cir_wake_addr = pnp_port_start(pdev, 1); + /* irq is always shared between cir and cir wake */ + nvt->cir_wake_irq = nvt->cir_irq; + + nvt->cr_efir = CR_EFIR; + nvt->cr_efdr = CR_EFDR; + + spin_lock_init(&nvt->nvt_lock); + spin_lock_init(&nvt->tx.lock); + init_ir_raw_event(&nvt->rawir); + + ret = -EBUSY; + /* now claim resources */ + if (!request_region(nvt->cir_addr, + CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) + goto failure; + + if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED, + NVT_DRIVER_NAME, (void *)nvt)) + goto failure; + + if (!request_region(nvt->cir_wake_addr, + CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) + goto failure; + + if (request_irq(nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED, + NVT_DRIVER_NAME, (void *)nvt)) + goto failure; + + pnp_set_drvdata(pdev, nvt); + nvt->pdev = pdev; + + init_waitqueue_head(&nvt->tx.queue); + + ret = nvt_hw_detect(nvt); + if (ret) + goto failure; + + /* Initialize CIR & CIR Wake Logical Devices */ + nvt_efm_enable(nvt); + nvt_cir_ldev_init(nvt); + nvt_cir_wake_ldev_init(nvt); + nvt_efm_disable(nvt); + + /* Initialize CIR & CIR Wake Config Registers */ + nvt_cir_regs_init(nvt); + nvt_cir_wake_regs_init(nvt); + + /* Set up ir-core props */ + props->priv = nvt; + props->driver_type = RC_DRIVER_IR_RAW; + props->allowed_protos = IR_TYPE_ALL; + props->open = nvt_open; + props->close = nvt_close; +#if 0 + props->min_timeout = XYZ; + props->max_timeout = XYZ; + props->timeout = XYZ; + /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ + props->rx_resolution = XYZ; + + /* tx bits */ + props->tx_resolution = XYZ; +#endif + props->tx_ir = nvt_tx_ir; + props->s_tx_carrier = nvt_set_tx_carrier; + + rdev->name = "Nuvoton w836x7hg Infrared Remote Transceiver"; + rdev->id.bustype = BUS_HOST; + rdev->id.vendor = PCI_VENDOR_ID_WINBOND2; + rdev->id.product = nvt->chip_major; + rdev->id.version = nvt->chip_minor; + + nvt->props = props; + nvt->rdev = rdev; + + device_set_wakeup_capable(&pdev->dev, 1); + device_set_wakeup_enable(&pdev->dev, 1); + + ret = ir_input_register(rdev, RC_MAP_RC6_MCE, props, NVT_DRIVER_NAME); + if (ret) + goto failure; + + nvt_pr(KERN_NOTICE, "driver has been successfully loaded\n"); + if (debug) { + cir_dump_regs(nvt); + cir_wake_dump_regs(nvt); + } + + return 0; + +failure: + if (nvt->cir_irq) + free_irq(nvt->cir_irq, nvt); + if (nvt->cir_addr) + release_region(nvt->cir_addr, CIR_IOREG_LENGTH); + + if (nvt->cir_wake_irq) + free_irq(nvt->cir_wake_irq, nvt); + if (nvt->cir_wake_addr) + release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH); + + input_free_device(rdev); + kfree(props); + kfree(nvt); + + return ret; +} + +static void __devexit nvt_remove(struct pnp_dev *pdev) +{ + struct nvt_dev *nvt = pnp_get_drvdata(pdev); + unsigned long flags; + + spin_lock_irqsave(&nvt->nvt_lock, flags); + /* disable CIR */ + nvt_cir_reg_write(nvt, 0, CIR_IREN); + nvt_disable_cir(nvt); + /* enable CIR Wake (for IR power-on) */ + nvt_enable_wake(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + + /* free resources */ + free_irq(nvt->cir_irq, nvt); + free_irq(nvt->cir_wake_irq, nvt); + release_region(nvt->cir_addr, CIR_IOREG_LENGTH); + release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH); + + ir_input_unregister(nvt->rdev); + + kfree(nvt->props); + kfree(nvt); +} + +static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) +{ + struct nvt_dev *nvt = pnp_get_drvdata(pdev); + unsigned long flags; + + nvt_dbg("%s called", __func__); + + /* zero out misc state tracking */ + spin_lock_irqsave(&nvt->nvt_lock, flags); + nvt->study_state = ST_STUDY_NONE; + nvt->wake_state = ST_WAKE_NONE; + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + + spin_lock_irqsave(&nvt->tx.lock, flags); + nvt->tx.tx_state = ST_TX_NONE; + spin_unlock_irqrestore(&nvt->tx.lock, flags); + + /* disable all CIR interrupts */ + nvt_cir_reg_write(nvt, 0, CIR_IREN); + + nvt_efm_enable(nvt); + + /* disable cir logical dev */ + nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); + nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); + + nvt_efm_disable(nvt); + + /* make sure wake is enabled */ + nvt_enable_wake(nvt); + + return 0; +} + +static int nvt_resume(struct pnp_dev *pdev) +{ + int ret = 0; + struct nvt_dev *nvt = pnp_get_drvdata(pdev); + + nvt_dbg("%s called", __func__); + + /* open interrupt */ + nvt_set_cir_iren(nvt); + + /* Enable CIR logical device */ + nvt_efm_enable(nvt); + nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); + nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); + + nvt_efm_disable(nvt); + + nvt_cir_regs_init(nvt); + nvt_cir_wake_regs_init(nvt); + + return ret; +} + +static void nvt_shutdown(struct pnp_dev *pdev) +{ + struct nvt_dev *nvt = pnp_get_drvdata(pdev); + nvt_enable_wake(nvt); +} + +static const struct pnp_device_id nvt_ids[] = { + { "WEC0530", 0 }, /* CIR */ + { "NTN0530", 0 }, /* CIR for new chip's pnp id*/ + { "", 0 }, +}; + +static struct pnp_driver nvt_driver = { + .name = NVT_DRIVER_NAME, + .id_table = nvt_ids, + .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, + .probe = nvt_probe, + .remove = __devexit_p(nvt_remove), + .suspend = nvt_suspend, + .resume = nvt_resume, + .shutdown = nvt_shutdown, +}; + +int nvt_init(void) +{ + return pnp_register_driver(&nvt_driver); +} + +void nvt_exit(void) +{ + pnp_unregister_driver(&nvt_driver); +} + +module_param(debug, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable debugging output"); + +MODULE_DEVICE_TABLE(pnp, nvt_ids); +MODULE_DESCRIPTION("Nuvoton W83667HG-A & W83677HG-I CIR driver"); + +MODULE_AUTHOR("Jarod Wilson "); +MODULE_LICENSE("GPL"); + +module_init(nvt_init); +module_exit(nvt_exit); diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h new file mode 100644 index 0000000..62dc530 --- /dev/null +++ b/drivers/media/rc/nuvoton-cir.h @@ -0,0 +1,408 @@ +/* + * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR + * + * Copyright (C) 2010 Jarod Wilson + * Copyright (C) 2009 Nuvoton PS Team + * + * Special thanks to Nuvoton for providing hardware, spec sheets and + * sample code upon which portions of this driver are based. Indirect + * thanks also to Maxim Levitsky, whose ene_ir driver this driver is + * modeled after. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include +#include + +/* platform driver name to register */ +#define NVT_DRIVER_NAME "nuvoton-cir" + +/* debugging module parameter */ +static int debug; + + +#define nvt_pr(level, text, ...) \ + printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__) + +#define nvt_dbg(text, ...) \ + if (debug) \ + printk(KERN_DEBUG \ + KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) + +#define nvt_dbg_verbose(text, ...) \ + if (debug > 1) \ + printk(KERN_DEBUG \ + KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) + +#define nvt_dbg_wake(text, ...) \ + if (debug > 2) \ + printk(KERN_DEBUG \ + KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) + + +/* + * Original lirc driver said min value of 76, and recommended value of 256 + * for the buffer length, but then used 2048. Never mind that the size of the + * RX FIFO is 32 bytes... So I'm using 32 for RX and 256 for TX atm, but I'm + * not sure if maybe that TX value is off by a factor of 8 (bits vs. bytes), + * and I don't have TX-capable hardware to test/debug on... + */ +#define TX_BUF_LEN 256 +#define RX_BUF_LEN 32 + +struct nvt_dev { + struct pnp_dev *pdev; + struct input_dev *rdev; + struct ir_dev_props *props; + struct ir_raw_event rawir; + + spinlock_t nvt_lock; + bool in_use; + + /* for rx */ + u8 buf[RX_BUF_LEN]; + unsigned int pkts; + + struct { + spinlock_t lock; + u8 buf[TX_BUF_LEN]; + unsigned int buf_count; + unsigned int cur_buf_num; + wait_queue_head_t queue; + u8 tx_state; + } tx; + + /* EFER Config register index/data pair */ + u8 cr_efir; + u8 cr_efdr; + + /* hardware I/O settings */ + unsigned long cir_addr; + unsigned long cir_wake_addr; + int cir_irq; + int cir_wake_irq; + + /* hardware id */ + u8 chip_major; + u8 chip_minor; + + /* hardware features */ + bool hw_learning_capable; + bool hw_tx_capable; + + /* rx settings */ + bool learning_enabled; + bool carrier_detect_enabled; + + /* track cir wake state */ + u8 wake_state; + /* for study */ + u8 study_state; + /* carrier period = 1 / frequency */ + u32 carrier; +}; + +/* study states */ +#define ST_STUDY_NONE 0x0 +#define ST_STUDY_START 0x1 +#define ST_STUDY_CARRIER 0x2 +#define ST_STUDY_ALL_RECV 0x4 + +/* wake states */ +#define ST_WAKE_NONE 0x0 +#define ST_WAKE_START 0x1 +#define ST_WAKE_FINISH 0x2 + +/* receive states */ +#define ST_RX_WAIT_7F 0x1 +#define ST_RX_WAIT_HEAD 0x2 +#define ST_RX_WAIT_SILENT_END 0x4 + +/* send states */ +#define ST_TX_NONE 0x0 +#define ST_TX_REQUEST 0x2 +#define ST_TX_REPLY 0x4 + +/* buffer packet constants */ +#define BUF_PULSE_BIT 0x80 +#define BUF_LEN_MASK 0x7f +#define BUF_REPEAT_BYTE 0x70 +#define BUF_REPEAT_MASK 0xf0 + +/* CIR settings */ + +/* total length of CIR and CIR WAKE */ +#define CIR_IOREG_LENGTH 0x0f + +/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL (0x7d0 = 2000) */ +#define CIR_RX_LIMIT_COUNT 0x7d0 + +/* CIR Regs */ +#define CIR_IRCON 0x00 +#define CIR_IRSTS 0x01 +#define CIR_IREN 0x02 +#define CIR_RXFCONT 0x03 +#define CIR_CP 0x04 +#define CIR_CC 0x05 +#define CIR_SLCH 0x06 +#define CIR_SLCL 0x07 +#define CIR_FIFOCON 0x08 +#define CIR_IRFIFOSTS 0x09 +#define CIR_SRXFIFO 0x0a +#define CIR_TXFCONT 0x0b +#define CIR_STXFIFO 0x0c +#define CIR_FCCH 0x0d +#define CIR_FCCL 0x0e +#define CIR_IRFSM 0x0f + +/* CIR IRCON settings */ +#define CIR_IRCON_RECV 0x80 +#define CIR_IRCON_WIREN 0x40 +#define CIR_IRCON_TXEN 0x20 +#define CIR_IRCON_RXEN 0x10 +#define CIR_IRCON_WRXINV 0x08 +#define CIR_IRCON_RXINV 0x04 + +#define CIR_IRCON_SAMPLE_PERIOD_SEL_1 0x00 +#define CIR_IRCON_SAMPLE_PERIOD_SEL_25 0x01 +#define CIR_IRCON_SAMPLE_PERIOD_SEL_50 0x02 +#define CIR_IRCON_SAMPLE_PERIOD_SEL_100 0x03 + +/* FIXME: make this a runtime option */ +/* select sample period as 50us */ +#define CIR_IRCON_SAMPLE_PERIOD_SEL CIR_IRCON_SAMPLE_PERIOD_SEL_50 + +/* CIR IRSTS settings */ +#define CIR_IRSTS_RDR 0x80 +#define CIR_IRSTS_RTR 0x40 +#define CIR_IRSTS_PE 0x20 +#define CIR_IRSTS_RFO 0x10 +#define CIR_IRSTS_TE 0x08 +#define CIR_IRSTS_TTR 0x04 +#define CIR_IRSTS_TFU 0x02 +#define CIR_IRSTS_GH 0x01 + +/* CIR IREN settings */ +#define CIR_IREN_RDR 0x80 +#define CIR_IREN_RTR 0x40 +#define CIR_IREN_PE 0x20 +#define CIR_IREN_RFO 0x10 +#define CIR_IREN_TE 0x08 +#define CIR_IREN_TTR 0x04 +#define CIR_IREN_TFU 0x02 +#define CIR_IREN_GH 0x01 + +/* CIR FIFOCON settings */ +#define CIR_FIFOCON_TXFIFOCLR 0x80 + +#define CIR_FIFOCON_TX_TRIGGER_LEV_31 0x00 +#define CIR_FIFOCON_TX_TRIGGER_LEV_24 0x10 +#define CIR_FIFOCON_TX_TRIGGER_LEV_16 0x20 +#define CIR_FIFOCON_TX_TRIGGER_LEV_8 0x30 + +/* FIXME: make this a runtime option */ +/* select TX trigger level as 16 */ +#define CIR_FIFOCON_TX_TRIGGER_LEV CIR_FIFOCON_TX_TRIGGER_LEV_16 + +#define CIR_FIFOCON_RXFIFOCLR 0x08 + +#define CIR_FIFOCON_RX_TRIGGER_LEV_1 0x00 +#define CIR_FIFOCON_RX_TRIGGER_LEV_8 0x01 +#define CIR_FIFOCON_RX_TRIGGER_LEV_16 0x02 +#define CIR_FIFOCON_RX_TRIGGER_LEV_24 0x03 + +/* FIXME: make this a runtime option */ +/* select RX trigger level as 24 */ +#define CIR_FIFOCON_RX_TRIGGER_LEV CIR_FIFOCON_RX_TRIGGER_LEV_24 + +/* CIR IRFIFOSTS settings */ +#define CIR_IRFIFOSTS_IR_PENDING 0x80 +#define CIR_IRFIFOSTS_RX_GS 0x40 +#define CIR_IRFIFOSTS_RX_FTA 0x20 +#define CIR_IRFIFOSTS_RX_EMPTY 0x10 +#define CIR_IRFIFOSTS_RX_FULL 0x08 +#define CIR_IRFIFOSTS_TX_FTA 0x04 +#define CIR_IRFIFOSTS_TX_EMPTY 0x02 +#define CIR_IRFIFOSTS_TX_FULL 0x01 + + +/* CIR WAKE UP Regs */ +#define CIR_WAKE_IRCON 0x00 +#define CIR_WAKE_IRSTS 0x01 +#define CIR_WAKE_IREN 0x02 +#define CIR_WAKE_FIFO_CMP_DEEP 0x03 +#define CIR_WAKE_FIFO_CMP_TOL 0x04 +#define CIR_WAKE_FIFO_COUNT 0x05 +#define CIR_WAKE_SLCH 0x06 +#define CIR_WAKE_SLCL 0x07 +#define CIR_WAKE_FIFOCON 0x08 +#define CIR_WAKE_SRXFSTS 0x09 +#define CIR_WAKE_SAMPLE_RX_FIFO 0x0a +#define CIR_WAKE_WR_FIFO_DATA 0x0b +#define CIR_WAKE_RD_FIFO_ONLY 0x0c +#define CIR_WAKE_RD_FIFO_ONLY_IDX 0x0d +#define CIR_WAKE_FIFO_IGNORE 0x0e +#define CIR_WAKE_IRFSM 0x0f + +/* CIR WAKE UP IRCON settings */ +#define CIR_WAKE_IRCON_DEC_RST 0x80 +#define CIR_WAKE_IRCON_MODE1 0x40 +#define CIR_WAKE_IRCON_MODE0 0x20 +#define CIR_WAKE_IRCON_RXEN 0x10 +#define CIR_WAKE_IRCON_R 0x08 +#define CIR_WAKE_IRCON_RXINV 0x04 + +/* FIXME/jarod: make this a runtime option */ +/* select a same sample period like cir register */ +#define CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL CIR_IRCON_SAMPLE_PERIOD_SEL_50 + +/* CIR WAKE IRSTS Bits */ +#define CIR_WAKE_IRSTS_RDR 0x80 +#define CIR_WAKE_IRSTS_RTR 0x40 +#define CIR_WAKE_IRSTS_PE 0x20 +#define CIR_WAKE_IRSTS_RFO 0x10 +#define CIR_WAKE_IRSTS_GH 0x08 +#define CIR_WAKE_IRSTS_IR_PENDING 0x01 + +/* CIR WAKE UP IREN Bits */ +#define CIR_WAKE_IREN_RDR 0x80 +#define CIR_WAKE_IREN_RTR 0x40 +#define CIR_WAKE_IREN_PE 0x20 +#define CIR_WAKE_IREN_RFO 0x10 +#define CIR_WAKE_IREN_TE 0x08 +#define CIR_WAKE_IREN_TTR 0x04 +#define CIR_WAKE_IREN_TFU 0x02 +#define CIR_WAKE_IREN_GH 0x01 + +/* CIR WAKE FIFOCON settings */ +#define CIR_WAKE_FIFOCON_RXFIFOCLR 0x08 + +#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67 0x00 +#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_66 0x01 +#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_65 0x02 +#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_64 0x03 + +/* FIXME: make this a runtime option */ +/* select WAKE UP RX trigger level as 67 */ +#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67 + +/* CIR WAKE SRXFSTS settings */ +#define CIR_WAKE_IRFIFOSTS_RX_GS 0x80 +#define CIR_WAKE_IRFIFOSTS_RX_FTA 0x40 +#define CIR_WAKE_IRFIFOSTS_RX_EMPTY 0x20 +#define CIR_WAKE_IRFIFOSTS_RX_FULL 0x10 + +/* CIR Wake FIFO buffer is 67 bytes long */ +#define CIR_WAKE_FIFO_LEN 67 +/* CIR Wake byte comparison tolerance */ +#define CIR_WAKE_CMP_TOLERANCE 5 + +/* + * Extended Function Enable Registers: + * Extended Function Index Register + * Extended Function Data Register + */ +#define CR_EFIR 0x2e +#define CR_EFDR 0x2f + +/* Possible alternate EFER values, depends on how the chip is wired */ +#define CR_EFIR2 0x4e +#define CR_EFDR2 0x4f + +/* Extended Function Mode enable/disable magic values */ +#define EFER_EFM_ENABLE 0x87 +#define EFER_EFM_DISABLE 0xaa + +/* Chip IDs found in CR_CHIP_ID_{HI,LO} */ +#define CHIP_ID_HIGH 0xb4 +#define CHIP_ID_LOW 0x72 +#define CHIP_ID_LOW2 0x73 + +/* Config regs we need to care about */ +#define CR_SOFTWARE_RESET 0x02 +#define CR_LOGICAL_DEV_SEL 0x07 +#define CR_CHIP_ID_HI 0x20 +#define CR_CHIP_ID_LO 0x21 +#define CR_DEV_POWER_DOWN 0x22 /* bit 2 is CIR power, default power on */ +#define CR_OUTPUT_PIN_SEL 0x27 +#define CR_LOGICAL_DEV_EN 0x30 /* valid for all logical devices */ +/* next three regs valid for both the CIR and CIR_WAKE logical devices */ +#define CR_CIR_BASE_ADDR_HI 0x60 +#define CR_CIR_BASE_ADDR_LO 0x61 +#define CR_CIR_IRQ_RSRC 0x70 +/* next three regs valid only for ACPI logical dev */ +#define CR_ACPI_CIR_WAKE 0xe0 +#define CR_ACPI_IRQ_EVENTS 0xf6 +#define CR_ACPI_IRQ_EVENTS2 0xf7 + +/* Logical devices that we need to care about */ +#define LOGICAL_DEV_LPT 0x01 +#define LOGICAL_DEV_CIR 0x06 +#define LOGICAL_DEV_ACPI 0x0a +#define LOGICAL_DEV_CIR_WAKE 0x0e + +#define LOGICAL_DEV_DISABLE 0x00 +#define LOGICAL_DEV_ENABLE 0x01 + +#define CIR_WAKE_ENABLE_BIT 0x08 +#define CIR_INTR_MOUSE_IRQ_BIT 0x80 +#define PME_INTR_CIR_PASS_BIT 0x08 + +#define OUTPUT_PIN_SEL_MASK 0xbc +#define OUTPUT_ENABLE_CIR 0x01 /* Pin95=CIRRX, Pin96=CIRTX1 */ +#define OUTPUT_ENABLE_CIRWB 0x40 /* enable wide-band sensor */ + +/* MCE CIR signal length, related on sample period */ + +/* MCE CIR controller signal length: about 43ms + * 43ms / 50us (sample period) * 0.85 (inaccuracy) + */ +#define CONTROLLER_BUF_LEN_MIN 830 + +/* MCE CIR keyboard signal length: about 26ms + * 26ms / 50us (sample period) * 0.85 (inaccuracy) + */ +#define KEYBOARD_BUF_LEN_MAX 650 +#define KEYBOARD_BUF_LEN_MIN 610 + +/* MCE CIR mouse signal length: about 24ms + * 24ms / 50us (sample period) * 0.85 (inaccuracy) + */ +#define MOUSE_BUF_LEN_MIN 565 + +#define CIR_SAMPLE_PERIOD 50 +#define CIR_SAMPLE_LOW_INACCURACY 0.85 + +/* MAX silence time that driver will sent to lirc */ +#define MAX_SILENCE_TIME 60000 + +#if CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_100 +#define SAMPLE_PERIOD 100 + +#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_50 +#define SAMPLE_PERIOD 50 + +#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_25 +#define SAMPLE_PERIOD 25 + +#else +#define SAMPLE_PERIOD 1 +#endif + +/* as VISTA MCE definition, valid carrier value */ +#define MAX_CARRIER 60000 +#define MIN_CARRIER 30000 diff --git a/drivers/media/rc/rc-map.c b/drivers/media/rc/rc-map.c new file mode 100644 index 0000000..689143f --- /dev/null +++ b/drivers/media/rc/rc-map.c @@ -0,0 +1,107 @@ +/* ir-raw-event.c - handle IR Pulse/Space event + * + * Copyright (C) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include + +/* Used to handle IR raw handler extensions */ +static LIST_HEAD(rc_map_list); +static DEFINE_SPINLOCK(rc_map_lock); + +static struct rc_keymap *seek_rc_map(const char *name) +{ + struct rc_keymap *map = NULL; + + spin_lock(&rc_map_lock); + list_for_each_entry(map, &rc_map_list, list) { + if (!strcmp(name, map->map.name)) { + spin_unlock(&rc_map_lock); + return map; + } + } + spin_unlock(&rc_map_lock); + + return NULL; +} + +struct ir_scancode_table *get_rc_map(const char *name) +{ + + struct rc_keymap *map; + + map = seek_rc_map(name); +#ifdef MODULE + if (!map) { + int rc = request_module(name); + if (rc < 0) { + printk(KERN_ERR "Couldn't load IR keymap %s\n", name); + return NULL; + } + msleep(20); /* Give some time for IR to register */ + + map = seek_rc_map(name); + } +#endif + if (!map) { + printk(KERN_ERR "IR keymap %s not found\n", name); + return NULL; + } + + printk(KERN_INFO "Registered IR keymap %s\n", map->map.name); + + return &map->map; +} +EXPORT_SYMBOL_GPL(get_rc_map); + +int ir_register_map(struct rc_keymap *map) +{ + spin_lock(&rc_map_lock); + list_add_tail(&map->list, &rc_map_list); + spin_unlock(&rc_map_lock); + return 0; +} +EXPORT_SYMBOL_GPL(ir_register_map); + +void ir_unregister_map(struct rc_keymap *map) +{ + spin_lock(&rc_map_lock); + list_del(&map->list); + spin_unlock(&rc_map_lock); +} +EXPORT_SYMBOL_GPL(ir_unregister_map); + + +static struct ir_scancode empty[] = { + { 0x2a, KEY_COFFEE }, +}; + +static struct rc_keymap empty_map = { + .map = { + .scan = empty, + .size = ARRAY_SIZE(empty), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_EMPTY, + } +}; + +int ir_rcmap_init(void) +{ + return ir_register_map(&empty_map); +} + +void ir_rcmap_cleanup(void) +{ + ir_unregister_map(&empty_map); +} diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c new file mode 100644 index 0000000..3a20aef --- /dev/null +++ b/drivers/media/rc/streamzap.c @@ -0,0 +1,572 @@ +/* + * Streamzap Remote Control driver + * + * Copyright (c) 2005 Christoph Bartelmus + * Copyright (c) 2010 Jarod Wilson + * + * This driver was based on the work of Greg Wickham and Adrian + * Dewhurst. It was substantially rewritten to support correct signal + * gaps and now maintains a delay buffer, which is used to present + * consistent timing behaviour to user space applications. Without the + * delay buffer an ugly hack would be required in lircd, which can + * cause sluggish signal decoding in certain situations. + * + * Ported to in-kernel ir-core interface by Jarod Wilson + * + * This driver is based on the USB skeleton driver packaged with the + * kernel; copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_VERSION "1.61" +#define DRIVER_NAME "streamzap" +#define DRIVER_DESC "Streamzap Remote Control driver" + +#ifdef CONFIG_USB_DEBUG +static int debug = 1; +#else +static int debug; +#endif + +#define USB_STREAMZAP_VENDOR_ID 0x0e9c +#define USB_STREAMZAP_PRODUCT_ID 0x0000 + +/* table of devices that work with this driver */ +static struct usb_device_id streamzap_table[] = { + /* Streamzap Remote Control */ + { USB_DEVICE(USB_STREAMZAP_VENDOR_ID, USB_STREAMZAP_PRODUCT_ID) }, + /* Terminating entry */ + { } +}; + +MODULE_DEVICE_TABLE(usb, streamzap_table); + +#define SZ_PULSE_MASK 0xf0 +#define SZ_SPACE_MASK 0x0f +#define SZ_TIMEOUT 0xff +#define SZ_RESOLUTION 256 + +/* number of samples buffered */ +#define SZ_BUF_LEN 128 + +/* from ir-rc5-sz-decoder.c */ +#ifdef CONFIG_IR_RC5_SZ_DECODER_MODULE +#define load_rc5_sz_decode() request_module("ir-rc5-sz-decoder") +#else +#define load_rc5_sz_decode() 0 +#endif + +enum StreamzapDecoderState { + PulseSpace, + FullPulse, + FullSpace, + IgnorePulse +}; + +/* structure to hold our device specific stuff */ +struct streamzap_ir { + + /* ir-core */ + struct ir_dev_props *props; + + /* core device info */ + struct device *dev; + struct input_dev *idev; + + /* usb */ + struct usb_device *usbdev; + struct usb_interface *interface; + struct usb_endpoint_descriptor *endpoint; + struct urb *urb_in; + + /* buffer & dma */ + unsigned char *buf_in; + dma_addr_t dma_in; + unsigned int buf_in_len; + + /* track what state we're in */ + enum StreamzapDecoderState decoder_state; + /* tracks whether we are currently receiving some signal */ + bool idle; + /* sum of signal lengths received since signal start */ + unsigned long sum; + /* start time of signal; necessary for gap tracking */ + struct timeval signal_last; + struct timeval signal_start; + bool timeout_enabled; + + char name[128]; + char phys[64]; +}; + + +/* local function prototypes */ +static int streamzap_probe(struct usb_interface *interface, + const struct usb_device_id *id); +static void streamzap_disconnect(struct usb_interface *interface); +static void streamzap_callback(struct urb *urb); +static int streamzap_suspend(struct usb_interface *intf, pm_message_t message); +static int streamzap_resume(struct usb_interface *intf); + +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver streamzap_driver = { + .name = DRIVER_NAME, + .probe = streamzap_probe, + .disconnect = streamzap_disconnect, + .suspend = streamzap_suspend, + .resume = streamzap_resume, + .id_table = streamzap_table, +}; + +static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir) +{ + dev_dbg(sz->dev, "Storing %s with duration %u us\n", + (rawir.pulse ? "pulse" : "space"), rawir.duration); + ir_raw_event_store_with_filter(sz->idev, &rawir); +} + +static void sz_push_full_pulse(struct streamzap_ir *sz, + unsigned char value) +{ + DEFINE_IR_RAW_EVENT(rawir); + + if (sz->idle) { + long deltv; + + sz->signal_last = sz->signal_start; + do_gettimeofday(&sz->signal_start); + + deltv = sz->signal_start.tv_sec - sz->signal_last.tv_sec; + rawir.pulse = false; + if (deltv > 15) { + /* really long time */ + rawir.duration = IR_MAX_DURATION; + } else { + rawir.duration = (int)(deltv * 1000000 + + sz->signal_start.tv_usec - + sz->signal_last.tv_usec); + rawir.duration -= sz->sum; + rawir.duration *= 1000; + rawir.duration &= IR_MAX_DURATION; + } + sz_push(sz, rawir); + + sz->idle = false; + sz->sum = 0; + } + + rawir.pulse = true; + rawir.duration = ((int) value) * SZ_RESOLUTION; + rawir.duration += SZ_RESOLUTION / 2; + sz->sum += rawir.duration; + rawir.duration *= 1000; + rawir.duration &= IR_MAX_DURATION; + sz_push(sz, rawir); +} + +static void sz_push_half_pulse(struct streamzap_ir *sz, + unsigned char value) +{ + sz_push_full_pulse(sz, (value & SZ_PULSE_MASK) >> 4); +} + +static void sz_push_full_space(struct streamzap_ir *sz, + unsigned char value) +{ + DEFINE_IR_RAW_EVENT(rawir); + + rawir.pulse = false; + rawir.duration = ((int) value) * SZ_RESOLUTION; + rawir.duration += SZ_RESOLUTION / 2; + sz->sum += rawir.duration; + rawir.duration *= 1000; + sz_push(sz, rawir); +} + +static void sz_push_half_space(struct streamzap_ir *sz, + unsigned long value) +{ + sz_push_full_space(sz, value & SZ_SPACE_MASK); +} + +/** + * streamzap_callback - usb IRQ handler callback + * + * This procedure is invoked on reception of data from + * the usb remote. + */ +static void streamzap_callback(struct urb *urb) +{ + struct streamzap_ir *sz; + unsigned int i; + int len; + + if (!urb) + return; + + sz = urb->context; + len = urb->actual_length; + + switch (urb->status) { + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* + * this urb is terminated, clean up. + * sz might already be invalid at this point + */ + dev_err(sz->dev, "urb terminated, status: %d\n", urb->status); + return; + default: + break; + } + + dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len); + for (i = 0; i < len; i++) { + dev_dbg(sz->dev, "sz->buf_in[%d]: %x\n", + i, (unsigned char)sz->buf_in[i]); + switch (sz->decoder_state) { + case PulseSpace: + if ((sz->buf_in[i] & SZ_PULSE_MASK) == + SZ_PULSE_MASK) { + sz->decoder_state = FullPulse; + continue; + } else if ((sz->buf_in[i] & SZ_SPACE_MASK) + == SZ_SPACE_MASK) { + sz_push_half_pulse(sz, sz->buf_in[i]); + sz->decoder_state = FullSpace; + continue; + } else { + sz_push_half_pulse(sz, sz->buf_in[i]); + sz_push_half_space(sz, sz->buf_in[i]); + } + break; + case FullPulse: + sz_push_full_pulse(sz, sz->buf_in[i]); + sz->decoder_state = IgnorePulse; + break; + case FullSpace: + if (sz->buf_in[i] == SZ_TIMEOUT) { + DEFINE_IR_RAW_EVENT(rawir); + + rawir.pulse = false; + rawir.duration = sz->props->timeout; + sz->idle = true; + if (sz->timeout_enabled) + sz_push(sz, rawir); + ir_raw_event_handle(sz->idev); + } else { + sz_push_full_space(sz, sz->buf_in[i]); + } + sz->decoder_state = PulseSpace; + break; + case IgnorePulse: + if ((sz->buf_in[i] & SZ_SPACE_MASK) == + SZ_SPACE_MASK) { + sz->decoder_state = FullSpace; + continue; + } + sz_push_half_space(sz, sz->buf_in[i]); + sz->decoder_state = PulseSpace; + break; + } + } + + usb_submit_urb(urb, GFP_ATOMIC); + + return; +} + +static struct input_dev *streamzap_init_input_dev(struct streamzap_ir *sz) +{ + struct input_dev *idev; + struct ir_dev_props *props; + struct device *dev = sz->dev; + int ret; + + idev = input_allocate_device(); + if (!idev) { + dev_err(dev, "remote input dev allocation failed\n"); + goto idev_alloc_failed; + } + + props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); + if (!props) { + dev_err(dev, "remote ir dev props allocation failed\n"); + goto props_alloc_failed; + } + + snprintf(sz->name, sizeof(sz->name), "Streamzap PC Remote Infrared " + "Receiver (%04x:%04x)", + le16_to_cpu(sz->usbdev->descriptor.idVendor), + le16_to_cpu(sz->usbdev->descriptor.idProduct)); + + idev->name = sz->name; + usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys)); + strlcat(sz->phys, "/input0", sizeof(sz->phys)); + idev->phys = sz->phys; + + props->priv = sz; + props->driver_type = RC_DRIVER_IR_RAW; + props->allowed_protos = IR_TYPE_ALL; + + sz->props = props; + + usb_to_input_id(sz->usbdev, &idev->id); + idev->dev.parent = sz->dev; + + ret = ir_input_register(idev, RC_MAP_STREAMZAP, props, DRIVER_NAME); + if (ret < 0) { + dev_err(dev, "remote input device register failed\n"); + goto irdev_failed; + } + + return idev; + +irdev_failed: + kfree(props); +props_alloc_failed: + input_free_device(idev); +idev_alloc_failed: + return NULL; +} + +/** + * streamzap_probe + * + * Called by usb-core to associated with a candidate device + * On any failure the return value is the ERROR + * On success return 0 + */ +static int __devinit streamzap_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *usbdev = interface_to_usbdev(intf); + struct usb_host_interface *iface_host; + struct streamzap_ir *sz = NULL; + char buf[63], name[128] = ""; + int retval = -ENOMEM; + int pipe, maxp; + + /* Allocate space for device driver specific data */ + sz = kzalloc(sizeof(struct streamzap_ir), GFP_KERNEL); + if (!sz) + return -ENOMEM; + + sz->usbdev = usbdev; + sz->interface = intf; + + /* Check to ensure endpoint information matches requirements */ + iface_host = intf->cur_altsetting; + + if (iface_host->desc.bNumEndpoints != 1) { + dev_err(&intf->dev, "%s: Unexpected desc.bNumEndpoints (%d)\n", + __func__, iface_host->desc.bNumEndpoints); + retval = -ENODEV; + goto free_sz; + } + + sz->endpoint = &(iface_host->endpoint[0].desc); + if ((sz->endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + != USB_DIR_IN) { + dev_err(&intf->dev, "%s: endpoint doesn't match input device " + "02%02x\n", __func__, sz->endpoint->bEndpointAddress); + retval = -ENODEV; + goto free_sz; + } + + if ((sz->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + != USB_ENDPOINT_XFER_INT) { + dev_err(&intf->dev, "%s: endpoint attributes don't match xfer " + "02%02x\n", __func__, sz->endpoint->bmAttributes); + retval = -ENODEV; + goto free_sz; + } + + pipe = usb_rcvintpipe(usbdev, sz->endpoint->bEndpointAddress); + maxp = usb_maxpacket(usbdev, pipe, usb_pipeout(pipe)); + + if (maxp == 0) { + dev_err(&intf->dev, "%s: endpoint Max Packet Size is 0!?!\n", + __func__); + retval = -ENODEV; + goto free_sz; + } + + /* Allocate the USB buffer and IRQ URB */ + sz->buf_in = usb_alloc_coherent(usbdev, maxp, GFP_ATOMIC, &sz->dma_in); + if (!sz->buf_in) + goto free_sz; + + sz->urb_in = usb_alloc_urb(0, GFP_KERNEL); + if (!sz->urb_in) + goto free_buf_in; + + sz->dev = &intf->dev; + sz->buf_in_len = maxp; + + if (usbdev->descriptor.iManufacturer + && usb_string(usbdev, usbdev->descriptor.iManufacturer, + buf, sizeof(buf)) > 0) + strlcpy(name, buf, sizeof(name)); + + if (usbdev->descriptor.iProduct + && usb_string(usbdev, usbdev->descriptor.iProduct, + buf, sizeof(buf)) > 0) + snprintf(name + strlen(name), sizeof(name) - strlen(name), + " %s", buf); + + sz->idev = streamzap_init_input_dev(sz); + if (!sz->idev) + goto input_dev_fail; + + sz->idle = true; + sz->decoder_state = PulseSpace; + /* FIXME: don't yet have a way to set this */ + sz->timeout_enabled = true; + sz->props->timeout = (((SZ_TIMEOUT * SZ_RESOLUTION * 1000) & + IR_MAX_DURATION) | 0x03000000); + #if 0 + /* not yet supported, depends on patches from maxim */ + /* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */ + sz->min_timeout = SZ_TIMEOUT * SZ_RESOLUTION * 1000; + sz->max_timeout = SZ_TIMEOUT * SZ_RESOLUTION * 1000; + #endif + + do_gettimeofday(&sz->signal_start); + + /* Complete final initialisations */ + usb_fill_int_urb(sz->urb_in, usbdev, pipe, sz->buf_in, + maxp, (usb_complete_t)streamzap_callback, + sz, sz->endpoint->bInterval); + sz->urb_in->transfer_dma = sz->dma_in; + sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + usb_set_intfdata(intf, sz); + + if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) + dev_err(sz->dev, "urb submit failed\n"); + + dev_info(sz->dev, "Registered %s on usb%d:%d\n", name, + usbdev->bus->busnum, usbdev->devnum); + + /* Load the streamzap not-quite-rc5 decoder too */ + load_rc5_sz_decode(); + + return 0; + +input_dev_fail: + usb_free_urb(sz->urb_in); +free_buf_in: + usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in); +free_sz: + kfree(sz); + + return retval; +} + +/** + * streamzap_disconnect + * + * Called by the usb core when the device is removed from the system. + * + * This routine guarantees that the driver will not submit any more urbs + * by clearing dev->usbdev. It is also supposed to terminate any currently + * active urbs. Unfortunately, usb_bulk_msg(), used in streamzap_read(), + * does not provide any way to do this. + */ +static void streamzap_disconnect(struct usb_interface *interface) +{ + struct streamzap_ir *sz = usb_get_intfdata(interface); + struct usb_device *usbdev = interface_to_usbdev(interface); + + usb_set_intfdata(interface, NULL); + + if (!sz) + return; + + sz->usbdev = NULL; + ir_input_unregister(sz->idev); + usb_kill_urb(sz->urb_in); + usb_free_urb(sz->urb_in); + usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in); + + kfree(sz); +} + +static int streamzap_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct streamzap_ir *sz = usb_get_intfdata(intf); + + usb_kill_urb(sz->urb_in); + + return 0; +} + +static int streamzap_resume(struct usb_interface *intf) +{ + struct streamzap_ir *sz = usb_get_intfdata(intf); + + if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) { + dev_err(sz->dev, "Error sumbiting urb\n"); + return -EIO; + } + + return 0; +} + +/** + * streamzap_init + */ +static int __init streamzap_init(void) +{ + int ret; + + /* register this driver with the USB subsystem */ + ret = usb_register(&streamzap_driver); + if (ret < 0) + printk(KERN_ERR DRIVER_NAME ": usb register failed, " + "result = %d\n", ret); + + return ret; +} + +/** + * streamzap_exit + */ +static void __exit streamzap_exit(void) +{ + usb_deregister(&streamzap_driver); +} + + +module_init(streamzap_init); +module_exit(streamzap_exit); + +MODULE_AUTHOR("Jarod Wilson "); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable debugging messages"); -- cgit v0.10.2 From f62de675f796a992011c598c405a3d6fada9aa20 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 9 Nov 2010 23:09:57 -0300 Subject: [media] Rename rc-core files from ir- to rc- As protocol decoders are specific to InfraRed, keep their names as-is. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 38873cf..479a8f4 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -1,9 +1,9 @@ ir-common-objs := ir-functions.o -ir-core-objs := ir-keytable.o ir-sysfs.o ir-raw-event.o rc-map.o +rc-core-objs := rc-main.o rc-sysfs.o rc-raw.o rc-map.o obj-y += keymaps/ -obj-$(CONFIG_IR_CORE) += ir-core.o +obj-$(CONFIG_IR_CORE) += rc-core.o obj-$(CONFIG_IR_LEGACY) += ir-common.o obj-$(CONFIG_LIRC) += lirc_dev.o obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o diff --git a/drivers/media/rc/ir-core-priv.h b/drivers/media/rc/ir-core-priv.h deleted file mode 100644 index 81c936b..0000000 --- a/drivers/media/rc/ir-core-priv.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Remote Controller core raw events header - * - * Copyright (C) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _IR_RAW_EVENT -#define _IR_RAW_EVENT - -#include -#include -#include - -struct ir_raw_handler { - struct list_head list; - - u64 protocols; /* which are handled by this handler */ - int (*decode)(struct input_dev *input_dev, struct ir_raw_event event); - - /* These two should only be used by the lirc decoder */ - int (*raw_register)(struct input_dev *input_dev); - int (*raw_unregister)(struct input_dev *input_dev); -}; - -struct ir_raw_event_ctrl { - struct list_head list; /* to keep track of raw clients */ - struct task_struct *thread; - spinlock_t lock; - struct kfifo kfifo; /* fifo for the pulse/space durations */ - ktime_t last_event; /* when last event occurred */ - enum raw_event_type last_type; /* last event type */ - struct input_dev *input_dev; /* pointer to the parent input_dev */ - u64 enabled_protocols; /* enabled raw protocol decoders */ - - /* raw decoder state follows */ - struct ir_raw_event prev_ev; - struct ir_raw_event this_ev; - struct nec_dec { - int state; - unsigned count; - u32 bits; - bool is_nec_x; - bool necx_repeat; - } nec; - struct rc5_dec { - int state; - u32 bits; - unsigned count; - unsigned wanted_bits; - } rc5; - struct rc6_dec { - int state; - u8 header; - u32 body; - bool toggle; - unsigned count; - unsigned wanted_bits; - } rc6; - struct sony_dec { - int state; - u32 bits; - unsigned count; - } sony; - struct jvc_dec { - int state; - u16 bits; - u16 old_bits; - unsigned count; - bool first; - bool toggle; - } jvc; - struct rc5_sz_dec { - int state; - u32 bits; - unsigned count; - unsigned wanted_bits; - } rc5_sz; - struct lirc_codec { - struct ir_input_dev *ir_dev; - struct lirc_driver *drv; - int carrier_low; - - ktime_t gap_start; - u64 gap_duration; - bool gap; - bool send_timeout_reports; - - } lirc; -}; - -/* macros for IR decoders */ -static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin) -{ - return d1 > (d2 - margin); -} - -static inline bool eq_margin(unsigned d1, unsigned d2, unsigned margin) -{ - return ((d1 > (d2 - margin)) && (d1 < (d2 + margin))); -} - -static inline bool is_transition(struct ir_raw_event *x, struct ir_raw_event *y) -{ - return x->pulse != y->pulse; -} - -static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration) -{ - if (duration > ev->duration) - ev->duration = 0; - else - ev->duration -= duration; -} - -/* Returns true if event is normal pulse/space event */ -static inline bool is_timing_event(struct ir_raw_event ev) -{ - return !ev.carrier_report && !ev.reset; -} - -#define TO_US(duration) DIV_ROUND_CLOSEST((duration), 1000) -#define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space") -/* - * Routines from ir-sysfs.c - Meant to be called only internally inside - * ir-core - */ -int ir_register_input(struct input_dev *input_dev); - -int ir_register_class(struct input_dev *input_dev); -void ir_unregister_class(struct input_dev *input_dev); - -/* - * Routines from ir-raw-event.c to be used internally and by decoders - */ -u64 ir_raw_get_allowed_protocols(void); -int ir_raw_event_register(struct input_dev *input_dev); -void ir_raw_event_unregister(struct input_dev *input_dev); -int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); -void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); -void ir_raw_init(void); - -int ir_rcmap_init(void); -void ir_rcmap_cleanup(void); -/* - * Decoder initialization code - * - * Those load logic are called during ir-core init, and automatically - * loads the compiled decoders for their usage with IR raw events - */ - -/* from ir-nec-decoder.c */ -#ifdef CONFIG_IR_NEC_DECODER_MODULE -#define load_nec_decode() request_module("ir-nec-decoder") -#else -#define load_nec_decode() 0 -#endif - -/* from ir-rc5-decoder.c */ -#ifdef CONFIG_IR_RC5_DECODER_MODULE -#define load_rc5_decode() request_module("ir-rc5-decoder") -#else -#define load_rc5_decode() 0 -#endif - -/* from ir-rc6-decoder.c */ -#ifdef CONFIG_IR_RC6_DECODER_MODULE -#define load_rc6_decode() request_module("ir-rc6-decoder") -#else -#define load_rc6_decode() 0 -#endif - -/* from ir-jvc-decoder.c */ -#ifdef CONFIG_IR_JVC_DECODER_MODULE -#define load_jvc_decode() request_module("ir-jvc-decoder") -#else -#define load_jvc_decode() 0 -#endif - -/* from ir-sony-decoder.c */ -#ifdef CONFIG_IR_SONY_DECODER_MODULE -#define load_sony_decode() request_module("ir-sony-decoder") -#else -#define load_sony_decode() 0 -#endif - -/* from ir-lirc-codec.c */ -#ifdef CONFIG_IR_LIRC_CODEC_MODULE -#define load_lirc_codec() request_module("ir-lirc-codec") -#else -#define load_lirc_codec() 0 -#endif - - -#endif /* _IR_RAW_EVENT */ diff --git a/drivers/media/rc/ir-functions.c b/drivers/media/rc/ir-functions.c index ec021c9..14397d0 100644 --- a/drivers/media/rc/ir-functions.c +++ b/drivers/media/rc/ir-functions.c @@ -24,7 +24,7 @@ #include #include #include -#include "ir-core-priv.h" +#include "rc-core-priv.h" /* -------------------------------------------------------------------------- */ diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c index 63dca6e..d83a5f6 100644 --- a/drivers/media/rc/ir-jvc-decoder.c +++ b/drivers/media/rc/ir-jvc-decoder.c @@ -13,7 +13,7 @@ */ #include -#include "ir-core-priv.h" +#include "rc-core-priv.h" #define JVC_NBITS 16 /* dev(8) + func(8) */ #define JVC_UNIT 525000 /* ns */ diff --git a/drivers/media/rc/ir-keytable.c b/drivers/media/rc/ir-keytable.c deleted file mode 100644 index 8039110..0000000 --- a/drivers/media/rc/ir-keytable.c +++ /dev/null @@ -1,766 +0,0 @@ -/* ir-keytable.c - handle IR scancode->keycode tables - * - * Copyright (C) 2009 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - - -#include -#include -#include "ir-core-priv.h" - -/* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */ -#define IR_TAB_MIN_SIZE 256 -#define IR_TAB_MAX_SIZE 8192 - -/* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */ -#define IR_KEYPRESS_TIMEOUT 250 - -/** - * ir_create_table() - initializes a scancode table - * @rc_tab: the ir_scancode_table to initialize - * @name: name to assign to the table - * @ir_type: ir type to assign to the new table - * @size: initial size of the table - * @return: zero on success or a negative error code - * - * This routine will initialize the ir_scancode_table and will allocate - * memory to hold at least the specified number elements. - */ -static int ir_create_table(struct ir_scancode_table *rc_tab, - const char *name, u64 ir_type, size_t size) -{ - rc_tab->name = name; - rc_tab->ir_type = ir_type; - rc_tab->alloc = roundup_pow_of_two(size * sizeof(struct ir_scancode)); - rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode); - rc_tab->scan = kmalloc(rc_tab->alloc, GFP_KERNEL); - if (!rc_tab->scan) - return -ENOMEM; - - IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", - rc_tab->size, rc_tab->alloc); - return 0; -} - -/** - * ir_free_table() - frees memory allocated by a scancode table - * @rc_tab: the table whose mappings need to be freed - * - * This routine will free memory alloctaed for key mappings used by given - * scancode table. - */ -static void ir_free_table(struct ir_scancode_table *rc_tab) -{ - rc_tab->size = 0; - kfree(rc_tab->scan); - rc_tab->scan = NULL; -} - -/** - * ir_resize_table() - resizes a scancode table if necessary - * @rc_tab: the ir_scancode_table to resize - * @gfp_flags: gfp flags to use when allocating memory - * @return: zero on success or a negative error code - * - * This routine will shrink the ir_scancode_table if it has lots of - * unused entries and grow it if it is full. - */ -static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags) -{ - unsigned int oldalloc = rc_tab->alloc; - unsigned int newalloc = oldalloc; - struct ir_scancode *oldscan = rc_tab->scan; - struct ir_scancode *newscan; - - if (rc_tab->size == rc_tab->len) { - /* All entries in use -> grow keytable */ - if (rc_tab->alloc >= IR_TAB_MAX_SIZE) - return -ENOMEM; - - newalloc *= 2; - IR_dprintk(1, "Growing table to %u bytes\n", newalloc); - } - - if ((rc_tab->len * 3 < rc_tab->size) && (oldalloc > IR_TAB_MIN_SIZE)) { - /* Less than 1/3 of entries in use -> shrink keytable */ - newalloc /= 2; - IR_dprintk(1, "Shrinking table to %u bytes\n", newalloc); - } - - if (newalloc == oldalloc) - return 0; - - newscan = kmalloc(newalloc, gfp_flags); - if (!newscan) { - IR_dprintk(1, "Failed to kmalloc %u bytes\n", newalloc); - return -ENOMEM; - } - - memcpy(newscan, rc_tab->scan, rc_tab->len * sizeof(struct ir_scancode)); - rc_tab->scan = newscan; - rc_tab->alloc = newalloc; - rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode); - kfree(oldscan); - return 0; -} - -/** - * ir_update_mapping() - set a keycode in the scancode->keycode table - * @dev: the struct input_dev device descriptor - * @rc_tab: scancode table to be adjusted - * @index: index of the mapping that needs to be updated - * @keycode: the desired keycode - * @return: previous keycode assigned to the mapping - * - * This routine is used to update scancode->keycopde mapping at given - * position. - */ -static unsigned int ir_update_mapping(struct input_dev *dev, - struct ir_scancode_table *rc_tab, - unsigned int index, - unsigned int new_keycode) -{ - int old_keycode = rc_tab->scan[index].keycode; - int i; - - /* Did the user wish to remove the mapping? */ - if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) { - IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", - index, rc_tab->scan[index].scancode); - rc_tab->len--; - memmove(&rc_tab->scan[index], &rc_tab->scan[index+ 1], - (rc_tab->len - index) * sizeof(struct ir_scancode)); - } else { - IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n", - index, - old_keycode == KEY_RESERVED ? "New" : "Replacing", - rc_tab->scan[index].scancode, new_keycode); - rc_tab->scan[index].keycode = new_keycode; - __set_bit(new_keycode, dev->keybit); - } - - if (old_keycode != KEY_RESERVED) { - /* A previous mapping was updated... */ - __clear_bit(old_keycode, dev->keybit); - /* ... but another scancode might use the same keycode */ - for (i = 0; i < rc_tab->len; i++) { - if (rc_tab->scan[i].keycode == old_keycode) { - __set_bit(old_keycode, dev->keybit); - break; - } - } - - /* Possibly shrink the keytable, failure is not a problem */ - ir_resize_table(rc_tab, GFP_ATOMIC); - } - - return old_keycode; -} - -/** - * ir_locate_scancode() - set a keycode in the scancode->keycode table - * @ir_dev: the struct ir_input_dev device descriptor - * @rc_tab: scancode table to be searched - * @scancode: the desired scancode - * @resize: controls whether we allowed to resize the table to - * accomodate not yet present scancodes - * @return: index of the mapping containing scancode in question - * or -1U in case of failure. - * - * This routine is used to locate given scancode in ir_scancode_table. - * If scancode is not yet present the routine will allocate a new slot - * for it. - */ -static unsigned int ir_establish_scancode(struct ir_input_dev *ir_dev, - struct ir_scancode_table *rc_tab, - unsigned int scancode, - bool resize) -{ - unsigned int i; - - /* - * Unfortunately, some hardware-based IR decoders don't provide - * all bits for the complete IR code. In general, they provide only - * the command part of the IR code. Yet, as it is possible to replace - * the provided IR with another one, it is needed to allow loading - * IR tables from other remotes. So, - */ - if (ir_dev->props && ir_dev->props->scanmask) - scancode &= ir_dev->props->scanmask; - - /* First check if we already have a mapping for this ir command */ - for (i = 0; i < rc_tab->len; i++) { - if (rc_tab->scan[i].scancode == scancode) - return i; - - /* Keytable is sorted from lowest to highest scancode */ - if (rc_tab->scan[i].scancode >= scancode) - break; - } - - /* No previous mapping found, we might need to grow the table */ - if (rc_tab->size == rc_tab->len) { - if (!resize || ir_resize_table(rc_tab, GFP_ATOMIC)) - return -1U; - } - - /* i is the proper index to insert our new keycode */ - if (i < rc_tab->len) - memmove(&rc_tab->scan[i + 1], &rc_tab->scan[i], - (rc_tab->len - i) * sizeof(struct ir_scancode)); - rc_tab->scan[i].scancode = scancode; - rc_tab->scan[i].keycode = KEY_RESERVED; - rc_tab->len++; - - return i; -} - -/** - * ir_setkeycode() - set a keycode in the scancode->keycode table - * @dev: the struct input_dev device descriptor - * @scancode: the desired scancode - * @keycode: result - * @return: -EINVAL if the keycode could not be inserted, otherwise zero. - * - * This routine is used to handle evdev EVIOCSKEY ioctl. - */ -static int ir_setkeycode(struct input_dev *dev, - const struct input_keymap_entry *ke, - unsigned int *old_keycode) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(dev); - struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; - unsigned int index; - unsigned int scancode; - int retval; - unsigned long flags; - - spin_lock_irqsave(&rc_tab->lock, flags); - - if (ke->flags & INPUT_KEYMAP_BY_INDEX) { - index = ke->index; - if (index >= rc_tab->len) { - retval = -EINVAL; - goto out; - } - } else { - retval = input_scancode_to_scalar(ke, &scancode); - if (retval) - goto out; - - index = ir_establish_scancode(ir_dev, rc_tab, scancode, true); - if (index >= rc_tab->len) { - retval = -ENOMEM; - goto out; - } - } - - *old_keycode = ir_update_mapping(dev, rc_tab, index, ke->keycode); - -out: - spin_unlock_irqrestore(&rc_tab->lock, flags); - return retval; -} - -/** - * ir_setkeytable() - sets several entries in the scancode->keycode table - * @dev: the struct input_dev device descriptor - * @to: the struct ir_scancode_table to copy entries to - * @from: the struct ir_scancode_table to copy entries from - * @return: -ENOMEM if all keycodes could not be inserted, otherwise zero. - * - * This routine is used to handle table initialization. - */ -static int ir_setkeytable(struct ir_input_dev *ir_dev, - const struct ir_scancode_table *from) -{ - struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; - unsigned int i, index; - int rc; - - rc = ir_create_table(&ir_dev->rc_tab, - from->name, from->ir_type, from->size); - if (rc) - return rc; - - IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", - rc_tab->size, rc_tab->alloc); - - for (i = 0; i < from->size; i++) { - index = ir_establish_scancode(ir_dev, rc_tab, - from->scan[i].scancode, false); - if (index >= rc_tab->len) { - rc = -ENOMEM; - break; - } - - ir_update_mapping(ir_dev->input_dev, rc_tab, index, - from->scan[i].keycode); - } - - if (rc) - ir_free_table(rc_tab); - - return rc; -} - -/** - * ir_lookup_by_scancode() - locate mapping by scancode - * @rc_tab: the &struct ir_scancode_table to search - * @scancode: scancode to look for in the table - * @return: index in the table, -1U if not found - * - * This routine performs binary search in RC keykeymap table for - * given scancode. - */ -static unsigned int ir_lookup_by_scancode(const struct ir_scancode_table *rc_tab, - unsigned int scancode) -{ - int start = 0; - int end = rc_tab->len - 1; - int mid; - - while (start <= end) { - mid = (start + end) / 2; - if (rc_tab->scan[mid].scancode < scancode) - start = mid + 1; - else if (rc_tab->scan[mid].scancode > scancode) - end = mid - 1; - else - return mid; - } - - return -1U; -} - -/** - * ir_getkeycode() - get a keycode from the scancode->keycode table - * @dev: the struct input_dev device descriptor - * @scancode: the desired scancode - * @keycode: used to return the keycode, if found, or KEY_RESERVED - * @return: always returns zero. - * - * This routine is used to handle evdev EVIOCGKEY ioctl. - */ -static int ir_getkeycode(struct input_dev *dev, - struct input_keymap_entry *ke) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(dev); - struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; - struct ir_scancode *entry; - unsigned long flags; - unsigned int index; - unsigned int scancode; - int retval; - - spin_lock_irqsave(&rc_tab->lock, flags); - - if (ke->flags & INPUT_KEYMAP_BY_INDEX) { - index = ke->index; - } else { - retval = input_scancode_to_scalar(ke, &scancode); - if (retval) - goto out; - - index = ir_lookup_by_scancode(rc_tab, scancode); - } - - if (index >= rc_tab->len) { - if (!(ke->flags & INPUT_KEYMAP_BY_INDEX)) - IR_dprintk(1, "unknown key for scancode 0x%04x\n", - scancode); - retval = -EINVAL; - goto out; - } - - entry = &rc_tab->scan[index]; - - ke->index = index; - ke->keycode = entry->keycode; - ke->len = sizeof(entry->scancode); - memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode)); - - retval = 0; - -out: - spin_unlock_irqrestore(&rc_tab->lock, flags); - return retval; -} - -/** - * ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode - * @input_dev: the struct input_dev descriptor of the device - * @scancode: the scancode that we're seeking - * - * This routine is used by the input routines when a key is pressed at the - * IR. The scancode is received and needs to be converted into a keycode. - * If the key is not found, it returns KEY_RESERVED. Otherwise, returns the - * corresponding keycode from the table. - */ -u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(dev); - struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; - unsigned int keycode; - unsigned int index; - unsigned long flags; - - spin_lock_irqsave(&rc_tab->lock, flags); - - index = ir_lookup_by_scancode(rc_tab, scancode); - keycode = index < rc_tab->len ? - rc_tab->scan[index].keycode : KEY_RESERVED; - - spin_unlock_irqrestore(&rc_tab->lock, flags); - - if (keycode != KEY_RESERVED) - IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", - dev->name, scancode, keycode); - - return keycode; -} -EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); - -/** - * ir_do_keyup() - internal function to signal the release of a keypress - * @ir: the struct ir_input_dev descriptor of the device - * - * This function is used internally to release a keypress, it must be - * called with keylock held. - */ -static void ir_do_keyup(struct ir_input_dev *ir) -{ - if (!ir->keypressed) - return; - - IR_dprintk(1, "keyup key 0x%04x\n", ir->last_keycode); - input_report_key(ir->input_dev, ir->last_keycode, 0); - input_sync(ir->input_dev); - ir->keypressed = false; -} - -/** - * ir_keyup() - generates input event to signal the release of a keypress - * @dev: the struct input_dev descriptor of the device - * - * This routine is used to signal that a key has been released on the - * remote control. - */ -void ir_keyup(struct input_dev *dev) -{ - unsigned long flags; - struct ir_input_dev *ir = input_get_drvdata(dev); - - spin_lock_irqsave(&ir->keylock, flags); - ir_do_keyup(ir); - spin_unlock_irqrestore(&ir->keylock, flags); -} -EXPORT_SYMBOL_GPL(ir_keyup); - -/** - * ir_timer_keyup() - generates a keyup event after a timeout - * @cookie: a pointer to struct ir_input_dev passed to setup_timer() - * - * This routine will generate a keyup event some time after a keydown event - * is generated when no further activity has been detected. - */ -static void ir_timer_keyup(unsigned long cookie) -{ - struct ir_input_dev *ir = (struct ir_input_dev *)cookie; - unsigned long flags; - - /* - * ir->keyup_jiffies is used to prevent a race condition if a - * hardware interrupt occurs at this point and the keyup timer - * event is moved further into the future as a result. - * - * The timer will then be reactivated and this function called - * again in the future. We need to exit gracefully in that case - * to allow the input subsystem to do its auto-repeat magic or - * a keyup event might follow immediately after the keydown. - */ - spin_lock_irqsave(&ir->keylock, flags); - if (time_is_before_eq_jiffies(ir->keyup_jiffies)) - ir_do_keyup(ir); - spin_unlock_irqrestore(&ir->keylock, flags); -} - -/** - * ir_repeat() - notifies the IR core that a key is still pressed - * @dev: the struct input_dev descriptor of the device - * - * This routine is used by IR decoders when a repeat message which does - * not include the necessary bits to reproduce the scancode has been - * received. - */ -void ir_repeat(struct input_dev *dev) -{ - unsigned long flags; - struct ir_input_dev *ir = input_get_drvdata(dev); - - spin_lock_irqsave(&ir->keylock, flags); - - input_event(dev, EV_MSC, MSC_SCAN, ir->last_scancode); - - if (!ir->keypressed) - goto out; - - ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); - mod_timer(&ir->timer_keyup, ir->keyup_jiffies); - -out: - spin_unlock_irqrestore(&ir->keylock, flags); -} -EXPORT_SYMBOL_GPL(ir_repeat); - -/** - * ir_do_keydown() - internal function to process a keypress - * @dev: the struct input_dev descriptor of the device - * @scancode: the scancode of the keypress - * @keycode: the keycode of the keypress - * @toggle: the toggle value of the keypress - * - * This function is used internally to register a keypress, it must be - * called with keylock held. - */ -static void ir_do_keydown(struct input_dev *dev, int scancode, - u32 keycode, u8 toggle) -{ - struct ir_input_dev *ir = input_get_drvdata(dev); - - input_event(dev, EV_MSC, MSC_SCAN, scancode); - - /* Repeat event? */ - if (ir->keypressed && - ir->last_scancode == scancode && - ir->last_toggle == toggle) - return; - - /* Release old keypress */ - ir_do_keyup(ir); - - ir->last_scancode = scancode; - ir->last_toggle = toggle; - ir->last_keycode = keycode; - - if (keycode == KEY_RESERVED) - return; - - /* Register a keypress */ - ir->keypressed = true; - IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", - dev->name, keycode, scancode); - input_report_key(dev, ir->last_keycode, 1); - input_sync(dev); -} - -/** - * ir_keydown() - generates input event for a key press - * @dev: the struct input_dev descriptor of the device - * @scancode: the scancode that we're seeking - * @toggle: the toggle value (protocol dependent, if the protocol doesn't - * support toggle values, this should be set to zero) - * - * This routine is used by the input routines when a key is pressed at the - * IR. It gets the keycode for a scancode and reports an input event via - * input_report_key(). - */ -void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) -{ - unsigned long flags; - struct ir_input_dev *ir = input_get_drvdata(dev); - u32 keycode = ir_g_keycode_from_table(dev, scancode); - - spin_lock_irqsave(&ir->keylock, flags); - ir_do_keydown(dev, scancode, keycode, toggle); - - if (ir->keypressed) { - ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); - mod_timer(&ir->timer_keyup, ir->keyup_jiffies); - } - spin_unlock_irqrestore(&ir->keylock, flags); -} -EXPORT_SYMBOL_GPL(ir_keydown); - -/** - * ir_keydown_notimeout() - generates input event for a key press without - * an automatic keyup event at a later time - * @dev: the struct input_dev descriptor of the device - * @scancode: the scancode that we're seeking - * @toggle: the toggle value (protocol dependent, if the protocol doesn't - * support toggle values, this should be set to zero) - * - * This routine is used by the input routines when a key is pressed at the - * IR. It gets the keycode for a scancode and reports an input event via - * input_report_key(). The driver must manually call ir_keyup() at a later - * stage. - */ -void ir_keydown_notimeout(struct input_dev *dev, int scancode, u8 toggle) -{ - unsigned long flags; - struct ir_input_dev *ir = input_get_drvdata(dev); - u32 keycode = ir_g_keycode_from_table(dev, scancode); - - spin_lock_irqsave(&ir->keylock, flags); - ir_do_keydown(dev, scancode, keycode, toggle); - spin_unlock_irqrestore(&ir->keylock, flags); -} -EXPORT_SYMBOL_GPL(ir_keydown_notimeout); - -static int ir_open(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - - return ir_dev->props->open(ir_dev->props->priv); -} - -static void ir_close(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - - ir_dev->props->close(ir_dev->props->priv); -} - -/** - * __ir_input_register() - sets the IR keycode table and add the handlers - * for keymap table get/set - * @input_dev: the struct input_dev descriptor of the device - * @rc_tab: the struct ir_scancode_table table of scancode/keymap - * - * This routine is used to initialize the input infrastructure - * to work with an IR. - * It will register the input/evdev interface for the device and - * register the syfs code for IR class - */ -int __ir_input_register(struct input_dev *input_dev, - const struct ir_scancode_table *rc_tab, - struct ir_dev_props *props, - const char *driver_name) -{ - struct ir_input_dev *ir_dev; - int rc; - - if (rc_tab->scan == NULL || !rc_tab->size) - return -EINVAL; - - ir_dev = kzalloc(sizeof(*ir_dev), GFP_KERNEL); - if (!ir_dev) - return -ENOMEM; - - ir_dev->driver_name = kasprintf(GFP_KERNEL, "%s", driver_name); - if (!ir_dev->driver_name) { - rc = -ENOMEM; - goto out_dev; - } - - input_dev->getkeycode_new = ir_getkeycode; - input_dev->setkeycode_new = ir_setkeycode; - input_set_drvdata(input_dev, ir_dev); - ir_dev->input_dev = input_dev; - - spin_lock_init(&ir_dev->rc_tab.lock); - spin_lock_init(&ir_dev->keylock); - setup_timer(&ir_dev->timer_keyup, ir_timer_keyup, (unsigned long)ir_dev); - - if (props) { - ir_dev->props = props; - if (props->open) - input_dev->open = ir_open; - if (props->close) - input_dev->close = ir_close; - } - - set_bit(EV_KEY, input_dev->evbit); - set_bit(EV_REP, input_dev->evbit); - set_bit(EV_MSC, input_dev->evbit); - set_bit(MSC_SCAN, input_dev->mscbit); - - rc = ir_setkeytable(ir_dev, rc_tab); - if (rc) - goto out_name; - - rc = ir_register_class(input_dev); - if (rc < 0) - goto out_table; - - if (ir_dev->props) - if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) { - rc = ir_raw_event_register(input_dev); - if (rc < 0) - goto out_event; - } - - rc = ir_register_input(input_dev); - if (rc < 0) - goto out_event; - - IR_dprintk(1, "Registered input device on %s for %s remote%s.\n", - driver_name, rc_tab->name, - (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ? - " in raw mode" : ""); - - /* - * Default delay of 250ms is too short for some protocols, expecially - * since the timeout is currently set to 250ms. Increase it to 500ms, - * to avoid wrong repetition of the keycodes. - */ - input_dev->rep[REP_DELAY] = 500; - - return 0; - -out_event: - ir_unregister_class(input_dev); -out_table: - ir_free_table(&ir_dev->rc_tab); -out_name: - kfree(ir_dev->driver_name); -out_dev: - kfree(ir_dev); - return rc; -} -EXPORT_SYMBOL_GPL(__ir_input_register); - -/** - * ir_input_unregister() - unregisters IR and frees resources - * @input_dev: the struct input_dev descriptor of the device - - * This routine is used to free memory and de-register interfaces. - */ -void ir_input_unregister(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - - if (!ir_dev) - return; - - IR_dprintk(1, "Freed keycode table\n"); - - del_timer_sync(&ir_dev->timer_keyup); - if (ir_dev->props) - if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) - ir_raw_event_unregister(input_dev); - - ir_free_table(&ir_dev->rc_tab); - - ir_unregister_class(input_dev); - - kfree(ir_dev->driver_name); - kfree(ir_dev); -} -EXPORT_SYMBOL_GPL(ir_input_unregister); - -int ir_core_debug; /* ir_debug level (0,1,2) */ -EXPORT_SYMBOL_GPL(ir_core_debug); -module_param_named(debug, ir_core_debug, int, 0644); - -MODULE_AUTHOR("Mauro Carvalho Chehab "); -MODULE_LICENSE("GPL"); diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index 9fc0db9..9345995d 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -17,7 +17,7 @@ #include #include #include -#include "ir-core-priv.h" +#include "rc-core-priv.h" #define LIRCBUF_SIZE 256 diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c index 70993f7..cad4e99 100644 --- a/drivers/media/rc/ir-nec-decoder.c +++ b/drivers/media/rc/ir-nec-decoder.c @@ -13,7 +13,7 @@ */ #include -#include "ir-core-priv.h" +#include "rc-core-priv.h" #define NEC_NBITS 32 #define NEC_UNIT 562500 /* ns */ diff --git a/drivers/media/rc/ir-raw-event.c b/drivers/media/rc/ir-raw-event.c deleted file mode 100644 index a06a07e..0000000 --- a/drivers/media/rc/ir-raw-event.c +++ /dev/null @@ -1,382 +0,0 @@ -/* ir-raw-event.c - handle IR Pulse/Space event - * - * Copyright (C) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include "ir-core-priv.h" - -/* Define the max number of pulse/space transitions to buffer */ -#define MAX_IR_EVENT_SIZE 512 - -/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */ -static LIST_HEAD(ir_raw_client_list); - -/* Used to handle IR raw handler extensions */ -static DEFINE_MUTEX(ir_raw_handler_lock); -static LIST_HEAD(ir_raw_handler_list); -static u64 available_protocols; - -#ifdef MODULE -/* Used to load the decoders */ -static struct work_struct wq_load; -#endif - -static int ir_raw_event_thread(void *data) -{ - struct ir_raw_event ev; - struct ir_raw_handler *handler; - struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data; - int retval; - - while (!kthread_should_stop()) { - - spin_lock_irq(&raw->lock); - retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev)); - - if (!retval) { - set_current_state(TASK_INTERRUPTIBLE); - - if (kthread_should_stop()) - set_current_state(TASK_RUNNING); - - spin_unlock_irq(&raw->lock); - schedule(); - continue; - } - - spin_unlock_irq(&raw->lock); - - - BUG_ON(retval != sizeof(ev)); - - mutex_lock(&ir_raw_handler_lock); - list_for_each_entry(handler, &ir_raw_handler_list, list) - handler->decode(raw->input_dev, ev); - raw->prev_ev = ev; - mutex_unlock(&ir_raw_handler_lock); - } - - return 0; -} - -/** - * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders - * @input_dev: the struct input_dev device descriptor - * @ev: the struct ir_raw_event descriptor of the pulse/space - * - * This routine (which may be called from an interrupt context) stores a - * pulse/space duration for the raw ir decoding state machines. Pulses are - * signalled as positive values and spaces as negative values. A zero value - * will reset the decoding state machines. - */ -int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev) -{ - struct ir_input_dev *ir = input_get_drvdata(input_dev); - - if (!ir->raw) - return -EINVAL; - - IR_dprintk(2, "sample: (%05dus %s)\n", - TO_US(ev->duration), TO_STR(ev->pulse)); - - if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) - return -ENOMEM; - - return 0; -} -EXPORT_SYMBOL_GPL(ir_raw_event_store); - -/** - * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space - * @input_dev: the struct input_dev device descriptor - * @type: the type of the event that has occurred - * - * This routine (which may be called from an interrupt context) is used to - * store the beginning of an ir pulse or space (or the start/end of ir - * reception) for the raw ir decoding state machines. This is used by - * hardware which does not provide durations directly but only interrupts - * (or similar events) on state change. - */ -int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type) -{ - struct ir_input_dev *ir = input_get_drvdata(input_dev); - ktime_t now; - s64 delta; /* ns */ - struct ir_raw_event ev; - int rc = 0; - - if (!ir->raw) - return -EINVAL; - - now = ktime_get(); - delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event)); - - /* Check for a long duration since last event or if we're - * being called for the first time, note that delta can't - * possibly be negative. - */ - ev.duration = 0; - if (delta > IR_MAX_DURATION || !ir->raw->last_type) - type |= IR_START_EVENT; - else - ev.duration = delta; - - if (type & IR_START_EVENT) - ir_raw_event_reset(input_dev); - else if (ir->raw->last_type & IR_SPACE) { - ev.pulse = false; - rc = ir_raw_event_store(input_dev, &ev); - } else if (ir->raw->last_type & IR_PULSE) { - ev.pulse = true; - rc = ir_raw_event_store(input_dev, &ev); - } else - return 0; - - ir->raw->last_event = now; - ir->raw->last_type = type; - return rc; -} -EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); - -/** - * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing - * @input_dev: the struct input_dev device descriptor - * @type: the type of the event that has occurred - * - * This routine (which may be called from an interrupt context) works - * in similiar manner to ir_raw_event_store_edge. - * This routine is intended for devices with limited internal buffer - * It automerges samples of same type, and handles timeouts - */ -int ir_raw_event_store_with_filter(struct input_dev *input_dev, - struct ir_raw_event *ev) -{ - struct ir_input_dev *ir = input_get_drvdata(input_dev); - struct ir_raw_event_ctrl *raw = ir->raw; - - if (!raw || !ir->props) - return -EINVAL; - - /* Ignore spaces in idle mode */ - if (ir->idle && !ev->pulse) - return 0; - else if (ir->idle) - ir_raw_event_set_idle(input_dev, false); - - if (!raw->this_ev.duration) { - raw->this_ev = *ev; - } else if (ev->pulse == raw->this_ev.pulse) { - raw->this_ev.duration += ev->duration; - } else { - ir_raw_event_store(input_dev, &raw->this_ev); - raw->this_ev = *ev; - } - - /* Enter idle mode if nessesary */ - if (!ev->pulse && ir->props->timeout && - raw->this_ev.duration >= ir->props->timeout) { - ir_raw_event_set_idle(input_dev, true); - } - return 0; -} -EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter); - -/** - * ir_raw_event_set_idle() - hint the ir core if device is receiving - * IR data or not - * @input_dev: the struct input_dev device descriptor - * @idle: the hint value - */ -void ir_raw_event_set_idle(struct input_dev *input_dev, bool idle) -{ - struct ir_input_dev *ir = input_get_drvdata(input_dev); - struct ir_raw_event_ctrl *raw = ir->raw; - - if (!ir->props || !ir->raw) - return; - - IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave"); - - if (idle) { - raw->this_ev.timeout = true; - ir_raw_event_store(input_dev, &raw->this_ev); - init_ir_raw_event(&raw->this_ev); - } - - if (ir->props->s_idle) - ir->props->s_idle(ir->props->priv, idle); - ir->idle = idle; -} -EXPORT_SYMBOL_GPL(ir_raw_event_set_idle); - -/** - * ir_raw_event_handle() - schedules the decoding of stored ir data - * @input_dev: the struct input_dev device descriptor - * - * This routine will signal the workqueue to start decoding stored ir data. - */ -void ir_raw_event_handle(struct input_dev *input_dev) -{ - struct ir_input_dev *ir = input_get_drvdata(input_dev); - unsigned long flags; - - if (!ir->raw) - return; - - spin_lock_irqsave(&ir->raw->lock, flags); - wake_up_process(ir->raw->thread); - spin_unlock_irqrestore(&ir->raw->lock, flags); -} -EXPORT_SYMBOL_GPL(ir_raw_event_handle); - -/* used internally by the sysfs interface */ -u64 -ir_raw_get_allowed_protocols() -{ - u64 protocols; - mutex_lock(&ir_raw_handler_lock); - protocols = available_protocols; - mutex_unlock(&ir_raw_handler_lock); - return protocols; -} - -/* - * Used to (un)register raw event clients - */ -int ir_raw_event_register(struct input_dev *input_dev) -{ - struct ir_input_dev *ir = input_get_drvdata(input_dev); - int rc; - struct ir_raw_handler *handler; - - ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); - if (!ir->raw) - return -ENOMEM; - - ir->raw->input_dev = input_dev; - - ir->raw->enabled_protocols = ~0; - rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, - GFP_KERNEL); - if (rc < 0) { - kfree(ir->raw); - ir->raw = NULL; - return rc; - } - - spin_lock_init(&ir->raw->lock); - ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw, - "rc%u", (unsigned int)ir->devno); - - if (IS_ERR(ir->raw->thread)) { - int ret = PTR_ERR(ir->raw->thread); - - kfree(ir->raw); - ir->raw = NULL; - return ret; - } - - mutex_lock(&ir_raw_handler_lock); - list_add_tail(&ir->raw->list, &ir_raw_client_list); - list_for_each_entry(handler, &ir_raw_handler_list, list) - if (handler->raw_register) - handler->raw_register(ir->raw->input_dev); - mutex_unlock(&ir_raw_handler_lock); - - return 0; -} - -void ir_raw_event_unregister(struct input_dev *input_dev) -{ - struct ir_input_dev *ir = input_get_drvdata(input_dev); - struct ir_raw_handler *handler; - - if (!ir->raw) - return; - - kthread_stop(ir->raw->thread); - - mutex_lock(&ir_raw_handler_lock); - list_del(&ir->raw->list); - list_for_each_entry(handler, &ir_raw_handler_list, list) - if (handler->raw_unregister) - handler->raw_unregister(ir->raw->input_dev); - mutex_unlock(&ir_raw_handler_lock); - - kfifo_free(&ir->raw->kfifo); - kfree(ir->raw); - ir->raw = NULL; -} - -/* - * Extension interface - used to register the IR decoders - */ - -int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) -{ - struct ir_raw_event_ctrl *raw; - - mutex_lock(&ir_raw_handler_lock); - list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); - if (ir_raw_handler->raw_register) - list_for_each_entry(raw, &ir_raw_client_list, list) - ir_raw_handler->raw_register(raw->input_dev); - available_protocols |= ir_raw_handler->protocols; - mutex_unlock(&ir_raw_handler_lock); - - return 0; -} -EXPORT_SYMBOL(ir_raw_handler_register); - -void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) -{ - struct ir_raw_event_ctrl *raw; - - mutex_lock(&ir_raw_handler_lock); - list_del(&ir_raw_handler->list); - if (ir_raw_handler->raw_unregister) - list_for_each_entry(raw, &ir_raw_client_list, list) - ir_raw_handler->raw_unregister(raw->input_dev); - available_protocols &= ~ir_raw_handler->protocols; - mutex_unlock(&ir_raw_handler_lock); -} -EXPORT_SYMBOL(ir_raw_handler_unregister); - -#ifdef MODULE -static void init_decoders(struct work_struct *work) -{ - /* Load the decoder modules */ - - load_nec_decode(); - load_rc5_decode(); - load_rc6_decode(); - load_jvc_decode(); - load_sony_decode(); - load_lirc_codec(); - - /* If needed, we may later add some init code. In this case, - it is needed to change the CONFIG_MODULE test at ir-core.h - */ -} -#endif - -void ir_raw_init(void) -{ -#ifdef MODULE - INIT_WORK(&wq_load, init_decoders); - schedule_work(&wq_load); -#endif -} diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c index 572ed4c..c07f6e0 100644 --- a/drivers/media/rc/ir-rc5-decoder.c +++ b/drivers/media/rc/ir-rc5-decoder.c @@ -20,7 +20,7 @@ * the first two bits are start bits, and a third one is a filing bit */ -#include "ir-core-priv.h" +#include "rc-core-priv.h" #define RC5_NBITS 14 #define RC5X_NBITS 20 diff --git a/drivers/media/rc/ir-rc5-sz-decoder.c b/drivers/media/rc/ir-rc5-sz-decoder.c index 7c41350..0c3b6eb 100644 --- a/drivers/media/rc/ir-rc5-sz-decoder.c +++ b/drivers/media/rc/ir-rc5-sz-decoder.c @@ -20,7 +20,7 @@ * the first two bits are start bits, and a third one is a filing bit */ -#include "ir-core-priv.h" +#include "rc-core-priv.h" #define RC5_SZ_NBITS 15 #define RC5_UNIT 888888 /* ns */ diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c index d25da91..48e82be 100644 --- a/drivers/media/rc/ir-rc6-decoder.c +++ b/drivers/media/rc/ir-rc6-decoder.c @@ -12,7 +12,7 @@ * GNU General Public License for more details. */ -#include "ir-core-priv.h" +#include "rc-core-priv.h" /* * This decoder currently supports: diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c index 2d15730..0a5cadb 100644 --- a/drivers/media/rc/ir-sony-decoder.c +++ b/drivers/media/rc/ir-sony-decoder.c @@ -13,7 +13,7 @@ */ #include -#include "ir-core-priv.h" +#include "rc-core-priv.h" #define SONY_UNIT 600000 /* ns */ #define SONY_HEADER_PULSE (4 * SONY_UNIT) diff --git a/drivers/media/rc/ir-sysfs.c b/drivers/media/rc/ir-sysfs.c deleted file mode 100644 index 38423a8..0000000 --- a/drivers/media/rc/ir-sysfs.c +++ /dev/null @@ -1,362 +0,0 @@ -/* ir-sysfs.c - sysfs interface for RC devices (/sys/class/rc) - * - * Copyright (C) 2009-2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include "ir-core-priv.h" - -#define IRRCV_NUM_DEVICES 256 - -/* bit array to represent IR sysfs device number */ -static unsigned long ir_core_dev_number; - -/* class for /sys/class/rc */ -static char *ir_devnode(struct device *dev, mode_t *mode) -{ - return kasprintf(GFP_KERNEL, "rc/%s", dev_name(dev)); -} - -static struct class ir_input_class = { - .name = "rc", - .devnode = ir_devnode, -}; - -static struct { - u64 type; - char *name; -} proto_names[] = { - { IR_TYPE_UNKNOWN, "unknown" }, - { IR_TYPE_RC5, "rc-5" }, - { IR_TYPE_NEC, "nec" }, - { IR_TYPE_RC6, "rc-6" }, - { IR_TYPE_JVC, "jvc" }, - { IR_TYPE_SONY, "sony" }, - { IR_TYPE_RC5_SZ, "rc-5-sz" }, - { IR_TYPE_LIRC, "lirc" }, -}; - -#define PROTO_NONE "none" - -/** - * show_protocols() - shows the current IR protocol(s) - * @d: the device descriptor - * @mattr: the device attribute struct (unused) - * @buf: a pointer to the output buffer - * - * This routine is a callback routine for input read the IR protocol type(s). - * it is trigged by reading /sys/class/rc/rc?/protocols. - * It returns the protocol names of supported protocols. - * Enabled protocols are printed in brackets. - */ -static ssize_t show_protocols(struct device *d, - struct device_attribute *mattr, char *buf) -{ - struct ir_input_dev *ir_dev = dev_get_drvdata(d); - u64 allowed, enabled; - char *tmp = buf; - int i; - - /* Device is being removed */ - if (!ir_dev) - return -EINVAL; - - if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { - enabled = ir_dev->rc_tab.ir_type; - allowed = ir_dev->props->allowed_protos; - } else if (ir_dev->raw) { - enabled = ir_dev->raw->enabled_protocols; - allowed = ir_raw_get_allowed_protocols(); - } else - return sprintf(tmp, "[builtin]\n"); - - IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", - (long long)allowed, - (long long)enabled); - - for (i = 0; i < ARRAY_SIZE(proto_names); i++) { - if (allowed & enabled & proto_names[i].type) - tmp += sprintf(tmp, "[%s] ", proto_names[i].name); - else if (allowed & proto_names[i].type) - tmp += sprintf(tmp, "%s ", proto_names[i].name); - } - - if (tmp != buf) - tmp--; - *tmp = '\n'; - return tmp + 1 - buf; -} - -/** - * store_protocols() - changes the current IR protocol(s) - * @d: the device descriptor - * @mattr: the device attribute struct (unused) - * @buf: a pointer to the input buffer - * @len: length of the input buffer - * - * This routine is a callback routine for changing the IR protocol type. - * It is trigged by writing to /sys/class/rc/rc?/protocols. - * Writing "+proto" will add a protocol to the list of enabled protocols. - * Writing "-proto" will remove a protocol from the list of enabled protocols. - * Writing "proto" will enable only "proto". - * Writing "none" will disable all protocols. - * Returns -EINVAL if an invalid protocol combination or unknown protocol name - * is used, otherwise @len. - */ -static ssize_t store_protocols(struct device *d, - struct device_attribute *mattr, - const char *data, - size_t len) -{ - struct ir_input_dev *ir_dev = dev_get_drvdata(d); - bool enable, disable; - const char *tmp; - u64 type; - u64 mask; - int rc, i, count = 0; - unsigned long flags; - - /* Device is being removed */ - if (!ir_dev) - return -EINVAL; - - if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) - type = ir_dev->rc_tab.ir_type; - else if (ir_dev->raw) - type = ir_dev->raw->enabled_protocols; - else { - IR_dprintk(1, "Protocol switching not supported\n"); - return -EINVAL; - } - - while ((tmp = strsep((char **) &data, " \n")) != NULL) { - if (!*tmp) - break; - - if (*tmp == '+') { - enable = true; - disable = false; - tmp++; - } else if (*tmp == '-') { - enable = false; - disable = true; - tmp++; - } else { - enable = false; - disable = false; - } - - if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) { - tmp += sizeof(PROTO_NONE); - mask = 0; - count++; - } else { - for (i = 0; i < ARRAY_SIZE(proto_names); i++) { - if (!strncasecmp(tmp, proto_names[i].name, strlen(proto_names[i].name))) { - tmp += strlen(proto_names[i].name); - mask = proto_names[i].type; - break; - } - } - if (i == ARRAY_SIZE(proto_names)) { - IR_dprintk(1, "Unknown protocol: '%s'\n", tmp); - return -EINVAL; - } - count++; - } - - if (enable) - type |= mask; - else if (disable) - type &= ~mask; - else - type = mask; - } - - if (!count) { - IR_dprintk(1, "Protocol not specified\n"); - return -EINVAL; - } - - if (ir_dev->props && ir_dev->props->change_protocol) { - rc = ir_dev->props->change_protocol(ir_dev->props->priv, - type); - if (rc < 0) { - IR_dprintk(1, "Error setting protocols to 0x%llx\n", - (long long)type); - return -EINVAL; - } - } - - if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { - spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); - ir_dev->rc_tab.ir_type = type; - spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); - } else { - ir_dev->raw->enabled_protocols = type; - } - - IR_dprintk(1, "Current protocol(s): 0x%llx\n", - (long long)type); - - return len; -} - -#define ADD_HOTPLUG_VAR(fmt, val...) \ - do { \ - int err = add_uevent_var(env, fmt, val); \ - if (err) \ - return err; \ - } while (0) - -static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) -{ - struct ir_input_dev *ir_dev = dev_get_drvdata(device); - - if (ir_dev->rc_tab.name) - ADD_HOTPLUG_VAR("NAME=%s", ir_dev->rc_tab.name); - if (ir_dev->driver_name) - ADD_HOTPLUG_VAR("DRV_NAME=%s", ir_dev->driver_name); - - return 0; -} - -/* - * Static device attribute struct with the sysfs attributes for IR's - */ -static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR, - show_protocols, store_protocols); - -static struct attribute *rc_dev_attrs[] = { - &dev_attr_protocols.attr, - NULL, -}; - -static struct attribute_group rc_dev_attr_grp = { - .attrs = rc_dev_attrs, -}; - -static const struct attribute_group *rc_dev_attr_groups[] = { - &rc_dev_attr_grp, - NULL -}; - -static struct device_type rc_dev_type = { - .groups = rc_dev_attr_groups, - .uevent = rc_dev_uevent, -}; - -/** - * ir_register_class() - creates the sysfs for /sys/class/rc/rc? - * @input_dev: the struct input_dev descriptor of the device - * - * This routine is used to register the syfs code for IR class - */ -int ir_register_class(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - int devno = find_first_zero_bit(&ir_core_dev_number, - IRRCV_NUM_DEVICES); - - if (unlikely(devno < 0)) - return devno; - - ir_dev->dev.type = &rc_dev_type; - ir_dev->devno = devno; - - ir_dev->dev.class = &ir_input_class; - ir_dev->dev.parent = input_dev->dev.parent; - input_dev->dev.parent = &ir_dev->dev; - dev_set_name(&ir_dev->dev, "rc%d", devno); - dev_set_drvdata(&ir_dev->dev, ir_dev); - return device_register(&ir_dev->dev); -}; - -/** - * ir_register_input - registers ir input device with input subsystem - * @input_dev: the struct input_dev descriptor of the device - */ - -int ir_register_input(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - int rc; - const char *path; - - - rc = input_register_device(input_dev); - if (rc < 0) { - device_del(&ir_dev->dev); - return rc; - } - - __module_get(THIS_MODULE); - - path = kobject_get_path(&ir_dev->dev.kobj, GFP_KERNEL); - printk(KERN_INFO "%s: %s as %s\n", - dev_name(&ir_dev->dev), - input_dev->name ? input_dev->name : "Unspecified device", - path ? path : "N/A"); - kfree(path); - - set_bit(ir_dev->devno, &ir_core_dev_number); - return 0; -} - -/** - * ir_unregister_class() - removes the sysfs for sysfs for - * /sys/class/rc/rc? - * @input_dev: the struct input_dev descriptor of the device - * - * This routine is used to unregister the syfs code for IR class - */ -void ir_unregister_class(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - - input_set_drvdata(input_dev, NULL); - clear_bit(ir_dev->devno, &ir_core_dev_number); - input_unregister_device(input_dev); - device_del(&ir_dev->dev); - - module_put(THIS_MODULE); -} - -/* - * Init/exit code for the module. Basically, creates/removes /sys/class/rc - */ - -static int __init ir_core_init(void) -{ - int rc = class_register(&ir_input_class); - if (rc) { - printk(KERN_ERR "ir_core: unable to register rc class\n"); - return rc; - } - - /* Initialize/load the decoders/keymap code that will be used */ - ir_raw_init(); - ir_rcmap_init(); - - return 0; -} - -static void __exit ir_core_exit(void) -{ - class_unregister(&ir_input_class); - ir_rcmap_cleanup(); -} - -module_init(ir_core_init); -module_exit(ir_core_exit); diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h new file mode 100644 index 0000000..81c936b --- /dev/null +++ b/drivers/media/rc/rc-core-priv.h @@ -0,0 +1,203 @@ +/* + * Remote Controller core raw events header + * + * Copyright (C) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _IR_RAW_EVENT +#define _IR_RAW_EVENT + +#include +#include +#include + +struct ir_raw_handler { + struct list_head list; + + u64 protocols; /* which are handled by this handler */ + int (*decode)(struct input_dev *input_dev, struct ir_raw_event event); + + /* These two should only be used by the lirc decoder */ + int (*raw_register)(struct input_dev *input_dev); + int (*raw_unregister)(struct input_dev *input_dev); +}; + +struct ir_raw_event_ctrl { + struct list_head list; /* to keep track of raw clients */ + struct task_struct *thread; + spinlock_t lock; + struct kfifo kfifo; /* fifo for the pulse/space durations */ + ktime_t last_event; /* when last event occurred */ + enum raw_event_type last_type; /* last event type */ + struct input_dev *input_dev; /* pointer to the parent input_dev */ + u64 enabled_protocols; /* enabled raw protocol decoders */ + + /* raw decoder state follows */ + struct ir_raw_event prev_ev; + struct ir_raw_event this_ev; + struct nec_dec { + int state; + unsigned count; + u32 bits; + bool is_nec_x; + bool necx_repeat; + } nec; + struct rc5_dec { + int state; + u32 bits; + unsigned count; + unsigned wanted_bits; + } rc5; + struct rc6_dec { + int state; + u8 header; + u32 body; + bool toggle; + unsigned count; + unsigned wanted_bits; + } rc6; + struct sony_dec { + int state; + u32 bits; + unsigned count; + } sony; + struct jvc_dec { + int state; + u16 bits; + u16 old_bits; + unsigned count; + bool first; + bool toggle; + } jvc; + struct rc5_sz_dec { + int state; + u32 bits; + unsigned count; + unsigned wanted_bits; + } rc5_sz; + struct lirc_codec { + struct ir_input_dev *ir_dev; + struct lirc_driver *drv; + int carrier_low; + + ktime_t gap_start; + u64 gap_duration; + bool gap; + bool send_timeout_reports; + + } lirc; +}; + +/* macros for IR decoders */ +static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin) +{ + return d1 > (d2 - margin); +} + +static inline bool eq_margin(unsigned d1, unsigned d2, unsigned margin) +{ + return ((d1 > (d2 - margin)) && (d1 < (d2 + margin))); +} + +static inline bool is_transition(struct ir_raw_event *x, struct ir_raw_event *y) +{ + return x->pulse != y->pulse; +} + +static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration) +{ + if (duration > ev->duration) + ev->duration = 0; + else + ev->duration -= duration; +} + +/* Returns true if event is normal pulse/space event */ +static inline bool is_timing_event(struct ir_raw_event ev) +{ + return !ev.carrier_report && !ev.reset; +} + +#define TO_US(duration) DIV_ROUND_CLOSEST((duration), 1000) +#define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space") +/* + * Routines from ir-sysfs.c - Meant to be called only internally inside + * ir-core + */ +int ir_register_input(struct input_dev *input_dev); + +int ir_register_class(struct input_dev *input_dev); +void ir_unregister_class(struct input_dev *input_dev); + +/* + * Routines from ir-raw-event.c to be used internally and by decoders + */ +u64 ir_raw_get_allowed_protocols(void); +int ir_raw_event_register(struct input_dev *input_dev); +void ir_raw_event_unregister(struct input_dev *input_dev); +int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); +void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); +void ir_raw_init(void); + +int ir_rcmap_init(void); +void ir_rcmap_cleanup(void); +/* + * Decoder initialization code + * + * Those load logic are called during ir-core init, and automatically + * loads the compiled decoders for their usage with IR raw events + */ + +/* from ir-nec-decoder.c */ +#ifdef CONFIG_IR_NEC_DECODER_MODULE +#define load_nec_decode() request_module("ir-nec-decoder") +#else +#define load_nec_decode() 0 +#endif + +/* from ir-rc5-decoder.c */ +#ifdef CONFIG_IR_RC5_DECODER_MODULE +#define load_rc5_decode() request_module("ir-rc5-decoder") +#else +#define load_rc5_decode() 0 +#endif + +/* from ir-rc6-decoder.c */ +#ifdef CONFIG_IR_RC6_DECODER_MODULE +#define load_rc6_decode() request_module("ir-rc6-decoder") +#else +#define load_rc6_decode() 0 +#endif + +/* from ir-jvc-decoder.c */ +#ifdef CONFIG_IR_JVC_DECODER_MODULE +#define load_jvc_decode() request_module("ir-jvc-decoder") +#else +#define load_jvc_decode() 0 +#endif + +/* from ir-sony-decoder.c */ +#ifdef CONFIG_IR_SONY_DECODER_MODULE +#define load_sony_decode() request_module("ir-sony-decoder") +#else +#define load_sony_decode() 0 +#endif + +/* from ir-lirc-codec.c */ +#ifdef CONFIG_IR_LIRC_CODEC_MODULE +#define load_lirc_codec() request_module("ir-lirc-codec") +#else +#define load_lirc_codec() 0 +#endif + + +#endif /* _IR_RAW_EVENT */ diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c new file mode 100644 index 0000000..d6de2e2 --- /dev/null +++ b/drivers/media/rc/rc-main.c @@ -0,0 +1,766 @@ +/* ir-keytable.c - handle IR scancode->keycode tables + * + * Copyright (C) 2009 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#include +#include +#include "rc-core-priv.h" + +/* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */ +#define IR_TAB_MIN_SIZE 256 +#define IR_TAB_MAX_SIZE 8192 + +/* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */ +#define IR_KEYPRESS_TIMEOUT 250 + +/** + * ir_create_table() - initializes a scancode table + * @rc_tab: the ir_scancode_table to initialize + * @name: name to assign to the table + * @ir_type: ir type to assign to the new table + * @size: initial size of the table + * @return: zero on success or a negative error code + * + * This routine will initialize the ir_scancode_table and will allocate + * memory to hold at least the specified number elements. + */ +static int ir_create_table(struct ir_scancode_table *rc_tab, + const char *name, u64 ir_type, size_t size) +{ + rc_tab->name = name; + rc_tab->ir_type = ir_type; + rc_tab->alloc = roundup_pow_of_two(size * sizeof(struct ir_scancode)); + rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode); + rc_tab->scan = kmalloc(rc_tab->alloc, GFP_KERNEL); + if (!rc_tab->scan) + return -ENOMEM; + + IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", + rc_tab->size, rc_tab->alloc); + return 0; +} + +/** + * ir_free_table() - frees memory allocated by a scancode table + * @rc_tab: the table whose mappings need to be freed + * + * This routine will free memory alloctaed for key mappings used by given + * scancode table. + */ +static void ir_free_table(struct ir_scancode_table *rc_tab) +{ + rc_tab->size = 0; + kfree(rc_tab->scan); + rc_tab->scan = NULL; +} + +/** + * ir_resize_table() - resizes a scancode table if necessary + * @rc_tab: the ir_scancode_table to resize + * @gfp_flags: gfp flags to use when allocating memory + * @return: zero on success or a negative error code + * + * This routine will shrink the ir_scancode_table if it has lots of + * unused entries and grow it if it is full. + */ +static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags) +{ + unsigned int oldalloc = rc_tab->alloc; + unsigned int newalloc = oldalloc; + struct ir_scancode *oldscan = rc_tab->scan; + struct ir_scancode *newscan; + + if (rc_tab->size == rc_tab->len) { + /* All entries in use -> grow keytable */ + if (rc_tab->alloc >= IR_TAB_MAX_SIZE) + return -ENOMEM; + + newalloc *= 2; + IR_dprintk(1, "Growing table to %u bytes\n", newalloc); + } + + if ((rc_tab->len * 3 < rc_tab->size) && (oldalloc > IR_TAB_MIN_SIZE)) { + /* Less than 1/3 of entries in use -> shrink keytable */ + newalloc /= 2; + IR_dprintk(1, "Shrinking table to %u bytes\n", newalloc); + } + + if (newalloc == oldalloc) + return 0; + + newscan = kmalloc(newalloc, gfp_flags); + if (!newscan) { + IR_dprintk(1, "Failed to kmalloc %u bytes\n", newalloc); + return -ENOMEM; + } + + memcpy(newscan, rc_tab->scan, rc_tab->len * sizeof(struct ir_scancode)); + rc_tab->scan = newscan; + rc_tab->alloc = newalloc; + rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode); + kfree(oldscan); + return 0; +} + +/** + * ir_update_mapping() - set a keycode in the scancode->keycode table + * @dev: the struct input_dev device descriptor + * @rc_tab: scancode table to be adjusted + * @index: index of the mapping that needs to be updated + * @keycode: the desired keycode + * @return: previous keycode assigned to the mapping + * + * This routine is used to update scancode->keycopde mapping at given + * position. + */ +static unsigned int ir_update_mapping(struct input_dev *dev, + struct ir_scancode_table *rc_tab, + unsigned int index, + unsigned int new_keycode) +{ + int old_keycode = rc_tab->scan[index].keycode; + int i; + + /* Did the user wish to remove the mapping? */ + if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) { + IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", + index, rc_tab->scan[index].scancode); + rc_tab->len--; + memmove(&rc_tab->scan[index], &rc_tab->scan[index+ 1], + (rc_tab->len - index) * sizeof(struct ir_scancode)); + } else { + IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n", + index, + old_keycode == KEY_RESERVED ? "New" : "Replacing", + rc_tab->scan[index].scancode, new_keycode); + rc_tab->scan[index].keycode = new_keycode; + __set_bit(new_keycode, dev->keybit); + } + + if (old_keycode != KEY_RESERVED) { + /* A previous mapping was updated... */ + __clear_bit(old_keycode, dev->keybit); + /* ... but another scancode might use the same keycode */ + for (i = 0; i < rc_tab->len; i++) { + if (rc_tab->scan[i].keycode == old_keycode) { + __set_bit(old_keycode, dev->keybit); + break; + } + } + + /* Possibly shrink the keytable, failure is not a problem */ + ir_resize_table(rc_tab, GFP_ATOMIC); + } + + return old_keycode; +} + +/** + * ir_locate_scancode() - set a keycode in the scancode->keycode table + * @ir_dev: the struct ir_input_dev device descriptor + * @rc_tab: scancode table to be searched + * @scancode: the desired scancode + * @resize: controls whether we allowed to resize the table to + * accomodate not yet present scancodes + * @return: index of the mapping containing scancode in question + * or -1U in case of failure. + * + * This routine is used to locate given scancode in ir_scancode_table. + * If scancode is not yet present the routine will allocate a new slot + * for it. + */ +static unsigned int ir_establish_scancode(struct ir_input_dev *ir_dev, + struct ir_scancode_table *rc_tab, + unsigned int scancode, + bool resize) +{ + unsigned int i; + + /* + * Unfortunately, some hardware-based IR decoders don't provide + * all bits for the complete IR code. In general, they provide only + * the command part of the IR code. Yet, as it is possible to replace + * the provided IR with another one, it is needed to allow loading + * IR tables from other remotes. So, + */ + if (ir_dev->props && ir_dev->props->scanmask) + scancode &= ir_dev->props->scanmask; + + /* First check if we already have a mapping for this ir command */ + for (i = 0; i < rc_tab->len; i++) { + if (rc_tab->scan[i].scancode == scancode) + return i; + + /* Keytable is sorted from lowest to highest scancode */ + if (rc_tab->scan[i].scancode >= scancode) + break; + } + + /* No previous mapping found, we might need to grow the table */ + if (rc_tab->size == rc_tab->len) { + if (!resize || ir_resize_table(rc_tab, GFP_ATOMIC)) + return -1U; + } + + /* i is the proper index to insert our new keycode */ + if (i < rc_tab->len) + memmove(&rc_tab->scan[i + 1], &rc_tab->scan[i], + (rc_tab->len - i) * sizeof(struct ir_scancode)); + rc_tab->scan[i].scancode = scancode; + rc_tab->scan[i].keycode = KEY_RESERVED; + rc_tab->len++; + + return i; +} + +/** + * ir_setkeycode() - set a keycode in the scancode->keycode table + * @dev: the struct input_dev device descriptor + * @scancode: the desired scancode + * @keycode: result + * @return: -EINVAL if the keycode could not be inserted, otherwise zero. + * + * This routine is used to handle evdev EVIOCSKEY ioctl. + */ +static int ir_setkeycode(struct input_dev *dev, + const struct input_keymap_entry *ke, + unsigned int *old_keycode) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(dev); + struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; + unsigned int index; + unsigned int scancode; + int retval; + unsigned long flags; + + spin_lock_irqsave(&rc_tab->lock, flags); + + if (ke->flags & INPUT_KEYMAP_BY_INDEX) { + index = ke->index; + if (index >= rc_tab->len) { + retval = -EINVAL; + goto out; + } + } else { + retval = input_scancode_to_scalar(ke, &scancode); + if (retval) + goto out; + + index = ir_establish_scancode(ir_dev, rc_tab, scancode, true); + if (index >= rc_tab->len) { + retval = -ENOMEM; + goto out; + } + } + + *old_keycode = ir_update_mapping(dev, rc_tab, index, ke->keycode); + +out: + spin_unlock_irqrestore(&rc_tab->lock, flags); + return retval; +} + +/** + * ir_setkeytable() - sets several entries in the scancode->keycode table + * @dev: the struct input_dev device descriptor + * @to: the struct ir_scancode_table to copy entries to + * @from: the struct ir_scancode_table to copy entries from + * @return: -ENOMEM if all keycodes could not be inserted, otherwise zero. + * + * This routine is used to handle table initialization. + */ +static int ir_setkeytable(struct ir_input_dev *ir_dev, + const struct ir_scancode_table *from) +{ + struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; + unsigned int i, index; + int rc; + + rc = ir_create_table(&ir_dev->rc_tab, + from->name, from->ir_type, from->size); + if (rc) + return rc; + + IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", + rc_tab->size, rc_tab->alloc); + + for (i = 0; i < from->size; i++) { + index = ir_establish_scancode(ir_dev, rc_tab, + from->scan[i].scancode, false); + if (index >= rc_tab->len) { + rc = -ENOMEM; + break; + } + + ir_update_mapping(ir_dev->input_dev, rc_tab, index, + from->scan[i].keycode); + } + + if (rc) + ir_free_table(rc_tab); + + return rc; +} + +/** + * ir_lookup_by_scancode() - locate mapping by scancode + * @rc_tab: the &struct ir_scancode_table to search + * @scancode: scancode to look for in the table + * @return: index in the table, -1U if not found + * + * This routine performs binary search in RC keykeymap table for + * given scancode. + */ +static unsigned int ir_lookup_by_scancode(const struct ir_scancode_table *rc_tab, + unsigned int scancode) +{ + int start = 0; + int end = rc_tab->len - 1; + int mid; + + while (start <= end) { + mid = (start + end) / 2; + if (rc_tab->scan[mid].scancode < scancode) + start = mid + 1; + else if (rc_tab->scan[mid].scancode > scancode) + end = mid - 1; + else + return mid; + } + + return -1U; +} + +/** + * ir_getkeycode() - get a keycode from the scancode->keycode table + * @dev: the struct input_dev device descriptor + * @scancode: the desired scancode + * @keycode: used to return the keycode, if found, or KEY_RESERVED + * @return: always returns zero. + * + * This routine is used to handle evdev EVIOCGKEY ioctl. + */ +static int ir_getkeycode(struct input_dev *dev, + struct input_keymap_entry *ke) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(dev); + struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; + struct ir_scancode *entry; + unsigned long flags; + unsigned int index; + unsigned int scancode; + int retval; + + spin_lock_irqsave(&rc_tab->lock, flags); + + if (ke->flags & INPUT_KEYMAP_BY_INDEX) { + index = ke->index; + } else { + retval = input_scancode_to_scalar(ke, &scancode); + if (retval) + goto out; + + index = ir_lookup_by_scancode(rc_tab, scancode); + } + + if (index >= rc_tab->len) { + if (!(ke->flags & INPUT_KEYMAP_BY_INDEX)) + IR_dprintk(1, "unknown key for scancode 0x%04x\n", + scancode); + retval = -EINVAL; + goto out; + } + + entry = &rc_tab->scan[index]; + + ke->index = index; + ke->keycode = entry->keycode; + ke->len = sizeof(entry->scancode); + memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode)); + + retval = 0; + +out: + spin_unlock_irqrestore(&rc_tab->lock, flags); + return retval; +} + +/** + * ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode + * @input_dev: the struct input_dev descriptor of the device + * @scancode: the scancode that we're seeking + * + * This routine is used by the input routines when a key is pressed at the + * IR. The scancode is received and needs to be converted into a keycode. + * If the key is not found, it returns KEY_RESERVED. Otherwise, returns the + * corresponding keycode from the table. + */ +u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(dev); + struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; + unsigned int keycode; + unsigned int index; + unsigned long flags; + + spin_lock_irqsave(&rc_tab->lock, flags); + + index = ir_lookup_by_scancode(rc_tab, scancode); + keycode = index < rc_tab->len ? + rc_tab->scan[index].keycode : KEY_RESERVED; + + spin_unlock_irqrestore(&rc_tab->lock, flags); + + if (keycode != KEY_RESERVED) + IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", + dev->name, scancode, keycode); + + return keycode; +} +EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); + +/** + * ir_do_keyup() - internal function to signal the release of a keypress + * @ir: the struct ir_input_dev descriptor of the device + * + * This function is used internally to release a keypress, it must be + * called with keylock held. + */ +static void ir_do_keyup(struct ir_input_dev *ir) +{ + if (!ir->keypressed) + return; + + IR_dprintk(1, "keyup key 0x%04x\n", ir->last_keycode); + input_report_key(ir->input_dev, ir->last_keycode, 0); + input_sync(ir->input_dev); + ir->keypressed = false; +} + +/** + * ir_keyup() - generates input event to signal the release of a keypress + * @dev: the struct input_dev descriptor of the device + * + * This routine is used to signal that a key has been released on the + * remote control. + */ +void ir_keyup(struct input_dev *dev) +{ + unsigned long flags; + struct ir_input_dev *ir = input_get_drvdata(dev); + + spin_lock_irqsave(&ir->keylock, flags); + ir_do_keyup(ir); + spin_unlock_irqrestore(&ir->keylock, flags); +} +EXPORT_SYMBOL_GPL(ir_keyup); + +/** + * ir_timer_keyup() - generates a keyup event after a timeout + * @cookie: a pointer to struct ir_input_dev passed to setup_timer() + * + * This routine will generate a keyup event some time after a keydown event + * is generated when no further activity has been detected. + */ +static void ir_timer_keyup(unsigned long cookie) +{ + struct ir_input_dev *ir = (struct ir_input_dev *)cookie; + unsigned long flags; + + /* + * ir->keyup_jiffies is used to prevent a race condition if a + * hardware interrupt occurs at this point and the keyup timer + * event is moved further into the future as a result. + * + * The timer will then be reactivated and this function called + * again in the future. We need to exit gracefully in that case + * to allow the input subsystem to do its auto-repeat magic or + * a keyup event might follow immediately after the keydown. + */ + spin_lock_irqsave(&ir->keylock, flags); + if (time_is_before_eq_jiffies(ir->keyup_jiffies)) + ir_do_keyup(ir); + spin_unlock_irqrestore(&ir->keylock, flags); +} + +/** + * ir_repeat() - notifies the IR core that a key is still pressed + * @dev: the struct input_dev descriptor of the device + * + * This routine is used by IR decoders when a repeat message which does + * not include the necessary bits to reproduce the scancode has been + * received. + */ +void ir_repeat(struct input_dev *dev) +{ + unsigned long flags; + struct ir_input_dev *ir = input_get_drvdata(dev); + + spin_lock_irqsave(&ir->keylock, flags); + + input_event(dev, EV_MSC, MSC_SCAN, ir->last_scancode); + + if (!ir->keypressed) + goto out; + + ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); + mod_timer(&ir->timer_keyup, ir->keyup_jiffies); + +out: + spin_unlock_irqrestore(&ir->keylock, flags); +} +EXPORT_SYMBOL_GPL(ir_repeat); + +/** + * ir_do_keydown() - internal function to process a keypress + * @dev: the struct input_dev descriptor of the device + * @scancode: the scancode of the keypress + * @keycode: the keycode of the keypress + * @toggle: the toggle value of the keypress + * + * This function is used internally to register a keypress, it must be + * called with keylock held. + */ +static void ir_do_keydown(struct input_dev *dev, int scancode, + u32 keycode, u8 toggle) +{ + struct ir_input_dev *ir = input_get_drvdata(dev); + + input_event(dev, EV_MSC, MSC_SCAN, scancode); + + /* Repeat event? */ + if (ir->keypressed && + ir->last_scancode == scancode && + ir->last_toggle == toggle) + return; + + /* Release old keypress */ + ir_do_keyup(ir); + + ir->last_scancode = scancode; + ir->last_toggle = toggle; + ir->last_keycode = keycode; + + if (keycode == KEY_RESERVED) + return; + + /* Register a keypress */ + ir->keypressed = true; + IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", + dev->name, keycode, scancode); + input_report_key(dev, ir->last_keycode, 1); + input_sync(dev); +} + +/** + * ir_keydown() - generates input event for a key press + * @dev: the struct input_dev descriptor of the device + * @scancode: the scancode that we're seeking + * @toggle: the toggle value (protocol dependent, if the protocol doesn't + * support toggle values, this should be set to zero) + * + * This routine is used by the input routines when a key is pressed at the + * IR. It gets the keycode for a scancode and reports an input event via + * input_report_key(). + */ +void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) +{ + unsigned long flags; + struct ir_input_dev *ir = input_get_drvdata(dev); + u32 keycode = ir_g_keycode_from_table(dev, scancode); + + spin_lock_irqsave(&ir->keylock, flags); + ir_do_keydown(dev, scancode, keycode, toggle); + + if (ir->keypressed) { + ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); + mod_timer(&ir->timer_keyup, ir->keyup_jiffies); + } + spin_unlock_irqrestore(&ir->keylock, flags); +} +EXPORT_SYMBOL_GPL(ir_keydown); + +/** + * ir_keydown_notimeout() - generates input event for a key press without + * an automatic keyup event at a later time + * @dev: the struct input_dev descriptor of the device + * @scancode: the scancode that we're seeking + * @toggle: the toggle value (protocol dependent, if the protocol doesn't + * support toggle values, this should be set to zero) + * + * This routine is used by the input routines when a key is pressed at the + * IR. It gets the keycode for a scancode and reports an input event via + * input_report_key(). The driver must manually call ir_keyup() at a later + * stage. + */ +void ir_keydown_notimeout(struct input_dev *dev, int scancode, u8 toggle) +{ + unsigned long flags; + struct ir_input_dev *ir = input_get_drvdata(dev); + u32 keycode = ir_g_keycode_from_table(dev, scancode); + + spin_lock_irqsave(&ir->keylock, flags); + ir_do_keydown(dev, scancode, keycode, toggle); + spin_unlock_irqrestore(&ir->keylock, flags); +} +EXPORT_SYMBOL_GPL(ir_keydown_notimeout); + +static int ir_open(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + + return ir_dev->props->open(ir_dev->props->priv); +} + +static void ir_close(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + + ir_dev->props->close(ir_dev->props->priv); +} + +/** + * __ir_input_register() - sets the IR keycode table and add the handlers + * for keymap table get/set + * @input_dev: the struct input_dev descriptor of the device + * @rc_tab: the struct ir_scancode_table table of scancode/keymap + * + * This routine is used to initialize the input infrastructure + * to work with an IR. + * It will register the input/evdev interface for the device and + * register the syfs code for IR class + */ +int __ir_input_register(struct input_dev *input_dev, + const struct ir_scancode_table *rc_tab, + struct ir_dev_props *props, + const char *driver_name) +{ + struct ir_input_dev *ir_dev; + int rc; + + if (rc_tab->scan == NULL || !rc_tab->size) + return -EINVAL; + + ir_dev = kzalloc(sizeof(*ir_dev), GFP_KERNEL); + if (!ir_dev) + return -ENOMEM; + + ir_dev->driver_name = kasprintf(GFP_KERNEL, "%s", driver_name); + if (!ir_dev->driver_name) { + rc = -ENOMEM; + goto out_dev; + } + + input_dev->getkeycode_new = ir_getkeycode; + input_dev->setkeycode_new = ir_setkeycode; + input_set_drvdata(input_dev, ir_dev); + ir_dev->input_dev = input_dev; + + spin_lock_init(&ir_dev->rc_tab.lock); + spin_lock_init(&ir_dev->keylock); + setup_timer(&ir_dev->timer_keyup, ir_timer_keyup, (unsigned long)ir_dev); + + if (props) { + ir_dev->props = props; + if (props->open) + input_dev->open = ir_open; + if (props->close) + input_dev->close = ir_close; + } + + set_bit(EV_KEY, input_dev->evbit); + set_bit(EV_REP, input_dev->evbit); + set_bit(EV_MSC, input_dev->evbit); + set_bit(MSC_SCAN, input_dev->mscbit); + + rc = ir_setkeytable(ir_dev, rc_tab); + if (rc) + goto out_name; + + rc = ir_register_class(input_dev); + if (rc < 0) + goto out_table; + + if (ir_dev->props) + if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) { + rc = ir_raw_event_register(input_dev); + if (rc < 0) + goto out_event; + } + + rc = ir_register_input(input_dev); + if (rc < 0) + goto out_event; + + IR_dprintk(1, "Registered input device on %s for %s remote%s.\n", + driver_name, rc_tab->name, + (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ? + " in raw mode" : ""); + + /* + * Default delay of 250ms is too short for some protocols, expecially + * since the timeout is currently set to 250ms. Increase it to 500ms, + * to avoid wrong repetition of the keycodes. + */ + input_dev->rep[REP_DELAY] = 500; + + return 0; + +out_event: + ir_unregister_class(input_dev); +out_table: + ir_free_table(&ir_dev->rc_tab); +out_name: + kfree(ir_dev->driver_name); +out_dev: + kfree(ir_dev); + return rc; +} +EXPORT_SYMBOL_GPL(__ir_input_register); + +/** + * ir_input_unregister() - unregisters IR and frees resources + * @input_dev: the struct input_dev descriptor of the device + + * This routine is used to free memory and de-register interfaces. + */ +void ir_input_unregister(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + + if (!ir_dev) + return; + + IR_dprintk(1, "Freed keycode table\n"); + + del_timer_sync(&ir_dev->timer_keyup); + if (ir_dev->props) + if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) + ir_raw_event_unregister(input_dev); + + ir_free_table(&ir_dev->rc_tab); + + ir_unregister_class(input_dev); + + kfree(ir_dev->driver_name); + kfree(ir_dev); +} +EXPORT_SYMBOL_GPL(ir_input_unregister); + +int ir_core_debug; /* ir_debug level (0,1,2) */ +EXPORT_SYMBOL_GPL(ir_core_debug); +module_param_named(debug, ir_core_debug, int, 0644); + +MODULE_AUTHOR("Mauro Carvalho Chehab "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/rc/rc-raw.c b/drivers/media/rc/rc-raw.c new file mode 100644 index 0000000..d6c556e --- /dev/null +++ b/drivers/media/rc/rc-raw.c @@ -0,0 +1,382 @@ +/* ir-raw-event.c - handle IR Pulse/Space event + * + * Copyright (C) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include "rc-core-priv.h" + +/* Define the max number of pulse/space transitions to buffer */ +#define MAX_IR_EVENT_SIZE 512 + +/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */ +static LIST_HEAD(ir_raw_client_list); + +/* Used to handle IR raw handler extensions */ +static DEFINE_MUTEX(ir_raw_handler_lock); +static LIST_HEAD(ir_raw_handler_list); +static u64 available_protocols; + +#ifdef MODULE +/* Used to load the decoders */ +static struct work_struct wq_load; +#endif + +static int ir_raw_event_thread(void *data) +{ + struct ir_raw_event ev; + struct ir_raw_handler *handler; + struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data; + int retval; + + while (!kthread_should_stop()) { + + spin_lock_irq(&raw->lock); + retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev)); + + if (!retval) { + set_current_state(TASK_INTERRUPTIBLE); + + if (kthread_should_stop()) + set_current_state(TASK_RUNNING); + + spin_unlock_irq(&raw->lock); + schedule(); + continue; + } + + spin_unlock_irq(&raw->lock); + + + BUG_ON(retval != sizeof(ev)); + + mutex_lock(&ir_raw_handler_lock); + list_for_each_entry(handler, &ir_raw_handler_list, list) + handler->decode(raw->input_dev, ev); + raw->prev_ev = ev; + mutex_unlock(&ir_raw_handler_lock); + } + + return 0; +} + +/** + * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders + * @input_dev: the struct input_dev device descriptor + * @ev: the struct ir_raw_event descriptor of the pulse/space + * + * This routine (which may be called from an interrupt context) stores a + * pulse/space duration for the raw ir decoding state machines. Pulses are + * signalled as positive values and spaces as negative values. A zero value + * will reset the decoding state machines. + */ +int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + + if (!ir->raw) + return -EINVAL; + + IR_dprintk(2, "sample: (%05dus %s)\n", + TO_US(ev->duration), TO_STR(ev->pulse)); + + if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) + return -ENOMEM; + + return 0; +} +EXPORT_SYMBOL_GPL(ir_raw_event_store); + +/** + * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space + * @input_dev: the struct input_dev device descriptor + * @type: the type of the event that has occurred + * + * This routine (which may be called from an interrupt context) is used to + * store the beginning of an ir pulse or space (or the start/end of ir + * reception) for the raw ir decoding state machines. This is used by + * hardware which does not provide durations directly but only interrupts + * (or similar events) on state change. + */ +int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + ktime_t now; + s64 delta; /* ns */ + struct ir_raw_event ev; + int rc = 0; + + if (!ir->raw) + return -EINVAL; + + now = ktime_get(); + delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event)); + + /* Check for a long duration since last event or if we're + * being called for the first time, note that delta can't + * possibly be negative. + */ + ev.duration = 0; + if (delta > IR_MAX_DURATION || !ir->raw->last_type) + type |= IR_START_EVENT; + else + ev.duration = delta; + + if (type & IR_START_EVENT) + ir_raw_event_reset(input_dev); + else if (ir->raw->last_type & IR_SPACE) { + ev.pulse = false; + rc = ir_raw_event_store(input_dev, &ev); + } else if (ir->raw->last_type & IR_PULSE) { + ev.pulse = true; + rc = ir_raw_event_store(input_dev, &ev); + } else + return 0; + + ir->raw->last_event = now; + ir->raw->last_type = type; + return rc; +} +EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); + +/** + * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing + * @input_dev: the struct input_dev device descriptor + * @type: the type of the event that has occurred + * + * This routine (which may be called from an interrupt context) works + * in similiar manner to ir_raw_event_store_edge. + * This routine is intended for devices with limited internal buffer + * It automerges samples of same type, and handles timeouts + */ +int ir_raw_event_store_with_filter(struct input_dev *input_dev, + struct ir_raw_event *ev) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + struct ir_raw_event_ctrl *raw = ir->raw; + + if (!raw || !ir->props) + return -EINVAL; + + /* Ignore spaces in idle mode */ + if (ir->idle && !ev->pulse) + return 0; + else if (ir->idle) + ir_raw_event_set_idle(input_dev, false); + + if (!raw->this_ev.duration) { + raw->this_ev = *ev; + } else if (ev->pulse == raw->this_ev.pulse) { + raw->this_ev.duration += ev->duration; + } else { + ir_raw_event_store(input_dev, &raw->this_ev); + raw->this_ev = *ev; + } + + /* Enter idle mode if nessesary */ + if (!ev->pulse && ir->props->timeout && + raw->this_ev.duration >= ir->props->timeout) { + ir_raw_event_set_idle(input_dev, true); + } + return 0; +} +EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter); + +/** + * ir_raw_event_set_idle() - hint the ir core if device is receiving + * IR data or not + * @input_dev: the struct input_dev device descriptor + * @idle: the hint value + */ +void ir_raw_event_set_idle(struct input_dev *input_dev, bool idle) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + struct ir_raw_event_ctrl *raw = ir->raw; + + if (!ir->props || !ir->raw) + return; + + IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave"); + + if (idle) { + raw->this_ev.timeout = true; + ir_raw_event_store(input_dev, &raw->this_ev); + init_ir_raw_event(&raw->this_ev); + } + + if (ir->props->s_idle) + ir->props->s_idle(ir->props->priv, idle); + ir->idle = idle; +} +EXPORT_SYMBOL_GPL(ir_raw_event_set_idle); + +/** + * ir_raw_event_handle() - schedules the decoding of stored ir data + * @input_dev: the struct input_dev device descriptor + * + * This routine will signal the workqueue to start decoding stored ir data. + */ +void ir_raw_event_handle(struct input_dev *input_dev) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + unsigned long flags; + + if (!ir->raw) + return; + + spin_lock_irqsave(&ir->raw->lock, flags); + wake_up_process(ir->raw->thread); + spin_unlock_irqrestore(&ir->raw->lock, flags); +} +EXPORT_SYMBOL_GPL(ir_raw_event_handle); + +/* used internally by the sysfs interface */ +u64 +ir_raw_get_allowed_protocols() +{ + u64 protocols; + mutex_lock(&ir_raw_handler_lock); + protocols = available_protocols; + mutex_unlock(&ir_raw_handler_lock); + return protocols; +} + +/* + * Used to (un)register raw event clients + */ +int ir_raw_event_register(struct input_dev *input_dev) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + int rc; + struct ir_raw_handler *handler; + + ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); + if (!ir->raw) + return -ENOMEM; + + ir->raw->input_dev = input_dev; + + ir->raw->enabled_protocols = ~0; + rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, + GFP_KERNEL); + if (rc < 0) { + kfree(ir->raw); + ir->raw = NULL; + return rc; + } + + spin_lock_init(&ir->raw->lock); + ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw, + "rc%u", (unsigned int)ir->devno); + + if (IS_ERR(ir->raw->thread)) { + int ret = PTR_ERR(ir->raw->thread); + + kfree(ir->raw); + ir->raw = NULL; + return ret; + } + + mutex_lock(&ir_raw_handler_lock); + list_add_tail(&ir->raw->list, &ir_raw_client_list); + list_for_each_entry(handler, &ir_raw_handler_list, list) + if (handler->raw_register) + handler->raw_register(ir->raw->input_dev); + mutex_unlock(&ir_raw_handler_lock); + + return 0; +} + +void ir_raw_event_unregister(struct input_dev *input_dev) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + struct ir_raw_handler *handler; + + if (!ir->raw) + return; + + kthread_stop(ir->raw->thread); + + mutex_lock(&ir_raw_handler_lock); + list_del(&ir->raw->list); + list_for_each_entry(handler, &ir_raw_handler_list, list) + if (handler->raw_unregister) + handler->raw_unregister(ir->raw->input_dev); + mutex_unlock(&ir_raw_handler_lock); + + kfifo_free(&ir->raw->kfifo); + kfree(ir->raw); + ir->raw = NULL; +} + +/* + * Extension interface - used to register the IR decoders + */ + +int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) +{ + struct ir_raw_event_ctrl *raw; + + mutex_lock(&ir_raw_handler_lock); + list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); + if (ir_raw_handler->raw_register) + list_for_each_entry(raw, &ir_raw_client_list, list) + ir_raw_handler->raw_register(raw->input_dev); + available_protocols |= ir_raw_handler->protocols; + mutex_unlock(&ir_raw_handler_lock); + + return 0; +} +EXPORT_SYMBOL(ir_raw_handler_register); + +void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) +{ + struct ir_raw_event_ctrl *raw; + + mutex_lock(&ir_raw_handler_lock); + list_del(&ir_raw_handler->list); + if (ir_raw_handler->raw_unregister) + list_for_each_entry(raw, &ir_raw_client_list, list) + ir_raw_handler->raw_unregister(raw->input_dev); + available_protocols &= ~ir_raw_handler->protocols; + mutex_unlock(&ir_raw_handler_lock); +} +EXPORT_SYMBOL(ir_raw_handler_unregister); + +#ifdef MODULE +static void init_decoders(struct work_struct *work) +{ + /* Load the decoder modules */ + + load_nec_decode(); + load_rc5_decode(); + load_rc6_decode(); + load_jvc_decode(); + load_sony_decode(); + load_lirc_codec(); + + /* If needed, we may later add some init code. In this case, + it is needed to change the CONFIG_MODULE test at ir-core.h + */ +} +#endif + +void ir_raw_init(void) +{ +#ifdef MODULE + INIT_WORK(&wq_load, init_decoders); + schedule_work(&wq_load); +#endif +} diff --git a/drivers/media/rc/rc-sysfs.c b/drivers/media/rc/rc-sysfs.c new file mode 100644 index 0000000..a5f81d1 --- /dev/null +++ b/drivers/media/rc/rc-sysfs.c @@ -0,0 +1,362 @@ +/* ir-sysfs.c - sysfs interface for RC devices (/sys/class/rc) + * + * Copyright (C) 2009-2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include "rc-core-priv.h" + +#define IRRCV_NUM_DEVICES 256 + +/* bit array to represent IR sysfs device number */ +static unsigned long ir_core_dev_number; + +/* class for /sys/class/rc */ +static char *ir_devnode(struct device *dev, mode_t *mode) +{ + return kasprintf(GFP_KERNEL, "rc/%s", dev_name(dev)); +} + +static struct class ir_input_class = { + .name = "rc", + .devnode = ir_devnode, +}; + +static struct { + u64 type; + char *name; +} proto_names[] = { + { IR_TYPE_UNKNOWN, "unknown" }, + { IR_TYPE_RC5, "rc-5" }, + { IR_TYPE_NEC, "nec" }, + { IR_TYPE_RC6, "rc-6" }, + { IR_TYPE_JVC, "jvc" }, + { IR_TYPE_SONY, "sony" }, + { IR_TYPE_RC5_SZ, "rc-5-sz" }, + { IR_TYPE_LIRC, "lirc" }, +}; + +#define PROTO_NONE "none" + +/** + * show_protocols() - shows the current IR protocol(s) + * @d: the device descriptor + * @mattr: the device attribute struct (unused) + * @buf: a pointer to the output buffer + * + * This routine is a callback routine for input read the IR protocol type(s). + * it is trigged by reading /sys/class/rc/rc?/protocols. + * It returns the protocol names of supported protocols. + * Enabled protocols are printed in brackets. + */ +static ssize_t show_protocols(struct device *d, + struct device_attribute *mattr, char *buf) +{ + struct ir_input_dev *ir_dev = dev_get_drvdata(d); + u64 allowed, enabled; + char *tmp = buf; + int i; + + /* Device is being removed */ + if (!ir_dev) + return -EINVAL; + + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { + enabled = ir_dev->rc_tab.ir_type; + allowed = ir_dev->props->allowed_protos; + } else if (ir_dev->raw) { + enabled = ir_dev->raw->enabled_protocols; + allowed = ir_raw_get_allowed_protocols(); + } else + return sprintf(tmp, "[builtin]\n"); + + IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", + (long long)allowed, + (long long)enabled); + + for (i = 0; i < ARRAY_SIZE(proto_names); i++) { + if (allowed & enabled & proto_names[i].type) + tmp += sprintf(tmp, "[%s] ", proto_names[i].name); + else if (allowed & proto_names[i].type) + tmp += sprintf(tmp, "%s ", proto_names[i].name); + } + + if (tmp != buf) + tmp--; + *tmp = '\n'; + return tmp + 1 - buf; +} + +/** + * store_protocols() - changes the current IR protocol(s) + * @d: the device descriptor + * @mattr: the device attribute struct (unused) + * @buf: a pointer to the input buffer + * @len: length of the input buffer + * + * This routine is a callback routine for changing the IR protocol type. + * It is trigged by writing to /sys/class/rc/rc?/protocols. + * Writing "+proto" will add a protocol to the list of enabled protocols. + * Writing "-proto" will remove a protocol from the list of enabled protocols. + * Writing "proto" will enable only "proto". + * Writing "none" will disable all protocols. + * Returns -EINVAL if an invalid protocol combination or unknown protocol name + * is used, otherwise @len. + */ +static ssize_t store_protocols(struct device *d, + struct device_attribute *mattr, + const char *data, + size_t len) +{ + struct ir_input_dev *ir_dev = dev_get_drvdata(d); + bool enable, disable; + const char *tmp; + u64 type; + u64 mask; + int rc, i, count = 0; + unsigned long flags; + + /* Device is being removed */ + if (!ir_dev) + return -EINVAL; + + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) + type = ir_dev->rc_tab.ir_type; + else if (ir_dev->raw) + type = ir_dev->raw->enabled_protocols; + else { + IR_dprintk(1, "Protocol switching not supported\n"); + return -EINVAL; + } + + while ((tmp = strsep((char **) &data, " \n")) != NULL) { + if (!*tmp) + break; + + if (*tmp == '+') { + enable = true; + disable = false; + tmp++; + } else if (*tmp == '-') { + enable = false; + disable = true; + tmp++; + } else { + enable = false; + disable = false; + } + + if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) { + tmp += sizeof(PROTO_NONE); + mask = 0; + count++; + } else { + for (i = 0; i < ARRAY_SIZE(proto_names); i++) { + if (!strncasecmp(tmp, proto_names[i].name, strlen(proto_names[i].name))) { + tmp += strlen(proto_names[i].name); + mask = proto_names[i].type; + break; + } + } + if (i == ARRAY_SIZE(proto_names)) { + IR_dprintk(1, "Unknown protocol: '%s'\n", tmp); + return -EINVAL; + } + count++; + } + + if (enable) + type |= mask; + else if (disable) + type &= ~mask; + else + type = mask; + } + + if (!count) { + IR_dprintk(1, "Protocol not specified\n"); + return -EINVAL; + } + + if (ir_dev->props && ir_dev->props->change_protocol) { + rc = ir_dev->props->change_protocol(ir_dev->props->priv, + type); + if (rc < 0) { + IR_dprintk(1, "Error setting protocols to 0x%llx\n", + (long long)type); + return -EINVAL; + } + } + + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { + spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); + ir_dev->rc_tab.ir_type = type; + spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); + } else { + ir_dev->raw->enabled_protocols = type; + } + + IR_dprintk(1, "Current protocol(s): 0x%llx\n", + (long long)type); + + return len; +} + +#define ADD_HOTPLUG_VAR(fmt, val...) \ + do { \ + int err = add_uevent_var(env, fmt, val); \ + if (err) \ + return err; \ + } while (0) + +static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) +{ + struct ir_input_dev *ir_dev = dev_get_drvdata(device); + + if (ir_dev->rc_tab.name) + ADD_HOTPLUG_VAR("NAME=%s", ir_dev->rc_tab.name); + if (ir_dev->driver_name) + ADD_HOTPLUG_VAR("DRV_NAME=%s", ir_dev->driver_name); + + return 0; +} + +/* + * Static device attribute struct with the sysfs attributes for IR's + */ +static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR, + show_protocols, store_protocols); + +static struct attribute *rc_dev_attrs[] = { + &dev_attr_protocols.attr, + NULL, +}; + +static struct attribute_group rc_dev_attr_grp = { + .attrs = rc_dev_attrs, +}; + +static const struct attribute_group *rc_dev_attr_groups[] = { + &rc_dev_attr_grp, + NULL +}; + +static struct device_type rc_dev_type = { + .groups = rc_dev_attr_groups, + .uevent = rc_dev_uevent, +}; + +/** + * ir_register_class() - creates the sysfs for /sys/class/rc/rc? + * @input_dev: the struct input_dev descriptor of the device + * + * This routine is used to register the syfs code for IR class + */ +int ir_register_class(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + int devno = find_first_zero_bit(&ir_core_dev_number, + IRRCV_NUM_DEVICES); + + if (unlikely(devno < 0)) + return devno; + + ir_dev->dev.type = &rc_dev_type; + ir_dev->devno = devno; + + ir_dev->dev.class = &ir_input_class; + ir_dev->dev.parent = input_dev->dev.parent; + input_dev->dev.parent = &ir_dev->dev; + dev_set_name(&ir_dev->dev, "rc%d", devno); + dev_set_drvdata(&ir_dev->dev, ir_dev); + return device_register(&ir_dev->dev); +}; + +/** + * ir_register_input - registers ir input device with input subsystem + * @input_dev: the struct input_dev descriptor of the device + */ + +int ir_register_input(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + int rc; + const char *path; + + + rc = input_register_device(input_dev); + if (rc < 0) { + device_del(&ir_dev->dev); + return rc; + } + + __module_get(THIS_MODULE); + + path = kobject_get_path(&ir_dev->dev.kobj, GFP_KERNEL); + printk(KERN_INFO "%s: %s as %s\n", + dev_name(&ir_dev->dev), + input_dev->name ? input_dev->name : "Unspecified device", + path ? path : "N/A"); + kfree(path); + + set_bit(ir_dev->devno, &ir_core_dev_number); + return 0; +} + +/** + * ir_unregister_class() - removes the sysfs for sysfs for + * /sys/class/rc/rc? + * @input_dev: the struct input_dev descriptor of the device + * + * This routine is used to unregister the syfs code for IR class + */ +void ir_unregister_class(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + + input_set_drvdata(input_dev, NULL); + clear_bit(ir_dev->devno, &ir_core_dev_number); + input_unregister_device(input_dev); + device_del(&ir_dev->dev); + + module_put(THIS_MODULE); +} + +/* + * Init/exit code for the module. Basically, creates/removes /sys/class/rc + */ + +static int __init ir_core_init(void) +{ + int rc = class_register(&ir_input_class); + if (rc) { + printk(KERN_ERR "ir_core: unable to register rc class\n"); + return rc; + } + + /* Initialize/load the decoders/keymap code that will be used */ + ir_raw_init(); + ir_rcmap_init(); + + return 0; +} + +static void __exit ir_core_exit(void) +{ + class_unregister(&ir_input_class); + ir_rcmap_cleanup(); +} + +module_init(ir_core_init); +module_exit(ir_core_exit); -- cgit v0.10.2 From bc2a6c5719efd74ce841ad0f0c9b6ea2590da6da Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 9 Nov 2010 23:18:24 -0300 Subject: [media] rc-core: Merge rc-sysfs.c into rc-main.c Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 479a8f4..5a1112c 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -1,5 +1,5 @@ ir-common-objs := ir-functions.o -rc-core-objs := rc-main.o rc-sysfs.o rc-raw.o rc-map.o +rc-core-objs := rc-main.o rc-raw.o rc-map.o obj-y += keymaps/ diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index d6de2e2..d772677 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -1,6 +1,6 @@ -/* ir-keytable.c - handle IR scancode->keycode tables +/* rc-core.c - handle IR scancode->keycode tables * - * Copyright (C) 2009 by Mauro Carvalho Chehab + * Copyright (C) 2009-2010 by Mauro Carvalho Chehab * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,8 +15,14 @@ #include #include +#include #include "rc-core-priv.h" +#define IRRCV_NUM_DEVICES 256 + +/* bit array to represent IR sysfs device number */ +static unsigned long ir_core_dev_number; + /* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */ #define IR_TAB_MIN_SIZE 256 #define IR_TAB_MAX_SIZE 8192 @@ -758,6 +764,345 @@ void ir_input_unregister(struct input_dev *input_dev) } EXPORT_SYMBOL_GPL(ir_input_unregister); +/* class for /sys/class/rc */ +static char *ir_devnode(struct device *dev, mode_t *mode) +{ + return kasprintf(GFP_KERNEL, "rc/%s", dev_name(dev)); +} + +static struct class ir_input_class = { + .name = "rc", + .devnode = ir_devnode, +}; + +static struct { + u64 type; + char *name; +} proto_names[] = { + { IR_TYPE_UNKNOWN, "unknown" }, + { IR_TYPE_RC5, "rc-5" }, + { IR_TYPE_NEC, "nec" }, + { IR_TYPE_RC6, "rc-6" }, + { IR_TYPE_JVC, "jvc" }, + { IR_TYPE_SONY, "sony" }, + { IR_TYPE_RC5_SZ, "rc-5-sz" }, + { IR_TYPE_LIRC, "lirc" }, +}; + +#define PROTO_NONE "none" + +/** + * show_protocols() - shows the current IR protocol(s) + * @d: the device descriptor + * @mattr: the device attribute struct (unused) + * @buf: a pointer to the output buffer + * + * This routine is a callback routine for input read the IR protocol type(s). + * it is trigged by reading /sys/class/rc/rc?/protocols. + * It returns the protocol names of supported protocols. + * Enabled protocols are printed in brackets. + */ +static ssize_t show_protocols(struct device *d, + struct device_attribute *mattr, char *buf) +{ + struct ir_input_dev *ir_dev = dev_get_drvdata(d); + u64 allowed, enabled; + char *tmp = buf; + int i; + + /* Device is being removed */ + if (!ir_dev) + return -EINVAL; + + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { + enabled = ir_dev->rc_tab.ir_type; + allowed = ir_dev->props->allowed_protos; + } else if (ir_dev->raw) { + enabled = ir_dev->raw->enabled_protocols; + allowed = ir_raw_get_allowed_protocols(); + } else + return sprintf(tmp, "[builtin]\n"); + + IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", + (long long)allowed, + (long long)enabled); + + for (i = 0; i < ARRAY_SIZE(proto_names); i++) { + if (allowed & enabled & proto_names[i].type) + tmp += sprintf(tmp, "[%s] ", proto_names[i].name); + else if (allowed & proto_names[i].type) + tmp += sprintf(tmp, "%s ", proto_names[i].name); + } + + if (tmp != buf) + tmp--; + *tmp = '\n'; + return tmp + 1 - buf; +} + +/** + * store_protocols() - changes the current IR protocol(s) + * @d: the device descriptor + * @mattr: the device attribute struct (unused) + * @buf: a pointer to the input buffer + * @len: length of the input buffer + * + * This routine is a callback routine for changing the IR protocol type. + * It is trigged by writing to /sys/class/rc/rc?/protocols. + * Writing "+proto" will add a protocol to the list of enabled protocols. + * Writing "-proto" will remove a protocol from the list of enabled protocols. + * Writing "proto" will enable only "proto". + * Writing "none" will disable all protocols. + * Returns -EINVAL if an invalid protocol combination or unknown protocol name + * is used, otherwise @len. + */ +static ssize_t store_protocols(struct device *d, + struct device_attribute *mattr, + const char *data, + size_t len) +{ + struct ir_input_dev *ir_dev = dev_get_drvdata(d); + bool enable, disable; + const char *tmp; + u64 type; + u64 mask; + int rc, i, count = 0; + unsigned long flags; + + /* Device is being removed */ + if (!ir_dev) + return -EINVAL; + + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) + type = ir_dev->rc_tab.ir_type; + else if (ir_dev->raw) + type = ir_dev->raw->enabled_protocols; + else { + IR_dprintk(1, "Protocol switching not supported\n"); + return -EINVAL; + } + + while ((tmp = strsep((char **) &data, " \n")) != NULL) { + if (!*tmp) + break; + + if (*tmp == '+') { + enable = true; + disable = false; + tmp++; + } else if (*tmp == '-') { + enable = false; + disable = true; + tmp++; + } else { + enable = false; + disable = false; + } + + if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) { + tmp += sizeof(PROTO_NONE); + mask = 0; + count++; + } else { + for (i = 0; i < ARRAY_SIZE(proto_names); i++) { + if (!strncasecmp(tmp, proto_names[i].name, strlen(proto_names[i].name))) { + tmp += strlen(proto_names[i].name); + mask = proto_names[i].type; + break; + } + } + if (i == ARRAY_SIZE(proto_names)) { + IR_dprintk(1, "Unknown protocol: '%s'\n", tmp); + return -EINVAL; + } + count++; + } + + if (enable) + type |= mask; + else if (disable) + type &= ~mask; + else + type = mask; + } + + if (!count) { + IR_dprintk(1, "Protocol not specified\n"); + return -EINVAL; + } + + if (ir_dev->props && ir_dev->props->change_protocol) { + rc = ir_dev->props->change_protocol(ir_dev->props->priv, + type); + if (rc < 0) { + IR_dprintk(1, "Error setting protocols to 0x%llx\n", + (long long)type); + return -EINVAL; + } + } + + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { + spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); + ir_dev->rc_tab.ir_type = type; + spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); + } else { + ir_dev->raw->enabled_protocols = type; + } + + IR_dprintk(1, "Current protocol(s): 0x%llx\n", + (long long)type); + + return len; +} + +#define ADD_HOTPLUG_VAR(fmt, val...) \ + do { \ + int err = add_uevent_var(env, fmt, val); \ + if (err) \ + return err; \ + } while (0) + +static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) +{ + struct ir_input_dev *ir_dev = dev_get_drvdata(device); + + if (ir_dev->rc_tab.name) + ADD_HOTPLUG_VAR("NAME=%s", ir_dev->rc_tab.name); + if (ir_dev->driver_name) + ADD_HOTPLUG_VAR("DRV_NAME=%s", ir_dev->driver_name); + + return 0; +} + +/* + * Static device attribute struct with the sysfs attributes for IR's + */ +static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR, + show_protocols, store_protocols); + +static struct attribute *rc_dev_attrs[] = { + &dev_attr_protocols.attr, + NULL, +}; + +static struct attribute_group rc_dev_attr_grp = { + .attrs = rc_dev_attrs, +}; + +static const struct attribute_group *rc_dev_attr_groups[] = { + &rc_dev_attr_grp, + NULL +}; + +static struct device_type rc_dev_type = { + .groups = rc_dev_attr_groups, + .uevent = rc_dev_uevent, +}; + +/** + * ir_register_class() - creates the sysfs for /sys/class/rc/rc? + * @input_dev: the struct input_dev descriptor of the device + * + * This routine is used to register the syfs code for IR class + */ +int ir_register_class(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + int devno = find_first_zero_bit(&ir_core_dev_number, + IRRCV_NUM_DEVICES); + + if (unlikely(devno < 0)) + return devno; + + ir_dev->dev.type = &rc_dev_type; + ir_dev->devno = devno; + + ir_dev->dev.class = &ir_input_class; + ir_dev->dev.parent = input_dev->dev.parent; + input_dev->dev.parent = &ir_dev->dev; + dev_set_name(&ir_dev->dev, "rc%d", devno); + dev_set_drvdata(&ir_dev->dev, ir_dev); + return device_register(&ir_dev->dev); +}; + +/** + * ir_register_input - registers ir input device with input subsystem + * @input_dev: the struct input_dev descriptor of the device + */ + +int ir_register_input(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + int rc; + const char *path; + + + rc = input_register_device(input_dev); + if (rc < 0) { + device_del(&ir_dev->dev); + return rc; + } + + __module_get(THIS_MODULE); + + path = kobject_get_path(&ir_dev->dev.kobj, GFP_KERNEL); + printk(KERN_INFO "%s: %s as %s\n", + dev_name(&ir_dev->dev), + input_dev->name ? input_dev->name : "Unspecified device", + path ? path : "N/A"); + kfree(path); + + set_bit(ir_dev->devno, &ir_core_dev_number); + return 0; +} + +/** + * ir_unregister_class() - removes the sysfs for sysfs for + * /sys/class/rc/rc? + * @input_dev: the struct input_dev descriptor of the device + * + * This routine is used to unregister the syfs code for IR class + */ +void ir_unregister_class(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + + input_set_drvdata(input_dev, NULL); + clear_bit(ir_dev->devno, &ir_core_dev_number); + input_unregister_device(input_dev); + device_del(&ir_dev->dev); + + module_put(THIS_MODULE); +} + +/* + * Init/exit code for the module. Basically, creates/removes /sys/class/rc + */ + +static int __init ir_core_init(void) +{ + int rc = class_register(&ir_input_class); + if (rc) { + printk(KERN_ERR "ir_core: unable to register rc class\n"); + return rc; + } + + /* Initialize/load the decoders/keymap code that will be used */ + ir_raw_init(); + ir_rcmap_init(); + + return 0; +} + +static void __exit ir_core_exit(void) +{ + class_unregister(&ir_input_class); + ir_rcmap_cleanup(); +} + +module_init(ir_core_init); +module_exit(ir_core_exit); + int ir_core_debug; /* ir_debug level (0,1,2) */ EXPORT_SYMBOL_GPL(ir_core_debug); module_param_named(debug, ir_core_debug, int, 0644); diff --git a/drivers/media/rc/rc-sysfs.c b/drivers/media/rc/rc-sysfs.c deleted file mode 100644 index a5f81d1..0000000 --- a/drivers/media/rc/rc-sysfs.c +++ /dev/null @@ -1,362 +0,0 @@ -/* ir-sysfs.c - sysfs interface for RC devices (/sys/class/rc) - * - * Copyright (C) 2009-2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include "rc-core-priv.h" - -#define IRRCV_NUM_DEVICES 256 - -/* bit array to represent IR sysfs device number */ -static unsigned long ir_core_dev_number; - -/* class for /sys/class/rc */ -static char *ir_devnode(struct device *dev, mode_t *mode) -{ - return kasprintf(GFP_KERNEL, "rc/%s", dev_name(dev)); -} - -static struct class ir_input_class = { - .name = "rc", - .devnode = ir_devnode, -}; - -static struct { - u64 type; - char *name; -} proto_names[] = { - { IR_TYPE_UNKNOWN, "unknown" }, - { IR_TYPE_RC5, "rc-5" }, - { IR_TYPE_NEC, "nec" }, - { IR_TYPE_RC6, "rc-6" }, - { IR_TYPE_JVC, "jvc" }, - { IR_TYPE_SONY, "sony" }, - { IR_TYPE_RC5_SZ, "rc-5-sz" }, - { IR_TYPE_LIRC, "lirc" }, -}; - -#define PROTO_NONE "none" - -/** - * show_protocols() - shows the current IR protocol(s) - * @d: the device descriptor - * @mattr: the device attribute struct (unused) - * @buf: a pointer to the output buffer - * - * This routine is a callback routine for input read the IR protocol type(s). - * it is trigged by reading /sys/class/rc/rc?/protocols. - * It returns the protocol names of supported protocols. - * Enabled protocols are printed in brackets. - */ -static ssize_t show_protocols(struct device *d, - struct device_attribute *mattr, char *buf) -{ - struct ir_input_dev *ir_dev = dev_get_drvdata(d); - u64 allowed, enabled; - char *tmp = buf; - int i; - - /* Device is being removed */ - if (!ir_dev) - return -EINVAL; - - if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { - enabled = ir_dev->rc_tab.ir_type; - allowed = ir_dev->props->allowed_protos; - } else if (ir_dev->raw) { - enabled = ir_dev->raw->enabled_protocols; - allowed = ir_raw_get_allowed_protocols(); - } else - return sprintf(tmp, "[builtin]\n"); - - IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", - (long long)allowed, - (long long)enabled); - - for (i = 0; i < ARRAY_SIZE(proto_names); i++) { - if (allowed & enabled & proto_names[i].type) - tmp += sprintf(tmp, "[%s] ", proto_names[i].name); - else if (allowed & proto_names[i].type) - tmp += sprintf(tmp, "%s ", proto_names[i].name); - } - - if (tmp != buf) - tmp--; - *tmp = '\n'; - return tmp + 1 - buf; -} - -/** - * store_protocols() - changes the current IR protocol(s) - * @d: the device descriptor - * @mattr: the device attribute struct (unused) - * @buf: a pointer to the input buffer - * @len: length of the input buffer - * - * This routine is a callback routine for changing the IR protocol type. - * It is trigged by writing to /sys/class/rc/rc?/protocols. - * Writing "+proto" will add a protocol to the list of enabled protocols. - * Writing "-proto" will remove a protocol from the list of enabled protocols. - * Writing "proto" will enable only "proto". - * Writing "none" will disable all protocols. - * Returns -EINVAL if an invalid protocol combination or unknown protocol name - * is used, otherwise @len. - */ -static ssize_t store_protocols(struct device *d, - struct device_attribute *mattr, - const char *data, - size_t len) -{ - struct ir_input_dev *ir_dev = dev_get_drvdata(d); - bool enable, disable; - const char *tmp; - u64 type; - u64 mask; - int rc, i, count = 0; - unsigned long flags; - - /* Device is being removed */ - if (!ir_dev) - return -EINVAL; - - if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) - type = ir_dev->rc_tab.ir_type; - else if (ir_dev->raw) - type = ir_dev->raw->enabled_protocols; - else { - IR_dprintk(1, "Protocol switching not supported\n"); - return -EINVAL; - } - - while ((tmp = strsep((char **) &data, " \n")) != NULL) { - if (!*tmp) - break; - - if (*tmp == '+') { - enable = true; - disable = false; - tmp++; - } else if (*tmp == '-') { - enable = false; - disable = true; - tmp++; - } else { - enable = false; - disable = false; - } - - if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) { - tmp += sizeof(PROTO_NONE); - mask = 0; - count++; - } else { - for (i = 0; i < ARRAY_SIZE(proto_names); i++) { - if (!strncasecmp(tmp, proto_names[i].name, strlen(proto_names[i].name))) { - tmp += strlen(proto_names[i].name); - mask = proto_names[i].type; - break; - } - } - if (i == ARRAY_SIZE(proto_names)) { - IR_dprintk(1, "Unknown protocol: '%s'\n", tmp); - return -EINVAL; - } - count++; - } - - if (enable) - type |= mask; - else if (disable) - type &= ~mask; - else - type = mask; - } - - if (!count) { - IR_dprintk(1, "Protocol not specified\n"); - return -EINVAL; - } - - if (ir_dev->props && ir_dev->props->change_protocol) { - rc = ir_dev->props->change_protocol(ir_dev->props->priv, - type); - if (rc < 0) { - IR_dprintk(1, "Error setting protocols to 0x%llx\n", - (long long)type); - return -EINVAL; - } - } - - if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { - spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); - ir_dev->rc_tab.ir_type = type; - spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); - } else { - ir_dev->raw->enabled_protocols = type; - } - - IR_dprintk(1, "Current protocol(s): 0x%llx\n", - (long long)type); - - return len; -} - -#define ADD_HOTPLUG_VAR(fmt, val...) \ - do { \ - int err = add_uevent_var(env, fmt, val); \ - if (err) \ - return err; \ - } while (0) - -static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) -{ - struct ir_input_dev *ir_dev = dev_get_drvdata(device); - - if (ir_dev->rc_tab.name) - ADD_HOTPLUG_VAR("NAME=%s", ir_dev->rc_tab.name); - if (ir_dev->driver_name) - ADD_HOTPLUG_VAR("DRV_NAME=%s", ir_dev->driver_name); - - return 0; -} - -/* - * Static device attribute struct with the sysfs attributes for IR's - */ -static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR, - show_protocols, store_protocols); - -static struct attribute *rc_dev_attrs[] = { - &dev_attr_protocols.attr, - NULL, -}; - -static struct attribute_group rc_dev_attr_grp = { - .attrs = rc_dev_attrs, -}; - -static const struct attribute_group *rc_dev_attr_groups[] = { - &rc_dev_attr_grp, - NULL -}; - -static struct device_type rc_dev_type = { - .groups = rc_dev_attr_groups, - .uevent = rc_dev_uevent, -}; - -/** - * ir_register_class() - creates the sysfs for /sys/class/rc/rc? - * @input_dev: the struct input_dev descriptor of the device - * - * This routine is used to register the syfs code for IR class - */ -int ir_register_class(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - int devno = find_first_zero_bit(&ir_core_dev_number, - IRRCV_NUM_DEVICES); - - if (unlikely(devno < 0)) - return devno; - - ir_dev->dev.type = &rc_dev_type; - ir_dev->devno = devno; - - ir_dev->dev.class = &ir_input_class; - ir_dev->dev.parent = input_dev->dev.parent; - input_dev->dev.parent = &ir_dev->dev; - dev_set_name(&ir_dev->dev, "rc%d", devno); - dev_set_drvdata(&ir_dev->dev, ir_dev); - return device_register(&ir_dev->dev); -}; - -/** - * ir_register_input - registers ir input device with input subsystem - * @input_dev: the struct input_dev descriptor of the device - */ - -int ir_register_input(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - int rc; - const char *path; - - - rc = input_register_device(input_dev); - if (rc < 0) { - device_del(&ir_dev->dev); - return rc; - } - - __module_get(THIS_MODULE); - - path = kobject_get_path(&ir_dev->dev.kobj, GFP_KERNEL); - printk(KERN_INFO "%s: %s as %s\n", - dev_name(&ir_dev->dev), - input_dev->name ? input_dev->name : "Unspecified device", - path ? path : "N/A"); - kfree(path); - - set_bit(ir_dev->devno, &ir_core_dev_number); - return 0; -} - -/** - * ir_unregister_class() - removes the sysfs for sysfs for - * /sys/class/rc/rc? - * @input_dev: the struct input_dev descriptor of the device - * - * This routine is used to unregister the syfs code for IR class - */ -void ir_unregister_class(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - - input_set_drvdata(input_dev, NULL); - clear_bit(ir_dev->devno, &ir_core_dev_number); - input_unregister_device(input_dev); - device_del(&ir_dev->dev); - - module_put(THIS_MODULE); -} - -/* - * Init/exit code for the module. Basically, creates/removes /sys/class/rc - */ - -static int __init ir_core_init(void) -{ - int rc = class_register(&ir_input_class); - if (rc) { - printk(KERN_ERR "ir_core: unable to register rc class\n"); - return rc; - } - - /* Initialize/load the decoders/keymap code that will be used */ - ir_raw_init(); - ir_rcmap_init(); - - return 0; -} - -static void __exit ir_core_exit(void) -{ - class_unregister(&ir_input_class); - ir_rcmap_cleanup(); -} - -module_init(ir_core_init); -module_exit(ir_core_exit); -- cgit v0.10.2 From 631493ecacd81f1af74de459c1d16f7ffa6c82c0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 9 Nov 2010 23:44:27 -0300 Subject: [media] rc-core: merge rc-map.c into rc-main.c With this change, all rc-core functions are into just one file, except for the rc-raw specific functions. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 5a1112c..1eb24e6 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -1,5 +1,5 @@ ir-common-objs := ir-functions.o -rc-core-objs := rc-main.o rc-raw.o rc-map.o +rc-core-objs := rc-main.o rc-raw.o obj-y += keymaps/ diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index d772677..afcf0a8 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -12,7 +12,9 @@ * GNU General Public License for more details. */ - +#include +#include +#include #include #include #include @@ -30,6 +32,96 @@ static unsigned long ir_core_dev_number; /* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */ #define IR_KEYPRESS_TIMEOUT 250 +/* Used to handle IR raw handler extensions */ +static LIST_HEAD(rc_map_list); +static DEFINE_SPINLOCK(rc_map_lock); + +static struct rc_keymap *seek_rc_map(const char *name) +{ + struct rc_keymap *map = NULL; + + spin_lock(&rc_map_lock); + list_for_each_entry(map, &rc_map_list, list) { + if (!strcmp(name, map->map.name)) { + spin_unlock(&rc_map_lock); + return map; + } + } + spin_unlock(&rc_map_lock); + + return NULL; +} + +struct ir_scancode_table *get_rc_map(const char *name) +{ + + struct rc_keymap *map; + + map = seek_rc_map(name); +#ifdef MODULE + if (!map) { + int rc = request_module(name); + if (rc < 0) { + printk(KERN_ERR "Couldn't load IR keymap %s\n", name); + return NULL; + } + msleep(20); /* Give some time for IR to register */ + + map = seek_rc_map(name); + } +#endif + if (!map) { + printk(KERN_ERR "IR keymap %s not found\n", name); + return NULL; + } + + printk(KERN_INFO "Registered IR keymap %s\n", map->map.name); + + return &map->map; +} +EXPORT_SYMBOL_GPL(get_rc_map); + +int ir_register_map(struct rc_keymap *map) +{ + spin_lock(&rc_map_lock); + list_add_tail(&map->list, &rc_map_list); + spin_unlock(&rc_map_lock); + return 0; +} +EXPORT_SYMBOL_GPL(ir_register_map); + +void ir_unregister_map(struct rc_keymap *map) +{ + spin_lock(&rc_map_lock); + list_del(&map->list); + spin_unlock(&rc_map_lock); +} +EXPORT_SYMBOL_GPL(ir_unregister_map); + + +static struct ir_scancode empty[] = { + { 0x2a, KEY_COFFEE }, +}; + +static struct rc_keymap empty_map = { + .map = { + .scan = empty, + .size = ARRAY_SIZE(empty), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_EMPTY, + } +}; + +int ir_rcmap_init(void) +{ + return ir_register_map(&empty_map); +} + +void ir_rcmap_cleanup(void) +{ + ir_unregister_map(&empty_map); +} + /** * ir_create_table() - initializes a scancode table * @rc_tab: the ir_scancode_table to initialize diff --git a/drivers/media/rc/rc-map.c b/drivers/media/rc/rc-map.c deleted file mode 100644 index 689143f..0000000 --- a/drivers/media/rc/rc-map.c +++ /dev/null @@ -1,107 +0,0 @@ -/* ir-raw-event.c - handle IR Pulse/Space event - * - * Copyright (C) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include - -/* Used to handle IR raw handler extensions */ -static LIST_HEAD(rc_map_list); -static DEFINE_SPINLOCK(rc_map_lock); - -static struct rc_keymap *seek_rc_map(const char *name) -{ - struct rc_keymap *map = NULL; - - spin_lock(&rc_map_lock); - list_for_each_entry(map, &rc_map_list, list) { - if (!strcmp(name, map->map.name)) { - spin_unlock(&rc_map_lock); - return map; - } - } - spin_unlock(&rc_map_lock); - - return NULL; -} - -struct ir_scancode_table *get_rc_map(const char *name) -{ - - struct rc_keymap *map; - - map = seek_rc_map(name); -#ifdef MODULE - if (!map) { - int rc = request_module(name); - if (rc < 0) { - printk(KERN_ERR "Couldn't load IR keymap %s\n", name); - return NULL; - } - msleep(20); /* Give some time for IR to register */ - - map = seek_rc_map(name); - } -#endif - if (!map) { - printk(KERN_ERR "IR keymap %s not found\n", name); - return NULL; - } - - printk(KERN_INFO "Registered IR keymap %s\n", map->map.name); - - return &map->map; -} -EXPORT_SYMBOL_GPL(get_rc_map); - -int ir_register_map(struct rc_keymap *map) -{ - spin_lock(&rc_map_lock); - list_add_tail(&map->list, &rc_map_list); - spin_unlock(&rc_map_lock); - return 0; -} -EXPORT_SYMBOL_GPL(ir_register_map); - -void ir_unregister_map(struct rc_keymap *map) -{ - spin_lock(&rc_map_lock); - list_del(&map->list); - spin_unlock(&rc_map_lock); -} -EXPORT_SYMBOL_GPL(ir_unregister_map); - - -static struct ir_scancode empty[] = { - { 0x2a, KEY_COFFEE }, -}; - -static struct rc_keymap empty_map = { - .map = { - .scan = empty, - .size = ARRAY_SIZE(empty), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ - .name = RC_MAP_EMPTY, - } -}; - -int ir_rcmap_init(void) -{ - return ir_register_map(&empty_map); -} - -void ir_rcmap_cleanup(void) -{ - ir_unregister_map(&empty_map); -} -- cgit v0.10.2 From 4c7b355df6e7f05304e05f6b7a286e59a5f1cc54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Wed, 10 Nov 2010 11:04:19 -0300 Subject: [media] rc-core: Code cleanup after merging rc-sysfs and rc-map into rc-main MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [mchehab@redhat.com: this patch were originally bundled with some renaming stuff and with the file merges, as seen at: https://patchwork.kernel.org/patch/291092/. Instead of using the original approach, I wrote the rename patches and the code merge as separate changes, then applied the difference on this patch. This way, it is easier to see the real changes at the code, and will be easier to merge upstream, especially if some conflict rises on the renaming patches] Signed-off-by: David Härdeman Acked-by: Jarod Wilson Tested-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index 81c936b..4be0757 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h @@ -129,14 +129,6 @@ static inline bool is_timing_event(struct ir_raw_event ev) #define TO_US(duration) DIV_ROUND_CLOSEST((duration), 1000) #define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space") -/* - * Routines from ir-sysfs.c - Meant to be called only internally inside - * ir-core - */ -int ir_register_input(struct input_dev *input_dev); - -int ir_register_class(struct input_dev *input_dev); -void ir_unregister_class(struct input_dev *input_dev); /* * Routines from ir-raw-event.c to be used internally and by decoders @@ -148,8 +140,6 @@ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); void ir_raw_init(void); -int ir_rcmap_init(void); -void ir_rcmap_cleanup(void); /* * Decoder initialization code * diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index afcf0a8..67a6bd5 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -32,10 +32,16 @@ static unsigned long ir_core_dev_number; /* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */ #define IR_KEYPRESS_TIMEOUT 250 -/* Used to handle IR raw handler extensions */ +/* Used to keep track of known keymaps */ static LIST_HEAD(rc_map_list); static DEFINE_SPINLOCK(rc_map_lock); +/* Forward declarations */ +static int ir_register_class(struct input_dev *input_dev); +static void ir_unregister_class(struct input_dev *input_dev); +static int ir_register_input(struct input_dev *input_dev); + + static struct rc_keymap *seek_rc_map(const char *name) { struct rc_keymap *map = NULL; @@ -112,16 +118,6 @@ static struct rc_keymap empty_map = { } }; -int ir_rcmap_init(void) -{ - return ir_register_map(&empty_map); -} - -void ir_rcmap_cleanup(void) -{ - ir_unregister_map(&empty_map); -} - /** * ir_create_table() - initializes a scancode table * @rc_tab: the ir_scancode_table to initialize @@ -265,7 +261,7 @@ static unsigned int ir_update_mapping(struct input_dev *dev, } /** - * ir_locate_scancode() - set a keycode in the scancode->keycode table + * ir_establish_scancode() - set a keycode in the scancode->keycode table * @ir_dev: the struct ir_input_dev device descriptor * @rc_tab: scancode table to be searched * @scancode: the desired scancode @@ -1097,7 +1093,7 @@ static struct device_type rc_dev_type = { * * This routine is used to register the syfs code for IR class */ -int ir_register_class(struct input_dev *input_dev) +static int ir_register_class(struct input_dev *input_dev) { struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); int devno = find_first_zero_bit(&ir_core_dev_number, @@ -1122,7 +1118,7 @@ int ir_register_class(struct input_dev *input_dev) * @input_dev: the struct input_dev descriptor of the device */ -int ir_register_input(struct input_dev *input_dev) +static int ir_register_input(struct input_dev *input_dev) { struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); int rc; @@ -1155,7 +1151,7 @@ int ir_register_input(struct input_dev *input_dev) * * This routine is used to unregister the syfs code for IR class */ -void ir_unregister_class(struct input_dev *input_dev) +static void ir_unregister_class(struct input_dev *input_dev) { struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); @@ -1181,7 +1177,7 @@ static int __init ir_core_init(void) /* Initialize/load the decoders/keymap code that will be used */ ir_raw_init(); - ir_rcmap_init(); + ir_register_map(&empty_map); return 0; } @@ -1189,7 +1185,7 @@ static int __init ir_core_init(void) static void __exit ir_core_exit(void) { class_unregister(&ir_input_class); - ir_rcmap_cleanup(); + ir_unregister_map(&empty_map); } module_init(ir_core_init); diff --git a/include/media/ir-core.h b/include/media/ir-core.h index 53048a2..d41502d 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h @@ -117,7 +117,6 @@ enum raw_event_type { #define to_ir_input_dev(_attr) container_of(_attr, struct ir_input_dev, attr) -/* From ir-keytable.c */ int __ir_input_register(struct input_dev *dev, const struct ir_scancode_table *ir_codes, struct ir_dev_props *props, @@ -164,7 +163,6 @@ void ir_keyup(struct input_dev *dev); u32 ir_g_keycode_from_table(struct input_dev *input_dev, u32 scancode); /* From ir-raw-event.c */ - struct ir_raw_event { union { u32 duration; -- cgit v0.10.2 From d8b4b5822f51e2142b731b42c81e3f03eec475b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=83=C2=A4rdeman?= Date: Fri, 29 Oct 2010 16:08:23 -0300 Subject: [media] ir-core: make struct rc_dev the primary interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch merges the ir_input_dev and ir_dev_props structs into a single struct called rc_dev. The drivers and various functions in rc-core used by the drivers are also changed to use rc_dev as the primary interface when dealing with rc-core. This means that the input_dev is abstracted away from the drivers which is necessary if we ever want to support multiple input devs per rc device. The new API is similar to what the input subsystem uses, i.e: rc_device_alloc() rc_device_free() rc_device_register() rc_device_unregister() [mchehab@redhat.com: Fix compilation on mceusb and cx231xx, due to merge conflicts] Signed-off-by: David Härdeman Acked-by: Jarod Wilson Tested-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index 5d404f1..d1a4385 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -266,7 +265,7 @@ static void dm1105_card_list(struct pci_dev *pci) /* infrared remote control */ struct infrared { - struct input_dev *input_dev; + struct rc_dev *dev; char input_phys[32]; struct work_struct work; u32 ir_command; @@ -532,7 +531,7 @@ static void dm1105_emit_key(struct work_struct *work) data = (ircom >> 8) & 0x7f; - ir_keydown(ir->input_dev, data, 0); + ir_keydown(ir->dev, data, 0); } /* work handler */ @@ -593,46 +592,47 @@ static irqreturn_t dm1105_irq(int irq, void *dev_id) int __devinit dm1105_ir_init(struct dm1105_dev *dm1105) { - struct input_dev *input_dev; - char *ir_codes = RC_MAP_DM1105_NEC; + struct rc_dev *dev; int err = -ENOMEM; - input_dev = input_allocate_device(); - if (!input_dev) + dev = rc_allocate_device(); + if (!dev) return -ENOMEM; - dm1105->ir.input_dev = input_dev; snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys), "pci-%s/ir0", pci_name(dm1105->pdev)); - input_dev->name = "DVB on-card IR receiver"; - input_dev->phys = dm1105->ir.input_phys; - input_dev->id.bustype = BUS_PCI; - input_dev->id.version = 1; + dev->driver_name = MODULE_NAME; + dev->map_name = RC_MAP_DM1105_NEC; + dev->driver_type = RC_DRIVER_SCANCODE; + dev->input_name = "DVB on-card IR receiver"; + dev->input_phys = dm1105->ir.input_phys; + dev->input_id.bustype = BUS_PCI; + dev->input_id.version = 1; if (dm1105->pdev->subsystem_vendor) { - input_dev->id.vendor = dm1105->pdev->subsystem_vendor; - input_dev->id.product = dm1105->pdev->subsystem_device; + dev->input_id.vendor = dm1105->pdev->subsystem_vendor; + dev->input_id.product = dm1105->pdev->subsystem_device; } else { - input_dev->id.vendor = dm1105->pdev->vendor; - input_dev->id.product = dm1105->pdev->device; + dev->input_id.vendor = dm1105->pdev->vendor; + dev->input_id.product = dm1105->pdev->device; } - - input_dev->dev.parent = &dm1105->pdev->dev; + dev->dev.parent = &dm1105->pdev->dev; INIT_WORK(&dm1105->ir.work, dm1105_emit_key); - err = ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME); + err = rc_register_device(dev); if (err < 0) { - input_free_device(input_dev); + rc_free_device(dev); return err; } + dm1105->ir.dev = dev; return 0; } void __devexit dm1105_ir_exit(struct dm1105_dev *dm1105) { - ir_input_unregister(dm1105->ir.input_dev); + rc_unregister_device(dm1105->ir.dev); } static int __devinit dm1105_hw_init(struct dm1105_dev *dev) diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 31c0a0e..8b9ab30 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -1041,13 +1041,13 @@ static int af9015_rc_query(struct dvb_usb_device *d) priv->rc_keycode = buf[12] << 16 | buf[13] << 8 | buf[14]; } - ir_keydown(d->rc_input_dev, priv->rc_keycode, 0); + ir_keydown(d->rc_dev, priv->rc_keycode, 0); } else { priv->rc_keycode = 0; /* clear just for sure */ } } else if (priv->rc_repeat != buf[6] || buf[0]) { deb_rc("%s: key repeated\n", __func__); - ir_keydown(d->rc_input_dev, priv->rc_keycode, 0); + ir_keydown(d->rc_dev, priv->rc_keycode, 0); } else { deb_rc("%s: no key press\n", __func__); } @@ -1348,9 +1348,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .module_name = "af9015", .rc_query = af9015_rc_query, .rc_interval = AF9015_RC_INTERVAL, - .rc_props = { - .allowed_protos = IR_TYPE_NEC, - }, + .allowed_protos = IR_TYPE_NEC, }, .i2c_algo = &af9015_i2c_algo, @@ -1478,9 +1476,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .module_name = "af9015", .rc_query = af9015_rc_query, .rc_interval = AF9015_RC_INTERVAL, - .rc_props = { - .allowed_protos = IR_TYPE_NEC, - }, + .allowed_protos = IR_TYPE_NEC, }, .i2c_algo = &af9015_i2c_algo, @@ -1592,9 +1588,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .module_name = "af9015", .rc_query = af9015_rc_query, .rc_interval = AF9015_RC_INTERVAL, - .rc_props = { - .allowed_protos = IR_TYPE_NEC, - }, + .allowed_protos = IR_TYPE_NEC, }, .i2c_algo = &af9015_i2c_algo, diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index 1759d26..c6e4ba5 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c @@ -394,7 +394,7 @@ static int anysee_rc_query(struct dvb_usb_device *d) if (ircode[0]) { deb_rc("%s: key pressed %02x\n", __func__, ircode[1]); - ir_keydown(d->rc_input_dev, 0x08 << 8 | ircode[1], 0); + ir_keydown(d->rc_dev, 0x08 << 8 | ircode[1], 0); } return 0; diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h index c2c9d23..1e7d780 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/dvb/dvb-usb/dib0700.h @@ -60,7 +60,7 @@ extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff); extern struct i2c_algorithm dib0700_i2c_algo; extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, int *cold); -extern int dib0700_change_protocol(void *priv, u64 ir_type); +extern int dib0700_change_protocol(struct rc_dev *dev, u64 ir_type); extern int dib0700_device_count; extern int dvb_usb_dib0700_ir_proto; diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index 48397f1..3b58f45 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -471,9 +471,9 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) return dib0700_ctrl_wr(adap->dev, b, 4); } -int dib0700_change_protocol(void *priv, u64 ir_type) +int dib0700_change_protocol(struct rc_dev *rc, u64 ir_type) { - struct dvb_usb_device *d = priv; + struct dvb_usb_device *d = rc->priv; struct dib0700_state *st = d->priv; u8 rc_setup[3] = { REQUEST_SET_RC, 0, 0 }; int new_proto, ret; @@ -535,7 +535,7 @@ static void dib0700_rc_urb_completion(struct urb *purb) if (d == NULL) return; - if (d->rc_input_dev == NULL) { + if (d->rc_dev == NULL) { /* This will occur if disable_rc_polling=1 */ usb_free_urb(purb); return; @@ -600,7 +600,7 @@ static void dib0700_rc_urb_completion(struct urb *purb) goto resubmit; } - ir_keydown(d->rc_input_dev, keycode, toggle); + ir_keydown(d->rc_dev, keycode, toggle); resubmit: /* Clean the buffer before we requeue */ diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index e06acd1..be167f2 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -520,13 +520,13 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d) d->last_event = keycode; } - ir_keydown(d->rc_input_dev, keycode, 0); + ir_keydown(d->rc_dev, keycode, 0); break; default: /* RC-5 protocol changes toggle bit on new keypress */ keycode = key[3-2] << 8 | key[3-3]; toggle = key[3-1]; - ir_keydown(d->rc_input_dev, keycode, toggle); + ir_keydown(d->rc_dev, keycode, toggle); break; } @@ -1924,12 +1924,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_interval = DEFAULT_RC_INTERVAL, .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .rc_query = dib0700_rc_query_old_firmware, - .rc_props = { - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, - .change_protocol = dib0700_change_protocol, - }, + .allowed_protos = IR_TYPE_RC5 | + IR_TYPE_RC6 | + IR_TYPE_NEC, + .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -1960,12 +1958,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_interval = DEFAULT_RC_INTERVAL, .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .rc_query = dib0700_rc_query_old_firmware, - .rc_props = { - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, - .change_protocol = dib0700_change_protocol, - }, + .allowed_protos = IR_TYPE_RC5 | + IR_TYPE_RC6 | + IR_TYPE_NEC, + .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2021,12 +2017,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_interval = DEFAULT_RC_INTERVAL, .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .rc_query = dib0700_rc_query_old_firmware, - .rc_props = { - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, - .change_protocol = dib0700_change_protocol, - }, + .allowed_protos = IR_TYPE_RC5 | + IR_TYPE_RC6 | + IR_TYPE_NEC, + .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2065,12 +2059,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .rc_props = { - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, - .change_protocol = dib0700_change_protocol, - }, + .allowed_protos = IR_TYPE_RC5 | + IR_TYPE_RC6 | + IR_TYPE_NEC, + .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2143,12 +2135,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .rc_props = { - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, - .change_protocol = dib0700_change_protocol, - }, + .allowed_protos = IR_TYPE_RC5 | + IR_TYPE_RC6 | + IR_TYPE_NEC, + .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2189,12 +2179,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .rc_props = { - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, - .change_protocol = dib0700_change_protocol, - }, + .allowed_protos = IR_TYPE_RC5 | + IR_TYPE_RC6 | + IR_TYPE_NEC, + .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2259,12 +2247,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .rc_props = { - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, - .change_protocol = dib0700_change_protocol, - }, + .allowed_protos = IR_TYPE_RC5 | + IR_TYPE_RC6 | + IR_TYPE_NEC, + .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2308,12 +2294,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_NEC_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .rc_props = { - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, - .change_protocol = dib0700_change_protocol, - }, + .allowed_protos = IR_TYPE_RC5 | + IR_TYPE_RC6 | + IR_TYPE_NEC, + .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2379,12 +2363,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .rc_props = { - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, - .change_protocol = dib0700_change_protocol, - }, + .allowed_protos = IR_TYPE_RC5 | + IR_TYPE_RC6 | + IR_TYPE_NEC, + .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, .num_adapters = 1, @@ -2417,12 +2399,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .rc_props = { - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, - .change_protocol = dib0700_change_protocol, - }, + .allowed_protos = IR_TYPE_RC5 | + IR_TYPE_RC6 | + IR_TYPE_NEC, + .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, .num_adapters = 1, @@ -2487,12 +2467,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .rc_props = { - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, - .change_protocol = dib0700_change_protocol, - }, + .allowed_protos = IR_TYPE_RC5 | + IR_TYPE_RC6 | + IR_TYPE_NEC, + .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, .num_adapters = 1, @@ -2533,12 +2511,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_NEC_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .rc_props = { - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, - .change_protocol = dib0700_change_protocol, - }, + .allowed_protos = IR_TYPE_RC5 | + IR_TYPE_RC6 | + IR_TYPE_NEC, + .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, .num_adapters = 2, @@ -2584,12 +2560,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .rc_props = { - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, - .change_protocol = dib0700_change_protocol, - }, + .allowed_protos = IR_TYPE_RC5 | + IR_TYPE_RC6 | + IR_TYPE_NEC, + .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, .num_adapters = 1, @@ -2623,12 +2597,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .rc_props = { - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, - .change_protocol = dib0700_change_protocol, - }, + .allowed_protos = IR_TYPE_RC5 | + IR_TYPE_RC6 | + IR_TYPE_NEC, + .change_protocol = dib0700_change_protocol, }, }, }; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index b579fed..bbba149 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -106,10 +106,10 @@ static void legacy_dvb_usb_read_remote_control(struct work_struct *work) d->last_event = event; case REMOTE_KEY_REPEAT: deb_rc("key repeated\n"); - input_event(d->rc_input_dev, EV_KEY, event, 1); - input_sync(d->rc_input_dev); - input_event(d->rc_input_dev, EV_KEY, d->last_event, 0); - input_sync(d->rc_input_dev); + input_event(d->input_dev, EV_KEY, event, 1); + input_sync(d->input_dev); + input_event(d->input_dev, EV_KEY, d->last_event, 0); + input_sync(d->input_dev); break; default: break; @@ -154,10 +154,22 @@ schedule: schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc.legacy.rc_interval)); } -static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d, - struct input_dev *input_dev) +static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d) { int i, err, rc_interval; + struct input_dev *input_dev; + + input_dev = input_allocate_device(); + if (!input_dev) + return -ENOMEM; + + input_dev->evbit[0] = BIT_MASK(EV_KEY); + input_dev->name = "IR-receiver inside an USB DVB receiver"; + input_dev->phys = d->rc_phys; + usb_to_input_id(d->udev, &input_dev->id); + input_dev->dev.parent = &d->udev->dev; + d->input_dev = input_dev; + d->rc_dev = NULL; input_dev->getkeycode = legacy_dvb_usb_getkeycode; input_dev->setkeycode = legacy_dvb_usb_setkeycode; @@ -221,18 +233,34 @@ static void dvb_usb_read_remote_control(struct work_struct *work) msecs_to_jiffies(d->props.rc.core.rc_interval)); } -static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d, - struct input_dev *input_dev) +static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d) { int err, rc_interval; + struct rc_dev *dev; + + dev = rc_allocate_device(); + if (!dev) + return -ENOMEM; - d->props.rc.core.rc_props.priv = d; - err = ir_input_register(input_dev, - d->props.rc.core.rc_codes, - &d->props.rc.core.rc_props, - d->props.rc.core.module_name); - if (err < 0) + dev->driver_name = d->props.rc.core.module_name; + dev->map_name = d->props.rc.core.rc_codes; + dev->change_protocol = d->props.rc.core.change_protocol; + dev->allowed_protos = d->props.rc.core.allowed_protos; + dev->driver_type = RC_DRIVER_SCANCODE; + usb_to_input_id(d->udev, &dev->input_id); + dev->input_name = "IR-receiver inside an USB DVB receiver"; + dev->input_phys = d->rc_phys; + dev->dev.parent = &d->udev->dev; + dev->priv = d; + + err = rc_register_device(dev); + if (err < 0) { + rc_free_device(dev); return err; + } + + d->input_dev = NULL; + d->rc_dev = dev; if (!d->props.rc.core.rc_query || d->props.rc.core.bulk_mode) return 0; @@ -251,7 +279,6 @@ static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d, int dvb_usb_remote_init(struct dvb_usb_device *d) { - struct input_dev *input_dev; int err; if (dvb_usb_disable_rc_polling) @@ -267,26 +294,14 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys)); - input_dev = input_allocate_device(); - if (!input_dev) - return -ENOMEM; - - input_dev->evbit[0] = BIT_MASK(EV_KEY); - input_dev->name = "IR-receiver inside an USB DVB receiver"; - input_dev->phys = d->rc_phys; - usb_to_input_id(d->udev, &input_dev->id); - input_dev->dev.parent = &d->udev->dev; - /* Start the remote-control polling. */ if (d->props.rc.legacy.rc_interval < 40) d->props.rc.legacy.rc_interval = 100; /* default */ - d->rc_input_dev = input_dev; - if (d->props.rc.mode == DVB_RC_LEGACY) - err = legacy_dvb_usb_remote_init(d, input_dev); + err = legacy_dvb_usb_remote_init(d); else - err = rc_core_dvb_usb_remote_init(d, input_dev); + err = rc_core_dvb_usb_remote_init(d); if (err) return err; @@ -301,9 +316,9 @@ int dvb_usb_remote_exit(struct dvb_usb_device *d) cancel_rearming_delayed_work(&d->rc_query_work); flush_scheduled_work(); if (d->props.rc.mode == DVB_RC_LEGACY) - input_unregister_device(d->rc_input_dev); + input_unregister_device(d->input_dev); else - ir_input_unregister(d->rc_input_dev); + rc_unregister_device(d->rc_dev); } d->state &= ~DVB_USB_STATE_REMOTE; return 0; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index 34f7b3b..83aa982 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -180,18 +180,20 @@ struct dvb_rc_legacy { * struct dvb_rc properties of remote controller, using rc-core * @rc_codes: name of rc codes table * @protocol: type of protocol(s) currently used by the driver + * @allowed_protos: protocol(s) supported by the driver + * @change_protocol: callback to change protocol * @rc_query: called to query an event event. * @rc_interval: time in ms between two queries. - * @rc_props: remote controller properties * @bulk_mode: device supports bulk mode for RC (disable polling mode) */ struct dvb_rc { char *rc_codes; u64 protocol; + u64 allowed_protos; + int (*change_protocol)(struct rc_dev *dev, u64 ir_type); char *module_name; int (*rc_query) (struct dvb_usb_device *d); int rc_interval; - struct ir_dev_props rc_props; bool bulk_mode; /* uses bulk mode */ }; @@ -385,7 +387,8 @@ struct dvb_usb_adapter { * * @i2c_adap: device's i2c_adapter if it uses I2CoverUSB * - * @rc_input_dev: input device for the remote control. + * @rc_dev: rc device for the remote control (rc-core mode) + * @input_dev: input device for the remote control (legacy mode) * @rc_query_work: struct work_struct frequent rc queries * @last_event: last triggered event * @last_state: last state (no, pressed, repeat) @@ -418,7 +421,8 @@ struct dvb_usb_device { struct dvb_usb_adapter adapter[MAX_NO_OF_ADAPTER_PER_DEVICE]; /* remote control */ - struct input_dev *rc_input_dev; + struct rc_dev *rc_dev; + struct input_dev *input_dev; char rc_phys[64]; struct delayed_work rc_query_work; u32 last_event; diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c index de7f1fb..d8f1b15 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/drivers/media/dvb/dvb-usb/lmedm04.c @@ -198,7 +198,7 @@ static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u16 keypress) deb_info(1, "INT Key Keypress =%04x", keypress); if (keypress > 0) - ir_keydown(d->rc_input_dev, keypress, 0); + ir_keydown(d->rc_dev, keypress, 0); return 0; } @@ -555,42 +555,39 @@ static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) static int lme2510_int_service(struct dvb_usb_adapter *adap) { struct dvb_usb_device *d = adap->dev; - struct input_dev *input_dev; - char *ir_codes = RC_MAP_LME2510; - int ret = 0; + struct rc_dev *rc; + int ret; info("STA Configuring Remote"); - usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); - - strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys)); - - input_dev = input_allocate_device(); - if (!input_dev) + rc = rc_allocate_device(); + if (!rc) return -ENOMEM; - input_dev->name = "LME2510 Remote Control"; - input_dev->phys = d->rc_phys; - - usb_to_input_id(d->udev, &input_dev->id); + usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); + strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys)); - ret |= ir_input_register(input_dev, ir_codes, NULL, "LME 2510"); + rc->input_name = "LME2510 Remote Control"; + rc->input_phys = d->rc_phys; + rc->map_name = RC_MAP_LME2510; + rc->driver_name = "LME 2510"; + usb_to_input_id(d->udev, &rc->input_id); + ret = rc_register_device(rc); if (ret) { - input_free_device(input_dev); + rc_free_device(rc); return ret; } + d->rc_dev = rc; - d->rc_input_dev = input_dev; /* Start the Interupt */ ret = lme2510_int_read(adap); - if (ret < 0) { - ir_input_unregister(input_dev); - input_free_device(input_dev); + rc_unregister_device(rc); + return -ENODEV; } - return (ret < 0) ? -ENODEV : 0; + return 0; } static u8 check_sum(u8 *p, u8 len) @@ -1025,7 +1022,7 @@ void *lme2510_exit_int(struct dvb_usb_device *d) usb_free_coherent(d->udev, 5000, st->buffer, st->lme_urb->transfer_dma); info("Interupt Service Stopped"); - ir_input_unregister(d->rc_input_dev); + rc_unregister_device(d->rc_dev); info("Remote Stopped"); } return buffer; diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index d0b645a..bd400d2 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -171,7 +171,9 @@ struct mantis_pci { struct work_struct uart_work; spinlock_t uart_lock; - struct input_dev *rc; + struct rc_dev *rc; + char input_name[80]; + char input_phys[80]; }; #define MANTIS_HIF_STATUS (mantis->gpio_status) diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c index a99489b..209f211 100644 --- a/drivers/media/dvb/mantis/mantis_input.c +++ b/drivers/media/dvb/mantis/mantis_input.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include @@ -33,6 +32,7 @@ #include "mantis_uart.h" #define MODULE_NAME "mantis_core" +#define RC_MAP_MANTIS "rc-mantis" static struct ir_scancode mantis_ir_table[] = { { 0x29, KEY_POWER }, @@ -95,53 +95,65 @@ static struct ir_scancode mantis_ir_table[] = { { 0x00, KEY_BLUE }, }; -struct ir_scancode_table ir_mantis = { - .scan = mantis_ir_table, - .size = ARRAY_SIZE(mantis_ir_table), +static struct rc_keymap ir_mantis_map = { + .map = { + .scan = mantis_ir_table, + .size = ARRAY_SIZE(mantis_ir_table), + .ir_type = IR_TYPE_UNKNOWN, + .name = RC_MAP_MANTIS, + } }; -EXPORT_SYMBOL_GPL(ir_mantis); int mantis_input_init(struct mantis_pci *mantis) { - struct input_dev *rc; - char name[80], dev[80]; + struct rc_dev *dev; int err; - rc = input_allocate_device(); - if (!rc) { - dprintk(MANTIS_ERROR, 1, "Input device allocate failed"); - return -ENOMEM; - } + err = ir_register_map(&ir_mantis_map); + if (err) + goto out; - sprintf(name, "Mantis %s IR receiver", mantis->hwconfig->model_name); - sprintf(dev, "pci-%s/ir0", pci_name(mantis->pdev)); + dev = rc_allocate_device(); + if (!dev) { + dprintk(MANTIS_ERROR, 1, "Remote device allocation failed"); + err = -ENOMEM; + goto out_map; + } - rc->name = name; - rc->phys = dev; + sprintf(mantis->input_name, "Mantis %s IR receiver", mantis->hwconfig->model_name); + sprintf(mantis->input_phys, "pci-%s/ir0", pci_name(mantis->pdev)); - rc->id.bustype = BUS_PCI; - rc->id.vendor = mantis->vendor_id; - rc->id.product = mantis->device_id; - rc->id.version = 1; - rc->dev = mantis->pdev->dev; + dev->input_name = mantis->input_name; + dev->input_phys = mantis->input_phys; + dev->input_id.bustype = BUS_PCI; + dev->input_id.vendor = mantis->vendor_id; + dev->input_id.product = mantis->device_id; + dev->input_id.version = 1; + dev->driver_name = MODULE_NAME; + dev->map_name = RC_MAP_MANTIS; + dev->dev.parent = &mantis->pdev->dev; - err = __ir_input_register(rc, &ir_mantis, NULL, MODULE_NAME); + err = rc_register_device(dev); if (err) { dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err); - input_free_device(rc); - return -ENODEV; + goto out_dev; } - mantis->rc = rc; - + mantis->rc = dev; return 0; + +out_dev: + rc_free_device(dev); +out_map: + ir_unregister_map(&ir_mantis_map); +out: + return err; } int mantis_exit(struct mantis_pci *mantis) { - struct input_dev *rc = mantis->rc; - - ir_input_unregister(rc); - + rc_unregister_device(mantis->rc); + ir_unregister_map(&ir_mantis_map); return 0; } + diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c index 135e45b..78765ed 100644 --- a/drivers/media/dvb/siano/smscoreapi.c +++ b/drivers/media/dvb/siano/smscoreapi.c @@ -438,7 +438,7 @@ static int smscore_init_ir(struct smscore_device_t *coredev) int rc; void *buffer; - coredev->ir.input_dev = NULL; + coredev->ir.dev = NULL; ir_io = sms_get_board(smscore_get_board_id(coredev))->board_cfg.ir; if (ir_io) {/* only if IR port exist we use IR sub-module */ sms_info("IR loading"); diff --git a/drivers/media/dvb/siano/smsir.c b/drivers/media/dvb/siano/smsir.c index a27c44a..ebd7305 100644 --- a/drivers/media/dvb/siano/smsir.c +++ b/drivers/media/dvb/siano/smsir.c @@ -45,25 +45,24 @@ void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len) ev.duration = abs(samples[i]) * 1000; /* Convert to ns */ ev.pulse = (samples[i] > 0) ? false : true; - ir_raw_event_store(coredev->ir.input_dev, &ev); + ir_raw_event_store(coredev->ir.dev, &ev); } - ir_raw_event_handle(coredev->ir.input_dev); + ir_raw_event_handle(coredev->ir.dev); } int sms_ir_init(struct smscore_device_t *coredev) { - struct input_dev *input_dev; + int err; int board_id = smscore_get_board_id(coredev); + struct rc_dev *dev; - sms_log("Allocating input device"); - input_dev = input_allocate_device(); - if (!input_dev) { + sms_log("Allocating rc device"); + dev = rc_allocate_device(); + if (!dev) { sms_err("Not enough memory"); return -ENOMEM; } - coredev->ir.input_dev = input_dev; - coredev->ir.controller = 0; /* Todo: vega/nova SPI number */ coredev->ir.timeout = IR_DEFAULT_TIMEOUT; sms_log("IR port %d, timeout %d ms", @@ -75,38 +74,41 @@ int sms_ir_init(struct smscore_device_t *coredev) strlcpy(coredev->ir.phys, coredev->devpath, sizeof(coredev->ir.phys)); strlcat(coredev->ir.phys, "/ir0", sizeof(coredev->ir.phys)); - input_dev->name = coredev->ir.name; - input_dev->phys = coredev->ir.phys; - input_dev->dev.parent = coredev->device; + dev->input_name = coredev->ir.name; + dev->input_phys = coredev->ir.phys; + dev->dev.parent = coredev->device; #if 0 /* TODO: properly initialize the parameters bellow */ - input_dev->id.bustype = BUS_USB; - input_dev->id.version = 1; - input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); - input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); + dev->input_id.bustype = BUS_USB; + dev->input_id.version = 1; + dev->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); + dev->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct); #endif - coredev->ir.props.priv = coredev; - coredev->ir.props.driver_type = RC_DRIVER_IR_RAW; - coredev->ir.props.allowed_protos = IR_TYPE_ALL; + dev->priv = coredev; + dev->driver_type = RC_DRIVER_IR_RAW; + dev->allowed_protos = IR_TYPE_ALL; + dev->map_name = sms_get_board(board_id)->rc_codes; + dev->driver_name = MODULE_NAME; - sms_log("Input device (IR) %s is set for key events", input_dev->name); + sms_log("Input device (IR) %s is set for key events", dev->input_name); - if (ir_input_register(input_dev, sms_get_board(board_id)->rc_codes, - &coredev->ir.props, MODULE_NAME)) { + err = rc_register_device(dev); + if (err < 0) { sms_err("Failed to register device"); - input_free_device(input_dev); - return -EACCES; + rc_free_device(dev); + return err; } + coredev->ir.dev = dev; return 0; } void sms_ir_exit(struct smscore_device_t *coredev) { - if (coredev->ir.input_dev) - ir_input_unregister(coredev->ir.input_dev); + if (coredev->ir.dev) + rc_unregister_device(coredev->ir.dev); sms_log(""); } diff --git a/drivers/media/dvb/siano/smsir.h b/drivers/media/dvb/siano/smsir.h index 926e247..c2f68a4 100644 --- a/drivers/media/dvb/siano/smsir.h +++ b/drivers/media/dvb/siano/smsir.h @@ -35,13 +35,12 @@ along with this program. If not, see . struct smscore_device_t; struct ir_t { - struct input_dev *input_dev; + struct rc_dev *dev; char name[40]; char phys[32]; char *rc_codes; u64 protocol; - struct ir_dev_props props; u32 timeout; u32 controller; diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index a9c2c32..9aca0f3 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -96,7 +95,7 @@ MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); struct budget_ci_ir { - struct input_dev *dev; + struct rc_dev *dev; struct tasklet_struct msp430_irq_tasklet; char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ char phys[32]; @@ -118,7 +117,7 @@ struct budget_ci { static void msp430_ir_interrupt(unsigned long data) { struct budget_ci *budget_ci = (struct budget_ci *) data; - struct input_dev *dev = budget_ci->ir.dev; + struct rc_dev *dev = budget_ci->ir.dev; u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; /* @@ -166,13 +165,11 @@ static void msp430_ir_interrupt(unsigned long data) static int msp430_ir_init(struct budget_ci *budget_ci) { struct saa7146_dev *saa = budget_ci->budget.dev; - struct input_dev *input_dev = budget_ci->ir.dev; + struct rc_dev *dev; int error; - char *ir_codes = NULL; - - budget_ci->ir.dev = input_dev = input_allocate_device(); - if (!input_dev) { + dev = rc_allocate_device(); + if (!dev) { printk(KERN_ERR "budget_ci: IR interface initialisation failed\n"); return -ENOMEM; } @@ -182,19 +179,19 @@ static int msp430_ir_init(struct budget_ci *budget_ci) snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys), "pci-%s/ir0", pci_name(saa->pci)); - input_dev->name = budget_ci->ir.name; - - input_dev->phys = budget_ci->ir.phys; - input_dev->id.bustype = BUS_PCI; - input_dev->id.version = 1; + dev->driver_name = MODULE_NAME; + dev->input_name = budget_ci->ir.name; + dev->input_phys = budget_ci->ir.phys; + dev->input_id.bustype = BUS_PCI; + dev->input_id.version = 1; if (saa->pci->subsystem_vendor) { - input_dev->id.vendor = saa->pci->subsystem_vendor; - input_dev->id.product = saa->pci->subsystem_device; + dev->input_id.vendor = saa->pci->subsystem_vendor; + dev->input_id.product = saa->pci->subsystem_device; } else { - input_dev->id.vendor = saa->pci->vendor; - input_dev->id.product = saa->pci->device; + dev->input_id.vendor = saa->pci->vendor; + dev->input_id.product = saa->pci->device; } - input_dev->dev.parent = &saa->pci->dev; + dev->dev.parent = &saa->pci->dev; if (rc5_device < 0) budget_ci->ir.rc5_device = IR_DEVICE_ANY; @@ -208,7 +205,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) case 0x1011: case 0x1012: /* The hauppauge keymap is a superset of these remotes */ - ir_codes = RC_MAP_HAUPPAUGE_NEW; + dev->map_name = RC_MAP_HAUPPAUGE_NEW; if (rc5_device < 0) budget_ci->ir.rc5_device = 0x1f; @@ -218,23 +215,22 @@ static int msp430_ir_init(struct budget_ci *budget_ci) case 0x1019: case 0x101a: /* for the Technotrend 1500 bundled remote */ - ir_codes = RC_MAP_TT_1500; + dev->map_name = RC_MAP_TT_1500; break; default: /* unknown remote */ - ir_codes = RC_MAP_BUDGET_CI_OLD; + dev->map_name = RC_MAP_BUDGET_CI_OLD; break; } - error = ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME); + error = rc_register_device(dev); if (error) { printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error); + rc_free_device(dev); return error; } - /* note: these must be after input_register_device */ - input_dev->rep[REP_DELAY] = 400; - input_dev->rep[REP_PERIOD] = 250; + budget_ci->ir.dev = dev; tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt, (unsigned long) budget_ci); @@ -248,13 +244,12 @@ static int msp430_ir_init(struct budget_ci *budget_ci) static void msp430_ir_deinit(struct budget_ci *budget_ci) { struct saa7146_dev *saa = budget_ci->budget.dev; - struct input_dev *dev = budget_ci->ir.dev; SAA7146_IER_DISABLE(saa, MASK_06); saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); tasklet_kill(&budget_ci->ir.msp430_irq_tasklet); - ir_input_unregister(dev); + rc_unregister_device(budget_ci->ir.dev); } static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c index 7637bab..0a4151f 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c @@ -37,9 +37,7 @@ #include #include #include -#include #include -#include #include "ene_ir.h" static int sample_period; @@ -357,7 +355,7 @@ void ene_rx_sense_carrier(struct ene_device *dev) ev.carrier_report = true; ev.carrier = carrier; ev.duty_cycle = duty_cycle; - ir_raw_event_store(dev->idev, &ev); + ir_raw_event_store(dev->rdev, &ev); } } @@ -448,32 +446,32 @@ static void ene_rx_setup(struct ene_device *dev) select_timeout: if (dev->rx_fan_input_inuse) { - dev->props->rx_resolution = MS_TO_NS(ENE_FW_SAMPLE_PERIOD_FAN); + dev->rdev->rx_resolution = MS_TO_NS(ENE_FW_SAMPLE_PERIOD_FAN); /* Fan input doesn't support timeouts, it just ends the input with a maximum sample */ - dev->props->min_timeout = dev->props->max_timeout = + dev->rdev->min_timeout = dev->rdev->max_timeout = MS_TO_NS(ENE_FW_SMPL_BUF_FAN_MSK * ENE_FW_SAMPLE_PERIOD_FAN); } else { - dev->props->rx_resolution = MS_TO_NS(sample_period); + dev->rdev->rx_resolution = MS_TO_NS(sample_period); /* Theoreticly timeout is unlimited, but we cap it * because it was seen that on one device, it * would stop sending spaces after around 250 msec. * Besides, this is close to 2^32 anyway and timeout is u32. */ - dev->props->min_timeout = MS_TO_NS(127 * sample_period); - dev->props->max_timeout = MS_TO_NS(200000); + dev->rdev->min_timeout = MS_TO_NS(127 * sample_period); + dev->rdev->max_timeout = MS_TO_NS(200000); } if (dev->hw_learning_and_tx_capable) - dev->props->tx_resolution = MS_TO_NS(sample_period); + dev->rdev->tx_resolution = MS_TO_NS(sample_period); - if (dev->props->timeout > dev->props->max_timeout) - dev->props->timeout = dev->props->max_timeout; - if (dev->props->timeout < dev->props->min_timeout) - dev->props->timeout = dev->props->min_timeout; + if (dev->rdev->timeout > dev->rdev->max_timeout) + dev->rdev->timeout = dev->rdev->max_timeout; + if (dev->rdev->timeout < dev->rdev->min_timeout) + dev->rdev->timeout = dev->rdev->min_timeout; } /* Enable the device for receive */ @@ -504,7 +502,7 @@ static void ene_rx_enable(struct ene_device *dev) ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ); /* enter idle mode */ - ir_raw_event_set_idle(dev->idev, true); + ir_raw_event_set_idle(dev->rdev, true); dev->rx_enabled = true; } @@ -518,7 +516,7 @@ static void ene_rx_disable(struct ene_device *dev) /* disable hardware IRQ and firmware flag */ ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ); - ir_raw_event_set_idle(dev->idev, true); + ir_raw_event_set_idle(dev->rdev, true); dev->rx_enabled = false; } @@ -805,10 +803,10 @@ static irqreturn_t ene_isr(int irq, void *data) ev.duration = MS_TO_NS(hw_sample); ev.pulse = pulse; - ir_raw_event_store_with_filter(dev->idev, &ev); + ir_raw_event_store_with_filter(dev->rdev, &ev); } - ir_raw_event_handle(dev->idev); + ir_raw_event_handle(dev->rdev); unlock: spin_unlock_irqrestore(&dev->hw_lock, flags); return retval; @@ -823,7 +821,7 @@ static void ene_setup_default_settings(struct ene_device *dev) dev->learning_mode_enabled = learning_mode_force; /* Set reasonable default timeout */ - dev->props->timeout = MS_TO_NS(150000); + dev->rdev->timeout = MS_TO_NS(150000); } /* Upload all hardware settings at once. Used at load and resume time */ @@ -838,9 +836,9 @@ static void ene_setup_hw_settings(struct ene_device *dev) } /* outside interface: called on first open*/ -static int ene_open(void *data) +static int ene_open(struct rc_dev *rdev) { - struct ene_device *dev = (struct ene_device *)data; + struct ene_device *dev = rdev->priv; unsigned long flags; spin_lock_irqsave(&dev->hw_lock, flags); @@ -850,9 +848,9 @@ static int ene_open(void *data) } /* outside interface: called on device close*/ -static void ene_close(void *data) +static void ene_close(struct rc_dev *rdev) { - struct ene_device *dev = (struct ene_device *)data; + struct ene_device *dev = rdev->priv; unsigned long flags; spin_lock_irqsave(&dev->hw_lock, flags); @@ -861,9 +859,9 @@ static void ene_close(void *data) } /* outside interface: set transmitter mask */ -static int ene_set_tx_mask(void *data, u32 tx_mask) +static int ene_set_tx_mask(struct rc_dev *rdev, u32 tx_mask) { - struct ene_device *dev = (struct ene_device *)data; + struct ene_device *dev = rdev->priv; dbg("TX: attempt to set transmitter mask %02x", tx_mask); /* invalid txmask */ @@ -879,9 +877,9 @@ static int ene_set_tx_mask(void *data, u32 tx_mask) } /* outside interface : set tx carrier */ -static int ene_set_tx_carrier(void *data, u32 carrier) +static int ene_set_tx_carrier(struct rc_dev *rdev, u32 carrier) { - struct ene_device *dev = (struct ene_device *)data; + struct ene_device *dev = rdev->priv; u32 period = 2000000 / carrier; dbg("TX: attempt to set tx carrier to %d kHz", carrier); @@ -900,9 +898,9 @@ static int ene_set_tx_carrier(void *data, u32 carrier) } /*outside interface : set tx duty cycle */ -static int ene_set_tx_duty_cycle(void *data, u32 duty_cycle) +static int ene_set_tx_duty_cycle(struct rc_dev *rdev, u32 duty_cycle) { - struct ene_device *dev = (struct ene_device *)data; + struct ene_device *dev = rdev->priv; dbg("TX: setting duty cycle to %d%%", duty_cycle); dev->tx_duty_cycle = duty_cycle; ene_tx_set_carrier(dev); @@ -910,9 +908,9 @@ static int ene_set_tx_duty_cycle(void *data, u32 duty_cycle) } /* outside interface: enable learning mode */ -static int ene_set_learning_mode(void *data, int enable) +static int ene_set_learning_mode(struct rc_dev *rdev, int enable) { - struct ene_device *dev = (struct ene_device *)data; + struct ene_device *dev = rdev->priv; unsigned long flags; if (enable == dev->learning_mode_enabled) return 0; @@ -926,9 +924,9 @@ static int ene_set_learning_mode(void *data, int enable) return 0; } -static int ene_set_carrier_report(void *data, int enable) +static int ene_set_carrier_report(struct rc_dev *rdev, int enable) { - struct ene_device *dev = (struct ene_device *)data; + struct ene_device *dev = rdev->priv; unsigned long flags; if (enable == dev->carrier_detect_enabled) @@ -944,18 +942,20 @@ static int ene_set_carrier_report(void *data, int enable) } /* outside interface: enable or disable idle mode */ -static void ene_set_idle(void *data, bool idle) +static void ene_set_idle(struct rc_dev *rdev, bool idle) { + struct ene_device *dev = rdev->priv; + if (idle) { - ene_rx_reset((struct ene_device *)data); + ene_rx_reset(dev); dbg("RX: end of data"); } } /* outside interface: transmit */ -static int ene_transmit(void *data, int *buf, u32 n) +static int ene_transmit(struct rc_dev *rdev, int *buf, u32 n) { - struct ene_device *dev = (struct ene_device *)data; + struct ene_device *dev = rdev->priv; unsigned long flags; dev->tx_buffer = buf; @@ -992,16 +992,13 @@ static int ene_transmit(void *data, int *buf, u32 n) static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) { int error = -ENOMEM; - struct ir_dev_props *ir_props; - struct input_dev *input_dev; + struct rc_dev *rdev; struct ene_device *dev; /* allocate memory */ - input_dev = input_allocate_device(); - ir_props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL); - - if (!input_dev || !ir_props || !dev) + rdev = rc_allocate_device(); + if (!dev || !rdev) goto error1; /* validate resources */ @@ -1054,24 +1051,25 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) if (!dev->hw_learning_and_tx_capable) learning_mode_force = false; - ir_props->driver_type = RC_DRIVER_IR_RAW; - ir_props->allowed_protos = IR_TYPE_ALL; - ir_props->priv = dev; - ir_props->open = ene_open; - ir_props->close = ene_close; - ir_props->s_idle = ene_set_idle; - - dev->props = ir_props; - dev->idev = input_dev; + rdev->driver_type = RC_DRIVER_IR_RAW; + rdev->allowed_protos = IR_TYPE_ALL; + rdev->priv = dev; + rdev->open = ene_open; + rdev->close = ene_close; + rdev->s_idle = ene_set_idle; + rdev->driver_name = ENE_DRIVER_NAME; + rdev->map_name = RC_MAP_RC6_MCE; + rdev->input_name = "ENE eHome Infrared Remote Receiver"; if (dev->hw_learning_and_tx_capable) { - ir_props->s_learning_mode = ene_set_learning_mode; + rdev->s_learning_mode = ene_set_learning_mode; init_completion(&dev->tx_complete); - ir_props->tx_ir = ene_transmit; - ir_props->s_tx_mask = ene_set_tx_mask; - ir_props->s_tx_carrier = ene_set_tx_carrier; - ir_props->s_tx_duty_cycle = ene_set_tx_duty_cycle; - ir_props->s_carrier_report = ene_set_carrier_report; + rdev->tx_ir = ene_transmit; + rdev->s_tx_mask = ene_set_tx_mask; + rdev->s_tx_carrier = ene_set_tx_carrier; + rdev->s_tx_duty_cycle = ene_set_tx_duty_cycle; + rdev->s_carrier_report = ene_set_carrier_report; + rdev->input_name = "ENE eHome Infrared Remote Transceiver"; } ene_rx_setup_hw_buffer(dev); @@ -1081,16 +1079,11 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) device_set_wakeup_capable(&pnp_dev->dev, true); device_set_wakeup_enable(&pnp_dev->dev, true); - if (dev->hw_learning_and_tx_capable) - input_dev->name = "ENE eHome Infrared Remote Transceiver"; - else - input_dev->name = "ENE eHome Infrared Remote Receiver"; - - error = -ENODEV; - if (ir_input_register(input_dev, RC_MAP_RC6_MCE, ir_props, - ENE_DRIVER_NAME)) + error = rc_register_device(rdev); + if (error < 0) goto error; + dev->rdev = rdev; ene_notice("driver has been succesfully loaded"); return 0; error: @@ -1099,8 +1092,7 @@ error: if (dev && dev->hw_io >= 0) release_region(dev->hw_io, ENE_IO_SIZE); error1: - input_free_device(input_dev); - kfree(ir_props); + rc_free_device(rdev); kfree(dev); return error; } @@ -1118,8 +1110,7 @@ static void ene_remove(struct pnp_dev *pnp_dev) free_irq(dev->irq, dev); release_region(dev->hw_io, ENE_IO_SIZE); - ir_input_unregister(dev->idev); - kfree(dev->props); + rc_unregister_device(dev->rdev); kfree(dev); } diff --git a/drivers/media/rc/ene_ir.h b/drivers/media/rc/ene_ir.h index f587066..c179baf 100644 --- a/drivers/media/rc/ene_ir.h +++ b/drivers/media/rc/ene_ir.h @@ -205,8 +205,7 @@ struct ene_device { struct pnp_dev *pnp_dev; - struct input_dev *idev; - struct ir_dev_props *props; + struct rc_dev *rdev; /* hw IO settings */ long hw_io; diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 79f4f58..8d4b35d 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -88,7 +88,6 @@ static ssize_t lcd_write(struct file *file, const char *buf, struct imon_context { struct device *dev; - struct ir_dev_props *props; /* Newer devices have two interfaces */ struct usb_device *usbdev_intf0; struct usb_device *usbdev_intf1; @@ -123,7 +122,7 @@ struct imon_context { u16 vendor; /* usb vendor ID */ u16 product; /* usb product ID */ - struct input_dev *rdev; /* input device for remote */ + struct rc_dev *rdev; /* rc-core device for remote */ struct input_dev *idev; /* input device for panel & IR mouse */ struct input_dev *touch; /* input device for touchscreen */ @@ -984,16 +983,16 @@ static void imon_touch_display_timeout(unsigned long data) * really just RC-6), but only one or the other at a time, as the signals * are decoded onboard the receiver. */ -int imon_ir_change_protocol(void *priv, u64 ir_type) +static int imon_ir_change_protocol(struct rc_dev *rc, u64 ir_type) { int retval; - struct imon_context *ictx = priv; + struct imon_context *ictx = rc->priv; struct device *dev = ictx->dev; bool pad_mouse; unsigned char ir_proto_packet[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 }; - if (ir_type && !(ir_type & ictx->props->allowed_protos)) + if (ir_type && !(ir_type & rc->allowed_protos)) dev_warn(dev, "Looks like you're trying to use an IR protocol " "this device does not support\n"); @@ -1757,7 +1756,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx) printk(KERN_CONT " (id 0x%02x)\n", ffdc_cfg_byte); ictx->display_type = detected_display_type; - ictx->props->allowed_protos = allowed_protos; + ictx->rdev->allowed_protos = allowed_protos; ictx->ir_type = allowed_protos; } @@ -1811,18 +1810,15 @@ static void imon_set_display_type(struct imon_context *ictx) ictx->display_type = configured_display_type; } -static struct input_dev *imon_init_rdev(struct imon_context *ictx) +static struct rc_dev *imon_init_rdev(struct imon_context *ictx) { - struct input_dev *rdev; - struct ir_dev_props *props; + struct rc_dev *rdev; int ret; - char *ir_codes = NULL; const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88 }; - rdev = input_allocate_device(); - props = kzalloc(sizeof(*props), GFP_KERNEL); - if (!rdev || !props) { + rdev = rc_allocate_device(); + if (!rdev) { dev_err(ictx->dev, "remote control dev allocation failed\n"); goto out; } @@ -1833,18 +1829,20 @@ static struct input_dev *imon_init_rdev(struct imon_context *ictx) sizeof(ictx->phys_rdev)); strlcat(ictx->phys_rdev, "/input0", sizeof(ictx->phys_rdev)); - rdev->name = ictx->name_rdev; - rdev->phys = ictx->phys_rdev; - usb_to_input_id(ictx->usbdev_intf0, &rdev->id); + rdev->input_name = ictx->name_rdev; + rdev->input_phys = ictx->phys_rdev; + usb_to_input_id(ictx->usbdev_intf0, &rdev->input_id); rdev->dev.parent = ictx->dev; - rdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); - input_set_drvdata(rdev, ictx); - props->priv = ictx; - props->driver_type = RC_DRIVER_SCANCODE; - props->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6; /* iMON PAD or MCE */ - props->change_protocol = imon_ir_change_protocol; - ictx->props = props; + rdev->priv = ictx; + rdev->driver_type = RC_DRIVER_SCANCODE; + rdev->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6; /* iMON PAD or MCE */ + rdev->change_protocol = imon_ir_change_protocol; + rdev->driver_name = MOD_NAME; + if (ictx->ir_type == IR_TYPE_RC6) + rdev->map_name = RC_MAP_IMON_MCE; + else + rdev->map_name = RC_MAP_IMON_PAD; /* Enable front-panel buttons and/or knobs */ memcpy(ictx->usb_tx_buf, &fp_packet, sizeof(fp_packet)); @@ -1858,12 +1856,7 @@ static struct input_dev *imon_init_rdev(struct imon_context *ictx) imon_set_display_type(ictx); - if (ictx->ir_type == IR_TYPE_RC6) - ir_codes = RC_MAP_IMON_MCE; - else - ir_codes = RC_MAP_IMON_PAD; - - ret = ir_input_register(rdev, ir_codes, props, MOD_NAME); + ret = rc_register_device(rdev); if (ret < 0) { dev_err(ictx->dev, "remote input dev register failed\n"); goto out; @@ -1872,8 +1865,7 @@ static struct input_dev *imon_init_rdev(struct imon_context *ictx) return rdev; out: - kfree(props); - input_free_device(rdev); + rc_free_device(rdev); return NULL; } @@ -2144,7 +2136,7 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf) return ictx; urb_submit_failed: - ir_input_unregister(ictx->rdev); + rc_unregister_device(ictx->rdev); rdev_setup_failed: input_unregister_device(ictx->idev); idev_setup_failed: @@ -2371,7 +2363,7 @@ static void __devexit imon_disconnect(struct usb_interface *interface) ictx->dev_present_intf0 = false; usb_kill_urb(ictx->rx_urb_intf0); input_unregister_device(ictx->idev); - ir_input_unregister(ictx->rdev); + rc_unregister_device(ictx->rdev); if (ictx->display_supported) { if (ictx->display_type == IMON_DISPLAY_TYPE_LCD) usb_deregister_dev(interface, &imon_lcd_class); diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c index d83a5f6..cfe0e70 100644 --- a/drivers/media/rc/ir-jvc-decoder.c +++ b/drivers/media/rc/ir-jvc-decoder.c @@ -37,17 +37,16 @@ enum jvc_state { /** * ir_jvc_decode() - Decode one JVC pulse or space - * @input_dev: the struct input_dev descriptor of the device + * @dev: the struct rc_dev descriptor of the device * @duration: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ -static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev) +static int ir_jvc_decode(struct rc_dev *dev, struct ir_raw_event ev) { - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct jvc_dec *data = &ir_dev->raw->jvc; + struct jvc_dec *data = &dev->raw->jvc; - if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC)) + if (!(dev->raw->enabled_protocols & IR_TYPE_JVC)) return 0; if (!is_timing_event(ev)) { @@ -140,12 +139,12 @@ again: scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) | (bitrev8((data->bits >> 0) & 0xff) << 0); IR_dprintk(1, "JVC scancode 0x%04x\n", scancode); - ir_keydown(input_dev, scancode, data->toggle); + ir_keydown(dev, scancode, data->toggle); data->first = false; data->old_bits = data->bits; } else if (data->bits == data->old_bits) { IR_dprintk(1, "JVC repeat\n"); - ir_repeat(input_dev); + ir_repeat(dev); } else { IR_dprintk(1, "JVC invalid repeat msg\n"); break; diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index 9345995d..ceabea6 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -24,21 +24,20 @@ /** * ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the * lircd userspace daemon for decoding. - * @input_dev: the struct input_dev descriptor of the device + * @input_dev: the struct rc_dev descriptor of the device * @duration: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the lirc interfaces aren't wired up. */ -static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) +static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) { - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct lirc_codec *lirc = &ir_dev->raw->lirc; + struct lirc_codec *lirc = &dev->raw->lirc; int sample; - if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC)) + if (!(dev->raw->enabled_protocols & IR_TYPE_LIRC)) return 0; - if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf) + if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf) return -EINVAL; /* Packet start */ @@ -79,7 +78,7 @@ static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) (u64)LIRC_VALUE_MASK); gap_sample = LIRC_SPACE(lirc->gap_duration); - lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, + lirc_buffer_write(dev->raw->lirc.drv->rbuf, (unsigned char *) &gap_sample); lirc->gap = false; } @@ -88,9 +87,9 @@ static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) LIRC_SPACE(ev.duration / 1000); } - lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, + lirc_buffer_write(dev->raw->lirc.drv->rbuf, (unsigned char *) &sample); - wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll); + wake_up(&dev->raw->lirc.drv->rbuf->wait_poll); return 0; } @@ -99,7 +98,7 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf, size_t n, loff_t *ppos) { struct lirc_codec *lirc; - struct ir_input_dev *ir_dev; + struct rc_dev *dev; int *txbuf; /* buffer with values to transmit */ int ret = 0, count; @@ -118,14 +117,14 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf, if (IS_ERR(txbuf)) return PTR_ERR(txbuf); - ir_dev = lirc->ir_dev; - if (!ir_dev) { + dev = lirc->dev; + if (!dev) { ret = -EFAULT; goto out; } - if (ir_dev->props && ir_dev->props->tx_ir) - ret = ir_dev->props->tx_ir(ir_dev->props->priv, txbuf, (u32)n); + if (dev->tx_ir) + ret = dev->tx_ir(dev, txbuf, (u32)n); out: kfree(txbuf); @@ -136,21 +135,18 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long __user arg) { struct lirc_codec *lirc; - struct ir_input_dev *ir_dev; + struct rc_dev *dev; int ret = 0; - void *drv_data; __u32 val = 0, tmp; lirc = lirc_get_pdata(filep); if (!lirc) return -EFAULT; - ir_dev = lirc->ir_dev; - if (!ir_dev || !ir_dev->props || !ir_dev->props->priv) + dev = lirc->dev; + if (!dev) return -EFAULT; - drv_data = ir_dev->props->priv; - if (_IOC_DIR(cmd) & _IOC_WRITE) { ret = get_user(val, (__u32 *)arg); if (ret) @@ -171,84 +167,85 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, /* TX settings */ case LIRC_SET_TRANSMITTER_MASK: - if (!ir_dev->props->s_tx_mask) + if (!dev->s_tx_mask) return -EINVAL; - return ir_dev->props->s_tx_mask(drv_data, val); + return dev->s_tx_mask(dev, val); case LIRC_SET_SEND_CARRIER: - if (!ir_dev->props->s_tx_carrier) + if (!dev->s_tx_carrier) return -EINVAL; - return ir_dev->props->s_tx_carrier(drv_data, val); + return dev->s_tx_carrier(dev, val); case LIRC_SET_SEND_DUTY_CYCLE: - if (!ir_dev->props->s_tx_duty_cycle) + if (!dev->s_tx_duty_cycle) return -ENOSYS; if (val <= 0 || val >= 100) return -EINVAL; - return ir_dev->props->s_tx_duty_cycle(drv_data, val); + return dev->s_tx_duty_cycle(dev, val); /* RX settings */ case LIRC_SET_REC_CARRIER: - if (!ir_dev->props->s_rx_carrier_range) + if (!dev->s_rx_carrier_range) return -ENOSYS; if (val <= 0) return -EINVAL; - return ir_dev->props->s_rx_carrier_range(drv_data, - ir_dev->raw->lirc.carrier_low, val); + return dev->s_rx_carrier_range(dev, + dev->raw->lirc.carrier_low, + val); case LIRC_SET_REC_CARRIER_RANGE: if (val <= 0) return -EINVAL; - ir_dev->raw->lirc.carrier_low = val; + dev->raw->lirc.carrier_low = val; return 0; case LIRC_GET_REC_RESOLUTION: - val = ir_dev->props->rx_resolution; + val = dev->rx_resolution; break; case LIRC_SET_WIDEBAND_RECEIVER: - if (!ir_dev->props->s_learning_mode) + if (!dev->s_learning_mode) return -ENOSYS; - return ir_dev->props->s_learning_mode(drv_data, !!val); + return dev->s_learning_mode(dev, !!val); case LIRC_SET_MEASURE_CARRIER_MODE: - if (!ir_dev->props->s_carrier_report) + if (!dev->s_carrier_report) return -ENOSYS; - return ir_dev->props->s_carrier_report(drv_data, !!val); + return dev->s_carrier_report(dev, !!val); /* Generic timeout support */ case LIRC_GET_MIN_TIMEOUT: - if (!ir_dev->props->max_timeout) + if (!dev->max_timeout) return -ENOSYS; - val = ir_dev->props->min_timeout / 1000; + val = dev->min_timeout / 1000; break; case LIRC_GET_MAX_TIMEOUT: - if (!ir_dev->props->max_timeout) + if (!dev->max_timeout) return -ENOSYS; - val = ir_dev->props->max_timeout / 1000; + val = dev->max_timeout / 1000; break; case LIRC_SET_REC_TIMEOUT: - if (!ir_dev->props->max_timeout) + if (!dev->max_timeout) return -ENOSYS; tmp = val * 1000; - if (tmp < ir_dev->props->min_timeout || - tmp > ir_dev->props->max_timeout) + if (tmp < dev->min_timeout || + tmp > dev->max_timeout) return -EINVAL; - ir_dev->props->timeout = tmp; + dev->timeout = tmp; break; case LIRC_SET_REC_TIMEOUT_REPORTS: @@ -289,9 +286,8 @@ static struct file_operations lirc_fops = { .llseek = no_llseek, }; -static int ir_lirc_register(struct input_dev *input_dev) +static int ir_lirc_register(struct rc_dev *dev) { - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); struct lirc_driver *drv; struct lirc_buffer *rbuf; int rc = -ENOMEM; @@ -310,44 +306,40 @@ static int ir_lirc_register(struct input_dev *input_dev) goto rbuf_init_failed; features = LIRC_CAN_REC_MODE2; - if (ir_dev->props->tx_ir) { - + if (dev->tx_ir) { features |= LIRC_CAN_SEND_PULSE; - if (ir_dev->props->s_tx_mask) + if (dev->s_tx_mask) features |= LIRC_CAN_SET_TRANSMITTER_MASK; - if (ir_dev->props->s_tx_carrier) + if (dev->s_tx_carrier) features |= LIRC_CAN_SET_SEND_CARRIER; - - if (ir_dev->props->s_tx_duty_cycle) + if (dev->s_tx_duty_cycle) features |= LIRC_CAN_SET_SEND_DUTY_CYCLE; } - if (ir_dev->props->s_rx_carrier_range) + if (dev->s_rx_carrier_range) features |= LIRC_CAN_SET_REC_CARRIER | LIRC_CAN_SET_REC_CARRIER_RANGE; - if (ir_dev->props->s_learning_mode) + if (dev->s_learning_mode) features |= LIRC_CAN_USE_WIDEBAND_RECEIVER; - if (ir_dev->props->s_carrier_report) + if (dev->s_carrier_report) features |= LIRC_CAN_MEASURE_CARRIER; - - if (ir_dev->props->max_timeout) + if (dev->max_timeout) features |= LIRC_CAN_SET_REC_TIMEOUT; - snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", - ir_dev->driver_name); + dev->driver_name); drv->minor = -1; drv->features = features; - drv->data = &ir_dev->raw->lirc; + drv->data = &dev->raw->lirc; drv->rbuf = rbuf; drv->set_use_inc = &ir_lirc_open; drv->set_use_dec = &ir_lirc_close; drv->code_length = sizeof(struct ir_raw_event) * 8; drv->fops = &lirc_fops; - drv->dev = &ir_dev->dev; + drv->dev = &dev->dev; drv->owner = THIS_MODULE; drv->minor = lirc_register_driver(drv); @@ -356,8 +348,8 @@ static int ir_lirc_register(struct input_dev *input_dev) goto lirc_register_failed; } - ir_dev->raw->lirc.drv = drv; - ir_dev->raw->lirc.ir_dev = ir_dev; + dev->raw->lirc.drv = drv; + dev->raw->lirc.dev = dev; return 0; lirc_register_failed: @@ -369,10 +361,9 @@ rbuf_alloc_failed: return rc; } -static int ir_lirc_unregister(struct input_dev *input_dev) +static int ir_lirc_unregister(struct rc_dev *dev) { - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct lirc_codec *lirc = &ir_dev->raw->lirc; + struct lirc_codec *lirc = &dev->raw->lirc; lirc_unregister_driver(lirc->drv->minor); lirc_buffer_free(lirc->drv->rbuf); diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c index cad4e99..8ff157a 100644 --- a/drivers/media/rc/ir-nec-decoder.c +++ b/drivers/media/rc/ir-nec-decoder.c @@ -39,19 +39,18 @@ enum nec_state { /** * ir_nec_decode() - Decode one NEC pulse or space - * @input_dev: the struct input_dev descriptor of the device + * @dev: the struct rc_dev descriptor of the device * @duration: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ -static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) +static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) { - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct nec_dec *data = &ir_dev->raw->nec; + struct nec_dec *data = &dev->raw->nec; u32 scancode; u8 address, not_address, command, not_command; - if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC)) + if (!(dev->raw->enabled_protocols & IR_TYPE_NEC)) return 0; if (!is_timing_event(ev)) { @@ -89,7 +88,7 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) data->state = STATE_BIT_PULSE; return 0; } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) { - ir_repeat(input_dev); + ir_repeat(dev); IR_dprintk(1, "Repeat last key\n"); data->state = STATE_TRAILER_PULSE; return 0; @@ -115,7 +114,7 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2)) { IR_dprintk(1, "Repeat last key\n"); - ir_repeat(input_dev); + ir_repeat(dev); data->state = STATE_INACTIVE; return 0; @@ -179,7 +178,7 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) if (data->is_nec_x) data->necx_repeat = true; - ir_keydown(input_dev, scancode, 0); + ir_keydown(dev, scancode, 0); data->state = STATE_INACTIVE; return 0; } diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c index c07f6e0..dae6f9a 100644 --- a/drivers/media/rc/ir-rc5-decoder.c +++ b/drivers/media/rc/ir-rc5-decoder.c @@ -40,19 +40,18 @@ enum rc5_state { /** * ir_rc5_decode() - Decode one RC-5 pulse or space - * @input_dev: the struct input_dev descriptor of the device + * @dev: the struct rc_dev descriptor of the device * @ev: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ -static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev) +static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev) { - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct rc5_dec *data = &ir_dev->raw->rc5; + struct rc5_dec *data = &dev->raw->rc5; u8 toggle; u32 scancode; - if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5)) + if (!(dev->raw->enabled_protocols & IR_TYPE_RC5)) return 0; if (!is_timing_event(ev)) { @@ -96,7 +95,7 @@ again: return 0; case STATE_BIT_END: - if (!is_transition(&ev, &ir_dev->raw->prev_ev)) + if (!is_transition(&ev, &dev->raw->prev_ev)) break; if (data->count == data->wanted_bits) @@ -151,7 +150,7 @@ again: scancode, toggle); } - ir_keydown(input_dev, scancode, toggle); + ir_keydown(dev, scancode, toggle); data->state = STATE_INACTIVE; return 0; } diff --git a/drivers/media/rc/ir-rc5-sz-decoder.c b/drivers/media/rc/ir-rc5-sz-decoder.c index 0c3b6eb..d8a53c0 100644 --- a/drivers/media/rc/ir-rc5-sz-decoder.c +++ b/drivers/media/rc/ir-rc5-sz-decoder.c @@ -36,19 +36,18 @@ enum rc5_sz_state { /** * ir_rc5_sz_decode() - Decode one RC-5 Streamzap pulse or space - * @input_dev: the struct input_dev descriptor of the device + * @dev: the struct rc_dev descriptor of the device * @ev: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ -static int ir_rc5_sz_decode(struct input_dev *input_dev, struct ir_raw_event ev) +static int ir_rc5_sz_decode(struct rc_dev *dev, struct ir_raw_event ev) { - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct rc5_sz_dec *data = &ir_dev->raw->rc5_sz; + struct rc5_sz_dec *data = &dev->raw->rc5_sz; u8 toggle, command, system; u32 scancode; - if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5_SZ)) + if (!(dev->raw->enabled_protocols & IR_TYPE_RC5_SZ)) return 0; if (!is_timing_event(ev)) { @@ -91,7 +90,7 @@ again: return 0; case STATE_BIT_END: - if (!is_transition(&ev, &ir_dev->raw->prev_ev)) + if (!is_transition(&ev, &dev->raw->prev_ev)) break; if (data->count == data->wanted_bits) @@ -115,7 +114,7 @@ again: IR_dprintk(1, "RC5-sz scancode 0x%04x (toggle: %u)\n", scancode, toggle); - ir_keydown(input_dev, scancode, toggle); + ir_keydown(dev, scancode, toggle); data->state = STATE_INACTIVE; return 0; } diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c index 48e82be..2435bbd 100644 --- a/drivers/media/rc/ir-rc6-decoder.c +++ b/drivers/media/rc/ir-rc6-decoder.c @@ -70,19 +70,18 @@ static enum rc6_mode rc6_mode(struct rc6_dec *data) /** * ir_rc6_decode() - Decode one RC6 pulse or space - * @input_dev: the struct input_dev descriptor of the device + * @dev: the struct rc_dev descriptor of the device * @ev: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ -static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev) +static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev) { - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct rc6_dec *data = &ir_dev->raw->rc6; + struct rc6_dec *data = &dev->raw->rc6; u32 scancode; u8 toggle; - if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6)) + if (!(dev->raw->enabled_protocols & IR_TYPE_RC6)) return 0; if (!is_timing_event(ev)) { @@ -139,7 +138,7 @@ again: return 0; case STATE_HEADER_BIT_END: - if (!is_transition(&ev, &ir_dev->raw->prev_ev)) + if (!is_transition(&ev, &dev->raw->prev_ev)) break; if (data->count == RC6_HEADER_NBITS) @@ -159,7 +158,7 @@ again: return 0; case STATE_TOGGLE_END: - if (!is_transition(&ev, &ir_dev->raw->prev_ev) || + if (!is_transition(&ev, &dev->raw->prev_ev) || !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2)) break; @@ -204,7 +203,7 @@ again: return 0; case STATE_BODY_BIT_END: - if (!is_transition(&ev, &ir_dev->raw->prev_ev)) + if (!is_transition(&ev, &dev->raw->prev_ev)) break; if (data->count == data->wanted_bits) @@ -243,7 +242,7 @@ again: goto out; } - ir_keydown(input_dev, scancode, toggle); + ir_keydown(dev, scancode, toggle); data->state = STATE_INACTIVE; return 0; } diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c index 0a5cadb..3138520 100644 --- a/drivers/media/rc/ir-sony-decoder.c +++ b/drivers/media/rc/ir-sony-decoder.c @@ -33,19 +33,18 @@ enum sony_state { /** * ir_sony_decode() - Decode one Sony pulse or space - * @input_dev: the struct input_dev descriptor of the device + * @dev: the struct rc_dev descriptor of the device * @ev: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ -static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev) +static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev) { - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct sony_dec *data = &ir_dev->raw->sony; + struct sony_dec *data = &dev->raw->sony; u32 scancode; u8 device, subdevice, function; - if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY)) + if (!(dev->raw->enabled_protocols & IR_TYPE_SONY)) return 0; if (!is_timing_event(ev)) { @@ -144,7 +143,7 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev) scancode = device << 16 | subdevice << 8 | function; IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode); - ir_keydown(input_dev, scancode, 0); + ir_keydown(dev, scancode, 0); data->state = STATE_INACTIVE; return 0; } diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 392ca24..539bec2 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -317,7 +316,7 @@ static struct usb_device_id mceusb_dev_table[] = { /* data structure for each usb transceiver */ struct mceusb_dev { /* ir-core bits */ - struct ir_dev_props *props; + struct rc_dev *rc; /* optional features we can enable */ bool carrier_report_enabled; @@ -325,7 +324,6 @@ struct mceusb_dev { /* core device bits */ struct device *dev; - struct input_dev *idev; /* usb */ struct usb_device *usbdev; @@ -663,9 +661,9 @@ static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size) } /* Send data out the IR blaster port(s) */ -static int mceusb_tx_ir(void *priv, int *txbuf, u32 n) +static int mceusb_tx_ir(struct rc_dev *dev, int *txbuf, u32 n) { - struct mceusb_dev *ir = priv; + struct mceusb_dev *ir = dev->priv; int i, ret = 0; int count, cmdcount = 0; unsigned char *cmdbuf; /* MCE command buffer */ @@ -749,9 +747,9 @@ out: } /* Sets active IR outputs -- mce devices typically have two */ -static int mceusb_set_tx_mask(void *priv, u32 mask) +static int mceusb_set_tx_mask(struct rc_dev *dev, u32 mask) { - struct mceusb_dev *ir = priv; + struct mceusb_dev *ir = dev->priv; if (ir->flags.tx_mask_normal) ir->tx_mask = mask; @@ -763,9 +761,9 @@ static int mceusb_set_tx_mask(void *priv, u32 mask) } /* Sets the send carrier frequency and mode */ -static int mceusb_set_tx_carrier(void *priv, u32 carrier) +static int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier) { - struct mceusb_dev *ir = priv; + struct mceusb_dev *ir = dev->priv; int clk = 10000000; int prescaler = 0, divisor = 0; unsigned char cmdbuf[4] = { MCE_COMMAND_HEADER, @@ -819,7 +817,7 @@ static void mceusb_handle_command(struct mceusb_dev *ir, int index) switch (ir->buf_in[index]) { /* 2-byte return value commands */ case MCE_CMD_S_TIMEOUT: - ir->props->timeout = MS_TO_NS((hi << 8 | lo) / 2); + ir->rc->timeout = MS_TO_NS((hi << 8 | lo) / 2); break; /* 1-byte return value commands */ @@ -866,7 +864,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) rawir.pulse ? "pulse" : "space", rawir.duration); - ir_raw_event_store_with_filter(ir->idev, &rawir); + ir_raw_event_store_with_filter(ir->rc, &rawir); break; case CMD_DATA: ir->rem--; @@ -893,7 +891,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) ir->parser_state = CMD_HEADER; } dev_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n"); - ir_raw_event_handle(ir->idev); + ir_raw_event_handle(ir->rc); } static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs) @@ -1035,72 +1033,54 @@ static void mceusb_get_parameters(struct mceusb_dev *ir) mce_sync_in(ir, NULL, maxp); } -static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir) +static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir) { - struct input_dev *idev; - struct ir_dev_props *props; struct device *dev = ir->dev; - const char *rc_map = RC_MAP_RC6_MCE; - const char *name = "Media Center Ed. eHome Infrared Remote Transceiver"; - int ret = -ENODEV; - - idev = input_allocate_device(); - if (!idev) { - dev_err(dev, "remote input dev allocation failed\n"); - goto idev_alloc_failed; - } + struct rc_dev *rc; + int ret; - ret = -ENOMEM; - props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); - if (!props) { - dev_err(dev, "remote ir dev props allocation failed\n"); - goto props_alloc_failed; + rc = rc_allocate_device(); + if (!rc) { + dev_err(dev, "remote dev allocation failed\n"); + goto out; } - if (mceusb_model[ir->model].name) - name = mceusb_model[ir->model].name; - snprintf(ir->name, sizeof(ir->name), "%s (%04x:%04x)", - name, + mceusb_model[ir->model].name ? + mceusb_model[ir->model].name : + "Media Center Ed. eHome Infrared Remote Transceiver", le16_to_cpu(ir->usbdev->descriptor.idVendor), le16_to_cpu(ir->usbdev->descriptor.idProduct)); - idev->name = ir->name; usb_make_path(ir->usbdev, ir->phys, sizeof(ir->phys)); - strlcat(ir->phys, "/input0", sizeof(ir->phys)); - idev->phys = ir->phys; - props->priv = ir; - props->driver_type = RC_DRIVER_IR_RAW; - props->allowed_protos = IR_TYPE_ALL; - props->timeout = MS_TO_NS(1000); + rc->input_name = ir->name; + rc->input_phys = ir->phys; + usb_to_input_id(ir->usbdev, &rc->input_id); + rc->dev.parent = dev; + rc->priv = ir; + rc->driver_type = RC_DRIVER_IR_RAW; + rc->allowed_protos = IR_TYPE_ALL; + rc->timeout = MS_TO_NS(1000); if (!ir->flags.no_tx) { - props->s_tx_mask = mceusb_set_tx_mask; - props->s_tx_carrier = mceusb_set_tx_carrier; - props->tx_ir = mceusb_tx_ir; + rc->s_tx_mask = mceusb_set_tx_mask; + rc->s_tx_carrier = mceusb_set_tx_carrier; + rc->tx_ir = mceusb_tx_ir; } + rc->driver_name = DRIVER_NAME; + rc->map_name = mceusb_model[ir->model].rc_map ? + mceusb_model[ir->model].rc_map : RC_MAP_RC6_MCE; - ir->props = props; - - usb_to_input_id(ir->usbdev, &idev->id); - idev->dev.parent = ir->dev; - - if (mceusb_model[ir->model].rc_map) - rc_map = mceusb_model[ir->model].rc_map; - - ret = ir_input_register(idev, rc_map, props, DRIVER_NAME); + ret = rc_register_device(rc); if (ret < 0) { - dev_err(dev, "remote input device register failed\n"); - goto irdev_failed; + dev_err(dev, "remote dev registration failed\n"); + goto out; } - return idev; + return rc; -irdev_failed: - kfree(props); -props_alloc_failed: - input_free_device(idev); -idev_alloc_failed: +out: + rc_free_device(rc); return NULL; } @@ -1212,9 +1192,9 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf, snprintf(name + strlen(name), sizeof(name) - strlen(name), " %s", buf); - ir->idev = mceusb_init_input_dev(ir); - if (!ir->idev) - goto input_dev_fail; + ir->rc = mceusb_init_rc_dev(ir); + if (!ir->rc) + goto rc_dev_fail; /* flush buffers on the device */ mce_sync_in(ir, NULL, maxp); @@ -1235,7 +1215,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf, mceusb_get_parameters(ir); if (!ir->flags.no_tx) - mceusb_set_tx_mask(ir, MCE_DEFAULT_TX_MASK); + mceusb_set_tx_mask(ir->rc, MCE_DEFAULT_TX_MASK); usb_set_intfdata(intf, ir); @@ -1245,7 +1225,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf, return 0; /* Error-handling path */ -input_dev_fail: +rc_dev_fail: usb_free_urb(ir->urb_in); urb_in_alloc_fail: usb_free_coherent(dev, maxp, ir->buf_in, ir->dma_in); @@ -1269,7 +1249,7 @@ static void __devexit mceusb_dev_disconnect(struct usb_interface *intf) return; ir->usbdev = NULL; - ir_input_unregister(ir->idev); + rc_unregister_device(ir->rc); usb_kill_urb(ir->urb_in); usb_free_urb(ir->urb_in); usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in); diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index acc729c..0ce328f 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -476,9 +475,9 @@ static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt) * always set CP as 0x81 * set CC by SPEC, CC = 3MHz/carrier - 1 */ -static int nvt_set_tx_carrier(void *data, u32 carrier) +static int nvt_set_tx_carrier(struct rc_dev *dev, u32 carrier) { - struct nvt_dev *nvt = data; + struct nvt_dev *nvt = dev->priv; u16 val; nvt_cir_reg_write(nvt, 1, CIR_CP); @@ -509,9 +508,9 @@ static int nvt_set_tx_carrier(void *data, u32 carrier) * number may larger than TXFCONT (0xff). So in interrupt_handler, it has to * set TXFCONT as 0xff, until buf_count less than 0xff. */ -static int nvt_tx_ir(void *priv, int *txbuf, u32 n) +static int nvt_tx_ir(struct rc_dev *dev, int *txbuf, u32 n) { - struct nvt_dev *nvt = priv; + struct nvt_dev *nvt = dev->priv; unsigned long flags; size_t cur_count; unsigned int i; @@ -948,9 +947,9 @@ static void nvt_disable_cir(struct nvt_dev *nvt) nvt_efm_disable(nvt); } -static int nvt_open(void *data) +static int nvt_open(struct rc_dev *dev) { - struct nvt_dev *nvt = (struct nvt_dev *)data; + struct nvt_dev *nvt = dev->priv; unsigned long flags; spin_lock_irqsave(&nvt->nvt_lock, flags); @@ -961,9 +960,9 @@ static int nvt_open(void *data) return 0; } -static void nvt_close(void *data) +static void nvt_close(struct rc_dev *dev) { - struct nvt_dev *nvt = (struct nvt_dev *)data; + struct nvt_dev *nvt = dev->priv; unsigned long flags; spin_lock_irqsave(&nvt->nvt_lock, flags); @@ -975,21 +974,16 @@ static void nvt_close(void *data) /* Allocate memory, probe hardware, and initialize everything */ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) { - struct nvt_dev *nvt = NULL; - struct input_dev *rdev = NULL; - struct ir_dev_props *props = NULL; + struct nvt_dev *nvt; + struct rc_dev *rdev; int ret = -ENOMEM; nvt = kzalloc(sizeof(struct nvt_dev), GFP_KERNEL); if (!nvt) return ret; - props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); - if (!props) - goto failure; - /* input device for IR remote (and tx) */ - rdev = input_allocate_device(); + rdev = rc_allocate_device(); if (!rdev) goto failure; @@ -1063,41 +1057,38 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) nvt_cir_regs_init(nvt); nvt_cir_wake_regs_init(nvt); - /* Set up ir-core props */ - props->priv = nvt; - props->driver_type = RC_DRIVER_IR_RAW; - props->allowed_protos = IR_TYPE_ALL; - props->open = nvt_open; - props->close = nvt_close; + /* Set up the rc device */ + rdev->priv = nvt; + rdev->driver_type = RC_DRIVER_IR_RAW; + rdev->allowed_protos = IR_TYPE_ALL; + rdev->open = nvt_open; + rdev->close = nvt_close; + rdev->tx_ir = nvt_tx_ir; + rdev->s_tx_carrier = nvt_set_tx_carrier; + rdev->input_name = "Nuvoton w836x7hg Infrared Remote Transceiver"; + rdev->input_id.bustype = BUS_HOST; + rdev->input_id.vendor = PCI_VENDOR_ID_WINBOND2; + rdev->input_id.product = nvt->chip_major; + rdev->input_id.version = nvt->chip_minor; + rdev->driver_name = NVT_DRIVER_NAME; + rdev->map_name = RC_MAP_RC6_MCE; #if 0 - props->min_timeout = XYZ; - props->max_timeout = XYZ; - props->timeout = XYZ; + rdev->min_timeout = XYZ; + rdev->max_timeout = XYZ; + rdev->timeout = XYZ; /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ - props->rx_resolution = XYZ; - + rdev->rx_resolution = XYZ; /* tx bits */ - props->tx_resolution = XYZ; + rdev->tx_resolution = XYZ; #endif - props->tx_ir = nvt_tx_ir; - props->s_tx_carrier = nvt_set_tx_carrier; - - rdev->name = "Nuvoton w836x7hg Infrared Remote Transceiver"; - rdev->id.bustype = BUS_HOST; - rdev->id.vendor = PCI_VENDOR_ID_WINBOND2; - rdev->id.product = nvt->chip_major; - rdev->id.version = nvt->chip_minor; - - nvt->props = props; - nvt->rdev = rdev; - device_set_wakeup_capable(&pdev->dev, 1); - device_set_wakeup_enable(&pdev->dev, 1); - - ret = ir_input_register(rdev, RC_MAP_RC6_MCE, props, NVT_DRIVER_NAME); + ret = rc_register_device(rdev); if (ret) goto failure; + device_set_wakeup_capable(&pdev->dev, 1); + device_set_wakeup_enable(&pdev->dev, 1); + nvt->rdev = rdev; nvt_pr(KERN_NOTICE, "driver has been successfully loaded\n"); if (debug) { cir_dump_regs(nvt); @@ -1117,8 +1108,7 @@ failure: if (nvt->cir_wake_addr) release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH); - input_free_device(rdev); - kfree(props); + rc_free_device(rdev); kfree(nvt); return ret; @@ -1143,9 +1133,8 @@ static void __devexit nvt_remove(struct pnp_dev *pdev) release_region(nvt->cir_addr, CIR_IOREG_LENGTH); release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH); - ir_input_unregister(nvt->rdev); + rc_unregister_device(nvt->rdev); - kfree(nvt->props); kfree(nvt); } diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h index 62dc530..1df8235 100644 --- a/drivers/media/rc/nuvoton-cir.h +++ b/drivers/media/rc/nuvoton-cir.h @@ -66,8 +66,7 @@ static int debug; struct nvt_dev { struct pnp_dev *pdev; - struct input_dev *rdev; - struct ir_dev_props *props; + struct rc_dev *rdev; struct ir_raw_event rawir; spinlock_t nvt_lock; diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index 4be0757..3616c32 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h @@ -24,11 +24,11 @@ struct ir_raw_handler { struct list_head list; u64 protocols; /* which are handled by this handler */ - int (*decode)(struct input_dev *input_dev, struct ir_raw_event event); + int (*decode)(struct rc_dev *dev, struct ir_raw_event event); /* These two should only be used by the lirc decoder */ - int (*raw_register)(struct input_dev *input_dev); - int (*raw_unregister)(struct input_dev *input_dev); + int (*raw_register)(struct rc_dev *dev); + int (*raw_unregister)(struct rc_dev *dev); }; struct ir_raw_event_ctrl { @@ -38,7 +38,7 @@ struct ir_raw_event_ctrl { struct kfifo kfifo; /* fifo for the pulse/space durations */ ktime_t last_event; /* when last event occurred */ enum raw_event_type last_type; /* last event type */ - struct input_dev *input_dev; /* pointer to the parent input_dev */ + struct rc_dev *dev; /* pointer to the parent rc_dev */ u64 enabled_protocols; /* enabled raw protocol decoders */ /* raw decoder state follows */ @@ -85,7 +85,7 @@ struct ir_raw_event_ctrl { unsigned wanted_bits; } rc5_sz; struct lirc_codec { - struct ir_input_dev *ir_dev; + struct rc_dev *dev; struct lirc_driver *drv; int carrier_low; @@ -131,11 +131,11 @@ static inline bool is_timing_event(struct ir_raw_event ev) #define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space") /* - * Routines from ir-raw-event.c to be used internally and by decoders + * Routines from rc-raw.c to be used internally and by decoders */ u64 ir_raw_get_allowed_protocols(void); -int ir_raw_event_register(struct input_dev *input_dev); -void ir_raw_event_unregister(struct input_dev *input_dev); +int ir_raw_event_register(struct rc_dev *dev); +void ir_raw_event_unregister(struct rc_dev *dev); int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); void ir_raw_init(void); diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 67a6bd5..5b67eea 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -20,11 +20,6 @@ #include #include "rc-core-priv.h" -#define IRRCV_NUM_DEVICES 256 - -/* bit array to represent IR sysfs device number */ -static unsigned long ir_core_dev_number; - /* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */ #define IR_TAB_MIN_SIZE 256 #define IR_TAB_MAX_SIZE 8192 @@ -36,12 +31,6 @@ static unsigned long ir_core_dev_number; static LIST_HEAD(rc_map_list); static DEFINE_SPINLOCK(rc_map_lock); -/* Forward declarations */ -static int ir_register_class(struct input_dev *input_dev); -static void ir_unregister_class(struct input_dev *input_dev); -static int ir_register_input(struct input_dev *input_dev); - - static struct rc_keymap *seek_rc_map(const char *name) { struct rc_keymap *map = NULL; @@ -127,7 +116,7 @@ static struct rc_keymap empty_map = { * @return: zero on success or a negative error code * * This routine will initialize the ir_scancode_table and will allocate - * memory to hold at least the specified number elements. + * memory to hold at least the specified number of elements. */ static int ir_create_table(struct ir_scancode_table *rc_tab, const char *name, u64 ir_type, size_t size) @@ -209,16 +198,16 @@ static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags) /** * ir_update_mapping() - set a keycode in the scancode->keycode table - * @dev: the struct input_dev device descriptor + * @dev: the struct rc_dev device descriptor * @rc_tab: scancode table to be adjusted * @index: index of the mapping that needs to be updated * @keycode: the desired keycode * @return: previous keycode assigned to the mapping * - * This routine is used to update scancode->keycopde mapping at given + * This routine is used to update scancode->keycode mapping at given * position. */ -static unsigned int ir_update_mapping(struct input_dev *dev, +static unsigned int ir_update_mapping(struct rc_dev *dev, struct ir_scancode_table *rc_tab, unsigned int index, unsigned int new_keycode) @@ -239,16 +228,16 @@ static unsigned int ir_update_mapping(struct input_dev *dev, old_keycode == KEY_RESERVED ? "New" : "Replacing", rc_tab->scan[index].scancode, new_keycode); rc_tab->scan[index].keycode = new_keycode; - __set_bit(new_keycode, dev->keybit); + __set_bit(new_keycode, dev->input_dev->keybit); } if (old_keycode != KEY_RESERVED) { /* A previous mapping was updated... */ - __clear_bit(old_keycode, dev->keybit); + __clear_bit(old_keycode, dev->input_dev->keybit); /* ... but another scancode might use the same keycode */ for (i = 0; i < rc_tab->len; i++) { if (rc_tab->scan[i].keycode == old_keycode) { - __set_bit(old_keycode, dev->keybit); + __set_bit(old_keycode, dev->input_dev->keybit); break; } } @@ -262,7 +251,7 @@ static unsigned int ir_update_mapping(struct input_dev *dev, /** * ir_establish_scancode() - set a keycode in the scancode->keycode table - * @ir_dev: the struct ir_input_dev device descriptor + * @dev: the struct rc_dev device descriptor * @rc_tab: scancode table to be searched * @scancode: the desired scancode * @resize: controls whether we allowed to resize the table to @@ -274,7 +263,7 @@ static unsigned int ir_update_mapping(struct input_dev *dev, * If scancode is not yet present the routine will allocate a new slot * for it. */ -static unsigned int ir_establish_scancode(struct ir_input_dev *ir_dev, +static unsigned int ir_establish_scancode(struct rc_dev *dev, struct ir_scancode_table *rc_tab, unsigned int scancode, bool resize) @@ -286,10 +275,11 @@ static unsigned int ir_establish_scancode(struct ir_input_dev *ir_dev, * all bits for the complete IR code. In general, they provide only * the command part of the IR code. Yet, as it is possible to replace * the provided IR with another one, it is needed to allow loading - * IR tables from other remotes. So, + * IR tables from other remotes. So, we support specifying a mask to + * indicate the valid bits of the scancodes. */ - if (ir_dev->props && ir_dev->props->scanmask) - scancode &= ir_dev->props->scanmask; + if (dev->scanmask) + scancode &= dev->scanmask; /* First check if we already have a mapping for this ir command */ for (i = 0; i < rc_tab->len; i++) { @@ -320,19 +310,19 @@ static unsigned int ir_establish_scancode(struct ir_input_dev *ir_dev, /** * ir_setkeycode() - set a keycode in the scancode->keycode table - * @dev: the struct input_dev device descriptor + * @idev: the struct input_dev device descriptor * @scancode: the desired scancode * @keycode: result * @return: -EINVAL if the keycode could not be inserted, otherwise zero. * * This routine is used to handle evdev EVIOCSKEY ioctl. */ -static int ir_setkeycode(struct input_dev *dev, +static int ir_setkeycode(struct input_dev *idev, const struct input_keymap_entry *ke, unsigned int *old_keycode) { - struct ir_input_dev *ir_dev = input_get_drvdata(dev); - struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; + struct rc_dev *rdev = input_get_drvdata(idev); + struct ir_scancode_table *rc_tab = &rdev->rc_tab; unsigned int index; unsigned int scancode; int retval; @@ -351,14 +341,14 @@ static int ir_setkeycode(struct input_dev *dev, if (retval) goto out; - index = ir_establish_scancode(ir_dev, rc_tab, scancode, true); + index = ir_establish_scancode(rdev, rc_tab, scancode, true); if (index >= rc_tab->len) { retval = -ENOMEM; goto out; } } - *old_keycode = ir_update_mapping(dev, rc_tab, index, ke->keycode); + *old_keycode = ir_update_mapping(rdev, rc_tab, index, ke->keycode); out: spin_unlock_irqrestore(&rc_tab->lock, flags); @@ -367,22 +357,22 @@ out: /** * ir_setkeytable() - sets several entries in the scancode->keycode table - * @dev: the struct input_dev device descriptor + * @dev: the struct rc_dev device descriptor * @to: the struct ir_scancode_table to copy entries to * @from: the struct ir_scancode_table to copy entries from * @return: -ENOMEM if all keycodes could not be inserted, otherwise zero. * * This routine is used to handle table initialization. */ -static int ir_setkeytable(struct ir_input_dev *ir_dev, +static int ir_setkeytable(struct rc_dev *dev, const struct ir_scancode_table *from) { - struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; + struct ir_scancode_table *rc_tab = &dev->rc_tab; unsigned int i, index; int rc; - rc = ir_create_table(&ir_dev->rc_tab, - from->name, from->ir_type, from->size); + rc = ir_create_table(rc_tab, from->name, + from->ir_type, from->size); if (rc) return rc; @@ -390,14 +380,14 @@ static int ir_setkeytable(struct ir_input_dev *ir_dev, rc_tab->size, rc_tab->alloc); for (i = 0; i < from->size; i++) { - index = ir_establish_scancode(ir_dev, rc_tab, + index = ir_establish_scancode(dev, rc_tab, from->scan[i].scancode, false); if (index >= rc_tab->len) { rc = -ENOMEM; break; } - ir_update_mapping(ir_dev->input_dev, rc_tab, index, + ir_update_mapping(dev, rc_tab, index, from->scan[i].keycode); } @@ -409,7 +399,7 @@ static int ir_setkeytable(struct ir_input_dev *ir_dev, /** * ir_lookup_by_scancode() - locate mapping by scancode - * @rc_tab: the &struct ir_scancode_table to search + * @rc_tab: the struct ir_scancode_table to search * @scancode: scancode to look for in the table * @return: index in the table, -1U if not found * @@ -438,18 +428,18 @@ static unsigned int ir_lookup_by_scancode(const struct ir_scancode_table *rc_tab /** * ir_getkeycode() - get a keycode from the scancode->keycode table - * @dev: the struct input_dev device descriptor + * @idev: the struct input_dev device descriptor * @scancode: the desired scancode * @keycode: used to return the keycode, if found, or KEY_RESERVED * @return: always returns zero. * * This routine is used to handle evdev EVIOCGKEY ioctl. */ -static int ir_getkeycode(struct input_dev *dev, +static int ir_getkeycode(struct input_dev *idev, struct input_keymap_entry *ke) { - struct ir_input_dev *ir_dev = input_get_drvdata(dev); - struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; + struct rc_dev *rdev = input_get_drvdata(idev); + struct ir_scancode_table *rc_tab = &rdev->rc_tab; struct ir_scancode *entry; unsigned long flags; unsigned int index; @@ -492,18 +482,17 @@ out: /** * ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode - * @input_dev: the struct input_dev descriptor of the device - * @scancode: the scancode that we're seeking + * @dev: the struct rc_dev descriptor of the device + * @scancode: the scancode to look for + * @return: the corresponding keycode, or KEY_RESERVED * - * This routine is used by the input routines when a key is pressed at the - * IR. The scancode is received and needs to be converted into a keycode. - * If the key is not found, it returns KEY_RESERVED. Otherwise, returns the - * corresponding keycode from the table. + * This routine is used by drivers which need to convert a scancode to a + * keycode. Normally it should not be used since drivers should have no + * interest in keycodes. */ -u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) +u32 ir_g_keycode_from_table(struct rc_dev *dev, u32 scancode) { - struct ir_input_dev *ir_dev = input_get_drvdata(dev); - struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; + struct ir_scancode_table *rc_tab = &dev->rc_tab; unsigned int keycode; unsigned int index; unsigned long flags; @@ -518,7 +507,7 @@ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) if (keycode != KEY_RESERVED) IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", - dev->name, scancode, keycode); + dev->input_name, scancode, keycode); return keycode; } @@ -526,50 +515,49 @@ EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); /** * ir_do_keyup() - internal function to signal the release of a keypress - * @ir: the struct ir_input_dev descriptor of the device + * @dev: the struct rc_dev descriptor of the device * * This function is used internally to release a keypress, it must be * called with keylock held. */ -static void ir_do_keyup(struct ir_input_dev *ir) +static void ir_do_keyup(struct rc_dev *dev) { - if (!ir->keypressed) + if (!dev->keypressed) return; - IR_dprintk(1, "keyup key 0x%04x\n", ir->last_keycode); - input_report_key(ir->input_dev, ir->last_keycode, 0); - input_sync(ir->input_dev); - ir->keypressed = false; + IR_dprintk(1, "keyup key 0x%04x\n", dev->last_keycode); + input_report_key(dev->input_dev, dev->last_keycode, 0); + input_sync(dev->input_dev); + dev->keypressed = false; } /** - * ir_keyup() - generates input event to signal the release of a keypress - * @dev: the struct input_dev descriptor of the device + * ir_keyup() - signals the release of a keypress + * @dev: the struct rc_dev descriptor of the device * * This routine is used to signal that a key has been released on the * remote control. */ -void ir_keyup(struct input_dev *dev) +void ir_keyup(struct rc_dev *dev) { unsigned long flags; - struct ir_input_dev *ir = input_get_drvdata(dev); - spin_lock_irqsave(&ir->keylock, flags); - ir_do_keyup(ir); - spin_unlock_irqrestore(&ir->keylock, flags); + spin_lock_irqsave(&dev->keylock, flags); + ir_do_keyup(dev); + spin_unlock_irqrestore(&dev->keylock, flags); } EXPORT_SYMBOL_GPL(ir_keyup); /** * ir_timer_keyup() - generates a keyup event after a timeout - * @cookie: a pointer to struct ir_input_dev passed to setup_timer() + * @cookie: a pointer to the struct rc_dev for the device * * This routine will generate a keyup event some time after a keydown event * is generated when no further activity has been detected. */ static void ir_timer_keyup(unsigned long cookie) { - struct ir_input_dev *ir = (struct ir_input_dev *)cookie; + struct rc_dev *dev = (struct rc_dev *)cookie; unsigned long flags; /* @@ -582,43 +570,42 @@ static void ir_timer_keyup(unsigned long cookie) * to allow the input subsystem to do its auto-repeat magic or * a keyup event might follow immediately after the keydown. */ - spin_lock_irqsave(&ir->keylock, flags); - if (time_is_before_eq_jiffies(ir->keyup_jiffies)) - ir_do_keyup(ir); - spin_unlock_irqrestore(&ir->keylock, flags); + spin_lock_irqsave(&dev->keylock, flags); + if (time_is_before_eq_jiffies(dev->keyup_jiffies)) + ir_do_keyup(dev); + spin_unlock_irqrestore(&dev->keylock, flags); } /** - * ir_repeat() - notifies the IR core that a key is still pressed - * @dev: the struct input_dev descriptor of the device + * ir_repeat() - signals that a key is still pressed + * @dev: the struct rc_dev descriptor of the device * * This routine is used by IR decoders when a repeat message which does * not include the necessary bits to reproduce the scancode has been * received. */ -void ir_repeat(struct input_dev *dev) +void ir_repeat(struct rc_dev *dev) { unsigned long flags; - struct ir_input_dev *ir = input_get_drvdata(dev); - spin_lock_irqsave(&ir->keylock, flags); + spin_lock_irqsave(&dev->keylock, flags); - input_event(dev, EV_MSC, MSC_SCAN, ir->last_scancode); + input_event(dev->input_dev, EV_MSC, MSC_SCAN, dev->last_scancode); - if (!ir->keypressed) + if (!dev->keypressed) goto out; - ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); - mod_timer(&ir->timer_keyup, ir->keyup_jiffies); + dev->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); + mod_timer(&dev->timer_keyup, dev->keyup_jiffies); out: - spin_unlock_irqrestore(&ir->keylock, flags); + spin_unlock_irqrestore(&dev->keylock, flags); } EXPORT_SYMBOL_GPL(ir_repeat); /** * ir_do_keydown() - internal function to process a keypress - * @dev: the struct input_dev descriptor of the device + * @dev: the struct rc_dev descriptor of the device * @scancode: the scancode of the keypress * @keycode: the keycode of the keypress * @toggle: the toggle value of the keypress @@ -626,231 +613,96 @@ EXPORT_SYMBOL_GPL(ir_repeat); * This function is used internally to register a keypress, it must be * called with keylock held. */ -static void ir_do_keydown(struct input_dev *dev, int scancode, +static void ir_do_keydown(struct rc_dev *dev, int scancode, u32 keycode, u8 toggle) { - struct ir_input_dev *ir = input_get_drvdata(dev); - - input_event(dev, EV_MSC, MSC_SCAN, scancode); + input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode); /* Repeat event? */ - if (ir->keypressed && - ir->last_scancode == scancode && - ir->last_toggle == toggle) + if (dev->keypressed && + dev->last_scancode == scancode && + dev->last_toggle == toggle) return; /* Release old keypress */ - ir_do_keyup(ir); + ir_do_keyup(dev); - ir->last_scancode = scancode; - ir->last_toggle = toggle; - ir->last_keycode = keycode; + dev->last_scancode = scancode; + dev->last_toggle = toggle; + dev->last_keycode = keycode; if (keycode == KEY_RESERVED) return; /* Register a keypress */ - ir->keypressed = true; + dev->keypressed = true; IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", - dev->name, keycode, scancode); - input_report_key(dev, ir->last_keycode, 1); - input_sync(dev); + dev->input_name, keycode, scancode); + input_report_key(dev->input_dev, dev->last_keycode, 1); + input_sync(dev->input_dev); } /** * ir_keydown() - generates input event for a key press - * @dev: the struct input_dev descriptor of the device + * @dev: the struct rc_dev descriptor of the device * @scancode: the scancode that we're seeking * @toggle: the toggle value (protocol dependent, if the protocol doesn't * support toggle values, this should be set to zero) * - * This routine is used by the input routines when a key is pressed at the - * IR. It gets the keycode for a scancode and reports an input event via - * input_report_key(). + * This routine is used to signal that a key has been pressed on the + * remote control. */ -void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) +void ir_keydown(struct rc_dev *dev, int scancode, u8 toggle) { unsigned long flags; - struct ir_input_dev *ir = input_get_drvdata(dev); u32 keycode = ir_g_keycode_from_table(dev, scancode); - spin_lock_irqsave(&ir->keylock, flags); + spin_lock_irqsave(&dev->keylock, flags); ir_do_keydown(dev, scancode, keycode, toggle); - if (ir->keypressed) { - ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); - mod_timer(&ir->timer_keyup, ir->keyup_jiffies); + if (dev->keypressed) { + dev->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); + mod_timer(&dev->timer_keyup, dev->keyup_jiffies); } - spin_unlock_irqrestore(&ir->keylock, flags); + spin_unlock_irqrestore(&dev->keylock, flags); } EXPORT_SYMBOL_GPL(ir_keydown); /** * ir_keydown_notimeout() - generates input event for a key press without * an automatic keyup event at a later time - * @dev: the struct input_dev descriptor of the device + * @dev: the struct rc_dev descriptor of the device * @scancode: the scancode that we're seeking * @toggle: the toggle value (protocol dependent, if the protocol doesn't * support toggle values, this should be set to zero) * - * This routine is used by the input routines when a key is pressed at the - * IR. It gets the keycode for a scancode and reports an input event via - * input_report_key(). The driver must manually call ir_keyup() at a later - * stage. + * This routine is used to signal that a key has been pressed on the + * remote control. The driver must manually call ir_keyup() at a later stage. */ -void ir_keydown_notimeout(struct input_dev *dev, int scancode, u8 toggle) +void ir_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle) { unsigned long flags; - struct ir_input_dev *ir = input_get_drvdata(dev); u32 keycode = ir_g_keycode_from_table(dev, scancode); - spin_lock_irqsave(&ir->keylock, flags); + spin_lock_irqsave(&dev->keylock, flags); ir_do_keydown(dev, scancode, keycode, toggle); - spin_unlock_irqrestore(&ir->keylock, flags); + spin_unlock_irqrestore(&dev->keylock, flags); } EXPORT_SYMBOL_GPL(ir_keydown_notimeout); -static int ir_open(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - - return ir_dev->props->open(ir_dev->props->priv); -} - -static void ir_close(struct input_dev *input_dev) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - - ir_dev->props->close(ir_dev->props->priv); -} - -/** - * __ir_input_register() - sets the IR keycode table and add the handlers - * for keymap table get/set - * @input_dev: the struct input_dev descriptor of the device - * @rc_tab: the struct ir_scancode_table table of scancode/keymap - * - * This routine is used to initialize the input infrastructure - * to work with an IR. - * It will register the input/evdev interface for the device and - * register the syfs code for IR class - */ -int __ir_input_register(struct input_dev *input_dev, - const struct ir_scancode_table *rc_tab, - struct ir_dev_props *props, - const char *driver_name) +static int ir_open(struct input_dev *idev) { - struct ir_input_dev *ir_dev; - int rc; - - if (rc_tab->scan == NULL || !rc_tab->size) - return -EINVAL; - - ir_dev = kzalloc(sizeof(*ir_dev), GFP_KERNEL); - if (!ir_dev) - return -ENOMEM; - - ir_dev->driver_name = kasprintf(GFP_KERNEL, "%s", driver_name); - if (!ir_dev->driver_name) { - rc = -ENOMEM; - goto out_dev; - } - - input_dev->getkeycode_new = ir_getkeycode; - input_dev->setkeycode_new = ir_setkeycode; - input_set_drvdata(input_dev, ir_dev); - ir_dev->input_dev = input_dev; - - spin_lock_init(&ir_dev->rc_tab.lock); - spin_lock_init(&ir_dev->keylock); - setup_timer(&ir_dev->timer_keyup, ir_timer_keyup, (unsigned long)ir_dev); - - if (props) { - ir_dev->props = props; - if (props->open) - input_dev->open = ir_open; - if (props->close) - input_dev->close = ir_close; - } - - set_bit(EV_KEY, input_dev->evbit); - set_bit(EV_REP, input_dev->evbit); - set_bit(EV_MSC, input_dev->evbit); - set_bit(MSC_SCAN, input_dev->mscbit); - - rc = ir_setkeytable(ir_dev, rc_tab); - if (rc) - goto out_name; + struct rc_dev *rdev = input_get_drvdata(idev); - rc = ir_register_class(input_dev); - if (rc < 0) - goto out_table; - - if (ir_dev->props) - if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) { - rc = ir_raw_event_register(input_dev); - if (rc < 0) - goto out_event; - } - - rc = ir_register_input(input_dev); - if (rc < 0) - goto out_event; - - IR_dprintk(1, "Registered input device on %s for %s remote%s.\n", - driver_name, rc_tab->name, - (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ? - " in raw mode" : ""); - - /* - * Default delay of 250ms is too short for some protocols, expecially - * since the timeout is currently set to 250ms. Increase it to 500ms, - * to avoid wrong repetition of the keycodes. - */ - input_dev->rep[REP_DELAY] = 500; - - return 0; - -out_event: - ir_unregister_class(input_dev); -out_table: - ir_free_table(&ir_dev->rc_tab); -out_name: - kfree(ir_dev->driver_name); -out_dev: - kfree(ir_dev); - return rc; + return rdev->open(rdev); } -EXPORT_SYMBOL_GPL(__ir_input_register); - -/** - * ir_input_unregister() - unregisters IR and frees resources - * @input_dev: the struct input_dev descriptor of the device - * This routine is used to free memory and de-register interfaces. - */ -void ir_input_unregister(struct input_dev *input_dev) +static void ir_close(struct input_dev *idev) { - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - - if (!ir_dev) - return; - - IR_dprintk(1, "Freed keycode table\n"); + struct rc_dev *rdev = input_get_drvdata(idev); - del_timer_sync(&ir_dev->timer_keyup); - if (ir_dev->props) - if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) - ir_raw_event_unregister(input_dev); - - ir_free_table(&ir_dev->rc_tab); - - ir_unregister_class(input_dev); - - kfree(ir_dev->driver_name); - kfree(ir_dev); + rdev->close(rdev); } -EXPORT_SYMBOL_GPL(ir_input_unregister); /* class for /sys/class/rc */ static char *ir_devnode(struct device *dev, mode_t *mode) @@ -881,7 +733,7 @@ static struct { /** * show_protocols() - shows the current IR protocol(s) - * @d: the device descriptor + * @device: the device descriptor * @mattr: the device attribute struct (unused) * @buf: a pointer to the output buffer * @@ -890,26 +742,25 @@ static struct { * It returns the protocol names of supported protocols. * Enabled protocols are printed in brackets. */ -static ssize_t show_protocols(struct device *d, +static ssize_t show_protocols(struct device *device, struct device_attribute *mattr, char *buf) { - struct ir_input_dev *ir_dev = dev_get_drvdata(d); + struct rc_dev *dev = to_rc_dev(device); u64 allowed, enabled; char *tmp = buf; int i; /* Device is being removed */ - if (!ir_dev) + if (!dev) return -EINVAL; - if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { - enabled = ir_dev->rc_tab.ir_type; - allowed = ir_dev->props->allowed_protos; - } else if (ir_dev->raw) { - enabled = ir_dev->raw->enabled_protocols; + if (dev->driver_type == RC_DRIVER_SCANCODE) { + enabled = dev->rc_tab.ir_type; + allowed = dev->allowed_protos; + } else { + enabled = dev->raw->enabled_protocols; allowed = ir_raw_get_allowed_protocols(); - } else - return sprintf(tmp, "[builtin]\n"); + } IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", (long long)allowed, @@ -930,12 +781,12 @@ static ssize_t show_protocols(struct device *d, /** * store_protocols() - changes the current IR protocol(s) - * @d: the device descriptor + * @device: the device descriptor * @mattr: the device attribute struct (unused) * @buf: a pointer to the input buffer * @len: length of the input buffer * - * This routine is a callback routine for changing the IR protocol type. + * This routine is for changing the IR protocol type. * It is trigged by writing to /sys/class/rc/rc?/protocols. * Writing "+proto" will add a protocol to the list of enabled protocols. * Writing "-proto" will remove a protocol from the list of enabled protocols. @@ -944,12 +795,12 @@ static ssize_t show_protocols(struct device *d, * Returns -EINVAL if an invalid protocol combination or unknown protocol name * is used, otherwise @len. */ -static ssize_t store_protocols(struct device *d, +static ssize_t store_protocols(struct device *device, struct device_attribute *mattr, const char *data, size_t len) { - struct ir_input_dev *ir_dev = dev_get_drvdata(d); + struct rc_dev *dev = to_rc_dev(device); bool enable, disable; const char *tmp; u64 type; @@ -958,13 +809,13 @@ static ssize_t store_protocols(struct device *d, unsigned long flags; /* Device is being removed */ - if (!ir_dev) + if (!dev) return -EINVAL; - if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) - type = ir_dev->rc_tab.ir_type; - else if (ir_dev->raw) - type = ir_dev->raw->enabled_protocols; + if (dev->driver_type == RC_DRIVER_SCANCODE) + type = dev->rc_tab.ir_type; + else if (dev->raw) + type = dev->raw->enabled_protocols; else { IR_dprintk(1, "Protocol switching not supported\n"); return -EINVAL; @@ -1019,9 +870,8 @@ static ssize_t store_protocols(struct device *d, return -EINVAL; } - if (ir_dev->props && ir_dev->props->change_protocol) { - rc = ir_dev->props->change_protocol(ir_dev->props->priv, - type); + if (dev->change_protocol) { + rc = dev->change_protocol(dev, type); if (rc < 0) { IR_dprintk(1, "Error setting protocols to 0x%llx\n", (long long)type); @@ -1029,12 +879,12 @@ static ssize_t store_protocols(struct device *d, } } - if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { - spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); - ir_dev->rc_tab.ir_type = type; - spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); + if (dev->driver_type == RC_DRIVER_SCANCODE) { + spin_lock_irqsave(&dev->rc_tab.lock, flags); + dev->rc_tab.ir_type = type; + spin_unlock_irqrestore(&dev->rc_tab.lock, flags); } else { - ir_dev->raw->enabled_protocols = type; + dev->raw->enabled_protocols = type; } IR_dprintk(1, "Current protocol(s): 0x%llx\n", @@ -1043,6 +893,14 @@ static ssize_t store_protocols(struct device *d, return len; } +static void rc_dev_release(struct device *device) +{ + struct rc_dev *dev = to_rc_dev(device); + + kfree(dev); + module_put(THIS_MODULE); +} + #define ADD_HOTPLUG_VAR(fmt, val...) \ do { \ int err = add_uevent_var(env, fmt, val); \ @@ -1052,12 +910,12 @@ static ssize_t store_protocols(struct device *d, static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) { - struct ir_input_dev *ir_dev = dev_get_drvdata(device); + struct rc_dev *dev = to_rc_dev(device); - if (ir_dev->rc_tab.name) - ADD_HOTPLUG_VAR("NAME=%s", ir_dev->rc_tab.name); - if (ir_dev->driver_name) - ADD_HOTPLUG_VAR("DRV_NAME=%s", ir_dev->driver_name); + if (dev->rc_tab.name) + ADD_HOTPLUG_VAR("NAME=%s", dev->rc_tab.name); + if (dev->driver_name) + ADD_HOTPLUG_VAR("DRV_NAME=%s", dev->driver_name); return 0; } @@ -1084,84 +942,162 @@ static const struct attribute_group *rc_dev_attr_groups[] = { static struct device_type rc_dev_type = { .groups = rc_dev_attr_groups, + .release = rc_dev_release, .uevent = rc_dev_uevent, }; -/** - * ir_register_class() - creates the sysfs for /sys/class/rc/rc? - * @input_dev: the struct input_dev descriptor of the device - * - * This routine is used to register the syfs code for IR class - */ -static int ir_register_class(struct input_dev *input_dev) +struct rc_dev *rc_allocate_device(void) { - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - int devno = find_first_zero_bit(&ir_core_dev_number, - IRRCV_NUM_DEVICES); - - if (unlikely(devno < 0)) - return devno; - - ir_dev->dev.type = &rc_dev_type; - ir_dev->devno = devno; - - ir_dev->dev.class = &ir_input_class; - ir_dev->dev.parent = input_dev->dev.parent; - input_dev->dev.parent = &ir_dev->dev; - dev_set_name(&ir_dev->dev, "rc%d", devno); - dev_set_drvdata(&ir_dev->dev, ir_dev); - return device_register(&ir_dev->dev); -}; + struct rc_dev *dev; -/** - * ir_register_input - registers ir input device with input subsystem - * @input_dev: the struct input_dev descriptor of the device - */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return NULL; + + dev->input_dev = input_allocate_device(); + if (!dev->input_dev) { + kfree(dev); + return NULL; + } + + dev->input_dev->getkeycode_new = ir_getkeycode; + dev->input_dev->setkeycode_new = ir_setkeycode; + input_set_drvdata(dev->input_dev, dev); + + spin_lock_init(&dev->rc_tab.lock); + spin_lock_init(&dev->keylock); + setup_timer(&dev->timer_keyup, ir_timer_keyup, (unsigned long)dev); -static int ir_register_input(struct input_dev *input_dev) + dev->dev.type = &rc_dev_type; + dev->dev.class = &ir_input_class; + device_initialize(&dev->dev); + + __module_get(THIS_MODULE); + return dev; +} +EXPORT_SYMBOL_GPL(rc_allocate_device); + +void rc_free_device(struct rc_dev *dev) { - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - int rc; + if (dev) { + input_free_device(dev->input_dev); + put_device(&dev->dev); + } +} +EXPORT_SYMBOL_GPL(rc_free_device); + +int rc_register_device(struct rc_dev *dev) +{ + static atomic_t devno = ATOMIC_INIT(0); + struct ir_scancode_table *rc_tab; const char *path; + int rc; + if (!dev || !dev->map_name) + return -EINVAL; - rc = input_register_device(input_dev); - if (rc < 0) { - device_del(&ir_dev->dev); + rc_tab = get_rc_map(dev->map_name); + if (!rc_tab) + rc_tab = get_rc_map(RC_MAP_EMPTY); + if (!rc_tab || !rc_tab->scan || rc_tab->size == 0) + return -EINVAL; + + set_bit(EV_KEY, dev->input_dev->evbit); + set_bit(EV_REP, dev->input_dev->evbit); + set_bit(EV_MSC, dev->input_dev->evbit); + set_bit(MSC_SCAN, dev->input_dev->mscbit); + if (dev->open) + dev->input_dev->open = ir_open; + if (dev->close) + dev->input_dev->close = ir_close; + + dev->devno = (unsigned long)(atomic_inc_return(&devno) - 1); + dev_set_name(&dev->dev, "rc%ld", dev->devno); + dev_set_drvdata(&dev->dev, dev); + rc = device_add(&dev->dev); + if (rc) return rc; - } - __module_get(THIS_MODULE); + rc = ir_setkeytable(dev, rc_tab); + if (rc) + goto out_dev; + + dev->input_dev->dev.parent = &dev->dev; + memcpy(&dev->input_dev->id, &dev->input_id, sizeof(dev->input_id)); + dev->input_dev->phys = dev->input_phys; + dev->input_dev->name = dev->input_name; + rc = input_register_device(dev->input_dev); + if (rc) + goto out_table; - path = kobject_get_path(&ir_dev->dev.kobj, GFP_KERNEL); + /* + * Default delay of 250ms is too short for some protocols, expecially + * since the timeout is currently set to 250ms. Increase it to 500ms, + * to avoid wrong repetition of the keycodes. Note that this must be + * set after the call to input_register_device(). + */ + dev->input_dev->rep[REP_DELAY] = 500; + + path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); printk(KERN_INFO "%s: %s as %s\n", - dev_name(&ir_dev->dev), - input_dev->name ? input_dev->name : "Unspecified device", + dev_name(&dev->dev), + dev->input_name ? dev->input_name : "Unspecified device", path ? path : "N/A"); kfree(path); - set_bit(ir_dev->devno, &ir_core_dev_number); + if (dev->driver_type == RC_DRIVER_IR_RAW) { + rc = ir_raw_event_register(dev); + if (rc < 0) + goto out_input; + } + + if (dev->change_protocol) { + rc = dev->change_protocol(dev, rc_tab->ir_type); + if (rc < 0) + goto out_raw; + } + + IR_dprintk(1, "Registered rc%ld (driver: %s, remote: %s, mode %s)\n", + dev->devno, + dev->driver_name ? dev->driver_name : "unknown", + rc_tab->name ? rc_tab->name : "unknown", + dev->driver_type == RC_DRIVER_IR_RAW ? "raw" : "cooked"); + return 0; + +out_raw: + if (dev->driver_type == RC_DRIVER_IR_RAW) + ir_raw_event_unregister(dev); +out_input: + input_unregister_device(dev->input_dev); + dev->input_dev = NULL; +out_table: + ir_free_table(&dev->rc_tab); +out_dev: + device_del(&dev->dev); + return rc; } +EXPORT_SYMBOL_GPL(rc_register_device); -/** - * ir_unregister_class() - removes the sysfs for sysfs for - * /sys/class/rc/rc? - * @input_dev: the struct input_dev descriptor of the device - * - * This routine is used to unregister the syfs code for IR class - */ -static void ir_unregister_class(struct input_dev *input_dev) +void rc_unregister_device(struct rc_dev *dev) { - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + if (!dev) + return; - input_set_drvdata(input_dev, NULL); - clear_bit(ir_dev->devno, &ir_core_dev_number); - input_unregister_device(input_dev); - device_del(&ir_dev->dev); + del_timer_sync(&dev->timer_keyup); - module_put(THIS_MODULE); + if (dev->driver_type == RC_DRIVER_IR_RAW) + ir_raw_event_unregister(dev); + + input_unregister_device(dev->input_dev); + dev->input_dev = NULL; + + ir_free_table(&dev->rc_tab); + IR_dprintk(1, "Freed keycode table\n"); + + device_unregister(&dev->dev); } +EXPORT_SYMBOL_GPL(rc_unregister_device); /* * Init/exit code for the module. Basically, creates/removes /sys/class/rc diff --git a/drivers/media/rc/rc-raw.c b/drivers/media/rc/rc-raw.c index d6c556e..ab9b1e4 100644 --- a/drivers/media/rc/rc-raw.c +++ b/drivers/media/rc/rc-raw.c @@ -64,7 +64,7 @@ static int ir_raw_event_thread(void *data) mutex_lock(&ir_raw_handler_lock); list_for_each_entry(handler, &ir_raw_handler_list, list) - handler->decode(raw->input_dev, ev); + handler->decode(raw->dev, ev); raw->prev_ev = ev; mutex_unlock(&ir_raw_handler_lock); } @@ -74,7 +74,7 @@ static int ir_raw_event_thread(void *data) /** * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders - * @input_dev: the struct input_dev device descriptor + * @dev: the struct rc_dev device descriptor * @ev: the struct ir_raw_event descriptor of the pulse/space * * This routine (which may be called from an interrupt context) stores a @@ -82,17 +82,15 @@ static int ir_raw_event_thread(void *data) * signalled as positive values and spaces as negative values. A zero value * will reset the decoding state machines. */ -int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev) +int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev) { - struct ir_input_dev *ir = input_get_drvdata(input_dev); - - if (!ir->raw) + if (!dev->raw) return -EINVAL; IR_dprintk(2, "sample: (%05dus %s)\n", - TO_US(ev->duration), TO_STR(ev->pulse)); + TO_US(ev->duration), TO_STR(ev->pulse)); - if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) + if (kfifo_in(&dev->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) return -ENOMEM; return 0; @@ -101,7 +99,7 @@ EXPORT_SYMBOL_GPL(ir_raw_event_store); /** * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space - * @input_dev: the struct input_dev device descriptor + * @dev: the struct rc_dev device descriptor * @type: the type of the event that has occurred * * This routine (which may be called from an interrupt context) is used to @@ -110,50 +108,49 @@ EXPORT_SYMBOL_GPL(ir_raw_event_store); * hardware which does not provide durations directly but only interrupts * (or similar events) on state change. */ -int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type) +int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type) { - struct ir_input_dev *ir = input_get_drvdata(input_dev); ktime_t now; s64 delta; /* ns */ struct ir_raw_event ev; int rc = 0; - if (!ir->raw) + if (!dev->raw) return -EINVAL; now = ktime_get(); - delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event)); + delta = ktime_to_ns(ktime_sub(now, dev->raw->last_event)); /* Check for a long duration since last event or if we're * being called for the first time, note that delta can't * possibly be negative. */ ev.duration = 0; - if (delta > IR_MAX_DURATION || !ir->raw->last_type) + if (delta > IR_MAX_DURATION || !dev->raw->last_type) type |= IR_START_EVENT; else ev.duration = delta; if (type & IR_START_EVENT) - ir_raw_event_reset(input_dev); - else if (ir->raw->last_type & IR_SPACE) { + ir_raw_event_reset(dev); + else if (dev->raw->last_type & IR_SPACE) { ev.pulse = false; - rc = ir_raw_event_store(input_dev, &ev); - } else if (ir->raw->last_type & IR_PULSE) { + rc = ir_raw_event_store(dev, &ev); + } else if (dev->raw->last_type & IR_PULSE) { ev.pulse = true; - rc = ir_raw_event_store(input_dev, &ev); + rc = ir_raw_event_store(dev, &ev); } else return 0; - ir->raw->last_event = now; - ir->raw->last_type = type; + dev->raw->last_event = now; + dev->raw->last_type = type; return rc; } EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); /** * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing - * @input_dev: the struct input_dev device descriptor + * @dev: the struct rc_dev device descriptor * @type: the type of the event that has occurred * * This routine (which may be called from an interrupt context) works @@ -161,84 +158,76 @@ EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); * This routine is intended for devices with limited internal buffer * It automerges samples of same type, and handles timeouts */ -int ir_raw_event_store_with_filter(struct input_dev *input_dev, - struct ir_raw_event *ev) +int ir_raw_event_store_with_filter(struct rc_dev *dev, struct ir_raw_event *ev) { - struct ir_input_dev *ir = input_get_drvdata(input_dev); - struct ir_raw_event_ctrl *raw = ir->raw; - - if (!raw || !ir->props) + if (!dev->raw) return -EINVAL; /* Ignore spaces in idle mode */ - if (ir->idle && !ev->pulse) + if (dev->idle && !ev->pulse) return 0; - else if (ir->idle) - ir_raw_event_set_idle(input_dev, false); - - if (!raw->this_ev.duration) { - raw->this_ev = *ev; - } else if (ev->pulse == raw->this_ev.pulse) { - raw->this_ev.duration += ev->duration; - } else { - ir_raw_event_store(input_dev, &raw->this_ev); - raw->this_ev = *ev; + else if (dev->idle) + ir_raw_event_set_idle(dev, false); + + if (!dev->raw->this_ev.duration) + dev->raw->this_ev = *ev; + else if (ev->pulse == dev->raw->this_ev.pulse) + dev->raw->this_ev.duration += ev->duration; + else { + ir_raw_event_store(dev, &dev->raw->this_ev); + dev->raw->this_ev = *ev; } /* Enter idle mode if nessesary */ - if (!ev->pulse && ir->props->timeout && - raw->this_ev.duration >= ir->props->timeout) { - ir_raw_event_set_idle(input_dev, true); - } + if (!ev->pulse && dev->timeout && + dev->raw->this_ev.duration >= dev->timeout) + ir_raw_event_set_idle(dev, true); + return 0; } EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter); /** - * ir_raw_event_set_idle() - hint the ir core if device is receiving - * IR data or not - * @input_dev: the struct input_dev device descriptor - * @idle: the hint value + * ir_raw_event_set_idle() - provide hint to rc-core when the device is idle or not + * @dev: the struct rc_dev device descriptor + * @idle: whether the device is idle or not */ -void ir_raw_event_set_idle(struct input_dev *input_dev, bool idle) +void ir_raw_event_set_idle(struct rc_dev *dev, bool idle) { - struct ir_input_dev *ir = input_get_drvdata(input_dev); - struct ir_raw_event_ctrl *raw = ir->raw; - - if (!ir->props || !ir->raw) + if (!dev->raw) return; IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave"); if (idle) { - raw->this_ev.timeout = true; - ir_raw_event_store(input_dev, &raw->this_ev); - init_ir_raw_event(&raw->this_ev); + dev->raw->this_ev.timeout = true; + ir_raw_event_store(dev, &dev->raw->this_ev); + init_ir_raw_event(&dev->raw->this_ev); } - if (ir->props->s_idle) - ir->props->s_idle(ir->props->priv, idle); - ir->idle = idle; + if (dev->s_idle) + dev->s_idle(dev, idle); + + dev->idle = idle; } EXPORT_SYMBOL_GPL(ir_raw_event_set_idle); /** * ir_raw_event_handle() - schedules the decoding of stored ir data - * @input_dev: the struct input_dev device descriptor + * @dev: the struct rc_dev device descriptor * - * This routine will signal the workqueue to start decoding stored ir data. + * This routine will tell rc-core to start decoding stored ir data. */ -void ir_raw_event_handle(struct input_dev *input_dev) +void ir_raw_event_handle(struct rc_dev *dev) { - struct ir_input_dev *ir = input_get_drvdata(input_dev); unsigned long flags; - if (!ir->raw) + if (!dev->raw) return; - spin_lock_irqsave(&ir->raw->lock, flags); - wake_up_process(ir->raw->thread); - spin_unlock_irqrestore(&ir->raw->lock, flags); + spin_lock_irqsave(&dev->raw->lock, flags); + wake_up_process(dev->raw->thread); + spin_unlock_irqrestore(&dev->raw->lock, flags); } EXPORT_SYMBOL_GPL(ir_raw_event_handle); @@ -256,69 +245,69 @@ ir_raw_get_allowed_protocols() /* * Used to (un)register raw event clients */ -int ir_raw_event_register(struct input_dev *input_dev) +int ir_raw_event_register(struct rc_dev *dev) { - struct ir_input_dev *ir = input_get_drvdata(input_dev); int rc; struct ir_raw_handler *handler; - ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); - if (!ir->raw) - return -ENOMEM; + if (!dev) + return -EINVAL; - ir->raw->input_dev = input_dev; + dev->raw = kzalloc(sizeof(*dev->raw), GFP_KERNEL); + if (!dev->raw) + return -ENOMEM; - ir->raw->enabled_protocols = ~0; - rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, + dev->raw->dev = dev; + dev->raw->enabled_protocols = ~0; + rc = kfifo_alloc(&dev->raw->kfifo, + sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE, GFP_KERNEL); - if (rc < 0) { - kfree(ir->raw); - ir->raw = NULL; - return rc; - } + if (rc < 0) + goto out; - spin_lock_init(&ir->raw->lock); - ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw, - "rc%u", (unsigned int)ir->devno); + spin_lock_init(&dev->raw->lock); + dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw, + "rc%ld", dev->devno); - if (IS_ERR(ir->raw->thread)) { - int ret = PTR_ERR(ir->raw->thread); - - kfree(ir->raw); - ir->raw = NULL; - return ret; + if (IS_ERR(dev->raw->thread)) { + rc = PTR_ERR(dev->raw->thread); + goto out; } mutex_lock(&ir_raw_handler_lock); - list_add_tail(&ir->raw->list, &ir_raw_client_list); + list_add_tail(&dev->raw->list, &ir_raw_client_list); list_for_each_entry(handler, &ir_raw_handler_list, list) if (handler->raw_register) - handler->raw_register(ir->raw->input_dev); + handler->raw_register(dev); mutex_unlock(&ir_raw_handler_lock); return 0; + +out: + kfree(dev->raw); + dev->raw = NULL; + return rc; } -void ir_raw_event_unregister(struct input_dev *input_dev) +void ir_raw_event_unregister(struct rc_dev *dev) { - struct ir_input_dev *ir = input_get_drvdata(input_dev); struct ir_raw_handler *handler; - if (!ir->raw) + if (!dev || !dev->raw) return; - kthread_stop(ir->raw->thread); + kthread_stop(dev->raw->thread); mutex_lock(&ir_raw_handler_lock); - list_del(&ir->raw->list); + list_del(&dev->raw->list); list_for_each_entry(handler, &ir_raw_handler_list, list) if (handler->raw_unregister) - handler->raw_unregister(ir->raw->input_dev); + handler->raw_unregister(dev); mutex_unlock(&ir_raw_handler_lock); - kfifo_free(&ir->raw->kfifo); - kfree(ir->raw); - ir->raw = NULL; + kfifo_free(&dev->raw->kfifo); + kfree(dev->raw); + dev->raw = NULL; } /* @@ -333,7 +322,7 @@ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); if (ir_raw_handler->raw_register) list_for_each_entry(raw, &ir_raw_client_list, list) - ir_raw_handler->raw_register(raw->input_dev); + ir_raw_handler->raw_register(raw->dev); available_protocols |= ir_raw_handler->protocols; mutex_unlock(&ir_raw_handler_lock); @@ -349,7 +338,7 @@ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) list_del(&ir_raw_handler->list); if (ir_raw_handler->raw_unregister) list_for_each_entry(raw, &ir_raw_client_list, list) - ir_raw_handler->raw_unregister(raw->input_dev); + ir_raw_handler->raw_unregister(raw->dev); available_protocols &= ~ir_raw_handler->protocols; mutex_unlock(&ir_raw_handler_lock); } diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c index 3a20aef..f05f5c1 100644 --- a/drivers/media/rc/streamzap.c +++ b/drivers/media/rc/streamzap.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -86,13 +85,11 @@ enum StreamzapDecoderState { /* structure to hold our device specific stuff */ struct streamzap_ir { - /* ir-core */ - struct ir_dev_props *props; + struct rc_dev *rdev; /* core device info */ struct device *dev; - struct input_dev *idev; /* usb */ struct usb_device *usbdev; @@ -143,7 +140,7 @@ static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir) { dev_dbg(sz->dev, "Storing %s with duration %u us\n", (rawir.pulse ? "pulse" : "space"), rawir.duration); - ir_raw_event_store_with_filter(sz->idev, &rawir); + ir_raw_event_store_with_filter(sz->rdev, &rawir); } static void sz_push_full_pulse(struct streamzap_ir *sz, @@ -271,11 +268,11 @@ static void streamzap_callback(struct urb *urb) DEFINE_IR_RAW_EVENT(rawir); rawir.pulse = false; - rawir.duration = sz->props->timeout; + rawir.duration = sz->rdev->timeout; sz->idle = true; if (sz->timeout_enabled) sz_push(sz, rawir); - ir_raw_event_handle(sz->idev); + ir_raw_event_handle(sz->rdev); } else { sz_push_full_space(sz, sz->buf_in[i]); } @@ -298,57 +295,43 @@ static void streamzap_callback(struct urb *urb) return; } -static struct input_dev *streamzap_init_input_dev(struct streamzap_ir *sz) +static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz) { - struct input_dev *idev; - struct ir_dev_props *props; + struct rc_dev *rdev; struct device *dev = sz->dev; int ret; - idev = input_allocate_device(); - if (!idev) { - dev_err(dev, "remote input dev allocation failed\n"); - goto idev_alloc_failed; - } - - props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); - if (!props) { - dev_err(dev, "remote ir dev props allocation failed\n"); - goto props_alloc_failed; + rdev = rc_allocate_device(); + if (!rdev) { + dev_err(dev, "remote dev allocation failed\n"); + goto out; } snprintf(sz->name, sizeof(sz->name), "Streamzap PC Remote Infrared " "Receiver (%04x:%04x)", le16_to_cpu(sz->usbdev->descriptor.idVendor), le16_to_cpu(sz->usbdev->descriptor.idProduct)); - - idev->name = sz->name; usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys)); strlcat(sz->phys, "/input0", sizeof(sz->phys)); - idev->phys = sz->phys; - - props->priv = sz; - props->driver_type = RC_DRIVER_IR_RAW; - props->allowed_protos = IR_TYPE_ALL; - - sz->props = props; - usb_to_input_id(sz->usbdev, &idev->id); - idev->dev.parent = sz->dev; + rdev->input_name = sz->name; + rdev->input_phys = sz->phys; + rdev->priv = sz; + rdev->driver_type = RC_DRIVER_IR_RAW; + rdev->allowed_protos = IR_TYPE_ALL; + rdev->driver_name = DRIVER_NAME; + rdev->map_name = RC_MAP_STREAMZAP; - ret = ir_input_register(idev, RC_MAP_STREAMZAP, props, DRIVER_NAME); + ret = rc_register_device(rdev); if (ret < 0) { dev_err(dev, "remote input device register failed\n"); - goto irdev_failed; + goto out; } - return idev; + return rdev; -irdev_failed: - kfree(props); -props_alloc_failed: - input_free_device(idev); -idev_alloc_failed: +out: + rc_free_device(rdev); return NULL; } @@ -437,15 +420,15 @@ static int __devinit streamzap_probe(struct usb_interface *intf, snprintf(name + strlen(name), sizeof(name) - strlen(name), " %s", buf); - sz->idev = streamzap_init_input_dev(sz); - if (!sz->idev) - goto input_dev_fail; + sz->rdev = streamzap_init_rc_dev(sz); + if (!sz->rdev) + goto rc_dev_fail; sz->idle = true; sz->decoder_state = PulseSpace; /* FIXME: don't yet have a way to set this */ sz->timeout_enabled = true; - sz->props->timeout = (((SZ_TIMEOUT * SZ_RESOLUTION * 1000) & + sz->rdev->timeout = (((SZ_TIMEOUT * SZ_RESOLUTION * 1000) & IR_MAX_DURATION) | 0x03000000); #if 0 /* not yet supported, depends on patches from maxim */ @@ -476,7 +459,7 @@ static int __devinit streamzap_probe(struct usb_interface *intf, return 0; -input_dev_fail: +rc_dev_fail: usb_free_urb(sz->urb_in); free_buf_in: usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in); @@ -507,7 +490,7 @@ static void streamzap_disconnect(struct usb_interface *interface) return; sz->usbdev = NULL; - ir_input_unregister(sz->idev); + rc_unregister_device(sz->rdev); usb_kill_urb(sz->urb_in); usb_free_urb(sz->urb_in); usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in); diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index eb71c3a..4b4f613 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -31,10 +31,6 @@ static int ir_debug; module_param(ir_debug, int, 0644); -static int repeat_delay = 500; -module_param(repeat_delay, int, 0644); -static int repeat_period = 33; -module_param(repeat_period, int, 0644); static int ir_rc5_remote_gap = 885; module_param(ir_rc5_remote_gap, int, 0644); @@ -317,15 +313,15 @@ int bttv_input_init(struct bttv *btv) { struct card_ir *ir; char *ir_codes = NULL; - struct input_dev *input_dev; + struct rc_dev *rc; int err = -ENOMEM; if (!btv->has_remote) return -ENODEV; ir = kzalloc(sizeof(*ir),GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ir || !input_dev) + rc = rc_allocate_device(); + if (!ir || !rc) goto err_out_free; /* detect & configure */ @@ -431,44 +427,43 @@ int bttv_input_init(struct bttv *btv) } /* init input device */ - ir->dev = input_dev; + ir->dev = rc; snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)", btv->c.type); snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(btv->c.pci)); - input_dev->name = ir->name; - input_dev->phys = ir->phys; - input_dev->id.bustype = BUS_PCI; - input_dev->id.version = 1; + rc->input_name = ir->name; + rc->input_phys = ir->phys; + rc->input_id.bustype = BUS_PCI; + rc->input_id.version = 1; if (btv->c.pci->subsystem_vendor) { - input_dev->id.vendor = btv->c.pci->subsystem_vendor; - input_dev->id.product = btv->c.pci->subsystem_device; + rc->input_id.vendor = btv->c.pci->subsystem_vendor; + rc->input_id.product = btv->c.pci->subsystem_device; } else { - input_dev->id.vendor = btv->c.pci->vendor; - input_dev->id.product = btv->c.pci->device; + rc->input_id.vendor = btv->c.pci->vendor; + rc->input_id.product = btv->c.pci->device; } - input_dev->dev.parent = &btv->c.pci->dev; + rc->dev.parent = &btv->c.pci->dev; + rc->map_name = ir_codes; + rc->driver_name = MODULE_NAME; btv->remote = ir; bttv_ir_start(btv, ir); /* all done */ - err = ir_input_register(btv->remote->dev, ir_codes, NULL, MODULE_NAME); + err = rc_register_device(rc); if (err) goto err_out_stop; - /* the remote isn't as bouncy as a keyboard */ - ir->dev->rep[REP_DELAY] = repeat_delay; - ir->dev->rep[REP_PERIOD] = repeat_period; - return 0; err_out_stop: bttv_ir_stop(btv); btv->remote = NULL; err_out_free: + rc_free_device(rc); kfree(ir); return err; } @@ -479,7 +474,7 @@ void bttv_input_fini(struct bttv *btv) return; bttv_ir_stop(btv); - ir_input_unregister(btv->remote->dev); + rc_unregister_device(btv->remote->dev); kfree(btv->remote); btv->remote = NULL; } diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h index a09cef4..c439e77 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/video/cx231xx/cx231xx.h @@ -607,7 +607,15 @@ struct cx231xx_ir_t { char name[40]; char phys[32]; +#if 0 + /* + * Due to a Kconfig change, cx231xx-input is not being compiled. + * This structure disappeared, but other fixes are also needed. + * So, as a workaround, let's just comment this struct and let a + * latter patch fix it. + */ struct ir_dev_props props; +#endif /* I2C keyboard data */ struct IR_i2c_init_data init_data; diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index bb61870..f1bb3a8 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c @@ -35,7 +35,6 @@ * 02110-1301, USA. */ -#include #include #include #include @@ -62,16 +61,16 @@ static void cx23885_input_process_measurements(struct cx23885_dev *dev, count = num / sizeof(struct ir_raw_event); for (i = 0; i < count; i++) { - ir_raw_event_store(kernel_ir->inp_dev, + ir_raw_event_store(kernel_ir->rc, &ir_core_event[i]); handle = true; } } while (num != 0); if (overrun) - ir_raw_event_reset(kernel_ir->inp_dev); + ir_raw_event_reset(kernel_ir->rc); else if (handle) - ir_raw_event_handle(kernel_ir->inp_dev); + ir_raw_event_handle(kernel_ir->rc); } void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) @@ -197,9 +196,9 @@ static int cx23885_input_ir_start(struct cx23885_dev *dev) return 0; } -static int cx23885_input_ir_open(void *priv) +static int cx23885_input_ir_open(struct rc_dev *rc) { - struct cx23885_kernel_ir *kernel_ir = priv; + struct cx23885_kernel_ir *kernel_ir = rc->priv; if (kernel_ir->cx == NULL) return -ENODEV; @@ -234,9 +233,9 @@ static void cx23885_input_ir_stop(struct cx23885_dev *dev) flush_scheduled_work(); } -static void cx23885_input_ir_close(void *priv) +static void cx23885_input_ir_close(struct rc_dev *rc) { - struct cx23885_kernel_ir *kernel_ir = priv; + struct cx23885_kernel_ir *kernel_ir = rc->priv; if (kernel_ir->cx != NULL) cx23885_input_ir_stop(kernel_ir->cx); @@ -245,9 +244,7 @@ static void cx23885_input_ir_close(void *priv) int cx23885_input_init(struct cx23885_dev *dev) { struct cx23885_kernel_ir *kernel_ir; - struct input_dev *inp_dev; - struct ir_dev_props *props; - + struct rc_dev *rc; char *rc_map; enum rc_driver_type driver_type; unsigned long allowed_protos; @@ -294,37 +291,36 @@ int cx23885_input_init(struct cx23885_dev *dev) pci_name(dev->pci)); /* input device */ - inp_dev = input_allocate_device(); - if (inp_dev == NULL) { + rc = rc_allocate_device(); + if (!rc) { ret = -ENOMEM; goto err_out_free; } - kernel_ir->inp_dev = inp_dev; - inp_dev->name = kernel_ir->name; - inp_dev->phys = kernel_ir->phys; - inp_dev->id.bustype = BUS_PCI; - inp_dev->id.version = 1; + kernel_ir->rc = rc; + rc->input_name = kernel_ir->name; + rc->input_phys = kernel_ir->phys; + rc->input_id.bustype = BUS_PCI; + rc->input_id.version = 1; if (dev->pci->subsystem_vendor) { - inp_dev->id.vendor = dev->pci->subsystem_vendor; - inp_dev->id.product = dev->pci->subsystem_device; + rc->input_id.vendor = dev->pci->subsystem_vendor; + rc->input_id.product = dev->pci->subsystem_device; } else { - inp_dev->id.vendor = dev->pci->vendor; - inp_dev->id.product = dev->pci->device; + rc->input_id.vendor = dev->pci->vendor; + rc->input_id.product = dev->pci->device; } - inp_dev->dev.parent = &dev->pci->dev; - - /* kernel ir device properties */ - props = &kernel_ir->props; - props->driver_type = driver_type; - props->allowed_protos = allowed_protos; - props->priv = kernel_ir; - props->open = cx23885_input_ir_open; - props->close = cx23885_input_ir_close; + rc->dev.parent = &dev->pci->dev; + rc->driver_type = driver_type; + rc->allowed_protos = allowed_protos; + rc->priv = kernel_ir; + rc->open = cx23885_input_ir_open; + rc->close = cx23885_input_ir_close; + rc->map_name = rc_map; + rc->driver_name = MODULE_NAME; /* Go */ dev->kernel_ir = kernel_ir; - ret = ir_input_register(inp_dev, rc_map, props, MODULE_NAME); + ret = rc_register_device(rc); if (ret) goto err_out_stop; @@ -333,7 +329,7 @@ int cx23885_input_init(struct cx23885_dev *dev) err_out_stop: cx23885_input_ir_stop(dev); dev->kernel_ir = NULL; - /* TODO: double check clean-up of kernel_ir->inp_dev */ + rc_free_device(rc); err_out_free: kfree(kernel_ir->phys); kfree(kernel_ir->name); @@ -348,7 +344,7 @@ void cx23885_input_fini(struct cx23885_dev *dev) if (dev->kernel_ir == NULL) return; - ir_input_unregister(dev->kernel_ir->inp_dev); + rc_unregister_device(dev->kernel_ir->rc); kfree(dev->kernel_ir->phys); kfree(dev->kernel_ir->name); kfree(dev->kernel_ir); diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index ed94b17..f350d88 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -310,8 +310,7 @@ struct cx23885_kernel_ir { char *name; char *phys; - struct input_dev *inp_dev; - struct ir_dev_props props; + struct rc_dev *rc; }; struct cx23885_dev { diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 8c41124..3b2ef45 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -38,8 +37,7 @@ struct cx88_IR { struct cx88_core *core; - struct input_dev *input; - struct ir_dev_props props; + struct rc_dev *dev; int users; @@ -125,26 +123,26 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) data = (data << 4) | ((gpio_key & 0xf0) >> 4); - ir_keydown(ir->input, data, 0); + ir_keydown(ir->dev, data, 0); } else if (ir->mask_keydown) { /* bit set on keydown */ if (gpio & ir->mask_keydown) - ir_keydown_notimeout(ir->input, data, 0); + ir_keydown_notimeout(ir->dev, data, 0); else - ir_keyup(ir->input); + ir_keyup(ir->dev); } else if (ir->mask_keyup) { /* bit cleared on keydown */ if (0 == (gpio & ir->mask_keyup)) - ir_keydown_notimeout(ir->input, data, 0); + ir_keydown_notimeout(ir->dev, data, 0); else - ir_keyup(ir->input); + ir_keyup(ir->dev); } else { /* can't distinguish keydown/up :-/ */ - ir_keydown_notimeout(ir->input, data, 0); - ir_keyup(ir->input); + ir_keydown_notimeout(ir->dev, data, 0); + ir_keyup(ir->dev); } } @@ -219,17 +217,17 @@ void cx88_ir_stop(struct cx88_core *core) __cx88_ir_stop(core); } -static int cx88_ir_open(void *priv) +static int cx88_ir_open(struct rc_dev *rc) { - struct cx88_core *core = priv; + struct cx88_core *core = rc->priv; core->ir->users++; return __cx88_ir_start(core); } -static void cx88_ir_close(void *priv) +static void cx88_ir_close(struct rc_dev *rc) { - struct cx88_core *core = priv; + struct cx88_core *core = rc->priv; core->ir->users--; if (!core->ir->users) @@ -241,7 +239,7 @@ static void cx88_ir_close(void *priv) int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) { struct cx88_IR *ir; - struct input_dev *input_dev; + struct rc_dev *dev; char *ir_codes = NULL; u64 ir_type = IR_TYPE_OTHER; int err = -ENOMEM; @@ -250,11 +248,11 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) */ ir = kzalloc(sizeof(*ir), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ir || !input_dev) + dev = rc_allocate_device(); + if (!ir || !dev) goto err_out_free; - ir->input = input_dev; + ir->dev = dev; /* detect & configure */ switch (core->boardnr) { @@ -435,43 +433,45 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); - input_dev->name = ir->name; - input_dev->phys = ir->phys; - input_dev->id.bustype = BUS_PCI; - input_dev->id.version = 1; + dev->input_name = ir->name; + dev->input_phys = ir->phys; + dev->input_id.bustype = BUS_PCI; + dev->input_id.version = 1; if (pci->subsystem_vendor) { - input_dev->id.vendor = pci->subsystem_vendor; - input_dev->id.product = pci->subsystem_device; + dev->input_id.vendor = pci->subsystem_vendor; + dev->input_id.product = pci->subsystem_device; } else { - input_dev->id.vendor = pci->vendor; - input_dev->id.product = pci->device; + dev->input_id.vendor = pci->vendor; + dev->input_id.product = pci->device; } - input_dev->dev.parent = &pci->dev; - /* record handles to ourself */ - ir->core = core; - core->ir = ir; + dev->dev.parent = &pci->dev; + dev->map_name = ir_codes; + dev->driver_name = MODULE_NAME; + dev->priv = core; + dev->open = cx88_ir_open; + dev->close = cx88_ir_close; + dev->scanmask = hardware_mask; if (ir->sampling) { - ir_type = IR_TYPE_ALL; - ir->props.driver_type = RC_DRIVER_IR_RAW; - ir->props.timeout = 10 * 1000 * 1000; /* 10 ms */ - } else - ir->props.driver_type = RC_DRIVER_SCANCODE; - - ir->props.priv = core; - ir->props.open = cx88_ir_open; - ir->props.close = cx88_ir_close; - ir->props.scanmask = hardware_mask; - ir->props.allowed_protos = ir_type; + dev->driver_type = RC_DRIVER_IR_RAW; + dev->timeout = 10 * 1000 * 1000; /* 10 ms */ + } else { + dev->driver_type = RC_DRIVER_SCANCODE; + dev->allowed_protos = ir_type; + } + + ir->core = core; + core->ir = ir; /* all done */ - err = ir_input_register(ir->input, ir_codes, &ir->props, MODULE_NAME); + err = rc_register_device(dev); if (err) goto err_out_free; return 0; - err_out_free: +err_out_free: + rc_free_device(dev); core->ir = NULL; kfree(ir); return err; @@ -486,7 +486,7 @@ int cx88_ir_fini(struct cx88_core *core) return 0; cx88_ir_stop(core); - ir_input_unregister(ir->input); + rc_unregister_device(ir->dev); kfree(ir); /* done */ @@ -502,7 +502,6 @@ void cx88_ir_irq(struct cx88_core *core) u32 samples; unsigned todo, bits; struct ir_raw_event ev; - struct ir_input_dev *irdev; if (!ir || !ir->sampling) return; @@ -513,9 +512,8 @@ void cx88_ir_irq(struct cx88_core *core) * represents a pulse. */ samples = cx_read(MO_SAMPLE_IO); - irdev = input_get_drvdata(ir->input); - if (samples == 0xff && irdev->idle) + if (samples == 0xff && ir->dev->idle) return; init_ir_raw_event(&ev); @@ -523,10 +521,10 @@ void cx88_ir_irq(struct cx88_core *core) ev.pulse = samples & 0x80000000 ? false : true; bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples)); ev.duration = (bits * NSEC_PER_SEC) / (1000 * ir_samplerate); - ir_raw_event_store_with_filter(ir->input, &ev); + ir_raw_event_store_with_filter(ir->dev, &ev); samples <<= bits; } - ir_raw_event_handle(ir->input); + ir_raw_event_handle(ir->dev); } void cx88_i2c_init_ir(struct cx88_core *core) diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 6759cd5..b7d3999 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -64,7 +63,7 @@ struct em28xx_ir_poll_result { struct em28xx_IR { struct em28xx *dev; - struct input_dev *input; + struct rc_dev *rc; char name[32]; char phys[32]; @@ -75,10 +74,6 @@ struct em28xx_IR { unsigned int last_readcount; int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); - - /* IR device properties */ - - struct ir_dev_props props; }; /********************************************************** @@ -302,12 +297,12 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) poll_result.toggle_bit, poll_result.read_count, poll_result.rc_address, poll_result.rc_data[0]); if (ir->full_code) - ir_keydown(ir->input, + ir_keydown(ir->rc, poll_result.rc_address << 8 | poll_result.rc_data[0], poll_result.toggle_bit); else - ir_keydown(ir->input, + ir_keydown(ir->rc, poll_result.rc_data[0], poll_result.toggle_bit); @@ -331,9 +326,9 @@ static void em28xx_ir_work(struct work_struct *work) schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); } -static int em28xx_ir_start(void *priv) +static int em28xx_ir_start(struct rc_dev *rc) { - struct em28xx_IR *ir = priv; + struct em28xx_IR *ir = rc->priv; INIT_DELAYED_WORK(&ir->work, em28xx_ir_work); schedule_delayed_work(&ir->work, 0); @@ -341,17 +336,17 @@ static int em28xx_ir_start(void *priv) return 0; } -static void em28xx_ir_stop(void *priv) +static void em28xx_ir_stop(struct rc_dev *rc) { - struct em28xx_IR *ir = priv; + struct em28xx_IR *ir = rc->priv; cancel_delayed_work_sync(&ir->work); } -int em28xx_ir_change_protocol(void *priv, u64 ir_type) +int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 ir_type) { int rc = 0; - struct em28xx_IR *ir = priv; + struct em28xx_IR *ir = rc_dev->priv; struct em28xx *dev = ir->dev; u8 ir_config = EM2874_IR_RC5; @@ -391,7 +386,7 @@ int em28xx_ir_change_protocol(void *priv, u64 ir_type) int em28xx_ir_init(struct em28xx *dev) { struct em28xx_IR *ir; - struct input_dev *input_dev; + struct rc_dev *rc; int err = -ENOMEM; if (dev->board.ir_codes == NULL) { @@ -400,28 +395,27 @@ int em28xx_ir_init(struct em28xx *dev) } ir = kzalloc(sizeof(*ir), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ir || !input_dev) + rc = rc_allocate_device(); + if (!ir || !rc) goto err_out_free; /* record handles to ourself */ ir->dev = dev; dev->ir = ir; - - ir->input = input_dev; + ir->rc = rc; /* * em2874 supports more protocols. For now, let's just announce * the two protocols that were already tested */ - ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; - ir->props.priv = ir; - ir->props.change_protocol = em28xx_ir_change_protocol; - ir->props.open = em28xx_ir_start; - ir->props.close = em28xx_ir_stop; + rc->allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; + rc->priv = ir; + rc->change_protocol = em28xx_ir_change_protocol; + rc->open = em28xx_ir_start; + rc->close = em28xx_ir_stop; /* By default, keep protocol field untouched */ - err = em28xx_ir_change_protocol(ir, IR_TYPE_UNKNOWN); + err = em28xx_ir_change_protocol(rc, IR_TYPE_UNKNOWN); if (err) goto err_out_free; @@ -435,27 +429,27 @@ int em28xx_ir_init(struct em28xx *dev) usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); strlcat(ir->phys, "/input0", sizeof(ir->phys)); - input_dev->name = ir->name; - input_dev->phys = ir->phys; - input_dev->id.bustype = BUS_USB; - input_dev->id.version = 1; - input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); - input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); - - input_dev->dev.parent = &dev->udev->dev; - - + rc->input_name = ir->name; + rc->input_phys = ir->phys; + rc->input_id.bustype = BUS_USB; + rc->input_id.version = 1; + rc->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); + rc->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct); + rc->dev.parent = &dev->udev->dev; + rc->map_name = dev->board.ir_codes; + rc->driver_name = MODULE_NAME; /* all done */ - err = ir_input_register(ir->input, dev->board.ir_codes, - &ir->props, MODULE_NAME); + err = rc_register_device(rc); if (err) goto err_out_stop; return 0; + err_out_stop: dev->ir = NULL; err_out_free: + rc_free_device(rc); kfree(ir); return err; } @@ -468,8 +462,8 @@ int em28xx_ir_fini(struct em28xx *dev) if (!ir) return 0; - em28xx_ir_stop(ir); - ir_input_unregister(ir->input); + em28xx_ir_stop(ir->rc); + rc_unregister_device(ir->rc); kfree(ir); /* done */ diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index a78883a..83b59a1 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -252,7 +252,7 @@ static void ir_key_poll(struct IR_i2c *ir) } if (rc) - ir_keydown(ir->input, ir_key, 0); + ir_keydown(ir->rc, ir_key, 0); } static void ir_work(struct work_struct *work) @@ -271,20 +271,20 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) const char *name = NULL; u64 ir_type = IR_TYPE_UNKNOWN; struct IR_i2c *ir; - struct input_dev *input_dev; + struct rc_dev *rc; struct i2c_adapter *adap = client->adapter; unsigned short addr = client->addr; int err; ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ir || !input_dev) { + rc = rc_allocate_device(); + if (!ir || !rc) { err = -ENOMEM; goto err_out_free; } ir->c = client; - ir->input = input_dev; + ir->rc = rc; ir->polling_interval = DEFAULT_POLLING_INTERVAL; i2c_set_clientdata(client, ir); @@ -383,16 +383,18 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) dev_name(&client->dev)); /* init + register input device */ - input_dev->id.bustype = BUS_I2C; - input_dev->name = ir->name; - input_dev->phys = ir->phys; + rc->input_id.bustype = BUS_I2C; + rc->input_name = ir->name; + rc->input_phys = ir->phys; + rc->map_name = ir->ir_codes; + rc->driver_name = MODULE_NAME; - err = ir_input_register(ir->input, ir->ir_codes, NULL, MODULE_NAME); + err = rc_register_device(rc); if (err) goto err_out_free; printk(MODULE_NAME ": %s detected at %s [%s]\n", - ir->input->name, ir->input->phys, adap->name); + ir->name, ir->phys, adap->name); /* start polling via eventd */ INIT_DELAYED_WORK(&ir->work, ir_work); @@ -401,6 +403,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) return 0; err_out_free: + rc_free_device(rc); kfree(ir); return err; } @@ -413,7 +416,7 @@ static int ir_remove(struct i2c_client *client) cancel_delayed_work_sync(&ir->work); /* unregister device */ - ir_input_unregister(ir->input); + rc_unregister_device(ir->rc); /* free memory */ kfree(ir); diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 3e37593..fbb2ff1 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include "saa7134-reg.h" @@ -45,14 +44,6 @@ MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=g static int ir_rc5_remote_gap = 885; module_param(ir_rc5_remote_gap, int, 0644); -static int repeat_delay = 500; -module_param(repeat_delay, int, 0644); -MODULE_PARM_DESC(repeat_delay, "delay before key repeat started"); -static int repeat_period = 33; -module_param(repeat_period, int, 0644); -MODULE_PARM_DESC(repeat_period, "repeat period between " - "keypresses when key is down"); - static unsigned int disable_other_ir; module_param(disable_other_ir, int, 0644); MODULE_PARM_DESC(disable_other_ir, "disable full codes of " @@ -523,17 +514,17 @@ void saa7134_ir_stop(struct saa7134_dev *dev) __saa7134_ir_stop(dev); } -static int saa7134_ir_open(void *priv) +static int saa7134_ir_open(struct rc_dev *rc) { - struct saa7134_dev *dev = priv; + struct saa7134_dev *dev = rc->priv; dev->remote->users++; return __saa7134_ir_start(dev); } -static void saa7134_ir_close(void *priv) +static void saa7134_ir_close(struct rc_dev *rc) { - struct saa7134_dev *dev = priv; + struct saa7134_dev *dev = rc->priv; dev->remote->users--; if (!dev->remote->users) @@ -541,9 +532,9 @@ static void saa7134_ir_close(void *priv) } -static int saa7134_ir_change_protocol(void *priv, u64 ir_type) +static int saa7134_ir_change_protocol(struct rc_dev *rc, u64 ir_type) { - struct saa7134_dev *dev = priv; + struct saa7134_dev *dev = rc->priv; struct card_ir *ir = dev->remote; u32 nec_gpio, rc5_gpio; @@ -577,7 +568,7 @@ static int saa7134_ir_change_protocol(void *priv, u64 ir_type) int saa7134_input_init1(struct saa7134_dev *dev) { struct card_ir *ir; - struct input_dev *input_dev; + struct rc_dev *rc; char *ir_codes = NULL; u32 mask_keycode = 0; u32 mask_keydown = 0; @@ -822,13 +813,13 @@ int saa7134_input_init1(struct saa7134_dev *dev) } ir = kzalloc(sizeof(*ir), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ir || !input_dev) { + rc = rc_allocate_device(); + if (!ir || !rc) { err = -ENOMEM; goto err_out_free; } - ir->dev = input_dev; + ir->dev = rc; dev->remote = ir; ir->running = 0; @@ -848,43 +839,40 @@ int saa7134_input_init1(struct saa7134_dev *dev) snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci)); - - ir->props.priv = dev; - ir->props.open = saa7134_ir_open; - ir->props.close = saa7134_ir_close; - + rc->priv = dev; + rc->open = saa7134_ir_open; + rc->close = saa7134_ir_close; if (raw_decode) - ir->props.driver_type = RC_DRIVER_IR_RAW; + rc->driver_type = RC_DRIVER_IR_RAW; if (!raw_decode && allow_protocol_change) { - ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; - ir->props.change_protocol = saa7134_ir_change_protocol; + rc->allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; + rc->change_protocol = saa7134_ir_change_protocol; } - input_dev->name = ir->name; - input_dev->phys = ir->phys; - input_dev->id.bustype = BUS_PCI; - input_dev->id.version = 1; + rc->input_name = ir->name; + rc->input_phys = ir->phys; + rc->input_id.bustype = BUS_PCI; + rc->input_id.version = 1; if (dev->pci->subsystem_vendor) { - input_dev->id.vendor = dev->pci->subsystem_vendor; - input_dev->id.product = dev->pci->subsystem_device; + rc->input_id.vendor = dev->pci->subsystem_vendor; + rc->input_id.product = dev->pci->subsystem_device; } else { - input_dev->id.vendor = dev->pci->vendor; - input_dev->id.product = dev->pci->device; + rc->input_id.vendor = dev->pci->vendor; + rc->input_id.product = dev->pci->device; } - input_dev->dev.parent = &dev->pci->dev; + rc->dev.parent = &dev->pci->dev; + rc->map_name = ir_codes; + rc->driver_name = MODULE_NAME; - err = ir_input_register(ir->dev, ir_codes, &ir->props, MODULE_NAME); + err = rc_register_device(rc); if (err) goto err_out_free; - /* the remote isn't as bouncy as a keyboard */ - ir->dev->rep[REP_DELAY] = repeat_delay; - ir->dev->rep[REP_PERIOD] = repeat_period; - return 0; err_out_free: + rc_free_device(rc); dev->remote = NULL; kfree(ir); return err; @@ -896,7 +884,7 @@ void saa7134_input_fini(struct saa7134_dev *dev) return; saa7134_ir_stop(dev); - ir_input_unregister(dev->remote->dev); + rc_unregister_device(dev->remote->dev); kfree(dev->remote); dev->remote = NULL; } diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/staging/tm6000/tm6000-input.c index 3e74884..3517d20 100644 --- a/drivers/staging/tm6000/tm6000-input.c +++ b/drivers/staging/tm6000/tm6000-input.c @@ -50,7 +50,7 @@ struct tm6000_ir_poll_result { struct tm6000_IR { struct tm6000_core *dev; - struct ir_input_dev *input; + struct rc_dev *rc; char name[32]; char phys[32]; @@ -66,7 +66,6 @@ struct tm6000_IR { /* IR device properties */ u64 ir_type; - struct ir_dev_props props; }; @@ -200,7 +199,7 @@ static void tm6000_ir_handle_key(struct tm6000_IR *ir) dprintk("ir->get_key result data=%04x\n", poll_result.rc_data); if (ir->key) { - ir_keydown(ir->input->input_dev, poll_result.rc_data, 0); + ir_keydown(ir->rc, poll_result.rc_data, 0); ir->key = 0; } return; @@ -214,9 +213,9 @@ static void tm6000_ir_work(struct work_struct *work) schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); } -static int tm6000_ir_start(void *priv) +static int tm6000_ir_start(struct rc_dev *rc) { - struct tm6000_IR *ir = priv; + struct tm6000_IR *ir = rc->priv; INIT_DELAYED_WORK(&ir->work, tm6000_ir_work); schedule_delayed_work(&ir->work, 0); @@ -224,16 +223,16 @@ static int tm6000_ir_start(void *priv) return 0; } -static void tm6000_ir_stop(void *priv) +static void tm6000_ir_stop(struct rc_dev *rc) { - struct tm6000_IR *ir = priv; + struct tm6000_IR *ir = rc->priv; cancel_delayed_work_sync(&ir->work); } -int tm6000_ir_change_protocol(void *priv, u64 ir_type) +int tm6000_ir_change_protocol(struct rc_dev *rc, u64 ir_type) { - struct tm6000_IR *ir = priv; + struct tm6000_IR *ir = rc->priv; ir->get_key = default_polling_getkey; @@ -245,9 +244,9 @@ int tm6000_ir_change_protocol(void *priv, u64 ir_type) int tm6000_ir_init(struct tm6000_core *dev) { struct tm6000_IR *ir; - struct ir_input_dev *ir_input_dev; + struct rc_dev *rc; int err = -ENOMEM; - int pipe, size, rc; + int pipe, size; if (!enable_ir) return -ENODEV; @@ -259,24 +258,22 @@ int tm6000_ir_init(struct tm6000_core *dev) return 0; ir = kzalloc(sizeof(*ir), GFP_KERNEL); - ir_input_dev = kzalloc(sizeof(*ir_input_dev), GFP_KERNEL); - ir_input_dev->input_dev = input_allocate_device(); - if (!ir || !ir_input_dev || !ir_input_dev->input_dev) - goto err_out_free; + rc = rc_allocate_device(); + if (!ir | !rc) + goto out; /* record handles to ourself */ ir->dev = dev; dev->ir = ir; - - ir->input = ir_input_dev; + ir->rc = rc; /* input einrichten */ - ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; - ir->props.priv = ir; - ir->props.change_protocol = tm6000_ir_change_protocol; - ir->props.open = tm6000_ir_start; - ir->props.close = tm6000_ir_stop; - ir->props.driver_type = RC_DRIVER_SCANCODE; + rc->allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; + rc->priv = ir; + rc->change_protocol = tm6000_ir_change_protocol; + rc->open = tm6000_ir_start; + rc->close = tm6000_ir_stop; + rc->driver_type = RC_DRIVER_SCANCODE; ir->polling = 50; @@ -286,16 +283,17 @@ int tm6000_ir_init(struct tm6000_core *dev) usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); strlcat(ir->phys, "/input0", sizeof(ir->phys)); - tm6000_ir_change_protocol(ir, IR_TYPE_UNKNOWN); - - ir_input_dev->input_dev->name = ir->name; - ir_input_dev->input_dev->phys = ir->phys; - ir_input_dev->input_dev->id.bustype = BUS_USB; - ir_input_dev->input_dev->id.version = 1; - ir_input_dev->input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); - ir_input_dev->input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); + tm6000_ir_change_protocol(rc, IR_TYPE_UNKNOWN); - ir_input_dev->input_dev->dev.parent = &dev->udev->dev; + rc->input_name = ir->name; + rc->input_phys = ir->phys; + rc->input_id.bustype = BUS_USB; + rc->input_id.version = 1; + rc->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); + rc->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct); + rc->map_name = dev->ir_codes; + rc->driver_name = "tm6000"; + rc->dev.parent = &dev->udev->dev; if (&dev->int_in) { dprintk("IR over int\n"); @@ -312,35 +310,32 @@ int tm6000_ir_init(struct tm6000_core *dev) ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL); if (ir->int_urb->transfer_buffer == NULL) { usb_free_urb(ir->int_urb); - goto err_out_stop; + goto out; } dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval); usb_fill_int_urb(ir->int_urb, dev->udev, pipe, ir->int_urb->transfer_buffer, size, tm6000_ir_urb_received, dev, dev->int_in.endp->desc.bInterval); - rc = usb_submit_urb(ir->int_urb, GFP_KERNEL); - if (rc) { + err = usb_submit_urb(ir->int_urb, GFP_KERNEL); + if (err) { kfree(ir->int_urb->transfer_buffer); usb_free_urb(ir->int_urb); - err = rc; - goto err_out_stop; + goto out; } ir->urb_data = kzalloc(size, GFP_KERNEL); } /* ir register */ - err = ir_input_register(ir->input->input_dev, dev->ir_codes, - &ir->props, "tm6000"); + err = rc_register_device(rc); if (err) - goto err_out_stop; + goto out; return 0; -err_out_stop: +out: dev->ir = NULL; -err_out_free: - kfree(ir_input_dev); + rc_free_device(rc); kfree(ir); return err; } @@ -354,7 +349,7 @@ int tm6000_ir_fini(struct tm6000_core *dev) if (!ir) return 0; - ir_input_unregister(ir->input->input_dev); + rc_unregister_device(ir->rc); if (ir->int_urb) { usb_kill_urb(ir->int_urb); @@ -365,8 +360,6 @@ int tm6000_ir_fini(struct tm6000_core *dev) ir->urb_data = NULL; } - kfree(ir->input); - ir->input = NULL; kfree(ir); dev->ir = NULL; diff --git a/include/media/ir-common.h b/include/media/ir-common.h index d1ae869f..41fefd9 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -36,12 +36,11 @@ /* this was saa7134_ir and bttv_ir, moved here for * rc5 decoding. */ struct card_ir { - struct input_dev *dev; + struct rc_dev *dev; char name[32]; char phys[32]; int users; u32 running:1; - struct ir_dev_props props; /* Usual gpio signalling */ u32 mask_keycode; diff --git a/include/media/ir-core.h b/include/media/ir-core.h index d41502d..c590998 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h @@ -32,21 +32,38 @@ enum rc_driver_type { }; /** - * struct ir_dev_props - Allow caller drivers to set special properties - * @driver_type: specifies if the driver or hardware have already a decoder, - * or if it needs to use the IR raw event decoders to produce a scancode + * struct rc_dev - represents a remote control device + * @dev: driver model's view of this device + * @input_name: name of the input child device + * @input_phys: physical path to the input child device + * @input_id: id of the input child device (struct input_id) + * @driver_name: name of the hardware driver which registered this device + * @map_name: name of the default keymap + * @rc_tab: current scan/key table + * @devno: unique remote control device number + * @raw: additional data for raw pulse/space devices + * @input_dev: the input child device used to communicate events to userspace + * @driver_type: specifies if protocol decoding is done in hardware or software + * @idle: used to keep track of RX state * @allowed_protos: bitmask with the supported IR_TYPE_* protocols * @scanmask: some hardware decoders are not capable of providing the full * scancode to the application. As this is a hardware limit, we can't do * anything with it. Yet, as the same keycode table can be used with other * devices, a mask is provided to allow its usage. Drivers should generally * leave this field in blank + * @priv: driver-specific data + * @keylock: protects the remaining members of the struct + * @keypressed: whether a key is currently pressed + * @keyup_jiffies: time (in jiffies) when the current keypress should be released + * @timer_keyup: timer for releasing a keypress + * @last_keycode: keycode of last keypress + * @last_scancode: scancode of last keypress + * @last_toggle: toggle value of last command * @timeout: optional time after which device stops sending data * @min_timeout: minimum timeout supported by device * @max_timeout: maximum timeout supported by device * @rx_resolution : resolution (in ns) of input sampler * @tx_resolution: resolution (in ns) of output sampler - * @priv: driver-specific data, to be used on the callbacks * @change_protocol: allow changing the protocol used on hardware decoders * @open: callback to allow drivers to enable polling/irq when IR input device * is opened. @@ -57,55 +74,50 @@ enum rc_driver_type { * @s_tx_duty_cycle: set transmit duty cycle (0% - 100%) * @s_rx_carrier: inform driver about carrier it is expected to handle * @tx_ir: transmit IR - * @s_idle: optional: enable/disable hardware idle mode, upon which, - device doesn't interrupt host until it sees IR pulses + * @s_idle: enable/disable hardware idle mode, upon which, + * device doesn't interrupt host until it sees IR pulses * @s_learning_mode: enable wide band receiver used for learning * @s_carrier_report: enable carrier reports */ -struct ir_dev_props { - enum rc_driver_type driver_type; - unsigned long allowed_protos; - u32 scanmask; - - u32 timeout; - u32 min_timeout; - u32 max_timeout; - - u32 rx_resolution; - u32 tx_resolution; - - void *priv; - int (*change_protocol)(void *priv, u64 ir_type); - int (*open)(void *priv); - void (*close)(void *priv); - int (*s_tx_mask)(void *priv, u32 mask); - int (*s_tx_carrier)(void *priv, u32 carrier); - int (*s_tx_duty_cycle)(void *priv, u32 duty_cycle); - int (*s_rx_carrier_range)(void *priv, u32 min, u32 max); - int (*tx_ir)(void *priv, int *txbuf, u32 n); - void (*s_idle)(void *priv, bool enable); - int (*s_learning_mode)(void *priv, int enable); - int (*s_carrier_report) (void *priv, int enable); -}; - -struct ir_input_dev { - struct device dev; /* device */ - char *driver_name; /* Name of the driver module */ - struct ir_scancode_table rc_tab; /* scan/key table */ - unsigned long devno; /* device number */ - struct ir_dev_props *props; /* Device properties */ - struct ir_raw_event_ctrl *raw; /* for raw pulse/space events */ - struct input_dev *input_dev; /* the input device associated with this device */ +struct rc_dev { + struct device dev; + const char *input_name; + const char *input_phys; + struct input_id input_id; + char *driver_name; + const char *map_name; + struct ir_scancode_table rc_tab; + unsigned long devno; + struct ir_raw_event_ctrl *raw; + struct input_dev *input_dev; + enum rc_driver_type driver_type; bool idle; - - /* key info - needed by IR keycode handlers */ - spinlock_t keylock; /* protects the below members */ - bool keypressed; /* current state */ - unsigned long keyup_jiffies; /* when should the current keypress be released? */ - struct timer_list timer_keyup; /* timer for releasing a keypress */ - u32 last_keycode; /* keycode of last command */ - u32 last_scancode; /* scancode of last command */ - u8 last_toggle; /* toggle of last command */ + u64 allowed_protos; + u32 scanmask; + void *priv; + spinlock_t keylock; + bool keypressed; + unsigned long keyup_jiffies; + struct timer_list timer_keyup; + u32 last_keycode; + u32 last_scancode; + u8 last_toggle; + u32 timeout; + u32 min_timeout; + u32 max_timeout; + u32 rx_resolution; + u32 tx_resolution; + int (*change_protocol)(struct rc_dev *dev, u64 ir_type); + int (*open)(struct rc_dev *dev); + void (*close)(struct rc_dev *dev); + int (*s_tx_mask)(struct rc_dev *dev, u32 mask); + int (*s_tx_carrier)(struct rc_dev *dev, u32 carrier); + int (*s_tx_duty_cycle)(struct rc_dev *dev, u32 duty_cycle); + int (*s_rx_carrier_range)(struct rc_dev *dev, u32 min, u32 max); + int (*tx_ir)(struct rc_dev *dev, int *txbuf, u32 n); + void (*s_idle)(struct rc_dev *dev, bool enable); + int (*s_learning_mode)(struct rc_dev *dev, int enable); + int (*s_carrier_report) (struct rc_dev *dev, int enable); }; enum raw_event_type { @@ -115,52 +127,14 @@ enum raw_event_type { IR_STOP_EVENT = (1 << 3), }; -#define to_ir_input_dev(_attr) container_of(_attr, struct ir_input_dev, attr) - -int __ir_input_register(struct input_dev *dev, - const struct ir_scancode_table *ir_codes, - struct ir_dev_props *props, - const char *driver_name); - -static inline int ir_input_register(struct input_dev *dev, - const char *map_name, - struct ir_dev_props *props, - const char *driver_name) { - struct ir_scancode_table *ir_codes; - struct ir_input_dev *ir_dev; - int rc; - - if (!map_name) - return -EINVAL; - - ir_codes = get_rc_map(map_name); - if (!ir_codes) { - ir_codes = get_rc_map(RC_MAP_EMPTY); +#define to_rc_dev(d) container_of(d, struct rc_dev, dev) - if (!ir_codes) - return -EINVAL; - } - rc = __ir_input_register(dev, ir_codes, props, driver_name); - if (rc < 0) - return -EINVAL; - - ir_dev = input_get_drvdata(dev); - - if (!rc && ir_dev->props && ir_dev->props->change_protocol) - rc = ir_dev->props->change_protocol(ir_dev->props->priv, - ir_codes->ir_type); - - return rc; -} - -void ir_input_unregister(struct input_dev *input_dev); - -void ir_repeat(struct input_dev *dev); -void ir_keydown(struct input_dev *dev, int scancode, u8 toggle); -void ir_keydown_notimeout(struct input_dev *dev, int scancode, u8 toggle); -void ir_keyup(struct input_dev *dev); -u32 ir_g_keycode_from_table(struct input_dev *input_dev, u32 scancode); +void ir_repeat(struct rc_dev *dev); +void ir_keydown(struct rc_dev *dev, int scancode, u8 toggle); +void ir_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle); +void ir_keyup(struct rc_dev *dev); +u32 ir_g_keycode_from_table(struct rc_dev *dev, u32 scancode); /* From ir-raw-event.c */ struct ir_raw_event { @@ -194,20 +168,25 @@ static inline void init_ir_raw_event(struct ir_raw_event *ev) #define IR_MAX_DURATION 0xFFFFFFFF /* a bit more than 4 seconds */ -void ir_raw_event_handle(struct input_dev *input_dev); -int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev); -int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type); -int ir_raw_event_store_with_filter(struct input_dev *input_dev, +struct rc_dev *rc_allocate_device(void); +void rc_free_device(struct rc_dev *dev); +int rc_register_device(struct rc_dev *dev); +void rc_unregister_device(struct rc_dev *dev); + +void ir_raw_event_handle(struct rc_dev *dev); +int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev); +int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type); +int ir_raw_event_store_with_filter(struct rc_dev *dev, struct ir_raw_event *ev); -void ir_raw_event_set_idle(struct input_dev *input_dev, bool idle); +void ir_raw_event_set_idle(struct rc_dev *dev, bool idle); -static inline void ir_raw_event_reset(struct input_dev *input_dev) +static inline void ir_raw_event_reset(struct rc_dev *dev) { DEFINE_IR_RAW_EVENT(ev); ev.reset = true; - ir_raw_event_store(input_dev, &ev); - ir_raw_event_handle(input_dev); + ir_raw_event_store(dev, &ev); + ir_raw_event_handle(dev); } diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h index 8c37b5e..4ee9b42 100644 --- a/include/media/ir-kbd-i2c.h +++ b/include/media/ir-kbd-i2c.h @@ -9,9 +9,8 @@ struct IR_i2c; struct IR_i2c { char *ir_codes; - struct i2c_client *c; - struct input_dev *input; + struct rc_dev *rc; /* Used to avoid fast repeating */ unsigned char old; -- cgit v0.10.2 From 5b2e303f6df1e0b1a903950c5d613a20c8c71a37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Fri, 29 Oct 2010 16:08:28 -0300 Subject: [media] rc-core: convert winbond-cir MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move winbond-cir from drivers/input/misc/ into drivers/media/rc/ and convert it to use rc-core. Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index b99b8cb..c1a81bc 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -294,24 +294,6 @@ config INPUT_SGI_BTNS To compile this driver as a module, choose M here: the module will be called sgi_btns. -config INPUT_WINBOND_CIR - tristate "Winbond IR remote control" - depends on X86 && PNP - select NEW_LEDS - select LEDS_CLASS - select LEDS_TRIGGERS - select BITREVERSE - help - Say Y here if you want to use the IR remote functionality found - in some Winbond SuperI/O chips. Currently only the WPCD376I - chip is supported (included in some Intel Media series motherboards). - - IR Receive and wake-on-IR from suspend and power-off is currently - supported. - - To compile this driver as a module, choose M here: the module will be - called winbond_cir. - config HP_SDC_RTC tristate "HP SDC Real Time Clock" depends on (GSC || HP300) && SERIO diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 1fe1f6c..06b2b51 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -38,7 +38,6 @@ obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o obj-$(CONFIG_INPUT_UINPUT) += uinput.o -obj-$(CONFIG_INPUT_WINBOND_CIR) += winbond-cir.o obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o obj-$(CONFIG_INPUT_YEALINK) += yealink.o diff --git a/drivers/input/misc/winbond-cir.c b/drivers/input/misc/winbond-cir.c deleted file mode 100644 index 64f1de7..0000000 --- a/drivers/input/misc/winbond-cir.c +++ /dev/null @@ -1,1608 +0,0 @@ -/* - * winbond-cir.c - Driver for the Consumer IR functionality of Winbond - * SuperI/O chips. - * - * Currently supports the Winbond WPCD376i chip (PNP id WEC1022), but - * could probably support others (Winbond WEC102X, NatSemi, etc) - * with minor modifications. - * - * Original Author: David Härdeman - * Copyright (C) 2009 David Härdeman - * - * Dedicated to Matilda, my newborn daughter, without whose loving attention - * this driver would have been finished in half the time and with a fraction - * of the bugs. - * - * Written using: - * o Winbond WPCD376I datasheet helpfully provided by Jesse Barnes at Intel - * o NatSemi PC87338/PC97338 datasheet (for the serial port stuff) - * o DSDT dumps - * - * Supported features: - * o RC6 - * o Wake-On-CIR functionality - * - * To do: - * o Test NEC and RC5 - * - * Left as an exercise for the reader: - * o Learning (I have neither the hardware, nor the need) - * o IR Transmit (ibid) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRVNAME "winbond-cir" - -/* CEIR Wake-Up Registers, relative to data->wbase */ -#define WBCIR_REG_WCEIR_CTL 0x03 /* CEIR Receiver Control */ -#define WBCIR_REG_WCEIR_STS 0x04 /* CEIR Receiver Status */ -#define WBCIR_REG_WCEIR_EV_EN 0x05 /* CEIR Receiver Event Enable */ -#define WBCIR_REG_WCEIR_CNTL 0x06 /* CEIR Receiver Counter Low */ -#define WBCIR_REG_WCEIR_CNTH 0x07 /* CEIR Receiver Counter High */ -#define WBCIR_REG_WCEIR_INDEX 0x08 /* CEIR Receiver Index */ -#define WBCIR_REG_WCEIR_DATA 0x09 /* CEIR Receiver Data */ -#define WBCIR_REG_WCEIR_CSL 0x0A /* CEIR Re. Compare Strlen */ -#define WBCIR_REG_WCEIR_CFG1 0x0B /* CEIR Re. Configuration 1 */ -#define WBCIR_REG_WCEIR_CFG2 0x0C /* CEIR Re. Configuration 2 */ - -/* CEIR Enhanced Functionality Registers, relative to data->ebase */ -#define WBCIR_REG_ECEIR_CTS 0x00 /* Enhanced IR Control Status */ -#define WBCIR_REG_ECEIR_CCTL 0x01 /* Infrared Counter Control */ -#define WBCIR_REG_ECEIR_CNT_LO 0x02 /* Infrared Counter LSB */ -#define WBCIR_REG_ECEIR_CNT_HI 0x03 /* Infrared Counter MSB */ -#define WBCIR_REG_ECEIR_IREM 0x04 /* Infrared Emitter Status */ - -/* SP3 Banked Registers, relative to data->sbase */ -#define WBCIR_REG_SP3_BSR 0x03 /* Bank Select, all banks */ - /* Bank 0 */ -#define WBCIR_REG_SP3_RXDATA 0x00 /* FIFO RX data (r) */ -#define WBCIR_REG_SP3_TXDATA 0x00 /* FIFO TX data (w) */ -#define WBCIR_REG_SP3_IER 0x01 /* Interrupt Enable */ -#define WBCIR_REG_SP3_EIR 0x02 /* Event Identification (r) */ -#define WBCIR_REG_SP3_FCR 0x02 /* FIFO Control (w) */ -#define WBCIR_REG_SP3_MCR 0x04 /* Mode Control */ -#define WBCIR_REG_SP3_LSR 0x05 /* Link Status */ -#define WBCIR_REG_SP3_MSR 0x06 /* Modem Status */ -#define WBCIR_REG_SP3_ASCR 0x07 /* Aux Status and Control */ - /* Bank 2 */ -#define WBCIR_REG_SP3_BGDL 0x00 /* Baud Divisor LSB */ -#define WBCIR_REG_SP3_BGDH 0x01 /* Baud Divisor MSB */ -#define WBCIR_REG_SP3_EXCR1 0x02 /* Extended Control 1 */ -#define WBCIR_REG_SP3_EXCR2 0x04 /* Extended Control 2 */ -#define WBCIR_REG_SP3_TXFLV 0x06 /* TX FIFO Level */ -#define WBCIR_REG_SP3_RXFLV 0x07 /* RX FIFO Level */ - /* Bank 3 */ -#define WBCIR_REG_SP3_MRID 0x00 /* Module Identification */ -#define WBCIR_REG_SP3_SH_LCR 0x01 /* LCR Shadow */ -#define WBCIR_REG_SP3_SH_FCR 0x02 /* FCR Shadow */ - /* Bank 4 */ -#define WBCIR_REG_SP3_IRCR1 0x02 /* Infrared Control 1 */ - /* Bank 5 */ -#define WBCIR_REG_SP3_IRCR2 0x04 /* Infrared Control 2 */ - /* Bank 6 */ -#define WBCIR_REG_SP3_IRCR3 0x00 /* Infrared Control 3 */ -#define WBCIR_REG_SP3_SIR_PW 0x02 /* SIR Pulse Width */ - /* Bank 7 */ -#define WBCIR_REG_SP3_IRRXDC 0x00 /* IR RX Demod Control */ -#define WBCIR_REG_SP3_IRTXMC 0x01 /* IR TX Mod Control */ -#define WBCIR_REG_SP3_RCCFG 0x02 /* CEIR Config */ -#define WBCIR_REG_SP3_IRCFG1 0x04 /* Infrared Config 1 */ -#define WBCIR_REG_SP3_IRCFG4 0x07 /* Infrared Config 4 */ - -/* - * Magic values follow - */ - -/* No interrupts for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ -#define WBCIR_IRQ_NONE 0x00 -/* RX data bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ -#define WBCIR_IRQ_RX 0x01 -/* Over/Under-flow bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ -#define WBCIR_IRQ_ERR 0x04 -/* Led enable/disable bit for WBCIR_REG_ECEIR_CTS */ -#define WBCIR_LED_ENABLE 0x80 -/* RX data available bit for WBCIR_REG_SP3_LSR */ -#define WBCIR_RX_AVAIL 0x01 -/* RX disable bit for WBCIR_REG_SP3_ASCR */ -#define WBCIR_RX_DISABLE 0x20 -/* Extended mode enable bit for WBCIR_REG_SP3_EXCR1 */ -#define WBCIR_EXT_ENABLE 0x01 -/* Select compare register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */ -#define WBCIR_REGSEL_COMPARE 0x10 -/* Select mask register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */ -#define WBCIR_REGSEL_MASK 0x20 -/* Starting address of selected register in WBCIR_REG_WCEIR_INDEX */ -#define WBCIR_REG_ADDR0 0x00 - -/* Valid banks for the SP3 UART */ -enum wbcir_bank { - WBCIR_BANK_0 = 0x00, - WBCIR_BANK_1 = 0x80, - WBCIR_BANK_2 = 0xE0, - WBCIR_BANK_3 = 0xE4, - WBCIR_BANK_4 = 0xE8, - WBCIR_BANK_5 = 0xEC, - WBCIR_BANK_6 = 0xF0, - WBCIR_BANK_7 = 0xF4, -}; - -/* Supported IR Protocols */ -enum wbcir_protocol { - IR_PROTOCOL_RC5 = 0x0, - IR_PROTOCOL_NEC = 0x1, - IR_PROTOCOL_RC6 = 0x2, -}; - -/* Misc */ -#define WBCIR_NAME "Winbond CIR" -#define WBCIR_ID_FAMILY 0xF1 /* Family ID for the WPCD376I */ -#define WBCIR_ID_CHIP 0x04 /* Chip ID for the WPCD376I */ -#define IR_KEYPRESS_TIMEOUT 250 /* FIXME: should be per-protocol? */ -#define INVALID_SCANCODE 0x7FFFFFFF /* Invalid with all protos */ -#define WAKEUP_IOMEM_LEN 0x10 /* Wake-Up I/O Reg Len */ -#define EHFUNC_IOMEM_LEN 0x10 /* Enhanced Func I/O Reg Len */ -#define SP_IOMEM_LEN 0x08 /* Serial Port 3 (IR) Reg Len */ -#define WBCIR_MAX_IDLE_BYTES 10 - -static DEFINE_SPINLOCK(wbcir_lock); -static DEFINE_RWLOCK(keytable_lock); - -struct wbcir_key { - u32 scancode; - unsigned int keycode; -}; - -struct wbcir_keyentry { - struct wbcir_key key; - struct list_head list; -}; - -static struct wbcir_key rc6_def_keymap[] = { - { 0x800F0400, KEY_NUMERIC_0 }, - { 0x800F0401, KEY_NUMERIC_1 }, - { 0x800F0402, KEY_NUMERIC_2 }, - { 0x800F0403, KEY_NUMERIC_3 }, - { 0x800F0404, KEY_NUMERIC_4 }, - { 0x800F0405, KEY_NUMERIC_5 }, - { 0x800F0406, KEY_NUMERIC_6 }, - { 0x800F0407, KEY_NUMERIC_7 }, - { 0x800F0408, KEY_NUMERIC_8 }, - { 0x800F0409, KEY_NUMERIC_9 }, - { 0x800F041D, KEY_NUMERIC_STAR }, - { 0x800F041C, KEY_NUMERIC_POUND }, - { 0x800F0410, KEY_VOLUMEUP }, - { 0x800F0411, KEY_VOLUMEDOWN }, - { 0x800F0412, KEY_CHANNELUP }, - { 0x800F0413, KEY_CHANNELDOWN }, - { 0x800F040E, KEY_MUTE }, - { 0x800F040D, KEY_VENDOR }, /* Vista Logo Key */ - { 0x800F041E, KEY_UP }, - { 0x800F041F, KEY_DOWN }, - { 0x800F0420, KEY_LEFT }, - { 0x800F0421, KEY_RIGHT }, - { 0x800F0422, KEY_OK }, - { 0x800F0423, KEY_ESC }, - { 0x800F040F, KEY_INFO }, - { 0x800F040A, KEY_CLEAR }, - { 0x800F040B, KEY_ENTER }, - { 0x800F045B, KEY_RED }, - { 0x800F045C, KEY_GREEN }, - { 0x800F045D, KEY_YELLOW }, - { 0x800F045E, KEY_BLUE }, - { 0x800F045A, KEY_TEXT }, - { 0x800F0427, KEY_SWITCHVIDEOMODE }, - { 0x800F040C, KEY_POWER }, - { 0x800F0450, KEY_RADIO }, - { 0x800F0448, KEY_PVR }, - { 0x800F0447, KEY_AUDIO }, - { 0x800F0426, KEY_EPG }, - { 0x800F0449, KEY_CAMERA }, - { 0x800F0425, KEY_TV }, - { 0x800F044A, KEY_VIDEO }, - { 0x800F0424, KEY_DVD }, - { 0x800F0416, KEY_PLAY }, - { 0x800F0418, KEY_PAUSE }, - { 0x800F0419, KEY_STOP }, - { 0x800F0414, KEY_FASTFORWARD }, - { 0x800F041A, KEY_NEXT }, - { 0x800F041B, KEY_PREVIOUS }, - { 0x800F0415, KEY_REWIND }, - { 0x800F0417, KEY_RECORD }, -}; - -/* Registers and other state is protected by wbcir_lock */ -struct wbcir_data { - unsigned long wbase; /* Wake-Up Baseaddr */ - unsigned long ebase; /* Enhanced Func. Baseaddr */ - unsigned long sbase; /* Serial Port Baseaddr */ - unsigned int irq; /* Serial Port IRQ */ - - struct input_dev *input_dev; - struct timer_list timer_keyup; - struct led_trigger *rxtrigger; - struct led_trigger *txtrigger; - struct led_classdev led; - - u32 last_scancode; - unsigned int last_keycode; - u8 last_toggle; - u8 keypressed; - unsigned long keyup_jiffies; - unsigned int idle_count; - - /* RX irdata and parsing state */ - unsigned long irdata[30]; - unsigned int irdata_count; - unsigned int irdata_idle; - unsigned int irdata_off; - unsigned int irdata_error; - - /* Protected by keytable_lock */ - struct list_head keytable; -}; - -static enum wbcir_protocol protocol = IR_PROTOCOL_RC6; -module_param(protocol, uint, 0444); -MODULE_PARM_DESC(protocol, "IR protocol to use " - "(0 = RC5, 1 = NEC, 2 = RC6A, default)"); - -static int invert; /* default = 0 */ -module_param(invert, bool, 0444); -MODULE_PARM_DESC(invert, "Invert the signal from the IR receiver"); - -static unsigned int wake_sc = 0x800F040C; -module_param(wake_sc, uint, 0644); -MODULE_PARM_DESC(wake_sc, "Scancode of the power-on IR command"); - -static unsigned int wake_rc6mode = 6; -module_param(wake_rc6mode, uint, 0644); -MODULE_PARM_DESC(wake_rc6mode, "RC6 mode for the power-on command " - "(0 = 0, 6 = 6A, default)"); - - - -/***************************************************************************** - * - * UTILITY FUNCTIONS - * - *****************************************************************************/ - -/* Caller needs to hold wbcir_lock */ -static void -wbcir_set_bits(unsigned long addr, u8 bits, u8 mask) -{ - u8 val; - - val = inb(addr); - val = ((val & ~mask) | (bits & mask)); - outb(val, addr); -} - -/* Selects the register bank for the serial port */ -static inline void -wbcir_select_bank(struct wbcir_data *data, enum wbcir_bank bank) -{ - outb(bank, data->sbase + WBCIR_REG_SP3_BSR); -} - -static enum led_brightness -wbcir_led_brightness_get(struct led_classdev *led_cdev) -{ - struct wbcir_data *data = container_of(led_cdev, - struct wbcir_data, - led); - - if (inb(data->ebase + WBCIR_REG_ECEIR_CTS) & WBCIR_LED_ENABLE) - return LED_FULL; - else - return LED_OFF; -} - -static void -wbcir_led_brightness_set(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - struct wbcir_data *data = container_of(led_cdev, - struct wbcir_data, - led); - - wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CTS, - brightness == LED_OFF ? 0x00 : WBCIR_LED_ENABLE, - WBCIR_LED_ENABLE); -} - -/* Manchester encodes bits to RC6 message cells (see wbcir_parse_rc6) */ -static u8 -wbcir_to_rc6cells(u8 val) -{ - u8 coded = 0x00; - int i; - - val &= 0x0F; - for (i = 0; i < 4; i++) { - if (val & 0x01) - coded |= 0x02 << (i * 2); - else - coded |= 0x01 << (i * 2); - val >>= 1; - } - - return coded; -} - - - -/***************************************************************************** - * - * INPUT FUNCTIONS - * - *****************************************************************************/ - -static unsigned int -wbcir_do_getkeycode(struct wbcir_data *data, u32 scancode) -{ - struct wbcir_keyentry *keyentry; - unsigned int keycode = KEY_RESERVED; - unsigned long flags; - - read_lock_irqsave(&keytable_lock, flags); - - list_for_each_entry(keyentry, &data->keytable, list) { - if (keyentry->key.scancode == scancode) { - keycode = keyentry->key.keycode; - break; - } - } - - read_unlock_irqrestore(&keytable_lock, flags); - return keycode; -} - -static int -wbcir_getkeycode(struct input_dev *dev, - unsigned int scancode, unsigned int *keycode) -{ - struct wbcir_data *data = input_get_drvdata(dev); - - *keycode = wbcir_do_getkeycode(data, scancode); - return 0; -} - -static int -wbcir_setkeycode(struct input_dev *dev, - unsigned int scancode, unsigned int keycode) -{ - struct wbcir_data *data = input_get_drvdata(dev); - struct wbcir_keyentry *keyentry; - struct wbcir_keyentry *new_keyentry; - unsigned long flags; - unsigned int old_keycode = KEY_RESERVED; - - new_keyentry = kmalloc(sizeof(*new_keyentry), GFP_KERNEL); - if (!new_keyentry) - return -ENOMEM; - - write_lock_irqsave(&keytable_lock, flags); - - list_for_each_entry(keyentry, &data->keytable, list) { - if (keyentry->key.scancode != scancode) - continue; - - old_keycode = keyentry->key.keycode; - keyentry->key.keycode = keycode; - - if (keyentry->key.keycode == KEY_RESERVED) { - list_del(&keyentry->list); - kfree(keyentry); - } - - break; - } - - set_bit(keycode, dev->keybit); - - if (old_keycode == KEY_RESERVED) { - new_keyentry->key.scancode = scancode; - new_keyentry->key.keycode = keycode; - list_add(&new_keyentry->list, &data->keytable); - } else { - kfree(new_keyentry); - clear_bit(old_keycode, dev->keybit); - list_for_each_entry(keyentry, &data->keytable, list) { - if (keyentry->key.keycode == old_keycode) { - set_bit(old_keycode, dev->keybit); - break; - } - } - } - - write_unlock_irqrestore(&keytable_lock, flags); - return 0; -} - -/* - * Timer function to report keyup event some time after keydown is - * reported by the ISR. - */ -static void -wbcir_keyup(unsigned long cookie) -{ - struct wbcir_data *data = (struct wbcir_data *)cookie; - unsigned long flags; - - /* - * data->keyup_jiffies is used to prevent a race condition if a - * hardware interrupt occurs at this point and the keyup timer - * event is moved further into the future as a result. - * - * The timer will then be reactivated and this function called - * again in the future. We need to exit gracefully in that case - * to allow the input subsystem to do its auto-repeat magic or - * a keyup event might follow immediately after the keydown. - */ - - spin_lock_irqsave(&wbcir_lock, flags); - - if (time_is_after_eq_jiffies(data->keyup_jiffies) && data->keypressed) { - data->keypressed = 0; - led_trigger_event(data->rxtrigger, LED_OFF); - input_report_key(data->input_dev, data->last_keycode, 0); - input_sync(data->input_dev); - } - - spin_unlock_irqrestore(&wbcir_lock, flags); -} - -static void -wbcir_keydown(struct wbcir_data *data, u32 scancode, u8 toggle) -{ - unsigned int keycode; - - /* Repeat? */ - if (data->last_scancode == scancode && - data->last_toggle == toggle && - data->keypressed) - goto set_timer; - data->last_scancode = scancode; - - /* Do we need to release an old keypress? */ - if (data->keypressed) { - input_report_key(data->input_dev, data->last_keycode, 0); - input_sync(data->input_dev); - data->keypressed = 0; - } - - /* Report scancode */ - input_event(data->input_dev, EV_MSC, MSC_SCAN, (int)scancode); - - /* Do we know this scancode? */ - keycode = wbcir_do_getkeycode(data, scancode); - if (keycode == KEY_RESERVED) - goto set_timer; - - /* Register a keypress */ - input_report_key(data->input_dev, keycode, 1); - data->keypressed = 1; - data->last_keycode = keycode; - data->last_toggle = toggle; - -set_timer: - input_sync(data->input_dev); - led_trigger_event(data->rxtrigger, - data->keypressed ? LED_FULL : LED_OFF); - data->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); - mod_timer(&data->timer_keyup, data->keyup_jiffies); -} - - - -/***************************************************************************** - * - * IR PARSING FUNCTIONS - * - *****************************************************************************/ - -/* Resets all irdata */ -static void -wbcir_reset_irdata(struct wbcir_data *data) -{ - memset(data->irdata, 0, sizeof(data->irdata)); - data->irdata_count = 0; - data->irdata_off = 0; - data->irdata_error = 0; - data->idle_count = 0; -} - -/* Adds one bit of irdata */ -static void -add_irdata_bit(struct wbcir_data *data, int set) -{ - if (data->irdata_count >= sizeof(data->irdata) * 8) { - data->irdata_error = 1; - return; - } - - if (set) - __set_bit(data->irdata_count, data->irdata); - data->irdata_count++; -} - -/* Gets count bits of irdata */ -static u16 -get_bits(struct wbcir_data *data, int count) -{ - u16 val = 0x0; - - if (data->irdata_count - data->irdata_off < count) { - data->irdata_error = 1; - return 0x0; - } - - while (count > 0) { - val <<= 1; - if (test_bit(data->irdata_off, data->irdata)) - val |= 0x1; - count--; - data->irdata_off++; - } - - return val; -} - -/* Reads 16 cells and converts them to a byte */ -static u8 -wbcir_rc6cells_to_byte(struct wbcir_data *data) -{ - u16 raw = get_bits(data, 16); - u8 val = 0x00; - int bit; - - for (bit = 0; bit < 8; bit++) { - switch (raw & 0x03) { - case 0x01: - break; - case 0x02: - val |= (0x01 << bit); - break; - default: - data->irdata_error = 1; - break; - } - raw >>= 2; - } - - return val; -} - -/* Decodes a number of bits from raw RC5 data */ -static u8 -wbcir_get_rc5bits(struct wbcir_data *data, unsigned int count) -{ - u16 raw = get_bits(data, count * 2); - u8 val = 0x00; - int bit; - - for (bit = 0; bit < count; bit++) { - switch (raw & 0x03) { - case 0x01: - val |= (0x01 << bit); - break; - case 0x02: - break; - default: - data->irdata_error = 1; - break; - } - raw >>= 2; - } - - return val; -} - -static void -wbcir_parse_rc6(struct device *dev, struct wbcir_data *data) -{ - /* - * Normal bits are manchester coded as follows: - * cell0 + cell1 = logic "0" - * cell1 + cell0 = logic "1" - * - * The IR pulse has the following components: - * - * Leader - 6 * cell1 - discarded - * Gap - 2 * cell0 - discarded - * Start bit - Normal Coding - always "1" - * Mode Bit 2 - 0 - Normal Coding - * Toggle bit - Normal Coding with double bit time, - * e.g. cell0 + cell0 + cell1 + cell1 - * means logic "0". - * - * The rest depends on the mode, the following modes are known: - * - * MODE 0: - * Address Bit 7 - 0 - Normal Coding - * Command Bit 7 - 0 - Normal Coding - * - * MODE 6: - * The above Toggle Bit is used as a submode bit, 0 = A, 1 = B. - * Submode B is for pointing devices, only remotes using submode A - * are supported. - * - * Customer range bit - 0 => Customer = 7 bits, 0...127 - * 1 => Customer = 15 bits, 32768...65535 - * Customer Bits - Normal Coding - * - * Customer codes are allocated by Philips. The rest of the bits - * are customer dependent. The following is commonly used (and the - * only supported config): - * - * Toggle Bit - Normal Coding - * Address Bit 6 - 0 - Normal Coding - * Command Bit 7 - 0 - Normal Coding - * - * All modes are followed by at least 6 * cell0. - * - * MODE 0 msglen: - * 1 * 2 (start bit) + 3 * 2 (mode) + 2 * 2 (toggle) + - * 8 * 2 (address) + 8 * 2 (command) = - * 44 cells - * - * MODE 6A msglen: - * 1 * 2 (start bit) + 3 * 2 (mode) + 2 * 2 (submode) + - * 1 * 2 (customer range bit) + 7/15 * 2 (customer bits) + - * 1 * 2 (toggle bit) + 7 * 2 (address) + 8 * 2 (command) = - * 60 - 76 cells - */ - u8 mode; - u8 toggle; - u16 customer = 0x0; - u8 address; - u8 command; - u32 scancode; - - /* Leader mark */ - while (get_bits(data, 1) && !data->irdata_error) - /* Do nothing */; - - /* Leader space */ - if (get_bits(data, 1)) { - dev_dbg(dev, "RC6 - Invalid leader space\n"); - return; - } - - /* Start bit */ - if (get_bits(data, 2) != 0x02) { - dev_dbg(dev, "RC6 - Invalid start bit\n"); - return; - } - - /* Mode */ - mode = get_bits(data, 6); - switch (mode) { - case 0x15: /* 010101 = b000 */ - mode = 0; - break; - case 0x29: /* 101001 = b110 */ - mode = 6; - break; - default: - dev_dbg(dev, "RC6 - Invalid mode\n"); - return; - } - - /* Toggle bit / Submode bit */ - toggle = get_bits(data, 4); - switch (toggle) { - case 0x03: - toggle = 0; - break; - case 0x0C: - toggle = 1; - break; - default: - dev_dbg(dev, "RC6 - Toggle bit error\n"); - break; - } - - /* Customer */ - if (mode == 6) { - if (toggle != 0) { - dev_dbg(dev, "RC6B - Not Supported\n"); - return; - } - - customer = wbcir_rc6cells_to_byte(data); - - if (customer & 0x80) { - /* 15 bit customer value */ - customer <<= 8; - customer |= wbcir_rc6cells_to_byte(data); - } - } - - /* Address */ - address = wbcir_rc6cells_to_byte(data); - if (mode == 6) { - toggle = address >> 7; - address &= 0x7F; - } - - /* Command */ - command = wbcir_rc6cells_to_byte(data); - - /* Create scancode */ - scancode = command; - scancode |= address << 8; - scancode |= customer << 16; - - /* Last sanity check */ - if (data->irdata_error) { - dev_dbg(dev, "RC6 - Cell error(s)\n"); - return; - } - - dev_dbg(dev, "IR-RC6 ad 0x%02X cm 0x%02X cu 0x%04X " - "toggle %u mode %u scan 0x%08X\n", - address, - command, - customer, - (unsigned int)toggle, - (unsigned int)mode, - scancode); - - wbcir_keydown(data, scancode, toggle); -} - -static void -wbcir_parse_rc5(struct device *dev, struct wbcir_data *data) -{ - /* - * Bits are manchester coded as follows: - * cell1 + cell0 = logic "0" - * cell0 + cell1 = logic "1" - * (i.e. the reverse of RC6) - * - * Start bit 1 - "1" - discarded - * Start bit 2 - Must be inverted to get command bit 6 - * Toggle bit - * Address Bit 4 - 0 - * Command Bit 5 - 0 - */ - u8 toggle; - u8 address; - u8 command; - u32 scancode; - - /* Start bit 1 */ - if (!get_bits(data, 1)) { - dev_dbg(dev, "RC5 - Invalid start bit\n"); - return; - } - - /* Start bit 2 */ - if (!wbcir_get_rc5bits(data, 1)) - command = 0x40; - else - command = 0x00; - - toggle = wbcir_get_rc5bits(data, 1); - address = wbcir_get_rc5bits(data, 5); - command |= wbcir_get_rc5bits(data, 6); - scancode = address << 7 | command; - - /* Last sanity check */ - if (data->irdata_error) { - dev_dbg(dev, "RC5 - Invalid message\n"); - return; - } - - dev_dbg(dev, "IR-RC5 ad %u cm %u t %u s %u\n", - (unsigned int)address, - (unsigned int)command, - (unsigned int)toggle, - (unsigned int)scancode); - - wbcir_keydown(data, scancode, toggle); -} - -static void -wbcir_parse_nec(struct device *dev, struct wbcir_data *data) -{ - /* - * Each bit represents 560 us. - * - * Leader - 9 ms burst - * Gap - 4.5 ms silence - * Address1 bit 0 - 7 - Address 1 - * Address2 bit 0 - 7 - Address 2 - * Command1 bit 0 - 7 - Command 1 - * Command2 bit 0 - 7 - Command 2 - * - * Note the bit order! - * - * With the old NEC protocol, Address2 was the inverse of Address1 - * and Command2 was the inverse of Command1 and were used as - * an error check. - * - * With NEC extended, Address1 is the LSB of the Address and - * Address2 is the MSB, Command parsing remains unchanged. - * - * A repeat message is coded as: - * Leader - 9 ms burst - * Gap - 2.25 ms silence - * Repeat - 560 us active - */ - u8 address1; - u8 address2; - u8 command1; - u8 command2; - u16 address; - u32 scancode; - - /* Leader mark */ - while (get_bits(data, 1) && !data->irdata_error) - /* Do nothing */; - - /* Leader space */ - if (get_bits(data, 4)) { - dev_dbg(dev, "NEC - Invalid leader space\n"); - return; - } - - /* Repeat? */ - if (get_bits(data, 1)) { - if (!data->keypressed) { - dev_dbg(dev, "NEC - Stray repeat message\n"); - return; - } - - dev_dbg(dev, "IR-NEC repeat s %u\n", - (unsigned int)data->last_scancode); - - wbcir_keydown(data, data->last_scancode, data->last_toggle); - return; - } - - /* Remaining leader space */ - if (get_bits(data, 3)) { - dev_dbg(dev, "NEC - Invalid leader space\n"); - return; - } - - address1 = bitrev8(get_bits(data, 8)); - address2 = bitrev8(get_bits(data, 8)); - command1 = bitrev8(get_bits(data, 8)); - command2 = bitrev8(get_bits(data, 8)); - - /* Sanity check */ - if (data->irdata_error) { - dev_dbg(dev, "NEC - Invalid message\n"); - return; - } - - /* Check command validity */ - if (command1 != ~command2) { - dev_dbg(dev, "NEC - Command bytes mismatch\n"); - return; - } - - /* Check for extended NEC protocol */ - address = address1; - if (address1 != ~address2) - address |= address2 << 8; - - scancode = address << 8 | command1; - - dev_dbg(dev, "IR-NEC ad %u cm %u s %u\n", - (unsigned int)address, - (unsigned int)command1, - (unsigned int)scancode); - - wbcir_keydown(data, scancode, !data->last_toggle); -} - - - -/***************************************************************************** - * - * INTERRUPT FUNCTIONS - * - *****************************************************************************/ - -static irqreturn_t -wbcir_irq_handler(int irqno, void *cookie) -{ - struct pnp_dev *device = cookie; - struct wbcir_data *data = pnp_get_drvdata(device); - struct device *dev = &device->dev; - u8 status; - unsigned long flags; - u8 irdata[8]; - int i; - unsigned int hw; - - spin_lock_irqsave(&wbcir_lock, flags); - - wbcir_select_bank(data, WBCIR_BANK_0); - - status = inb(data->sbase + WBCIR_REG_SP3_EIR); - - if (!(status & (WBCIR_IRQ_RX | WBCIR_IRQ_ERR))) { - spin_unlock_irqrestore(&wbcir_lock, flags); - return IRQ_NONE; - } - - if (status & WBCIR_IRQ_ERR) - data->irdata_error = 1; - - if (!(status & WBCIR_IRQ_RX)) - goto out; - - /* Since RXHDLEV is set, at least 8 bytes are in the FIFO */ - insb(data->sbase + WBCIR_REG_SP3_RXDATA, &irdata[0], 8); - - for (i = 0; i < sizeof(irdata); i++) { - hw = hweight8(irdata[i]); - if (hw > 4) - add_irdata_bit(data, 0); - else - add_irdata_bit(data, 1); - - if (hw == 8) - data->idle_count++; - else - data->idle_count = 0; - } - - if (data->idle_count > WBCIR_MAX_IDLE_BYTES) { - /* Set RXINACTIVE... */ - outb(WBCIR_RX_DISABLE, data->sbase + WBCIR_REG_SP3_ASCR); - - /* ...and drain the FIFO */ - while (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_AVAIL) - inb(data->sbase + WBCIR_REG_SP3_RXDATA); - - dev_dbg(dev, "IRDATA:\n"); - for (i = 0; i < data->irdata_count; i += BITS_PER_LONG) - dev_dbg(dev, "0x%08lX\n", data->irdata[i/BITS_PER_LONG]); - - switch (protocol) { - case IR_PROTOCOL_RC5: - wbcir_parse_rc5(dev, data); - break; - case IR_PROTOCOL_RC6: - wbcir_parse_rc6(dev, data); - break; - case IR_PROTOCOL_NEC: - wbcir_parse_nec(dev, data); - break; - } - - wbcir_reset_irdata(data); - } - -out: - spin_unlock_irqrestore(&wbcir_lock, flags); - return IRQ_HANDLED; -} - - - -/***************************************************************************** - * - * SETUP/INIT/SUSPEND/RESUME FUNCTIONS - * - *****************************************************************************/ - -static void -wbcir_shutdown(struct pnp_dev *device) -{ - struct device *dev = &device->dev; - struct wbcir_data *data = pnp_get_drvdata(device); - int do_wake = 1; - u8 match[11]; - u8 mask[11]; - u8 rc6_csl = 0; - int i; - - memset(match, 0, sizeof(match)); - memset(mask, 0, sizeof(mask)); - - if (wake_sc == INVALID_SCANCODE || !device_may_wakeup(dev)) { - do_wake = 0; - goto finish; - } - - switch (protocol) { - case IR_PROTOCOL_RC5: - if (wake_sc > 0xFFF) { - do_wake = 0; - dev_err(dev, "RC5 - Invalid wake scancode\n"); - break; - } - - /* Mask = 13 bits, ex toggle */ - mask[0] = 0xFF; - mask[1] = 0x17; - - match[0] = (wake_sc & 0x003F); /* 6 command bits */ - match[0] |= (wake_sc & 0x0180) >> 1; /* 2 address bits */ - match[1] = (wake_sc & 0x0E00) >> 9; /* 3 address bits */ - if (!(wake_sc & 0x0040)) /* 2nd start bit */ - match[1] |= 0x10; - - break; - - case IR_PROTOCOL_NEC: - if (wake_sc > 0xFFFFFF) { - do_wake = 0; - dev_err(dev, "NEC - Invalid wake scancode\n"); - break; - } - - mask[0] = mask[1] = mask[2] = mask[3] = 0xFF; - - match[1] = bitrev8((wake_sc & 0xFF)); - match[0] = ~match[1]; - - match[3] = bitrev8((wake_sc & 0xFF00) >> 8); - if (wake_sc > 0xFFFF) - match[2] = bitrev8((wake_sc & 0xFF0000) >> 16); - else - match[2] = ~match[3]; - - break; - - case IR_PROTOCOL_RC6: - - if (wake_rc6mode == 0) { - if (wake_sc > 0xFFFF) { - do_wake = 0; - dev_err(dev, "RC6 - Invalid wake scancode\n"); - break; - } - - /* Command */ - match[0] = wbcir_to_rc6cells(wake_sc >> 0); - mask[0] = 0xFF; - match[1] = wbcir_to_rc6cells(wake_sc >> 4); - mask[1] = 0xFF; - - /* Address */ - match[2] = wbcir_to_rc6cells(wake_sc >> 8); - mask[2] = 0xFF; - match[3] = wbcir_to_rc6cells(wake_sc >> 12); - mask[3] = 0xFF; - - /* Header */ - match[4] = 0x50; /* mode1 = mode0 = 0, ignore toggle */ - mask[4] = 0xF0; - match[5] = 0x09; /* start bit = 1, mode2 = 0 */ - mask[5] = 0x0F; - - rc6_csl = 44; - - } else if (wake_rc6mode == 6) { - i = 0; - - /* Command */ - match[i] = wbcir_to_rc6cells(wake_sc >> 0); - mask[i++] = 0xFF; - match[i] = wbcir_to_rc6cells(wake_sc >> 4); - mask[i++] = 0xFF; - - /* Address + Toggle */ - match[i] = wbcir_to_rc6cells(wake_sc >> 8); - mask[i++] = 0xFF; - match[i] = wbcir_to_rc6cells(wake_sc >> 12); - mask[i++] = 0x3F; - - /* Customer bits 7 - 0 */ - match[i] = wbcir_to_rc6cells(wake_sc >> 16); - mask[i++] = 0xFF; - match[i] = wbcir_to_rc6cells(wake_sc >> 20); - mask[i++] = 0xFF; - - if (wake_sc & 0x80000000) { - /* Customer range bit and bits 15 - 8 */ - match[i] = wbcir_to_rc6cells(wake_sc >> 24); - mask[i++] = 0xFF; - match[i] = wbcir_to_rc6cells(wake_sc >> 28); - mask[i++] = 0xFF; - rc6_csl = 76; - } else if (wake_sc <= 0x007FFFFF) { - rc6_csl = 60; - } else { - do_wake = 0; - dev_err(dev, "RC6 - Invalid wake scancode\n"); - break; - } - - /* Header */ - match[i] = 0x93; /* mode1 = mode0 = 1, submode = 0 */ - mask[i++] = 0xFF; - match[i] = 0x0A; /* start bit = 1, mode2 = 1 */ - mask[i++] = 0x0F; - - } else { - do_wake = 0; - dev_err(dev, "RC6 - Invalid wake mode\n"); - } - - break; - - default: - do_wake = 0; - break; - } - -finish: - if (do_wake) { - /* Set compare and compare mask */ - wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_INDEX, - WBCIR_REGSEL_COMPARE | WBCIR_REG_ADDR0, - 0x3F); - outsb(data->wbase + WBCIR_REG_WCEIR_DATA, match, 11); - wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_INDEX, - WBCIR_REGSEL_MASK | WBCIR_REG_ADDR0, - 0x3F); - outsb(data->wbase + WBCIR_REG_WCEIR_DATA, mask, 11); - - /* RC6 Compare String Len */ - outb(rc6_csl, data->wbase + WBCIR_REG_WCEIR_CSL); - - /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ - wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17); - - /* Clear BUFF_EN, Clear END_EN, Set MATCH_EN */ - wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x01, 0x07); - - /* Set CEIR_EN */ - wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x01, 0x01); - - } else { - /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */ - wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); - - /* Clear CEIR_EN */ - wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01); - } - - /* Disable interrupts */ - wbcir_select_bank(data, WBCIR_BANK_0); - outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); - - /* - * ACPI will set the HW disable bit for SP3 which means that the - * output signals are left in an undefined state which may cause - * spurious interrupts which we need to ignore until the hardware - * is reinitialized. - */ - disable_irq(data->irq); -} - -static int -wbcir_suspend(struct pnp_dev *device, pm_message_t state) -{ - wbcir_shutdown(device); - return 0; -} - -static void -wbcir_init_hw(struct wbcir_data *data) -{ - u8 tmp; - - /* Disable interrupts */ - wbcir_select_bank(data, WBCIR_BANK_0); - outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); - - /* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */ - tmp = protocol << 4; - if (invert) - tmp |= 0x08; - outb(tmp, data->wbase + WBCIR_REG_WCEIR_CTL); - - /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ - wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17); - - /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */ - wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); - - /* Set RC5 cell time to correspond to 36 kHz */ - wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CFG1, 0x4A, 0x7F); - - /* Set IRTX_INV */ - if (invert) - outb(0x04, data->ebase + WBCIR_REG_ECEIR_CCTL); - else - outb(0x00, data->ebase + WBCIR_REG_ECEIR_CCTL); - - /* - * Clear IR LED, set SP3 clock to 24Mhz - * set SP3_IRRX_SW to binary 01, helpfully not documented - */ - outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS); - - /* Enable extended mode */ - wbcir_select_bank(data, WBCIR_BANK_2); - outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1); - - /* - * Configure baud generator, IR data will be sampled at - * a bitrate of: (24Mhz * prescaler) / (divisor * 16). - * - * The ECIR registers include a flag to change the - * 24Mhz clock freq to 48Mhz. - * - * It's not documented in the specs, but fifo levels - * other than 16 seems to be unsupported. - */ - - /* prescaler 1.0, tx/rx fifo lvl 16 */ - outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2); - - /* Set baud divisor to generate one byte per bit/cell */ - switch (protocol) { - case IR_PROTOCOL_RC5: - outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL); - break; - case IR_PROTOCOL_RC6: - outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL); - break; - case IR_PROTOCOL_NEC: - outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL); - break; - } - outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH); - - /* Set CEIR mode */ - wbcir_select_bank(data, WBCIR_BANK_0); - outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR); - inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */ - inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */ - - /* Disable RX demod, run-length encoding/decoding, set freq span */ - wbcir_select_bank(data, WBCIR_BANK_7); - outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG); - - /* Disable timer */ - wbcir_select_bank(data, WBCIR_BANK_4); - outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1); - - /* Enable MSR interrupt, Clear AUX_IRX */ - wbcir_select_bank(data, WBCIR_BANK_5); - outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2); - - /* Disable CRC */ - wbcir_select_bank(data, WBCIR_BANK_6); - outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3); - - /* Set RX/TX (de)modulation freq, not really used */ - wbcir_select_bank(data, WBCIR_BANK_7); - outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC); - outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC); - - /* Set invert and pin direction */ - if (invert) - outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4); - else - outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4); - - /* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */ - wbcir_select_bank(data, WBCIR_BANK_0); - outb(0x97, data->sbase + WBCIR_REG_SP3_FCR); - - /* Clear AUX status bits */ - outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR); - - /* Enable interrupts */ - wbcir_reset_irdata(data); - outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER); -} - -static int -wbcir_resume(struct pnp_dev *device) -{ - struct wbcir_data *data = pnp_get_drvdata(device); - - wbcir_init_hw(data); - enable_irq(data->irq); - - return 0; -} - -static int __devinit -wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) -{ - struct device *dev = &device->dev; - struct wbcir_data *data; - int err; - - if (!(pnp_port_len(device, 0) == EHFUNC_IOMEM_LEN && - pnp_port_len(device, 1) == WAKEUP_IOMEM_LEN && - pnp_port_len(device, 2) == SP_IOMEM_LEN)) { - dev_err(dev, "Invalid resources\n"); - return -ENODEV; - } - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - pnp_set_drvdata(device, data); - - data->ebase = pnp_port_start(device, 0); - data->wbase = pnp_port_start(device, 1); - data->sbase = pnp_port_start(device, 2); - data->irq = pnp_irq(device, 0); - - if (data->wbase == 0 || data->ebase == 0 || - data->sbase == 0 || data->irq == 0) { - err = -ENODEV; - dev_err(dev, "Invalid resources\n"); - goto exit_free_data; - } - - dev_dbg(&device->dev, "Found device " - "(w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n", - data->wbase, data->ebase, data->sbase, data->irq); - - if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) { - dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", - data->wbase, data->wbase + WAKEUP_IOMEM_LEN - 1); - err = -EBUSY; - goto exit_free_data; - } - - if (!request_region(data->ebase, EHFUNC_IOMEM_LEN, DRVNAME)) { - dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", - data->ebase, data->ebase + EHFUNC_IOMEM_LEN - 1); - err = -EBUSY; - goto exit_release_wbase; - } - - if (!request_region(data->sbase, SP_IOMEM_LEN, DRVNAME)) { - dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", - data->sbase, data->sbase + SP_IOMEM_LEN - 1); - err = -EBUSY; - goto exit_release_ebase; - } - - err = request_irq(data->irq, wbcir_irq_handler, - IRQF_DISABLED, DRVNAME, device); - if (err) { - dev_err(dev, "Failed to claim IRQ %u\n", data->irq); - err = -EBUSY; - goto exit_release_sbase; - } - - led_trigger_register_simple("cir-tx", &data->txtrigger); - if (!data->txtrigger) { - err = -ENOMEM; - goto exit_free_irq; - } - - led_trigger_register_simple("cir-rx", &data->rxtrigger); - if (!data->rxtrigger) { - err = -ENOMEM; - goto exit_unregister_txtrigger; - } - - data->led.name = "cir::activity"; - data->led.default_trigger = "cir-rx"; - data->led.brightness_set = wbcir_led_brightness_set; - data->led.brightness_get = wbcir_led_brightness_get; - err = led_classdev_register(&device->dev, &data->led); - if (err) - goto exit_unregister_rxtrigger; - - data->input_dev = input_allocate_device(); - if (!data->input_dev) { - err = -ENOMEM; - goto exit_unregister_led; - } - - data->input_dev->evbit[0] = BIT(EV_KEY); - data->input_dev->name = WBCIR_NAME; - data->input_dev->phys = "wbcir/cir0"; - data->input_dev->id.bustype = BUS_HOST; - data->input_dev->id.vendor = PCI_VENDOR_ID_WINBOND; - data->input_dev->id.product = WBCIR_ID_FAMILY; - data->input_dev->id.version = WBCIR_ID_CHIP; - data->input_dev->getkeycode = wbcir_getkeycode; - data->input_dev->setkeycode = wbcir_setkeycode; - input_set_capability(data->input_dev, EV_MSC, MSC_SCAN); - input_set_drvdata(data->input_dev, data); - - err = input_register_device(data->input_dev); - if (err) - goto exit_free_input; - - data->last_scancode = INVALID_SCANCODE; - INIT_LIST_HEAD(&data->keytable); - setup_timer(&data->timer_keyup, wbcir_keyup, (unsigned long)data); - - /* Load default keymaps */ - if (protocol == IR_PROTOCOL_RC6) { - int i; - for (i = 0; i < ARRAY_SIZE(rc6_def_keymap); i++) { - err = wbcir_setkeycode(data->input_dev, - (int)rc6_def_keymap[i].scancode, - (int)rc6_def_keymap[i].keycode); - if (err) - goto exit_unregister_keys; - } - } - - device_init_wakeup(&device->dev, 1); - - wbcir_init_hw(data); - - return 0; - -exit_unregister_keys: - if (!list_empty(&data->keytable)) { - struct wbcir_keyentry *key; - struct wbcir_keyentry *keytmp; - - list_for_each_entry_safe(key, keytmp, &data->keytable, list) { - list_del(&key->list); - kfree(key); - } - } - input_unregister_device(data->input_dev); - /* Can't call input_free_device on an unregistered device */ - data->input_dev = NULL; -exit_free_input: - input_free_device(data->input_dev); -exit_unregister_led: - led_classdev_unregister(&data->led); -exit_unregister_rxtrigger: - led_trigger_unregister_simple(data->rxtrigger); -exit_unregister_txtrigger: - led_trigger_unregister_simple(data->txtrigger); -exit_free_irq: - free_irq(data->irq, device); -exit_release_sbase: - release_region(data->sbase, SP_IOMEM_LEN); -exit_release_ebase: - release_region(data->ebase, EHFUNC_IOMEM_LEN); -exit_release_wbase: - release_region(data->wbase, WAKEUP_IOMEM_LEN); -exit_free_data: - kfree(data); - pnp_set_drvdata(device, NULL); -exit: - return err; -} - -static void __devexit -wbcir_remove(struct pnp_dev *device) -{ - struct wbcir_data *data = pnp_get_drvdata(device); - struct wbcir_keyentry *key; - struct wbcir_keyentry *keytmp; - - /* Disable interrupts */ - wbcir_select_bank(data, WBCIR_BANK_0); - outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); - - del_timer_sync(&data->timer_keyup); - - free_irq(data->irq, device); - - /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ - wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17); - - /* Clear CEIR_EN */ - wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01); - - /* Clear BUFF_EN, END_EN, MATCH_EN */ - wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); - - /* This will generate a keyup event if necessary */ - input_unregister_device(data->input_dev); - - led_trigger_unregister_simple(data->rxtrigger); - led_trigger_unregister_simple(data->txtrigger); - led_classdev_unregister(&data->led); - - /* This is ok since &data->led isn't actually used */ - wbcir_led_brightness_set(&data->led, LED_OFF); - - release_region(data->wbase, WAKEUP_IOMEM_LEN); - release_region(data->ebase, EHFUNC_IOMEM_LEN); - release_region(data->sbase, SP_IOMEM_LEN); - - list_for_each_entry_safe(key, keytmp, &data->keytable, list) { - list_del(&key->list); - kfree(key); - } - - kfree(data); - - pnp_set_drvdata(device, NULL); -} - -static const struct pnp_device_id wbcir_ids[] = { - { "WEC1022", 0 }, - { "", 0 } -}; -MODULE_DEVICE_TABLE(pnp, wbcir_ids); - -static struct pnp_driver wbcir_driver = { - .name = WBCIR_NAME, - .id_table = wbcir_ids, - .probe = wbcir_probe, - .remove = __devexit_p(wbcir_remove), - .suspend = wbcir_suspend, - .resume = wbcir_resume, - .shutdown = wbcir_shutdown -}; - -static int __init -wbcir_init(void) -{ - int ret; - - switch (protocol) { - case IR_PROTOCOL_RC5: - case IR_PROTOCOL_NEC: - case IR_PROTOCOL_RC6: - break; - default: - printk(KERN_ERR DRVNAME ": Invalid protocol argument\n"); - return -EINVAL; - } - - ret = pnp_register_driver(&wbcir_driver); - if (ret) - printk(KERN_ERR DRVNAME ": Unable to register driver\n"); - - return ret; -} - -static void __exit -wbcir_exit(void) -{ - pnp_unregister_driver(&wbcir_driver); -} - -MODULE_AUTHOR("David Härdeman "); -MODULE_DESCRIPTION("Winbond SuperI/O Consumer IR Driver"); -MODULE_LICENSE("GPL"); - -module_init(wbcir_init); -module_exit(wbcir_exit); - - diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index d05003d..2d15468 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -164,4 +164,21 @@ config IR_STREAMZAP To compile this driver as a module, choose M here: the module will be called streamzap. +config IR_WINBOND_CIR + tristate "Winbond IR remote control" + depends on X86 && PNP + depends on IR_CORE + select NEW_LEDS + select LEDS_CLASS + select LEDS_TRIGGERS + select BITREVERSE + ---help--- + Say Y here if you want to use the IR remote functionality found + in some Winbond SuperI/O chips. Currently only the WPCD376I + chip is supported (included in some Intel Media series + motherboards). + + To compile this driver as a module, choose M here: the module will + be called winbond_cir. + endif #IR_CORE diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 1eb24e6..859c12c 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -20,3 +20,4 @@ obj-$(CONFIG_IR_MCEUSB) += mceusb.o obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o obj-$(CONFIG_IR_ENE) += ene_ir.o obj-$(CONFIG_IR_STREAMZAP) += streamzap.o +obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c new file mode 100644 index 0000000..0ee16ec --- /dev/null +++ b/drivers/media/rc/winbond-cir.c @@ -0,0 +1,932 @@ +/* + * winbond-cir.c - Driver for the Consumer IR functionality of Winbond + * SuperI/O chips. + * + * Currently supports the Winbond WPCD376i chip (PNP id WEC1022), but + * could probably support others (Winbond WEC102X, NatSemi, etc) + * with minor modifications. + * + * Original Author: David Härdeman + * Copyright (C) 2009 - 2010 David Härdeman + * + * Dedicated to my daughter Matilda, without whose loving attention this + * driver would have been finished in half the time and with a fraction + * of the bugs. + * + * Written using: + * o Winbond WPCD376I datasheet helpfully provided by Jesse Barnes at Intel + * o NatSemi PC87338/PC97338 datasheet (for the serial port stuff) + * o DSDT dumps + * + * Supported features: + * o Wake-On-CIR functionality + * + * To do: + * o Learning + * o IR Transmit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "winbond-cir" + +/* CEIR Wake-Up Registers, relative to data->wbase */ +#define WBCIR_REG_WCEIR_CTL 0x03 /* CEIR Receiver Control */ +#define WBCIR_REG_WCEIR_STS 0x04 /* CEIR Receiver Status */ +#define WBCIR_REG_WCEIR_EV_EN 0x05 /* CEIR Receiver Event Enable */ +#define WBCIR_REG_WCEIR_CNTL 0x06 /* CEIR Receiver Counter Low */ +#define WBCIR_REG_WCEIR_CNTH 0x07 /* CEIR Receiver Counter High */ +#define WBCIR_REG_WCEIR_INDEX 0x08 /* CEIR Receiver Index */ +#define WBCIR_REG_WCEIR_DATA 0x09 /* CEIR Receiver Data */ +#define WBCIR_REG_WCEIR_CSL 0x0A /* CEIR Re. Compare Strlen */ +#define WBCIR_REG_WCEIR_CFG1 0x0B /* CEIR Re. Configuration 1 */ +#define WBCIR_REG_WCEIR_CFG2 0x0C /* CEIR Re. Configuration 2 */ + +/* CEIR Enhanced Functionality Registers, relative to data->ebase */ +#define WBCIR_REG_ECEIR_CTS 0x00 /* Enhanced IR Control Status */ +#define WBCIR_REG_ECEIR_CCTL 0x01 /* Infrared Counter Control */ +#define WBCIR_REG_ECEIR_CNT_LO 0x02 /* Infrared Counter LSB */ +#define WBCIR_REG_ECEIR_CNT_HI 0x03 /* Infrared Counter MSB */ +#define WBCIR_REG_ECEIR_IREM 0x04 /* Infrared Emitter Status */ + +/* SP3 Banked Registers, relative to data->sbase */ +#define WBCIR_REG_SP3_BSR 0x03 /* Bank Select, all banks */ + /* Bank 0 */ +#define WBCIR_REG_SP3_RXDATA 0x00 /* FIFO RX data (r) */ +#define WBCIR_REG_SP3_TXDATA 0x00 /* FIFO TX data (w) */ +#define WBCIR_REG_SP3_IER 0x01 /* Interrupt Enable */ +#define WBCIR_REG_SP3_EIR 0x02 /* Event Identification (r) */ +#define WBCIR_REG_SP3_FCR 0x02 /* FIFO Control (w) */ +#define WBCIR_REG_SP3_MCR 0x04 /* Mode Control */ +#define WBCIR_REG_SP3_LSR 0x05 /* Link Status */ +#define WBCIR_REG_SP3_MSR 0x06 /* Modem Status */ +#define WBCIR_REG_SP3_ASCR 0x07 /* Aux Status and Control */ + /* Bank 2 */ +#define WBCIR_REG_SP3_BGDL 0x00 /* Baud Divisor LSB */ +#define WBCIR_REG_SP3_BGDH 0x01 /* Baud Divisor MSB */ +#define WBCIR_REG_SP3_EXCR1 0x02 /* Extended Control 1 */ +#define WBCIR_REG_SP3_EXCR2 0x04 /* Extended Control 2 */ +#define WBCIR_REG_SP3_TXFLV 0x06 /* TX FIFO Level */ +#define WBCIR_REG_SP3_RXFLV 0x07 /* RX FIFO Level */ + /* Bank 3 */ +#define WBCIR_REG_SP3_MRID 0x00 /* Module Identification */ +#define WBCIR_REG_SP3_SH_LCR 0x01 /* LCR Shadow */ +#define WBCIR_REG_SP3_SH_FCR 0x02 /* FCR Shadow */ + /* Bank 4 */ +#define WBCIR_REG_SP3_IRCR1 0x02 /* Infrared Control 1 */ + /* Bank 5 */ +#define WBCIR_REG_SP3_IRCR2 0x04 /* Infrared Control 2 */ + /* Bank 6 */ +#define WBCIR_REG_SP3_IRCR3 0x00 /* Infrared Control 3 */ +#define WBCIR_REG_SP3_SIR_PW 0x02 /* SIR Pulse Width */ + /* Bank 7 */ +#define WBCIR_REG_SP3_IRRXDC 0x00 /* IR RX Demod Control */ +#define WBCIR_REG_SP3_IRTXMC 0x01 /* IR TX Mod Control */ +#define WBCIR_REG_SP3_RCCFG 0x02 /* CEIR Config */ +#define WBCIR_REG_SP3_IRCFG1 0x04 /* Infrared Config 1 */ +#define WBCIR_REG_SP3_IRCFG4 0x07 /* Infrared Config 4 */ + +/* + * Magic values follow + */ + +/* No interrupts for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ +#define WBCIR_IRQ_NONE 0x00 +/* RX data bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ +#define WBCIR_IRQ_RX 0x01 +/* Over/Under-flow bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ +#define WBCIR_IRQ_ERR 0x04 +/* Led enable/disable bit for WBCIR_REG_ECEIR_CTS */ +#define WBCIR_LED_ENABLE 0x80 +/* RX data available bit for WBCIR_REG_SP3_LSR */ +#define WBCIR_RX_AVAIL 0x01 +/* RX disable bit for WBCIR_REG_SP3_ASCR */ +#define WBCIR_RX_DISABLE 0x20 +/* Extended mode enable bit for WBCIR_REG_SP3_EXCR1 */ +#define WBCIR_EXT_ENABLE 0x01 +/* Select compare register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */ +#define WBCIR_REGSEL_COMPARE 0x10 +/* Select mask register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */ +#define WBCIR_REGSEL_MASK 0x20 +/* Starting address of selected register in WBCIR_REG_WCEIR_INDEX */ +#define WBCIR_REG_ADDR0 0x00 + +/* Valid banks for the SP3 UART */ +enum wbcir_bank { + WBCIR_BANK_0 = 0x00, + WBCIR_BANK_1 = 0x80, + WBCIR_BANK_2 = 0xE0, + WBCIR_BANK_3 = 0xE4, + WBCIR_BANK_4 = 0xE8, + WBCIR_BANK_5 = 0xEC, + WBCIR_BANK_6 = 0xF0, + WBCIR_BANK_7 = 0xF4, +}; + +/* Supported power-on IR Protocols */ +enum wbcir_protocol { + IR_PROTOCOL_RC5 = 0x0, + IR_PROTOCOL_NEC = 0x1, + IR_PROTOCOL_RC6 = 0x2, +}; + +/* Misc */ +#define WBCIR_NAME "Winbond CIR" +#define WBCIR_ID_FAMILY 0xF1 /* Family ID for the WPCD376I */ +#define WBCIR_ID_CHIP 0x04 /* Chip ID for the WPCD376I */ +#define INVALID_SCANCODE 0x7FFFFFFF /* Invalid with all protos */ +#define WAKEUP_IOMEM_LEN 0x10 /* Wake-Up I/O Reg Len */ +#define EHFUNC_IOMEM_LEN 0x10 /* Enhanced Func I/O Reg Len */ +#define SP_IOMEM_LEN 0x08 /* Serial Port 3 (IR) Reg Len */ + +/* Per-device data */ +struct wbcir_data { + spinlock_t spinlock; + + unsigned long wbase; /* Wake-Up Baseaddr */ + unsigned long ebase; /* Enhanced Func. Baseaddr */ + unsigned long sbase; /* Serial Port Baseaddr */ + unsigned int irq; /* Serial Port IRQ */ + + struct rc_dev *dev; + + struct led_trigger *rxtrigger; + struct led_trigger *txtrigger; + struct led_classdev led; + + /* RX irdata state */ + bool irdata_active; + bool irdata_error; + struct ir_raw_event ev; +}; + +static enum wbcir_protocol protocol = IR_PROTOCOL_RC6; +module_param(protocol, uint, 0444); +MODULE_PARM_DESC(protocol, "IR protocol to use for the power-on command " + "(0 = RC5, 1 = NEC, 2 = RC6A, default)"); + +static int invert; /* default = 0 */ +module_param(invert, bool, 0444); +MODULE_PARM_DESC(invert, "Invert the signal from the IR receiver"); + +static unsigned int wake_sc = 0x800F040C; +module_param(wake_sc, uint, 0644); +MODULE_PARM_DESC(wake_sc, "Scancode of the power-on IR command"); + +static unsigned int wake_rc6mode = 6; +module_param(wake_rc6mode, uint, 0644); +MODULE_PARM_DESC(wake_rc6mode, "RC6 mode for the power-on command " + "(0 = 0, 6 = 6A, default)"); + + + +/***************************************************************************** + * + * UTILITY FUNCTIONS + * + *****************************************************************************/ + +/* Caller needs to hold wbcir_lock */ +static void +wbcir_set_bits(unsigned long addr, u8 bits, u8 mask) +{ + u8 val; + + val = inb(addr); + val = ((val & ~mask) | (bits & mask)); + outb(val, addr); +} + +/* Selects the register bank for the serial port */ +static inline void +wbcir_select_bank(struct wbcir_data *data, enum wbcir_bank bank) +{ + outb(bank, data->sbase + WBCIR_REG_SP3_BSR); +} + +static enum led_brightness +wbcir_led_brightness_get(struct led_classdev *led_cdev) +{ + struct wbcir_data *data = container_of(led_cdev, + struct wbcir_data, + led); + + if (inb(data->ebase + WBCIR_REG_ECEIR_CTS) & WBCIR_LED_ENABLE) + return LED_FULL; + else + return LED_OFF; +} + +static void +wbcir_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct wbcir_data *data = container_of(led_cdev, + struct wbcir_data, + led); + + wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CTS, + brightness == LED_OFF ? 0x00 : WBCIR_LED_ENABLE, + WBCIR_LED_ENABLE); +} + +/* Manchester encodes bits to RC6 message cells (see wbcir_shutdown) */ +static u8 +wbcir_to_rc6cells(u8 val) +{ + u8 coded = 0x00; + int i; + + val &= 0x0F; + for (i = 0; i < 4; i++) { + if (val & 0x01) + coded |= 0x02 << (i * 2); + else + coded |= 0x01 << (i * 2); + val >>= 1; + } + + return coded; +} + +/***************************************************************************** + * + * INTERRUPT FUNCTIONS + * + *****************************************************************************/ + +static irqreturn_t +wbcir_irq_handler(int irqno, void *cookie) +{ + struct pnp_dev *device = cookie; + struct wbcir_data *data = pnp_get_drvdata(device); + unsigned long flags; + u8 irdata[8]; + u8 disable = true; + u8 status; + int i; + + spin_lock_irqsave(&data->spinlock, flags); + + wbcir_select_bank(data, WBCIR_BANK_0); + + status = inb(data->sbase + WBCIR_REG_SP3_EIR); + + if (!(status & (WBCIR_IRQ_RX | WBCIR_IRQ_ERR))) { + spin_unlock_irqrestore(&data->spinlock, flags); + return IRQ_NONE; + } + + /* Check for e.g. buffer overflow */ + if (status & WBCIR_IRQ_ERR) { + data->irdata_error = true; + ir_raw_event_reset(data->dev); + } + + if (!(status & WBCIR_IRQ_RX)) + goto out; + + if (!data->irdata_active) { + data->irdata_active = true; + led_trigger_event(data->rxtrigger, LED_FULL); + } + + /* Since RXHDLEV is set, at least 8 bytes are in the FIFO */ + insb(data->sbase + WBCIR_REG_SP3_RXDATA, &irdata[0], 8); + + for (i = 0; i < 8; i++) { + u8 pulse; + u32 duration; + + if (irdata[i] != 0xFF && irdata[i] != 0x00) + disable = false; + + if (data->irdata_error) + continue; + + pulse = irdata[i] & 0x80 ? false : true; + duration = (irdata[i] & 0x7F) * 10000; /* ns */ + + if (data->ev.pulse != pulse) { + if (data->ev.duration != 0) { + ir_raw_event_store(data->dev, &data->ev); + data->ev.duration = 0; + } + + data->ev.pulse = pulse; + } + + data->ev.duration += duration; + } + + if (disable) { + if (data->ev.duration != 0 && !data->irdata_error) { + ir_raw_event_store(data->dev, &data->ev); + data->ev.duration = 0; + } + + /* Set RXINACTIVE */ + outb(WBCIR_RX_DISABLE, data->sbase + WBCIR_REG_SP3_ASCR); + + /* Drain the FIFO */ + while (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_AVAIL) + inb(data->sbase + WBCIR_REG_SP3_RXDATA); + + ir_raw_event_reset(data->dev); + data->irdata_error = false; + data->irdata_active = false; + led_trigger_event(data->rxtrigger, LED_OFF); + } + + ir_raw_event_handle(data->dev); + +out: + spin_unlock_irqrestore(&data->spinlock, flags); + return IRQ_HANDLED; +} + + + +/***************************************************************************** + * + * SETUP/INIT/SUSPEND/RESUME FUNCTIONS + * + *****************************************************************************/ + +static void +wbcir_shutdown(struct pnp_dev *device) +{ + struct device *dev = &device->dev; + struct wbcir_data *data = pnp_get_drvdata(device); + int do_wake = 1; + u8 match[11]; + u8 mask[11]; + u8 rc6_csl = 0; + int i; + + memset(match, 0, sizeof(match)); + memset(mask, 0, sizeof(mask)); + + if (wake_sc == INVALID_SCANCODE || !device_may_wakeup(dev)) { + do_wake = 0; + goto finish; + } + + switch (protocol) { + case IR_PROTOCOL_RC5: + if (wake_sc > 0xFFF) { + do_wake = 0; + dev_err(dev, "RC5 - Invalid wake scancode\n"); + break; + } + + /* Mask = 13 bits, ex toggle */ + mask[0] = 0xFF; + mask[1] = 0x17; + + match[0] = (wake_sc & 0x003F); /* 6 command bits */ + match[0] |= (wake_sc & 0x0180) >> 1; /* 2 address bits */ + match[1] = (wake_sc & 0x0E00) >> 9; /* 3 address bits */ + if (!(wake_sc & 0x0040)) /* 2nd start bit */ + match[1] |= 0x10; + + break; + + case IR_PROTOCOL_NEC: + if (wake_sc > 0xFFFFFF) { + do_wake = 0; + dev_err(dev, "NEC - Invalid wake scancode\n"); + break; + } + + mask[0] = mask[1] = mask[2] = mask[3] = 0xFF; + + match[1] = bitrev8((wake_sc & 0xFF)); + match[0] = ~match[1]; + + match[3] = bitrev8((wake_sc & 0xFF00) >> 8); + if (wake_sc > 0xFFFF) + match[2] = bitrev8((wake_sc & 0xFF0000) >> 16); + else + match[2] = ~match[3]; + + break; + + case IR_PROTOCOL_RC6: + + if (wake_rc6mode == 0) { + if (wake_sc > 0xFFFF) { + do_wake = 0; + dev_err(dev, "RC6 - Invalid wake scancode\n"); + break; + } + + /* Command */ + match[0] = wbcir_to_rc6cells(wake_sc >> 0); + mask[0] = 0xFF; + match[1] = wbcir_to_rc6cells(wake_sc >> 4); + mask[1] = 0xFF; + + /* Address */ + match[2] = wbcir_to_rc6cells(wake_sc >> 8); + mask[2] = 0xFF; + match[3] = wbcir_to_rc6cells(wake_sc >> 12); + mask[3] = 0xFF; + + /* Header */ + match[4] = 0x50; /* mode1 = mode0 = 0, ignore toggle */ + mask[4] = 0xF0; + match[5] = 0x09; /* start bit = 1, mode2 = 0 */ + mask[5] = 0x0F; + + rc6_csl = 44; + + } else if (wake_rc6mode == 6) { + i = 0; + + /* Command */ + match[i] = wbcir_to_rc6cells(wake_sc >> 0); + mask[i++] = 0xFF; + match[i] = wbcir_to_rc6cells(wake_sc >> 4); + mask[i++] = 0xFF; + + /* Address + Toggle */ + match[i] = wbcir_to_rc6cells(wake_sc >> 8); + mask[i++] = 0xFF; + match[i] = wbcir_to_rc6cells(wake_sc >> 12); + mask[i++] = 0x3F; + + /* Customer bits 7 - 0 */ + match[i] = wbcir_to_rc6cells(wake_sc >> 16); + mask[i++] = 0xFF; + match[i] = wbcir_to_rc6cells(wake_sc >> 20); + mask[i++] = 0xFF; + + if (wake_sc & 0x80000000) { + /* Customer range bit and bits 15 - 8 */ + match[i] = wbcir_to_rc6cells(wake_sc >> 24); + mask[i++] = 0xFF; + match[i] = wbcir_to_rc6cells(wake_sc >> 28); + mask[i++] = 0xFF; + rc6_csl = 76; + } else if (wake_sc <= 0x007FFFFF) { + rc6_csl = 60; + } else { + do_wake = 0; + dev_err(dev, "RC6 - Invalid wake scancode\n"); + break; + } + + /* Header */ + match[i] = 0x93; /* mode1 = mode0 = 1, submode = 0 */ + mask[i++] = 0xFF; + match[i] = 0x0A; /* start bit = 1, mode2 = 1 */ + mask[i++] = 0x0F; + + } else { + do_wake = 0; + dev_err(dev, "RC6 - Invalid wake mode\n"); + } + + break; + + default: + do_wake = 0; + break; + } + +finish: + if (do_wake) { + /* Set compare and compare mask */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_INDEX, + WBCIR_REGSEL_COMPARE | WBCIR_REG_ADDR0, + 0x3F); + outsb(data->wbase + WBCIR_REG_WCEIR_DATA, match, 11); + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_INDEX, + WBCIR_REGSEL_MASK | WBCIR_REG_ADDR0, + 0x3F); + outsb(data->wbase + WBCIR_REG_WCEIR_DATA, mask, 11); + + /* RC6 Compare String Len */ + outb(rc6_csl, data->wbase + WBCIR_REG_WCEIR_CSL); + + /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17); + + /* Clear BUFF_EN, Clear END_EN, Set MATCH_EN */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x01, 0x07); + + /* Set CEIR_EN */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x01, 0x01); + + } else { + /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); + + /* Clear CEIR_EN */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01); + } + + /* Disable interrupts */ + wbcir_select_bank(data, WBCIR_BANK_0); + outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); + + /* Disable LED */ + data->irdata_active = false; + led_trigger_event(data->rxtrigger, LED_OFF); + + /* + * ACPI will set the HW disable bit for SP3 which means that the + * output signals are left in an undefined state which may cause + * spurious interrupts which we need to ignore until the hardware + * is reinitialized. + */ + disable_irq(data->irq); +} + +static int +wbcir_suspend(struct pnp_dev *device, pm_message_t state) +{ + wbcir_shutdown(device); + return 0; +} + +static void +wbcir_init_hw(struct wbcir_data *data) +{ + u8 tmp; + + /* Disable interrupts */ + wbcir_select_bank(data, WBCIR_BANK_0); + outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); + + /* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */ + tmp = protocol << 4; + if (invert) + tmp |= 0x08; + outb(tmp, data->wbase + WBCIR_REG_WCEIR_CTL); + + /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17); + + /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); + + /* Set RC5 cell time to correspond to 36 kHz */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CFG1, 0x4A, 0x7F); + + /* Set IRTX_INV */ + if (invert) + outb(0x04, data->ebase + WBCIR_REG_ECEIR_CCTL); + else + outb(0x00, data->ebase + WBCIR_REG_ECEIR_CCTL); + + /* + * Clear IR LED, set SP3 clock to 24Mhz + * set SP3_IRRX_SW to binary 01, helpfully not documented + */ + outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS); + + /* Enable extended mode */ + wbcir_select_bank(data, WBCIR_BANK_2); + outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1); + + /* + * Configure baud generator, IR data will be sampled at + * a bitrate of: (24Mhz * prescaler) / (divisor * 16). + * + * The ECIR registers include a flag to change the + * 24Mhz clock freq to 48Mhz. + * + * It's not documented in the specs, but fifo levels + * other than 16 seems to be unsupported. + */ + + /* prescaler 1.0, tx/rx fifo lvl 16 */ + outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2); + + /* Set baud divisor to generate one byte per bit/cell */ + switch (protocol) { + case IR_PROTOCOL_RC5: + outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL); + break; + case IR_PROTOCOL_RC6: + outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL); + break; + case IR_PROTOCOL_NEC: + outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL); + break; + } + outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH); + + /* Set CEIR mode */ + wbcir_select_bank(data, WBCIR_BANK_0); + outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR); + inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */ + inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */ + + /* Disable RX demod, run-length encoding/decoding, set freq span */ + wbcir_select_bank(data, WBCIR_BANK_7); + outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG); + + /* Disable timer */ + wbcir_select_bank(data, WBCIR_BANK_4); + outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1); + + /* Enable MSR interrupt, Clear AUX_IRX */ + wbcir_select_bank(data, WBCIR_BANK_5); + outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2); + + /* Disable CRC */ + wbcir_select_bank(data, WBCIR_BANK_6); + outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3); + + /* Set RX/TX (de)modulation freq, not really used */ + wbcir_select_bank(data, WBCIR_BANK_7); + outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC); + outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC); + + /* Set invert and pin direction */ + if (invert) + outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4); + else + outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4); + + /* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */ + wbcir_select_bank(data, WBCIR_BANK_0); + outb(0x97, data->sbase + WBCIR_REG_SP3_FCR); + + /* Clear AUX status bits */ + outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR); + + /* Clear IR decoding state */ + data->irdata_active = false; + led_trigger_event(data->rxtrigger, LED_OFF); + data->irdata_error = false; + data->ev.duration = 0; + ir_raw_event_reset(data->dev); + ir_raw_event_handle(data->dev); + + /* Enable interrupts */ + outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER); +} + +static int +wbcir_resume(struct pnp_dev *device) +{ + struct wbcir_data *data = pnp_get_drvdata(device); + + wbcir_init_hw(data); + enable_irq(data->irq); + + return 0; +} + +static int __devinit +wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) +{ + struct device *dev = &device->dev; + struct wbcir_data *data; + int err; + + if (!(pnp_port_len(device, 0) == EHFUNC_IOMEM_LEN && + pnp_port_len(device, 1) == WAKEUP_IOMEM_LEN && + pnp_port_len(device, 2) == SP_IOMEM_LEN)) { + dev_err(dev, "Invalid resources\n"); + return -ENODEV; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + pnp_set_drvdata(device, data); + + spin_lock_init(&data->spinlock); + data->ebase = pnp_port_start(device, 0); + data->wbase = pnp_port_start(device, 1); + data->sbase = pnp_port_start(device, 2); + data->irq = pnp_irq(device, 0); + + if (data->wbase == 0 || data->ebase == 0 || + data->sbase == 0 || data->irq == 0) { + err = -ENODEV; + dev_err(dev, "Invalid resources\n"); + goto exit_free_data; + } + + dev_dbg(&device->dev, "Found device " + "(w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n", + data->wbase, data->ebase, data->sbase, data->irq); + + if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) { + dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", + data->wbase, data->wbase + WAKEUP_IOMEM_LEN - 1); + err = -EBUSY; + goto exit_free_data; + } + + if (!request_region(data->ebase, EHFUNC_IOMEM_LEN, DRVNAME)) { + dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", + data->ebase, data->ebase + EHFUNC_IOMEM_LEN - 1); + err = -EBUSY; + goto exit_release_wbase; + } + + if (!request_region(data->sbase, SP_IOMEM_LEN, DRVNAME)) { + dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", + data->sbase, data->sbase + SP_IOMEM_LEN - 1); + err = -EBUSY; + goto exit_release_ebase; + } + + err = request_irq(data->irq, wbcir_irq_handler, + IRQF_DISABLED, DRVNAME, device); + if (err) { + dev_err(dev, "Failed to claim IRQ %u\n", data->irq); + err = -EBUSY; + goto exit_release_sbase; + } + + led_trigger_register_simple("cir-tx", &data->txtrigger); + if (!data->txtrigger) { + err = -ENOMEM; + goto exit_free_irq; + } + + led_trigger_register_simple("cir-rx", &data->rxtrigger); + if (!data->rxtrigger) { + err = -ENOMEM; + goto exit_unregister_txtrigger; + } + + data->led.name = "cir::activity"; + data->led.default_trigger = "cir-rx"; + data->led.brightness_set = wbcir_led_brightness_set; + data->led.brightness_get = wbcir_led_brightness_get; + err = led_classdev_register(&device->dev, &data->led); + if (err) + goto exit_unregister_rxtrigger; + + data->dev = rc_allocate_device(); + if (!data->dev) { + err = -ENOMEM; + goto exit_unregister_led; + } + + data->dev->driver_name = WBCIR_NAME; + data->dev->input_name = WBCIR_NAME; + data->dev->input_phys = "wbcir/cir0"; + data->dev->input_id.bustype = BUS_HOST; + data->dev->input_id.vendor = PCI_VENDOR_ID_WINBOND; + data->dev->input_id.product = WBCIR_ID_FAMILY; + data->dev->input_id.version = WBCIR_ID_CHIP; + data->dev->priv = data; + data->dev->dev.parent = &device->dev; + + err = rc_register_device(data->dev); + if (err) + goto exit_free_rc; + + device_init_wakeup(&device->dev, 1); + + wbcir_init_hw(data); + + return 0; + +exit_free_rc: + rc_free_device(data->dev); +exit_unregister_led: + led_classdev_unregister(&data->led); +exit_unregister_rxtrigger: + led_trigger_unregister_simple(data->rxtrigger); +exit_unregister_txtrigger: + led_trigger_unregister_simple(data->txtrigger); +exit_free_irq: + free_irq(data->irq, device); +exit_release_sbase: + release_region(data->sbase, SP_IOMEM_LEN); +exit_release_ebase: + release_region(data->ebase, EHFUNC_IOMEM_LEN); +exit_release_wbase: + release_region(data->wbase, WAKEUP_IOMEM_LEN); +exit_free_data: + kfree(data); + pnp_set_drvdata(device, NULL); +exit: + return err; +} + +static void __devexit +wbcir_remove(struct pnp_dev *device) +{ + struct wbcir_data *data = pnp_get_drvdata(device); + + /* Disable interrupts */ + wbcir_select_bank(data, WBCIR_BANK_0); + outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); + + free_irq(data->irq, device); + + /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17); + + /* Clear CEIR_EN */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01); + + /* Clear BUFF_EN, END_EN, MATCH_EN */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); + + rc_unregister_device(data->dev); + + led_trigger_unregister_simple(data->rxtrigger); + led_trigger_unregister_simple(data->txtrigger); + led_classdev_unregister(&data->led); + + /* This is ok since &data->led isn't actually used */ + wbcir_led_brightness_set(&data->led, LED_OFF); + + release_region(data->wbase, WAKEUP_IOMEM_LEN); + release_region(data->ebase, EHFUNC_IOMEM_LEN); + release_region(data->sbase, SP_IOMEM_LEN); + + kfree(data); + + pnp_set_drvdata(device, NULL); +} + +static const struct pnp_device_id wbcir_ids[] = { + { "WEC1022", 0 }, + { "", 0 } +}; +MODULE_DEVICE_TABLE(pnp, wbcir_ids); + +static struct pnp_driver wbcir_driver = { + .name = WBCIR_NAME, + .id_table = wbcir_ids, + .probe = wbcir_probe, + .remove = __devexit_p(wbcir_remove), + .suspend = wbcir_suspend, + .resume = wbcir_resume, + .shutdown = wbcir_shutdown +}; + +static int __init +wbcir_init(void) +{ + int ret; + + switch (protocol) { + case IR_PROTOCOL_RC5: + case IR_PROTOCOL_NEC: + case IR_PROTOCOL_RC6: + break; + default: + printk(KERN_ERR DRVNAME ": Invalid power-on protocol\n"); + } + + ret = pnp_register_driver(&wbcir_driver); + if (ret) + printk(KERN_ERR DRVNAME ": Unable to register driver\n"); + + return ret; +} + +static void __exit +wbcir_exit(void) +{ + pnp_unregister_driver(&wbcir_driver); +} + +module_init(wbcir_init); +module_exit(wbcir_exit); + +MODULE_AUTHOR("David Härdeman "); +MODULE_DESCRIPTION("Winbond SuperI/O Consumer IR Driver"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 2eb258327722de3ed4d84ce1b9add2bad21a0ec4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Nov 2010 09:02:40 -0300 Subject: [media] ir-kbd-i2c: add rc_dev as a parameter to the driver There are several fields on rc_dev that drivers can benefit. Allow drivers to pass it as a parameter to the driver. For now, the rc_dev parameter is optional. If drivers don't pass it, create them internally. However, the best is to create rc_dev inside the drivers, in order to fill other fields, like open(), close(), driver_name, etc. So, a latter patch making it mandatory and changing the caller drivers is welcome. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 83b59a1..de0060f 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -271,20 +271,16 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) const char *name = NULL; u64 ir_type = IR_TYPE_UNKNOWN; struct IR_i2c *ir; - struct rc_dev *rc; + struct rc_dev *rc = NULL; struct i2c_adapter *adap = client->adapter; unsigned short addr = client->addr; int err; - ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL); - rc = rc_allocate_device(); - if (!ir || !rc) { - err = -ENOMEM; - goto err_out_free; - } + ir = kzalloc(sizeof(struct IR_i2c), GFP_KERNEL); + if (!ir) + return -ENOMEM; ir->c = client; - ir->rc = rc; ir->polling_interval = DEFAULT_POLLING_INTERVAL; i2c_set_clientdata(client, ir); @@ -333,6 +329,8 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) client->dev.platform_data; ir_codes = init_data->ir_codes; + rc = init_data->rc_dev; + name = init_data->name; if (init_data->type) ir_type = init_data->type; @@ -366,6 +364,19 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) } } + if (!rc) { + /* + * If platform_data doesn't specify rc_dev, initilize it + * internally + */ + rc = rc_allocate_device(); + if (!rc) { + err = -ENOMEM; + goto err_out_free; + } + } + ir->rc = rc; + /* Make sure we are all setup before going on */ if (!name || !ir->get_key || !ir_type || !ir_codes) { dprintk(1, ": Unsupported device at address 0x%02x\n", @@ -382,12 +393,21 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) dev_name(&adap->dev), dev_name(&client->dev)); - /* init + register input device */ + /* + * Initialize input_dev fields + * It doesn't make sense to allow overriding them via platform_data + */ rc->input_id.bustype = BUS_I2C; - rc->input_name = ir->name; rc->input_phys = ir->phys; - rc->map_name = ir->ir_codes; - rc->driver_name = MODULE_NAME; + rc->input_name = ir->name; + + /* + * Initialize the other fields of rc_dev + */ + rc->map_name = ir->ir_codes; + rc->allowed_protos = ir_type; + if (!rc->driver_name) + rc->driver_name = MODULE_NAME; err = rc_register_device(rc); if (err) @@ -403,6 +423,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) return 0; err_out_free: + /* Only frees rc if it were allocated internally */ rc_free_device(rc); kfree(ir); return err; diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h index 4ee9b42..aca015e 100644 --- a/include/media/ir-kbd-i2c.h +++ b/include/media/ir-kbd-i2c.h @@ -46,5 +46,7 @@ struct IR_i2c_init_data { */ int (*get_key)(struct IR_i2c*, u32*, u32*); enum ir_kbd_get_key_fn internal_get_key_func; + + struct rc_dev *rc_dev; }; #endif -- cgit v0.10.2 From 141bb0dc2d0ad03202aef7c070555cd970ca6bf9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Nov 2010 08:14:16 -0300 Subject: [media] cx231xx: Fix i2c support at cx231xx-input There was a bug at cx231xx-input, where it were registering the remote controls twice, one via ir-kbd-i2c and another directly. Also, the patch that added rc_register_device() broke compilation for it. This patch fixes cx231xx-input by fixing the depends on, to point to the new symbol, and initializing the scanmask via platform_data. While here, also fix Kconfig symbol change for IR core dependencies. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/video/cx231xx/Kconfig index ab7d5df..d6a2350 100644 --- a/drivers/media/video/cx231xx/Kconfig +++ b/drivers/media/video/cx231xx/Kconfig @@ -16,7 +16,7 @@ config VIDEO_CX231XX config VIDEO_CX231XX_RC bool "Conexant cx231xx Remote Controller additional support" - depends on VIDEO_IR + depends on IR_CORE depends on VIDEO_CX231XX default y ---help--- diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c index 6725244..65d951e 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/video/cx231xx/cx231xx-input.c @@ -29,6 +29,8 @@ static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key, { u8 cmd; + dev_dbg(&ir->rc->input_dev->dev, "%s\n", __func__); + /* poll IR chip */ if (1 != i2c_master_recv(ir->c, &cmd, 1)) return -EIO; @@ -40,7 +42,7 @@ static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key, if (cmd == 0xff) return 0; - dev_dbg(&ir->input->dev, "scancode = %02x\n", cmd); + dev_dbg(&ir->rc->input_dev->dev, "scancode = %02x\n", cmd); *ir_key = cmd; *ir_raw = cmd; @@ -49,9 +51,7 @@ static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key, int cx231xx_ir_init(struct cx231xx *dev) { - struct input_dev *input_dev; struct i2c_board_info info; - int rc; u8 ir_i2c_bus; dev_dbg(&dev->udev->dev, "%s\n", __func__); @@ -60,34 +60,18 @@ int cx231xx_ir_init(struct cx231xx *dev) if (!cx231xx_boards[dev->model].rc_map) return -ENODEV; - input_dev = input_allocate_device(); - if (!input_dev) - return -ENOMEM; - request_module("ir-kbd-i2c"); memset(&info, 0, sizeof(struct i2c_board_info)); - memset(&dev->ir.init_data, 0, sizeof(dev->ir.init_data)); + memset(&dev->init_data, 0, sizeof(dev->init_data)); + dev->init_data.rc_dev = rc_allocate_device(); + if (!dev->init_data.rc_dev) + return -ENOMEM; - dev->ir.input_dev = input_dev; - dev->ir.init_data.name = cx231xx_boards[dev->model].name; - dev->ir.props.priv = dev; - dev->ir.props.allowed_protos = IR_TYPE_NEC; - snprintf(dev->ir.name, sizeof(dev->ir.name), - "cx231xx IR (%s)", cx231xx_boards[dev->model].name); - usb_make_path(dev->udev, dev->ir.phys, sizeof(dev->ir.phys)); - strlcat(dev->ir.phys, "/input0", sizeof(dev->ir.phys)); + dev->init_data.name = cx231xx_boards[dev->model].name; strlcpy(info.type, "ir_video", I2C_NAME_SIZE); - info.platform_data = &dev->ir.init_data; - - input_dev->name = dev->ir.name; - input_dev->phys = dev->ir.phys; - input_dev->dev.parent = &dev->udev->dev; - input_dev->id.bustype = BUS_USB; - input_dev->id.version = 1; - input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); - input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); + info.platform_data = &dev->init_data; /* * Board-dependent values @@ -95,28 +79,23 @@ int cx231xx_ir_init(struct cx231xx *dev) * For now, there's just one type of hardware design using * an i2c device. */ - dev->ir.init_data.get_key = get_key_isdbt; - dev->ir.init_data.ir_codes = cx231xx_boards[dev->model].rc_map; + dev->init_data.get_key = get_key_isdbt; + dev->init_data.ir_codes = cx231xx_boards[dev->model].rc_map; /* The i2c micro-controller only outputs the cmd part of NEC protocol */ - dev->ir.props.scanmask = 0xff; + dev->init_data.rc_dev->scanmask = 0xff; + dev->init_data.rc_dev->driver_name = "cx231xx"; + dev->init_data.type = IR_TYPE_NEC; info.addr = 0x30; - rc = ir_input_register(input_dev, cx231xx_boards[dev->model].rc_map, - &dev->ir.props, MODULE_NAME); - if (rc < 0) - return rc; - /* Load and bind ir-kbd-i2c */ ir_i2c_bus = cx231xx_boards[dev->model].ir_i2c_master; + dev_dbg(&dev->udev->dev, "Trying to bind ir at bus %d, addr 0x%02x\n", + ir_i2c_bus, info.addr); i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info); - return rc; + return 0; } void cx231xx_ir_exit(struct cx231xx *dev) { - if (dev->ir.input_dev) { - ir_input_unregister(dev->ir.input_dev); - dev->ir.input_dev = NULL; - } } diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h index c439e77..fcccc9d 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/video/cx231xx/cx231xx.h @@ -602,25 +602,6 @@ struct cx231xx_tsport { void *port_priv; }; -struct cx231xx_ir_t { - struct input_dev *input_dev; - char name[40]; - char phys[32]; - -#if 0 - /* - * Due to a Kconfig change, cx231xx-input is not being compiled. - * This structure disappeared, but other fixes are also needed. - * So, as a workaround, let's just comment this struct and let a - * latter patch fix it. - */ - struct ir_dev_props props; -#endif - - /* I2C keyboard data */ - struct IR_i2c_init_data init_data; -}; - /* main device struct */ struct cx231xx { /* generic device properties */ @@ -631,7 +612,7 @@ struct cx231xx { struct cx231xx_board board; /* For I2C IR support */ - struct cx231xx_ir_t ir; + struct IR_i2c_init_data init_data; unsigned int stream_on:1; /* Locks streams */ unsigned int vbi_stream_on:1; /* Locks streams for VBI */ -- cgit v0.10.2 From 9e21ccaa69674e1b0aa887722801258f7de842db Mon Sep 17 00:00:00 2001 From: VDR User Date: Sat, 30 Oct 2010 15:49:49 -0300 Subject: [media] dvb-usb-gp8psk: get firmware and fpga versions This patch adds retrieval of firmware and FPGA versions of Genpix devices. That information is useful for users who experience performance differences with the various firmware versions, and may want to use a specific firmware that best suits their needs. Example dmesg output: gp8psk: FW Version = 2.09.4 (0x20904) Build 2009/04/02 gp8psk: FPGA Version = 1 Signed-off-by: Derek Kelly Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c index c821293..1cb3d9a 100644 --- a/drivers/media/dvb/dvb-usb/gp8psk.c +++ b/drivers/media/dvb/dvb-usb/gp8psk.c @@ -24,6 +24,33 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DV DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); +static int gp8psk_get_fw_version(struct dvb_usb_device *d, u8 *fw_vers) +{ + return (gp8psk_usb_in_op(d, GET_FW_VERS, 0, 0, fw_vers, 6)); +} + +static int gp8psk_get_fpga_version(struct dvb_usb_device *d, u8 *fpga_vers) +{ + return (gp8psk_usb_in_op(d, GET_FPGA_VERS, 0, 0, fpga_vers, 1)); +} + +static void gp8psk_info(struct dvb_usb_device *d) +{ + u8 fpga_vers, fw_vers[6]; + + if (!gp8psk_get_fw_version(d, fw_vers)) + info("FW Version = %i.%02i.%i (0x%x) Build %4i/%02i/%02i", + fw_vers[2], fw_vers[1], fw_vers[0], GP8PSK_FW_VERS(fw_vers), + 2000 + fw_vers[5], fw_vers[4], fw_vers[3]); + else + info("failed to get FW version"); + + if (!gp8psk_get_fpga_version(d, &fpga_vers)) + info("FPGA Version = %i", fpga_vers); + else + info("failed to get FPGA version"); +} + int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) { int ret = 0,try = 0; @@ -146,6 +173,7 @@ static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff) gp8psk_usb_out_op(d, CW3K_INIT, 1, 0, NULL, 0); if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1)) return -EINVAL; + gp8psk_info(d); } if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) diff --git a/drivers/media/dvb/dvb-usb/gp8psk.h b/drivers/media/dvb/dvb-usb/gp8psk.h index e83a575..831749a 100644 --- a/drivers/media/dvb/dvb-usb/gp8psk.h +++ b/drivers/media/dvb/dvb-usb/gp8psk.h @@ -25,7 +25,6 @@ extern int dvb_usb_gp8psk_debug; #define deb_xfer(args...) dprintk(dvb_usb_gp8psk_debug,0x02,args) #define deb_rc(args...) dprintk(dvb_usb_gp8psk_debug,0x04,args) #define deb_fe(args...) dprintk(dvb_usb_gp8psk_debug,0x08,args) -/* gp8psk commands */ /* Twinhan Vendor requests */ #define TH_COMMAND_IN 0xC0 @@ -49,8 +48,10 @@ extern int dvb_usb_gp8psk_debug; #define SET_DVB_MODE 0x8E #define SET_DN_SWITCH 0x8F #define GET_SIGNAL_LOCK 0x90 /* in */ +#define GET_FW_VERS 0x92 #define GET_SERIAL_NUMBER 0x93 /* in */ #define USE_EXTRA_VOLT 0x94 +#define GET_FPGA_VERS 0x95 #define CW3K_INIT 0x9d /* PSK_configuration bits */ @@ -88,6 +89,11 @@ extern int dvb_usb_gp8psk_debug; #define PRODUCT_STRING_READ 0x0D #define FW_BCD_VERSION_READ 0x14 +/* firmware revision id's */ +#define GP8PSK_FW_REV1 0x020604 +#define GP8PSK_FW_REV2 0x020704 +#define GP8PSK_FW_VERS(_fw_vers) ((_fw_vers)[2]<<0x10 | (_fw_vers)[1]<<0x08 | (_fw_vers)[0]) + extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d); extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, -- cgit v0.10.2 From 1ce6a1433572c650247480e1bbbca6bd61db7874 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 30 Oct 2010 18:08:31 -0300 Subject: [media] drivers/media/video: Update WARN uses Add missing newlines. Signed-off-by: Joe Perches Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index bb99f2d..817aa66 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c @@ -543,7 +543,7 @@ static void fimc_dma_run(void *priv) unsigned long flags; u32 ret; - if (WARN(!ctx, "null hardware context")) + if (WARN(!ctx, "null hardware context\n")) return; fimc = ctx->fimc_dev; diff --git a/drivers/media/video/sr030pc30.c b/drivers/media/video/sr030pc30.c index c9dc67a..864696b 100644 --- a/drivers/media/video/sr030pc30.c +++ b/drivers/media/video/sr030pc30.c @@ -735,7 +735,7 @@ static int sr030pc30_s_power(struct v4l2_subdev *sd, int on) const struct sr030pc30_platform_data *pdata = info->pdata; int ret; - if (WARN(pdata == NULL, "No platform data!")) + if (WARN(pdata == NULL, "No platform data!\n")) return -ENOMEM; /* -- cgit v0.10.2 From 76e4a9a7164263d8ffe816920f84a91e7dfee444 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 1 Nov 2010 06:25:39 -0300 Subject: [media] tea6415c: return -EIO if i2c_check_functionality fails If the adapter does not support I2C_FUNC_SMBUS_WRITE_BYTE, return -EIO instead of 0. Signed-off-by: Axel Lin Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c index 3e99cea..19621ed5 100644 --- a/drivers/media/video/tea6415c.c +++ b/drivers/media/video/tea6415c.c @@ -148,7 +148,7 @@ static int tea6415c_probe(struct i2c_client *client, /* let's see whether this adapter can support what we need */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) - return 0; + return -EIO; v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); -- cgit v0.10.2 From 0e72cc8b8d48ba05e705f432fb99aaa0ea6737c6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 2 Nov 2010 00:22:23 -0300 Subject: [media] saa7164: make buffer smaller This isn't a runtime bug, it's just to make static checkers happy. In vidioc_querycap() we copy a saa7164_dev ->name driver array into a v4l2_capability -> driver array. The ->driver array is only 16 chars long so ->name also can't be more than 16 characters. The ->name gets set in v4l2_capability() and it always is less than 16 characters so we can easily make the buffer smaller. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/saa7164/saa7164-core.c b/drivers/media/video/saa7164/saa7164-core.c index e1bac50..b66f78f 100644 --- a/drivers/media/video/saa7164/saa7164-core.c +++ b/drivers/media/video/saa7164/saa7164-core.c @@ -1001,7 +1001,7 @@ static int saa7164_dev_setup(struct saa7164_dev *dev) atomic_inc(&dev->refcount); dev->nr = saa7164_devcount++; - sprintf(dev->name, "saa7164[%d]", dev->nr); + snprintf(dev->name, sizeof(dev->name), "saa7164[%d]", dev->nr); mutex_lock(&devlist); list_add_tail(&dev->devlist, &saa7164_devlist); diff --git a/drivers/media/video/saa7164/saa7164.h b/drivers/media/video/saa7164/saa7164.h index 041ae8e..74df9c6 100644 --- a/drivers/media/video/saa7164/saa7164.h +++ b/drivers/media/video/saa7164/saa7164.h @@ -447,7 +447,7 @@ struct saa7164_dev { int nr; int hwrevision; u32 board; - char name[32]; + char name[16]; /* firmware status */ struct saa7164_fw_status fw_status; -- cgit v0.10.2 From bc25068495b110fcdf35a22f43d32637e99fd018 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Fri, 12 Nov 2010 18:32:36 -0300 Subject: [media] saa7164: Checkpatch compliance cleanup Checkpatch compliance cleanup across files in the saa7164 driver. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/saa7164/saa7164-api.c b/drivers/media/video/saa7164/saa7164-api.c index ad3bc41..bd86d97 100644 --- a/drivers/media/video/saa7164/saa7164-api.c +++ b/drivers/media/video/saa7164/saa7164-api.c @@ -40,9 +40,8 @@ int saa7164_api_get_load_info(struct saa7164_dev *dev, struct tmFwInfoStruct *i) ret = saa7164_cmd_send(dev, 0, GET_CUR, GET_FW_STATUS_CONTROL, sizeof(struct tmFwInfoStruct), i); - if (ret != SAA_OK) { + if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); - } printk(KERN_INFO "saa7164[%d]-CPU: %d percent", dev->nr, i->CPULoad); @@ -63,14 +62,15 @@ int saa7164_api_collect_debug(struct saa7164_dev *dev) ret = saa7164_cmd_send(dev, 0, GET_CUR, GET_DEBUG_DATA_CONTROL, sizeof(d), &d); - if (ret != SAA_OK) { - printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); - } + if (ret != SAA_OK) + printk(KERN_ERR "%s() error, ret = 0x%x\n", + __func__, ret); if (d.dwResult != SAA_OK) break; - printk(KERN_INFO "saa7164[%d]-FWMSG: %s", dev->nr, d.ucDebugData); + printk(KERN_INFO "saa7164[%d]-FWMSG: %s", dev->nr, + d.ucDebugData); } return 0; @@ -86,9 +86,9 @@ int saa7164_api_set_debug(struct saa7164_dev *dev, u8 level) /* Retrieve current state */ ret = saa7164_cmd_send(dev, 0, GET_CUR, SET_DEBUG_LEVEL_CONTROL, sizeof(lvl), &lvl); - if (ret != SAA_OK) { + if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); - } + dprintk(DBGLVL_API, "%s() Was %d\n", __func__, lvl.dwDebugLevel); lvl.dwDebugLevel = level; @@ -96,9 +96,8 @@ int saa7164_api_set_debug(struct saa7164_dev *dev, u8 level) /* set new state */ ret = saa7164_cmd_send(dev, 0, SET_CUR, SET_DEBUG_LEVEL_CONTROL, sizeof(lvl), &lvl); - if (ret != SAA_OK) { + if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); - } return ret; } @@ -152,8 +151,10 @@ int saa7164_api_set_vbi_format(struct saa7164_port *port) dprintk(DBGLVL_API, "SET/COMMIT Verified\n"); dprintk(DBGLVL_API, "rsp.bmHint = 0x%x\n", rsp.bmHint); - dprintk(DBGLVL_API, "rsp.bFormatIndex = 0x%x\n", rsp.bFormatIndex); - dprintk(DBGLVL_API, "rsp.bFrameIndex = 0x%x\n", rsp.bFrameIndex); + dprintk(DBGLVL_API, "rsp.bFormatIndex = 0x%x\n", + rsp.bFormatIndex); + dprintk(DBGLVL_API, "rsp.bFrameIndex = 0x%x\n", + rsp.bFrameIndex); } else printk(KERN_ERR "%s() compare failed\n", __func__); } @@ -210,14 +211,17 @@ int saa7164_api_set_encoder(struct saa7164_port *port) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); /* Establish video bitrates */ - if (port->encoder_params.bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) + if (port->encoder_params.bitrate_mode == + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) vb.ucVideoBitRateMode = EU_VIDEO_BIT_RATE_MODE_CONSTANT; else vb.ucVideoBitRateMode = EU_VIDEO_BIT_RATE_MODE_VARIABLE_PEAK; vb.dwVideoBitRate = port->encoder_params.bitrate; vb.dwVideoBitRatePeak = port->encoder_params.bitrate_peak; ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR, - EU_VIDEO_BIT_RATE_CONTROL, sizeof(struct tmComResEncVideoBitRate), &vb); + EU_VIDEO_BIT_RATE_CONTROL, + sizeof(struct tmComResEncVideoBitRate), + &vb); if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); @@ -226,9 +230,12 @@ int saa7164_api_set_encoder(struct saa7164_port *port) ab.dwAudioBitRate = 384000; ab.dwAudioBitRatePeak = ab.dwAudioBitRate; ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR, - EU_AUDIO_BIT_RATE_CONTROL, sizeof(struct tmComResEncAudioBitRate), &ab); + EU_AUDIO_BIT_RATE_CONTROL, + sizeof(struct tmComResEncAudioBitRate), + &ab); if (ret != SAA_OK) - printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); + printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, + ret); saa7164_api_set_aspect_ratio(port); saa7164_api_set_gop_size(port); @@ -244,7 +251,8 @@ int saa7164_api_get_encoder(struct saa7164_port *port) struct tmComResEncVideoInputAspectRatio ar; int ret; - dprintk(DBGLVL_ENC, "%s() unitid=0x%x\n", __func__, port->hwcfg.sourceid); + dprintk(DBGLVL_ENC, "%s() unitid=0x%x\n", __func__, + port->hwcfg.sourceid); port->encoder_profile = 0; port->video_format = 0; @@ -257,7 +265,8 @@ int saa7164_api_get_encoder(struct saa7164_port *port) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR, - EU_VIDEO_RESOLUTION_CONTROL, sizeof(u8), &port->video_resolution); + EU_VIDEO_RESOLUTION_CONTROL, sizeof(u8), + &port->video_resolution); if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); @@ -294,13 +303,20 @@ int saa7164_api_get_encoder(struct saa7164_port *port) dprintk(DBGLVL_ENC, "video_format = %d\n", port->video_format); dprintk(DBGLVL_ENC, "audio_format = %d\n", port->audio_format); dprintk(DBGLVL_ENC, "video_resolution= %d\n", port->video_resolution); - dprintk(DBGLVL_ENC, "v.ucVideoBitRateMode = %d\n", v.ucVideoBitRateMode); - dprintk(DBGLVL_ENC, "v.dwVideoBitRate = %d\n", v.dwVideoBitRate); - dprintk(DBGLVL_ENC, "v.dwVideoBitRatePeak = %d\n", v.dwVideoBitRatePeak); - dprintk(DBGLVL_ENC, "a.ucVideoBitRateMode = %d\n", a.ucAudioBitRateMode); - dprintk(DBGLVL_ENC, "a.dwVideoBitRate = %d\n", a.dwAudioBitRate); - dprintk(DBGLVL_ENC, "a.dwVideoBitRatePeak = %d\n", a.dwAudioBitRatePeak); - dprintk(DBGLVL_ENC, "aspect.width / height = %d:%d\n", ar.width, ar.height); + dprintk(DBGLVL_ENC, "v.ucVideoBitRateMode = %d\n", + v.ucVideoBitRateMode); + dprintk(DBGLVL_ENC, "v.dwVideoBitRate = %d\n", + v.dwVideoBitRate); + dprintk(DBGLVL_ENC, "v.dwVideoBitRatePeak = %d\n", + v.dwVideoBitRatePeak); + dprintk(DBGLVL_ENC, "a.ucVideoBitRateMode = %d\n", + a.ucAudioBitRateMode); + dprintk(DBGLVL_ENC, "a.dwVideoBitRate = %d\n", + a.dwAudioBitRate); + dprintk(DBGLVL_ENC, "a.dwVideoBitRatePeak = %d\n", + a.dwAudioBitRatePeak); + dprintk(DBGLVL_ENC, "aspect.width / height = %d:%d\n", + ar.width, ar.height); return ret; } @@ -439,7 +455,8 @@ int saa7164_api_set_videomux(struct saa7164_port *port) /* Audio Mux */ ret = saa7164_cmd_send(port->dev, port->audfeat.sourceid, SET_CUR, - SU_INPUT_SELECT_CONTROL, sizeof(u8), &inputs[port->mux_input - 1]); + SU_INPUT_SELECT_CONTROL, sizeof(u8), + &inputs[port->mux_input - 1]); if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); @@ -492,7 +509,8 @@ int saa7164_api_set_audio_volume(struct saa7164_port *port, s8 level) if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); - dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__, level, min, max, v); + dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__, + level, min, max, v); v = level; if (v < min) @@ -517,7 +535,8 @@ int saa7164_api_set_audio_volume(struct saa7164_port *port, s8 level) if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); - dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__, level, min, max, v); + dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__, + level, min, max, v); return ret; } @@ -539,7 +558,8 @@ int saa7164_api_set_audio_std(struct saa7164_port *port) lvl.ucSAP_Level = TMHW_LEV_ADJ_SAPLEV_DEFAULT; lvl.ucADC_Level = TMHW_LEV_ADJ_ADCLEV_DEFAULT; ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR, - AUDIO_DEFAULT_CONTROL, sizeof(struct tmComResAudioDefaults), &lvl); + AUDIO_DEFAULT_CONTROL, sizeof(struct tmComResAudioDefaults), + &lvl); if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret); @@ -555,7 +575,8 @@ int saa7164_api_set_audio_std(struct saa7164_port *port) ret = saa7164_cmd_send(port->dev, port->tunerunit.unitid, SET_CUR, TU_STANDARD_CONTROL, sizeof(tvaudio), &tvaudio); if (ret != SAA_OK) - printk(KERN_ERR "%s() TU_STANDARD_CONTROL error, ret = 0x%x\n", __func__, ret); + printk(KERN_ERR "%s() TU_STANDARD_CONTROL error, ret = 0x%x\n", + __func__, ret); return ret; } @@ -575,7 +596,9 @@ int saa7164_api_set_audio_detection(struct saa7164_port *port, int autodetect) ret = saa7164_cmd_send(port->dev, port->tunerunit.unitid, SET_CUR, TU_STANDARD_AUTO_CONTROL, sizeof(p), &p); if (ret != SAA_OK) - printk(KERN_ERR "%s() TU_STANDARD_AUTO_CONTROL error, ret = 0x%x\n", __func__, ret); + printk(KERN_ERR + "%s() TU_STANDARD_AUTO_CONTROL error, ret = 0x%x\n", + __func__, ret); return ret; } @@ -646,9 +669,9 @@ int saa7164_api_set_dif(struct saa7164_port *port, u8 reg, u8 val) EXU_REGISTER_ACCESS_CONTROL, len, &buf); if (ret != SAA_OK) printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret); - - //saa7164_dumphex16(dev, buf, 16); - +#if 0 + saa7164_dumphex16(dev, buf, 16); +#endif return ret == SAA_OK ? 0 : -EIO; } @@ -696,7 +719,8 @@ int saa7164_api_configure_dif(struct saa7164_port *port, u32 std) } else { /* Unknown standard, assume DTV */ dprintk(DBGLVL_API, " Unknown (assuming DTV)\n"); - saa7164_api_set_dif(port, 0x00, 0x80); /* Undefined Video Standard */ + /* Undefinded Video Standard */ + saa7164_api_set_dif(port, 0x00, 0x80); agc_disable = 1; } @@ -933,7 +957,7 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len) if (hdr->type != CS_INTERFACE) return SAA_ERR_NOT_SUPPORTED; - dprintk(DBGLVL_API, "@ 0x%x = \n", idx); + dprintk(DBGLVL_API, "@ 0x%x =\n", idx); switch (hdr->subtype) { case GENERAL_REQUEST: dprintk(DBGLVL_API, " GENERAL_REQUEST\n"); @@ -1085,7 +1109,8 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len) vbiport = &dev->ports[SAA7164_PORT_VBI2]; memcpy(&vbiport->hwcfg, vcoutputtermhdr, sizeof(*vcoutputtermhdr)); - memcpy(&vbiport->vbi_fmt_ntsc, vbifmt, sizeof(*vbifmt)); + memcpy(&vbiport->vbi_fmt_ntsc, vbifmt, + sizeof(*vbifmt)); saa7164_api_configure_port_vbi(dev, vbiport); break; @@ -1134,7 +1159,9 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len) encport = &dev->ports[SAA7164_PORT_ENC2]; memcpy(&encport->tunerunit, tunerunithdr, sizeof(struct tmComResTunerDescrHeader)); - dprintk(DBGLVL_API, " (becomes dev->enc[%d] tuner)\n", encport->nr); + dprintk(DBGLVL_API, + " (becomes dev->enc[%d] tuner)\n", + encport->nr); } break; case VC_SELECTOR_UNIT: @@ -1163,7 +1190,8 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len) encport = &dev->ports[SAA7164_PORT_ENC2]; memcpy(&encport->vidproc, pdh, sizeof(struct tmComResProcDescrHeader)); - dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", encport->nr); + dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", + encport->nr); } break; case FEATURE_UNIT: @@ -1181,15 +1209,18 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len) encport = &dev->ports[SAA7164_PORT_ENC2]; memcpy(&encport->audfeat, afd, sizeof(struct tmComResAFeatureDescrHeader)); - dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", encport->nr); + dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", + encport->nr); break; case ENCODER_UNIT: edh = (struct tmComResEncoderDescrHeader *)(buf + idx); dprintk(DBGLVL_API, " ENCODER_UNIT\n"); dprintk(DBGLVL_API, " subtype = 0x%x\n", edh->subtype); dprintk(DBGLVL_API, " unitid = 0x%x\n", edh->unitid); - dprintk(DBGLVL_API, " vsourceid = 0x%x\n", edh->vsourceid); - dprintk(DBGLVL_API, " asourceid = 0x%x\n", edh->asourceid); + dprintk(DBGLVL_API, " vsourceid = 0x%x\n", + edh->vsourceid); + dprintk(DBGLVL_API, " asourceid = 0x%x\n", + edh->asourceid); dprintk(DBGLVL_API, " iunit = 0x%x\n", edh->iunit); if (edh->iunit == edh->unitid) { if (currpath == 1) @@ -1198,7 +1229,9 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len) encport = &dev->ports[SAA7164_PORT_ENC2]; memcpy(&encport->encunit, edh, sizeof(struct tmComResEncoderDescrHeader)); - dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", encport->nr); + dprintk(DBGLVL_API, + " (becomes dev->enc[%d])\n", + encport->nr); } break; case EXTENSION_UNIT: @@ -1262,7 +1295,9 @@ int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len) encport = &dev->ports[SAA7164_PORT_ENC2]; memcpy(&encport->ifunit, exthdr, sizeof(struct tmComResExtDevDescrHeader)); - dprintk(DBGLVL_API, " (becomes dev->enc[%d])\n", encport->nr); + dprintk(DBGLVL_API, + " (becomes dev->enc[%d])\n", + encport->nr); } break; case PVC_INFRARED_UNIT: diff --git a/drivers/media/video/saa7164/saa7164-buffer.c b/drivers/media/video/saa7164/saa7164-buffer.c index 7230912..ddd2521 100644 --- a/drivers/media/video/saa7164/saa7164-buffer.c +++ b/drivers/media/video/saa7164/saa7164-buffer.c @@ -24,46 +24,46 @@ #include "saa7164.h" /* The PCI address space for buffer handling looks like this: - - +-u32 wide-------------+ - | + - +-u64 wide------------------------------------+ - + + - +----------------------+ - | CurrentBufferPtr + Pointer to current PCI buffer >-+ - +----------------------+ | - | Unused + | - +----------------------+ | - | Pitch + = 188 (bytes) | - +----------------------+ | - | PCI buffer size + = pitch * number of lines (312) | - +----------------------+ | - |0| Buf0 Write Offset + | - +----------------------+ v - |1| Buf1 Write Offset + | - +----------------------+ | - |2| Buf2 Write Offset + | - +----------------------+ | - |3| Buf3 Write Offset + | - +----------------------+ | - ... More write offsets | - +---------------------------------------------+ | - +0| set of ptrs to PCI pagetables + | - +---------------------------------------------+ | - +1| set of ptrs to PCI pagetables + <--------+ - +---------------------------------------------+ - +2| set of ptrs to PCI pagetables + - +---------------------------------------------+ - +3| set of ptrs to PCI pagetables + >--+ - +---------------------------------------------+ | - ... More buffer pointers | +----------------+ - +->| pt[0] TS data | - | +----------------+ - | - | +----------------+ - +->| pt[1] TS data | - | +----------------+ - | etc + * + * +-u32 wide-------------+ + * | + + * +-u64 wide------------------------------------+ + * + + + * +----------------------+ + * | CurrentBufferPtr + Pointer to current PCI buffer >-+ + * +----------------------+ | + * | Unused + | + * +----------------------+ | + * | Pitch + = 188 (bytes) | + * +----------------------+ | + * | PCI buffer size + = pitch * number of lines (312) | + * +----------------------+ | + * |0| Buf0 Write Offset + | + * +----------------------+ v + * |1| Buf1 Write Offset + | + * +----------------------+ | + * |2| Buf2 Write Offset + | + * +----------------------+ | + * |3| Buf3 Write Offset + | + * +----------------------+ | + * ... More write offsets | + * +---------------------------------------------+ | + * +0| set of ptrs to PCI pagetables + | + * +---------------------------------------------+ | + * +1| set of ptrs to PCI pagetables + <--------+ + * +---------------------------------------------+ + * +2| set of ptrs to PCI pagetables + + * +---------------------------------------------+ + * +3| set of ptrs to PCI pagetables + >--+ + * +---------------------------------------------+ | + * ... More buffer pointers | +----------------+ + * +->| pt[0] TS data | + * | +----------------+ + * | + * | +----------------+ + * +->| pt[1] TS data | + * | +----------------+ + * | etc */ void saa7164_buffer_display(struct saa7164_buffer *buf) @@ -283,7 +283,8 @@ int saa7164_buffer_cfg_port(struct saa7164_port *port) return 0; } -struct saa7164_user_buffer *saa7164_buffer_alloc_user(struct saa7164_dev *dev, u32 len) +struct saa7164_user_buffer *saa7164_buffer_alloc_user(struct saa7164_dev *dev, + u32 len) { struct saa7164_user_buffer *buf; @@ -313,12 +314,9 @@ void saa7164_buffer_dealloc_user(struct saa7164_user_buffer *buf) if (!buf) return; - if (buf->data) { - kfree(buf->data); - buf->data = 0; - } + kfree(buf->data); + buf->data = 0; - if (buf) - kfree(buf); + kfree(buf); } diff --git a/drivers/media/video/saa7164/saa7164-bus.c b/drivers/media/video/saa7164/saa7164-bus.c index 30d5283..b2b0d97 100644 --- a/drivers/media/video/saa7164/saa7164-bus.c +++ b/drivers/media/video/saa7164/saa7164-bus.c @@ -43,7 +43,8 @@ int saa7164_bus_setup(struct saa7164_dev *dev) b->m_dwSizeGetRing = SAA_DEVICE_BUFFERBLOCKSIZE; - b->m_dwSetWritePos = ((u32)dev->intfdesc.BARLocation) + (2 * sizeof(u64)); + b->m_dwSetWritePos = ((u32)dev->intfdesc.BARLocation) + + (2 * sizeof(u64)); b->m_dwSetReadPos = b->m_dwSetWritePos + (1 * sizeof(u32)); b->m_dwGetWritePos = b->m_dwSetWritePos + (2 * sizeof(u32)); @@ -105,7 +106,8 @@ void saa7164_bus_verify(struct saa7164_dev *dev) } } -void saa7164_bus_dumpmsg(struct saa7164_dev *dev, struct tmComResInfo* m, void *buf) +void saa7164_bus_dumpmsg(struct saa7164_dev *dev, struct tmComResInfo* m, + void *buf) { dprintk(DBGLVL_BUS, "Dumping msg structure:\n"); dprintk(DBGLVL_BUS, " .id = %d\n", m->id); @@ -129,7 +131,8 @@ void saa7164_bus_dumpmsg(struct saa7164_dev *dev, struct tmComResInfo* m, void * * SAA_OK The function executed successfully. * < 0 One or more members are not initialized. */ -int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg, void *buf) +int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg, + void *buf) { struct tmComResBusInfo *bus = &dev->bus; u32 bytes_to_write, free_write_space, timeout, curr_srp, curr_swp; @@ -294,14 +297,15 @@ out: /* * Receive a command or a response from the bus. The implementation does not * know if it is a command or a response it simply dequeues the data, - * depending on the bus information given in the struct tmComResBusInfo structure. + * depending on the bus information given in the struct tmComResBusInfo + * structure. * * Return Value: * 0 The function executed successfully. * < 0 One or more members are not initialized. */ -int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg, void *buf, - int peekonly) +int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg, + void *buf, int peekonly) { struct tmComResBusInfo *bus = &dev->bus; u32 bytes_to_read, write_distance, curr_grp, curr_gwp, diff --git a/drivers/media/video/saa7164/saa7164-cards.c b/drivers/media/video/saa7164/saa7164-cards.c index 4cb634e..69822a4 100644 --- a/drivers/media/video/saa7164/saa7164-cards.c +++ b/drivers/media/video/saa7164/saa7164-cards.c @@ -482,7 +482,7 @@ void saa7164_gpio_setup(struct saa7164_dev *dev) saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 2); saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 3); - msleep(10); + msleep(20); saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 2); saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 3); diff --git a/drivers/media/video/saa7164/saa7164-cmd.c b/drivers/media/video/saa7164/saa7164-cmd.c index 301a9e3..a97ae17 100644 --- a/drivers/media/video/saa7164/saa7164-cmd.c +++ b/drivers/media/video/saa7164/saa7164-cmd.c @@ -122,8 +122,8 @@ int saa7164_irq_dequeue(struct saa7164_dev *dev) return ret; } - /* It's unlikely to have more than 4 or 5 pending messages, ensure we exit - * at some point regardles. + /* It's unlikely to have more than 4 or 5 pending messages, + * ensure we exit at some point regardless. */ } while (i++ < 32); @@ -186,7 +186,8 @@ int saa7164_cmd_dequeue(struct saa7164_dev *dev) return SAA_OK; } -int saa7164_cmd_set(struct saa7164_dev *dev, struct tmComResInfo* msg, void *buf) +int saa7164_cmd_set(struct saa7164_dev *dev, struct tmComResInfo *msg, + void *buf) { struct tmComResBusInfo *bus = &dev->bus; u8 cmd_sent; @@ -292,7 +293,8 @@ int saa7164_cmd_wait(struct saa7164_dev *dev, u8 seqno) * We typically are signalled in < 50ms but it can * take MUCH longer. */ - wait_event_timeout(*q, dev->cmds[seqno].signalled, (HZ * waitsecs)); + wait_event_timeout(*q, dev->cmds[seqno].signalled, + (HZ * waitsecs)); r = time_before(jiffies, stamp + (HZ * waitsecs)); if (r) ret = SAA_OK; diff --git a/drivers/media/video/saa7164/saa7164-core.c b/drivers/media/video/saa7164/saa7164-core.c index b66f78f..d6bf3f8 100644 --- a/drivers/media/video/saa7164/saa7164-core.c +++ b/drivers/media/video/saa7164/saa7164-core.c @@ -40,12 +40,12 @@ MODULE_AUTHOR("Steven Toth "); MODULE_LICENSE("GPL"); /* - 1 Basic - 2 - 4 i2c - 8 api - 16 cmd - 32 bus + * 1 Basic + * 2 + * 4 i2c + * 8 api + * 16 cmd + * 32 bus */ unsigned int saa_debug; @@ -82,7 +82,8 @@ MODULE_PARM_DESC(crc_checking, "enable crc sanity checking on buffers"); unsigned int guard_checking = 1; module_param(guard_checking, int, 0644); -MODULE_PARM_DESC(guard_checking, "enable dma sanity checking for buffer overruns"); +MODULE_PARM_DESC(guard_checking, + "enable dma sanity checking for buffer overruns"); static unsigned int saa7164_devcount; @@ -123,7 +124,9 @@ static void saa7164_pack_verifier(struct saa7164_buffer *buf) if ((*(p + i + 0) != 0x00) || (*(p + i + 1) != 0x00) || (*(p + i + 2) != 0x01) || (*(p + i + 3) != 0xBA)) { printk(KERN_ERR "No pack at 0x%x\n", i); -// saa7164_dumphex16FF(buf->port->dev, (p + i), 32); +#if 0 + saa7164_dumphex16FF(buf->port->dev, (p + i), 32); +#endif } } } @@ -199,19 +202,16 @@ static void saa7164_histogram_reset(struct saa7164_histogram *hg, char *name) strcpy(hg->name, name); /* First 30ms x 1ms */ - for (i = 0; i < 30; i++) { + for (i = 0; i < 30; i++) hg->counter1[0 + i].val = i; - } /* 30 - 200ms x 10ms */ - for (i = 0; i < 18; i++) { + for (i = 0; i < 18; i++) hg->counter1[30 + i].val = 30 + (i * 10); - } /* 200 - 2000ms x 100ms */ - for (i = 0; i < 15; i++) { + for (i = 0; i < 15; i++) hg->counter1[48 + i].val = 200 + (i * 200); - } /* Catch all massive value (2secs) */ hg->counter1[55].val = 2000; @@ -315,7 +315,9 @@ static void saa7164_work_enchandler_helper(struct saa7164_port *port, int bufnr) (*(p + buf->actual_size + 0x13) != 0xff)) { printk(KERN_ERR "%s() buf %p guard buffer breach\n", __func__, buf); -// saa7164_dumphex16FF(dev, (p + buf->actual_size) - 32 , 64); +#if 0 + saa7164_dumphex16FF(dev, (p + buf->actual_size) - 32 , 64); +#endif } } @@ -961,9 +963,7 @@ static int saa7164_port_init(struct saa7164_dev *dev, int portnr) /* We need a deferred interrupt handler for cmd handling */ INIT_WORK(&port->workenc, saa7164_work_enchandler); - } - else - if ((portnr == SAA7164_PORT_VBI1) || (portnr == SAA7164_PORT_VBI2)) { + } else if ((portnr == SAA7164_PORT_VBI1) || (portnr == SAA7164_PORT_VBI2)) { port->type = SAA7164_MPEG_VBI; /* We need a deferred interrupt handler for cmd handling */ @@ -1169,7 +1169,7 @@ static int saa7164_proc_open(struct inode *inode, struct file *filp) return single_open(filp, saa7164_proc_show, NULL); } -static struct file_operations saa7164_proc_fops = { +static const struct file_operations saa7164_proc_fops = { .open = saa7164_proc_open, .read = seq_read, .llseek = seq_lseek, diff --git a/drivers/media/video/saa7164/saa7164-encoder.c b/drivers/media/video/saa7164/saa7164-encoder.c index cbb53d0..1838408 100644 --- a/drivers/media/video/saa7164/saa7164-encoder.c +++ b/drivers/media/video/saa7164/saa7164-encoder.c @@ -125,16 +125,22 @@ static int saa7164_encoder_buffers_alloc(struct saa7164_port *port) dprintk(DBGLVL_ENC, "%s()\n", __func__); - if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) { - dprintk(DBGLVL_ENC, "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_PS\n", __func__); + if (port->encoder_params.stream_type == + V4L2_MPEG_STREAM_TYPE_MPEG2_PS) { + dprintk(DBGLVL_ENC, + "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_PS\n", + __func__); params->samplesperline = 128; params->numberoflines = 256; params->pitch = 128; params->numpagetables = 2 + ((SAA7164_PS_NUMBER_OF_LINES * 128) / PAGE_SIZE); } else - if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS) { - dprintk(DBGLVL_ENC, "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_TS\n", __func__); + if (port->encoder_params.stream_type == + V4L2_MPEG_STREAM_TYPE_MPEG2_TS) { + dprintk(DBGLVL_ENC, + "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_TS\n", + __func__); params->samplesperline = 188; params->numberoflines = 312; params->pitch = 188; @@ -826,7 +832,8 @@ static int fill_queryctrl(struct saa7164_encoder_params *params, return v4l2_ctrl_query_fill(c, 1, 255, 1, 15); case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: return v4l2_ctrl_query_fill(c, - V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); case V4L2_CID_MPEG_VIDEO_B_FRAMES: return v4l2_ctrl_query_fill(c, @@ -1113,7 +1120,9 @@ struct saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port) if (crc_checking) { crc = crc32(0, ubuf->data, ubuf->actual_size); if (crc != ubuf->crc) { - printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n", __func__, + printk(KERN_ERR + "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n", + __func__, ubuf, ubuf->crc, crc); } } @@ -1201,9 +1210,8 @@ static ssize_t fops_read(struct file *file, char __user *buffer, buffer += cnt; ret += cnt; - if (ubuf->pos > ubuf->actual_size) { + if (ubuf->pos > ubuf->actual_size) printk(KERN_ERR "read() pos > actual, huh?\n"); - } if (ubuf->pos == ubuf->actual_size) { @@ -1227,16 +1235,16 @@ static ssize_t fops_read(struct file *file, char __user *buffer, } } err: - if (!ret && !ubuf) { + if (!ret && !ubuf) ret = -EAGAIN; - } return ret; } static unsigned int fops_poll(struct file *file, poll_table *wait) { - struct saa7164_encoder_fh *fh = (struct saa7164_encoder_fh *)file->private_data; + struct saa7164_encoder_fh *fh = + (struct saa7164_encoder_fh *)file->private_data; struct saa7164_port *port = fh->port; struct saa7164_user_buffer *ubuf; unsigned int mask = 0; @@ -1249,9 +1257,8 @@ static unsigned int fops_poll(struct file *file, poll_table *wait) saa7164_histogram_update(&port->poll_interval, port->last_poll_msecs_diff); - if (!video_is_registered(port->v4l_device)) { + if (!video_is_registered(port->v4l_device)) return -EIO; - } if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { if (atomic_inc_return(&port->v4l_reader_count) == 1) { diff --git a/drivers/media/video/saa7164/saa7164-fw.c b/drivers/media/video/saa7164/saa7164-fw.c index 484533c..22b0232 100644 --- a/drivers/media/video/saa7164/saa7164-fw.c +++ b/drivers/media/video/saa7164/saa7164-fw.c @@ -178,7 +178,7 @@ int saa7164_downloadimage(struct saa7164_dev *dev, u8 *src, u32 srcsize, goto out; } - msleep(10); + msleep(10); /* Checkpatch throws a < 20ms warning */ if (timeout++ > 60) break; } @@ -235,7 +235,7 @@ int saa7164_downloadfirmware(struct saa7164_dev *dev) while (err_flags != SAA_DEVICE_IMAGE_BOOTING) { dprintk(DBGLVL_FW, "%s() err_flags = %x\n", __func__, err_flags); - msleep(10); + msleep(10); /* Checkpatch throws a < 20ms warning */ if (err_flags & SAA_DEVICE_IMAGE_CORRUPT) { printk(KERN_ERR "%s() firmware corrupt\n", @@ -294,7 +294,7 @@ int saa7164_downloadfirmware(struct saa7164_dev *dev) while (err_flags != SAA_DEVICE_IMAGE_BOOTING) { dprintk(DBGLVL_FW, "%s() err_flags2 = %x\n", __func__, err_flags); - msleep(10); + msleep(10); /* Checkpatch throws a < 20ms warning */ if (err_flags & SAA_DEVICE_IMAGE_CORRUPT) { printk(KERN_ERR @@ -365,7 +365,7 @@ int saa7164_downloadfirmware(struct saa7164_dev *dev) first_timeout = SAA_DEVICE_TIMEOUT; while (first_timeout) { - msleep(10); + msleep(10); /* Checkpatch throws a < 20ms warning */ version = saa7164_getcurrentfirmwareversion(dev); diff --git a/drivers/media/video/saa7164/saa7164-i2c.c b/drivers/media/video/saa7164/saa7164-i2c.c index b5167d3..26148f7 100644 --- a/drivers/media/video/saa7164/saa7164-i2c.c +++ b/drivers/media/video/saa7164/saa7164-i2c.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include "saa7164.h" @@ -65,7 +65,7 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) } return num; - err: +err: return retval; } diff --git a/drivers/media/video/saa7164/saa7164-vbi.c b/drivers/media/video/saa7164/saa7164-vbi.c index 323c7cd..8abbe6d 100644 --- a/drivers/media/video/saa7164/saa7164-vbi.c +++ b/drivers/media/video/saa7164/saa7164-vbi.c @@ -51,11 +51,15 @@ static void saa7164_vbi_configure(struct saa7164_port *port) /* Set up the DIF (enable it) for analog mode by default */ saa7164_api_initialize_dif(port); -// /* Configure the correct video standard */ -// saa7164_api_configure_dif(port, port->encodernorm.id); + /* Configure the correct video standard */ +#if 0 + saa7164_api_configure_dif(port, port->encodernorm.id); +#endif -// /* Ensure the audio decoder is correct configured */ -// saa7164_api_set_audio_std(port); +#if 0 + /* Ensure the audio decoder is correct configured */ + saa7164_api_set_audio_std(port); +#endif dprintk(DBGLVL_VBI, "%s() ends\n", __func__); } @@ -919,8 +923,10 @@ static int saa7164_vbi_start_streaming(struct saa7164_port *port) saa7164_vbi_buffers_alloc(port); /* Configure the encoder with any cache values */ -// saa7164_api_set_encoder(port); -// saa7164_api_get_encoder(port); +#if 0 + saa7164_api_set_encoder(port); + saa7164_api_get_encoder(port); +#endif /* Place the empty buffers on the hardware */ saa7164_buffer_cfg_port(port); @@ -1060,7 +1066,8 @@ struct saa7164_user_buffer *saa7164_vbi_next_buf(struct saa7164_port *port) if (crc_checking) { crc = crc32(0, ubuf->data, ubuf->actual_size); if (crc != ubuf->crc) { - printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n", __func__, + printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n", + __func__, ubuf, ubuf->crc, crc); } } @@ -1148,9 +1155,8 @@ static ssize_t fops_read(struct file *file, char __user *buffer, buffer += cnt; ret += cnt; - if (ubuf->pos > ubuf->actual_size) { + if (ubuf->pos > ubuf->actual_size) printk(KERN_ERR "read() pos > actual, huh?\n"); - } if (ubuf->pos == ubuf->actual_size) { @@ -1197,9 +1203,8 @@ static unsigned int fops_poll(struct file *file, poll_table *wait) saa7164_histogram_update(&port->poll_interval, port->last_poll_msecs_diff); - if (!video_is_registered(port->v4l_device)) { + if (!video_is_registered(port->v4l_device)) return -EIO; - } if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { if (atomic_inc_return(&port->v4l_reader_count) == 1) { @@ -1257,10 +1262,14 @@ static const struct v4l2_ioctl_ops vbi_ioctl_ops = { .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, .vidioc_log_status = vidioc_log_status, .vidioc_queryctrl = vidioc_queryctrl, -// .vidioc_g_chip_ident = saa7164_g_chip_ident, +#if 0 + .vidioc_g_chip_ident = saa7164_g_chip_ident, +#endif #ifdef CONFIG_VIDEO_ADV_DEBUG -// .vidioc_g_register = saa7164_g_register, -// .vidioc_s_register = saa7164_s_register, +#if 0 + .vidioc_g_register = saa7164_g_register, + .vidioc_s_register = saa7164_s_register, +#endif #endif .vidioc_g_fmt_vbi_cap = saa7164_vbi_fmt, .vidioc_try_fmt_vbi_cap = saa7164_vbi_fmt, diff --git a/drivers/media/video/saa7164/saa7164.h b/drivers/media/video/saa7164/saa7164.h index 74df9c6..16745d2 100644 --- a/drivers/media/video/saa7164/saa7164.h +++ b/drivers/media/video/saa7164/saa7164.h @@ -113,7 +113,8 @@ #define DBGLVL_THR 4096 #define DBGLVL_CPU 8192 -#define SAA7164_NORMS (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_443) +#define SAA7164_NORMS \ + (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_443) enum port_t { SAA7164_MPEG_UNDEFINED = 0, @@ -182,15 +183,11 @@ struct saa7164_subid { struct saa7164_encoder_fh { struct saa7164_port *port; -// u32 freq; -// u32 tuner_type; atomic_t v4l_reading; }; struct saa7164_vbi_fh { struct saa7164_port *port; -// u32 freq; -// u32 tuner_type; atomic_t v4l_reading; }; @@ -265,8 +262,6 @@ struct saa7164_ctrl { struct saa7164_tvnorm { char *name; v4l2_std_id id; -// u32 cxiformat; -// u32 cxoformat; }; struct saa7164_encoder_params { @@ -510,7 +505,8 @@ extern void saa7164_call_i2c_clients(struct saa7164_i2c *bus, /* saa7164-bus.c */ int saa7164_bus_setup(struct saa7164_dev *dev); void saa7164_bus_dump(struct saa7164_dev *dev); -int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg, void *buf); +int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg, + void *buf); int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg, void *buf, int peekonly); @@ -552,7 +548,8 @@ int saa7164_api_get_videomux(struct saa7164_port *port); int saa7164_api_set_vbi_format(struct saa7164_port *port); int saa7164_api_set_debug(struct saa7164_dev *dev, u8 level); int saa7164_api_collect_debug(struct saa7164_dev *dev); -int saa7164_api_get_load_info(struct saa7164_dev *dev, struct tmFwInfoStruct *i); +int saa7164_api_get_load_info(struct saa7164_dev *dev, + struct tmFwInfoStruct *i); /* ----------------------------------------------------------- */ /* saa7164-cards.c */ -- cgit v0.10.2 From c0b33bdc5b8d9c1120dece660480d4dd86b817ee Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 27 Oct 2010 09:12:30 -0300 Subject: [media] gspca-stv06xx: support bandwidth changing stv06xx devices have only one altsetting, but the actual used bandwidth can be programmed through a register. We were already setting this register lower then the max packetsize of the altsetting indicates. This patch makes the gspca-stv06xx update the usb descriptor for the alt setting to reflect the actual packetsize in use, so that the usb subsystem uses the correct information for scheduling usb transfers. This patch also tries to fallback to lower speeds in case a ENOSPC error is received when submitting urbs, but currently this is only supported with stv06xx cams with the pb0100 sensor, as this is the only one for which we know how to change the framerate. This patch is based on an initial incomplete patch by Lee Jones Signed-off-by: Lee Jones Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c index 544d5f7..28ea417 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx.c @@ -263,7 +263,21 @@ static int stv06xx_init(struct gspca_dev *gspca_dev) static int stv06xx_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int err; + struct usb_host_interface *alt; + struct usb_interface *intf; + int err, packet_size; + + intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); + alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); + if (!alt) { + PDEBUG(D_ERR, "Couldn't get altsetting"); + return -EIO; + } + + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size); + if (err < 0) + return err; /* Prepare the sensor for start */ err = sd->sensor->start(sd); @@ -282,6 +296,43 @@ out: return (err < 0) ? err : 0; } +static int stv06xx_isoc_init(struct gspca_dev *gspca_dev) +{ + struct usb_host_interface *alt; + struct sd *sd = (struct sd *) gspca_dev; + + /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ + alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; + alt->endpoint[0].desc.wMaxPacketSize = + cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]); + + return 0; +} + +static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev) +{ + int ret, packet_size, min_packet_size; + struct usb_host_interface *alt; + struct sd *sd = (struct sd *) gspca_dev; + + alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode]; + if (packet_size <= min_packet_size) + return -EIO; + + packet_size -= 100; + if (packet_size < min_packet_size) + packet_size = min_packet_size; + alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size); + + ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); + if (ret < 0) + PDEBUG(D_ERR|D_STREAM, "set alt 1 err %d", ret); + + return ret; +} + static void stv06xx_stopN(struct gspca_dev *gspca_dev) { int err; @@ -462,6 +513,8 @@ static const struct sd_desc sd_desc = { .start = stv06xx_start, .stopN = stv06xx_stopN, .pkt_scan = stv06xx_pkt_scan, + .isoc_init = stv06xx_isoc_init, + .isoc_nego = stv06xx_isoc_nego, #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) .int_pkt_scan = sd_int_pkt_scan, #endif diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h index cf3d0cc..b538dce 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h @@ -146,6 +146,11 @@ const struct stv06xx_sensor stv06xx_sensor_hdcs1x00 = { .i2c_addr = (0x55 << 1), .i2c_len = 1, + /* FIXME (see if we can lower min_packet_size, needs testing, and also + adjusting framerate when the bandwidth gets lower) */ + .min_packet_size = { 847 }, + .max_packet_size = { 847 }, + .init = hdcs_init, .probe = hdcs_probe_1x00, .start = hdcs_start, @@ -160,6 +165,11 @@ const struct stv06xx_sensor stv06xx_sensor_hdcs1020 = { .i2c_addr = (0x55 << 1), .i2c_len = 1, + /* FIXME (see if we can lower min_packet_size, needs testing, and also + adjusting framerate when the bandwidthm gets lower) */ + .min_packet_size = { 847 }, + .max_packet_size = { 847 }, + .init = hdcs_init, .probe = hdcs_probe_1020, .start = hdcs_start, @@ -177,7 +187,6 @@ static const u16 stv_bridge_init[][2] = { {STV_REG04, 0x07}, {STV_SCAN_RATE, 0x20}, - {STV_ISO_SIZE_L, 847}, {STV_Y_CTRL, 0x01}, {STV_X_CTRL, 0x0a} }; diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c index 285221e..ac47b4c 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c @@ -208,11 +208,24 @@ static int pb0100_probe(struct sd *sd) static int pb0100_start(struct sd *sd) { - int err; + int err, packet_size, max_packet_size; + struct usb_host_interface *alt; + struct usb_interface *intf; struct cam *cam = &sd->gspca_dev.cam; s32 *sensor_settings = sd->sensor_priv; u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv; + intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); + alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + + /* If we don't have enough bandwidth use a lower framerate */ + max_packet_size = sd->sensor->max_packet_size[sd->gspca_dev.curr_mode]; + if (packet_size < max_packet_size) + stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1)); + else + stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(5)|BIT(3)|BIT(1)); + /* Setup sensor window */ if (mode & PB0100_CROP_TO_VGA) { stv06xx_write_sensor(sd, PB_RSTART, 30); @@ -328,9 +341,6 @@ static int pb0100_init(struct sd *sd) stv06xx_write_bridge(sd, STV_REG03, 0x45); stv06xx_write_bridge(sd, STV_REG04, 0x07); - /* ISO-Size (0x27b: 635... why? - HDCS uses 847) */ - stv06xx_write_bridge(sd, STV_ISO_SIZE_L, 847); - /* Scan/timing for the sensor */ stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1)); stv06xx_write_sensor(sd, PB_CFILLIN, 14); diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h index 4de4fa5..757de24 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h @@ -138,6 +138,9 @@ const struct stv06xx_sensor stv06xx_sensor_pb0100 = { .i2c_addr = 0xba, .i2c_len = 2, + .min_packet_size = { 635, 847 }, + .max_packet_size = { 847, 923 }, + .init = pb0100_init, .probe = pb0100_probe, .start = pb0100_start, diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h index 934b9ce..fb229d8 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h @@ -53,6 +53,10 @@ struct stv06xx_sensor { /* length of an i2c word */ u8 i2c_len; + /* Isoc packet size (per mode) */ + int min_packet_size[4]; + int max_packet_size[4]; + /* Probes if the sensor is connected */ int (*probe)(struct sd *sd); diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c index ea677b5..42f3a1e 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c @@ -213,7 +213,6 @@ static int st6422_init(struct sd *sd) { 0x150e, 0x8e }, { 0x150f, 0x37 }, { 0x15c0, 0x00 }, - { 0x15c1, 1023 }, /* 160x120, ISOC_PACKET_SIZE */ { 0x15c3, 0x08 }, /* 0x04/0x14 ... test pictures ??? */ @@ -237,23 +236,9 @@ static void st6422_disconnect(struct sd *sd) static int st6422_start(struct sd *sd) { - int err, packet_size; + int err; struct cam *cam = &sd->gspca_dev.cam; s32 *sensor_settings = sd->sensor_priv; - struct usb_host_interface *alt; - struct usb_interface *intf; - - intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); - alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); - if (!alt) { - err("Couldn't get altsetting"); - return -EIO; - } - - packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); - err = stv06xx_write_bridge(sd, 0x15c1, packet_size); - if (err < 0) - return err; if (cam->cam_mode[sd->gspca_dev.curr_mode].priv) err = stv06xx_write_bridge(sd, 0x1505, 0x0f); diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h index b2d45fe..12608ae 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h @@ -49,6 +49,9 @@ static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val); const struct stv06xx_sensor stv06xx_sensor_st6422 = { .name = "ST6422", + /* No known way to lower framerate in case of less bandwidth */ + .min_packet_size = { 300, 847 }, + .max_packet_size = { 300, 847 }, .init = st6422_init, .probe = st6422_probe, .start = st6422_start, diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h index b3b5508..7fe3587 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h @@ -197,6 +197,10 @@ const struct stv06xx_sensor stv06xx_sensor_vv6410 = { .i2c_flush = 5, .i2c_addr = 0x20, .i2c_len = 1, + /* FIXME (see if we can lower packet_size-s, needs testing, and also + adjusting framerate when the bandwidth gets lower) */ + .min_packet_size = { 1023 }, + .max_packet_size = { 1023 }, .init = vv6410_init, .probe = vv6410_probe, .start = vv6410_start, @@ -220,10 +224,6 @@ static const u8 x1536[] = { /* 0x1536 - 0x153b */ 0x02, 0x00, 0x60, 0x01, 0x20, 0x01 }; -static const u8 x15c1[] = { /* 0x15c1 - 0x15c2 */ - 0xff, 0x03 /* Output word 0x03ff = 1023 (ISO size) */ -}; - static const struct stv_init stv_bridge_init[] = { /* This reg is written twice. Some kind of reset? */ {NULL, 0x1620, 0x80}, @@ -232,7 +232,6 @@ static const struct stv_init stv_bridge_init[] = { {NULL, 0x1423, 0x04}, {x1500, 0x1500, ARRAY_SIZE(x1500)}, {x1536, 0x1536, ARRAY_SIZE(x1536)}, - {x15c1, 0x15c1, ARRAY_SIZE(x15c1)} }; static const u8 vv6410_sensor_init[][2] = { -- cgit v0.10.2 From 14653e64e9db48e91cbd00fba335a6a459e66cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Thu, 11 Nov 2010 06:17:01 -0300 Subject: [media] gspca - ov519: Handle the snapshot on capture stop when CONFIG_INPUT=m MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 19f943e..7e86faf 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -3940,7 +3940,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) if (sd->bridge == BRIDGE_W9968CF) w9968cf_stop0(sd); -#ifdef CONFIG_INPUT +#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) /* If the last button state is pressed, release it now! */ if (sd->snapshot_pressed) { input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); -- cgit v0.10.2 From d65174c06f2bf4ff73d1c71960be317b89561c06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Thu, 11 Nov 2010 06:20:42 -0300 Subject: [media] gspca - ov519: Don't do USB exchanges after disconnection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 7e86faf..ed70229 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -3937,6 +3937,8 @@ static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + if (!sd->gspca_dev.present) + return; if (sd->bridge == BRIDGE_W9968CF) w9968cf_stop0(sd); diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c index 4066ac8..b5a93e3 100644 --- a/drivers/media/video/gspca/w996Xcf.c +++ b/drivers/media/video/gspca/w996Xcf.c @@ -549,10 +549,8 @@ static int w9968cf_mode_init_regs(struct sd *sd) static void w9968cf_stop0(struct sd *sd) { - if (sd->gspca_dev.present) { - reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */ - reg_w(sd, 0x16, 0x0000); /* stop video capture */ - } + reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */ + reg_w(sd, 0x16, 0x0000); /* stop video capture */ } /* The w9968cf docs say that a 0 sized packet means EOF (and also SOF -- cgit v0.10.2 From 9d1593a84c09e57a9565baab931a6cf116120e05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Thu, 11 Nov 2010 08:04:06 -0300 Subject: [media] gspca - ov519: Change types '__xx' to 'xx' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index ed70229..8355c63 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -75,7 +75,7 @@ struct sd { struct gspca_ctrl ctrls[NCTRL]; - __u8 packet_nr; + u8 packet_nr; char bridge; #define BRIDGE_OV511 0 @@ -94,20 +94,20 @@ struct sd { char snapshot_needs_reset; /* Determined by sensor type */ - __u8 sif; + u8 sif; - __u8 quality; + u8 quality; #define QUALITY_MIN 50 #define QUALITY_MAX 70 #define QUALITY_DEF 50 - __u8 stopped; /* Streaming is temporarily paused */ - __u8 first_frame; + u8 stopped; /* Streaming is temporarily paused */ + u8 first_frame; - __u8 frame_rate; /* current Framerate */ - __u8 clockdiv; /* clockdiv override */ + u8 frame_rate; /* current Framerate */ + u8 clockdiv; /* clockdiv override */ - char sensor; /* Type of image sensor chip (SEN_*) */ + u8 sensor; /* Type of image sensor chip (SEN_*) */ #define SEN_UNKNOWN 0 #define SEN_OV2610 1 #define SEN_OV3610 2 @@ -594,12 +594,12 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */ struct ov_regvals { - __u8 reg; - __u8 val; + u8 reg; + u8 val; }; struct ov_i2c_regvals { - __u8 reg; - __u8 val; + u8 reg; + u8 val; }; /* Settings for OV2610 camera chip */ @@ -1825,7 +1825,7 @@ static unsigned char ov7670_abs_to_sm(unsigned char v) } /* Write a OV519 register */ -static int reg_w(struct sd *sd, __u16 index, __u16 value) +static int reg_w(struct sd *sd, u16 index, u16 value) { int ret, req = 0; @@ -1868,7 +1868,7 @@ leave: /* Read from a OV519 register, note not valid for the w9968cf!! */ /* returns: negative is error, pos or zero is data */ -static int reg_r(struct sd *sd, __u16 index) +static int reg_r(struct sd *sd, u16 index) { int ret; int req; @@ -1902,7 +1902,7 @@ static int reg_r(struct sd *sd, __u16 index) /* Read 8 values from a OV519 register */ static int reg_r8(struct sd *sd, - __u16 index) + u16 index) { int ret; @@ -1927,12 +1927,12 @@ static int reg_r8(struct sd *sd, * of their respective state in "value". */ static int reg_w_mask(struct sd *sd, - __u16 index, - __u8 value, - __u8 mask) + u16 index, + u8 value, + u8 mask) { int ret; - __u8 oldval; + u8 oldval; if (mask != 0xff) { value &= mask; /* Enforce mask on value */ @@ -1950,7 +1950,7 @@ static int reg_w_mask(struct sd *sd, * Writes multiple (n) byte value to a single register. Only valid with certain * registers (0x30 and 0xc4 - 0xce). */ -static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n) +static int ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n) { int ret; @@ -1970,7 +1970,7 @@ static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n) return 0; } -static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value) +static int ov511_i2c_w(struct sd *sd, u8 reg, u8 value) { int rc, retries; @@ -2011,7 +2011,7 @@ static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value) return 0; } -static int ov511_i2c_r(struct sd *sd, __u8 reg) +static int ov511_i2c_r(struct sd *sd, u8 reg) { int rc, value, retries; @@ -2092,8 +2092,8 @@ static int ov511_i2c_r(struct sd *sd, __u8 reg) * always succeeds regardless of whether the sensor is present and working. */ static int ov518_i2c_w(struct sd *sd, - __u8 reg, - __u8 value) + u8 reg, + u8 value) { int rc; @@ -2126,7 +2126,7 @@ static int ov518_i2c_w(struct sd *sd, * This is normally only called from i2c_r(). Note that this function * always succeeds regardless of whether the sensor is present and working. */ -static int ov518_i2c_r(struct sd *sd, __u8 reg) +static int ov518_i2c_r(struct sd *sd, u8 reg) { int rc, value; @@ -2149,7 +2149,7 @@ static int ov518_i2c_r(struct sd *sd, __u8 reg) return value; } -static int ovfx2_i2c_w(struct sd *sd, __u8 reg, __u8 value) +static int ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value) { int ret; @@ -2157,7 +2157,7 @@ static int ovfx2_i2c_w(struct sd *sd, __u8 reg, __u8 value) usb_sndctrlpipe(sd->gspca_dev.dev, 0), 0x02, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - (__u16)value, (__u16)reg, NULL, 0, 500); + (u16) value, (u16) reg, NULL, 0, 500); if (ret < 0) { err("i2c 0x%02x -> [0x%02x] failed", value, reg); @@ -2168,7 +2168,7 @@ static int ovfx2_i2c_w(struct sd *sd, __u8 reg, __u8 value) return 0; } -static int ovfx2_i2c_r(struct sd *sd, __u8 reg) +static int ovfx2_i2c_r(struct sd *sd, u8 reg) { int ret; @@ -2176,7 +2176,7 @@ static int ovfx2_i2c_r(struct sd *sd, __u8 reg) usb_rcvctrlpipe(sd->gspca_dev.dev, 0), 0x03, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, (__u16)reg, sd->gspca_dev.usb_buf, 1, 500); + 0, (u16) reg, sd->gspca_dev.usb_buf, 1, 500); if (ret >= 0) { ret = sd->gspca_dev.usb_buf[0]; @@ -2187,7 +2187,7 @@ static int ovfx2_i2c_r(struct sd *sd, __u8 reg) return ret; } -static int i2c_w(struct sd *sd, __u8 reg, __u8 value) +static int i2c_w(struct sd *sd, u8 reg, u8 value) { int ret = -1; @@ -2224,7 +2224,7 @@ static int i2c_w(struct sd *sd, __u8 reg, __u8 value) return ret; } -static int i2c_r(struct sd *sd, __u8 reg) +static int i2c_r(struct sd *sd, u8 reg) { int ret = -1; @@ -2261,12 +2261,12 @@ static int i2c_r(struct sd *sd, __u8 reg) * of their respective state in "value". */ static int i2c_w_mask(struct sd *sd, - __u8 reg, - __u8 value, - __u8 mask) + u8 reg, + u8 value, + u8 mask) { int rc; - __u8 oldval; + u8 oldval; value &= mask; /* Enforce mask on value */ rc = i2c_r(sd, reg); @@ -2334,12 +2334,12 @@ static inline int ov51x_restart(struct sd *sd) return 0; } -static int ov51x_set_slave_ids(struct sd *sd, __u8 slave); +static int ov51x_set_slave_ids(struct sd *sd, u8 slave); /* This does an initial reset of an OmniVision sensor and ensures that I2C * is synchronized. Returns <0 on failure. */ -static int init_ov_sensor(struct sd *sd, __u8 slave) +static int init_ov_sensor(struct sd *sd, u8 slave) { int i; @@ -2378,7 +2378,7 @@ static int init_ov_sensor(struct sd *sd, __u8 slave) * Sets I2C read and write slave IDs. Returns <0 for error */ static int ov51x_set_slave_ids(struct sd *sd, - __u8 slave) + u8 slave) { int rc; @@ -3601,7 +3601,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) { struct gspca_dev *gspca_dev; int qvga, xstart, xend, ystart, yend; - __u8 v; + u8 v; gspca_dev = &sd->gspca_dev; qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; @@ -4213,7 +4213,7 @@ static void setcontrast(struct gspca_dev *gspca_dev) i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f); break; case SEN_OV8610: { - static const __u8 ctab[] = { + static const u8 ctab[] = { 0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f }; @@ -4223,7 +4223,7 @@ static void setcontrast(struct gspca_dev *gspca_dev) } case SEN_OV7620: case SEN_OV7620AE: { - static const __u8 ctab[] = { + static const u8 ctab[] = { 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57, 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff }; diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c index b5a93e3..5d73420 100644 --- a/drivers/media/video/gspca/w996Xcf.c +++ b/drivers/media/video/gspca/w996Xcf.c @@ -59,7 +59,7 @@ static const struct v4l2_pix_format w9968cf_vga_mode[] = { .colorspace = V4L2_COLORSPACE_JPEG}, }; -static int reg_w(struct sd *sd, __u16 index, __u16 value); +static int reg_w(struct sd *sd, u16 index, u16 value); /*-------------------------------------------------------------------------- Write 64-bit data to the fast serial bus registers. -- cgit v0.10.2 From d6fa66384b38165126ce2866b4bdff756c6fc761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Thu, 11 Nov 2010 08:05:50 -0300 Subject: [media] gspca - ov519: Reduce the size of some variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 8355c63..d73e1c7 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -124,9 +124,9 @@ struct sd { #define SEN_OV8610 13 u8 sensor_addr; - int sensor_width; - int sensor_height; - int sensor_reg_cache[256]; + u16 sensor_width; + u16 sensor_height; + s16 sensor_reg_cache[256]; u8 jpeg_hdr[JPEG_HDR_SZ]; }; -- cgit v0.10.2 From 7bbe6b8d1f63c2f7482c93d8cd986b1774e6436d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Thu, 11 Nov 2010 08:27:24 -0300 Subject: [media] gspca - ov519: Define the sensor types in an enum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch also checks if the sensor is well detected at connection time. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index d73e1c7..5da1a4e 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -107,21 +107,7 @@ struct sd { u8 frame_rate; /* current Framerate */ u8 clockdiv; /* clockdiv override */ - u8 sensor; /* Type of image sensor chip (SEN_*) */ -#define SEN_UNKNOWN 0 -#define SEN_OV2610 1 -#define SEN_OV3610 2 -#define SEN_OV6620 3 -#define SEN_OV6630 4 -#define SEN_OV66308AF 5 -#define SEN_OV7610 6 -#define SEN_OV7620 7 -#define SEN_OV7620AE 8 -#define SEN_OV7640 9 -#define SEN_OV7648 10 -#define SEN_OV7670 11 -#define SEN_OV76BE 12 -#define SEN_OV8610 13 + s8 sensor; /* Type of image sensor chip (SEN_*) */ u8 sensor_addr; u16 sensor_width; @@ -130,6 +116,21 @@ struct sd { u8 jpeg_hdr[JPEG_HDR_SZ]; }; +enum sensors { + SEN_OV2610, + SEN_OV3610, + SEN_OV6620, + SEN_OV6630, + SEN_OV66308AF, + SEN_OV7610, + SEN_OV7620, + SEN_OV7620AE, + SEN_OV7640, + SEN_OV7648, + SEN_OV7670, + SEN_OV76BE, + SEN_OV8610, +}; /* Note this is a bit of a hack, but the w9968cf driver needs the code for all the ov sensors which is already present here. When we have the time we @@ -3010,6 +3011,7 @@ static int sd_config(struct gspca_dev *gspca_dev, /* The OV519 must be more aggressive about sensor detection since * I2C write will never fail if the sensor is not present. We have * to try to initialize the sensor to detect its presence */ + sd->sensor = -1; /* Test for 76xx */ if (init_ov_sensor(sd, OV7xx0_SID) >= 0) { @@ -3040,6 +3042,9 @@ static int sd_config(struct gspca_dev *gspca_dev, goto error; } + if (sd->sensor < 0) + goto error; + switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: @@ -3117,7 +3122,7 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; error: PDEBUG(D_ERR, "OV519 Config failed"); - return -EBUSY; + return -EINVAL; } /* this function is called at probe and resume time */ -- cgit v0.10.2 From 9be1d6cde936dcf9a325eeee01ed64005c98d456 Mon Sep 17 00:00:00 2001 From: Nicolas Kaiser Date: Fri, 12 Nov 2010 04:32:35 -0300 Subject: [media] gspca - cpia1: Fix error check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It looks to me like it was intended to check the return value at this point. Signed-off-by: Nicolas Kaiser Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c index 80b8dae..c1ae05f 100644 --- a/drivers/media/video/gspca/cpia1.c +++ b/drivers/media/video/gspca/cpia1.c @@ -829,7 +829,7 @@ static int goto_low_power(struct gspca_dev *gspca_dev) if (ret) return ret; - do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); + ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); if (ret) return ret; -- cgit v0.10.2 From 87bae740fd50df49337017b3ccbed9dbaeaad610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Fri, 12 Nov 2010 05:31:34 -0300 Subject: [media] gspca - ov519: Cleanup source MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - move hexadecimal value to lowercase - remove/add empty lines and spaces - comment unused macros - change some comments Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 5da1a4e..85fc433 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -226,7 +226,7 @@ static const struct ctrl sd_ctrls[] = { .type = V4L2_CTRL_TYPE_MENU, .name = "Light frequency filter", .minimum = 0, - .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ + .maximum = 2, /* 0: no flicker, 1: 50Hz, 2:60Hz, 3: auto */ .step = 1, .default_value = 0, }, @@ -413,7 +413,6 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { .priv = 0}, }; - /* Registers common to OV511 / OV518 */ #define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */ #define R51x_SYS_RESET 0x50 @@ -421,7 +420,7 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define OV511_RESET_OMNICE 0x08 #define R51x_SYS_INIT 0x53 #define R51x_SYS_SNAP 0x52 -#define R51x_SYS_CUST_ID 0x5F +#define R51x_SYS_CUST_ID 0x5f #define R51x_COMP_LUT_BEGIN 0x80 /* OV511 Camera interface register numbers */ @@ -436,13 +435,13 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define R511_CAM_OPTS 0x18 #define R511_SNAP_FRAME 0x19 -#define R511_SNAP_PXCNT 0x1A -#define R511_SNAP_LNCNT 0x1B -#define R511_SNAP_PXDIV 0x1C -#define R511_SNAP_LNDIV 0x1D -#define R511_SNAP_UV_EN 0x1E -#define R511_SNAP_UV_EN 0x1E -#define R511_SNAP_OPTS 0x1F +#define R511_SNAP_PXCNT 0x1a +#define R511_SNAP_LNCNT 0x1b +#define R511_SNAP_PXDIV 0x1c +#define R511_SNAP_LNDIV 0x1d +#define R511_SNAP_UV_EN 0x1e +#define R511_SNAP_UV_EN 0x1e +#define R511_SNAP_OPTS 0x1f #define R511_DRAM_FLOW_CTL 0x20 #define R511_FIFO_OPTS 0x31 @@ -467,13 +466,13 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define OV519_R25_FORMAT 0x25 /* OV519 System Controller register numbers */ -#define OV519_SYS_RESET1 0x51 -#define OV519_SYS_EN_CLK1 0x54 +#define OV519_SYS_RESET1 0x51 +#define OV519_SYS_EN_CLK1 0x54 #define OV519_GPIO_DATA_OUT0 0x71 #define OV519_GPIO_IO_CTRL0 0x72 -#define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */ +/*#define OV511_ENDPOINT_ADDRESS 1 * Isoc endpoint number */ /* * The FX2 chip does not give us a zero length read at end of frame. @@ -528,71 +527,71 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define OV7610_REG_COM_I 0x29 /* misc settings */ /* OV7670 registers */ -#define OV7670_REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ -#define OV7670_REG_BLUE 0x01 /* blue gain */ -#define OV7670_REG_RED 0x02 /* red gain */ -#define OV7670_REG_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ -#define OV7670_REG_COM1 0x04 /* Control 1 */ -#define OV7670_REG_AECHH 0x07 /* AEC MS 5 bits */ -#define OV7670_REG_COM3 0x0c /* Control 3 */ -#define OV7670_REG_COM4 0x0d /* Control 4 */ -#define OV7670_REG_COM5 0x0e /* All "reserved" */ -#define OV7670_REG_COM6 0x0f /* Control 6 */ -#define OV7670_REG_AECH 0x10 /* More bits of AEC value */ -#define OV7670_REG_CLKRC 0x11 /* Clock control */ -#define OV7670_REG_COM7 0x12 /* Control 7 */ -#define OV7670_COM7_FMT_VGA 0x00 -#define OV7670_COM7_YUV 0x00 /* YUV */ -#define OV7670_COM7_FMT_QVGA 0x10 /* QVGA format */ -#define OV7670_COM7_FMT_MASK 0x38 -#define OV7670_COM7_RESET 0x80 /* Register reset */ -#define OV7670_REG_COM8 0x13 /* Control 8 */ -#define OV7670_COM8_AEC 0x01 /* Auto exposure enable */ -#define OV7670_COM8_AWB 0x02 /* White balance enable */ -#define OV7670_COM8_AGC 0x04 /* Auto gain enable */ -#define OV7670_COM8_BFILT 0x20 /* Band filter enable */ -#define OV7670_COM8_AECSTEP 0x40 /* Unlimited AEC step size */ -#define OV7670_COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */ -#define OV7670_REG_COM9 0x14 /* Control 9 - gain ceiling */ -#define OV7670_REG_COM10 0x15 /* Control 10 */ -#define OV7670_REG_HSTART 0x17 /* Horiz start high bits */ -#define OV7670_REG_HSTOP 0x18 /* Horiz stop high bits */ -#define OV7670_REG_VSTART 0x19 /* Vert start high bits */ -#define OV7670_REG_VSTOP 0x1a /* Vert stop high bits */ -#define OV7670_REG_MVFP 0x1e /* Mirror / vflip */ -#define OV7670_MVFP_VFLIP 0x10 /* vertical flip */ -#define OV7670_MVFP_MIRROR 0x20 /* Mirror image */ -#define OV7670_REG_AEW 0x24 /* AGC upper limit */ -#define OV7670_REG_AEB 0x25 /* AGC lower limit */ -#define OV7670_REG_VPT 0x26 /* AGC/AEC fast mode op region */ -#define OV7670_REG_HREF 0x32 /* HREF pieces */ -#define OV7670_REG_TSLB 0x3a /* lots of stuff */ -#define OV7670_REG_COM11 0x3b /* Control 11 */ -#define OV7670_COM11_EXP 0x02 -#define OV7670_COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ -#define OV7670_REG_COM12 0x3c /* Control 12 */ -#define OV7670_REG_COM13 0x3d /* Control 13 */ -#define OV7670_COM13_GAMMA 0x80 /* Gamma enable */ -#define OV7670_COM13_UVSAT 0x40 /* UV saturation auto adjustment */ -#define OV7670_REG_COM14 0x3e /* Control 14 */ -#define OV7670_REG_EDGE 0x3f /* Edge enhancement factor */ -#define OV7670_REG_COM15 0x40 /* Control 15 */ -#define OV7670_COM15_R00FF 0xc0 /* 00 to FF */ -#define OV7670_REG_COM16 0x41 /* Control 16 */ -#define OV7670_COM16_AWBGAIN 0x08 /* AWB gain enable */ -#define OV7670_REG_BRIGHT 0x55 /* Brightness */ -#define OV7670_REG_CONTRAS 0x56 /* Contrast control */ -#define OV7670_REG_GFIX 0x69 /* Fix gain control */ -#define OV7670_REG_RGB444 0x8c /* RGB 444 control */ -#define OV7670_REG_HAECC1 0x9f /* Hist AEC/AGC control 1 */ -#define OV7670_REG_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ -#define OV7670_REG_BD50MAX 0xa5 /* 50hz banding step limit */ -#define OV7670_REG_HAECC3 0xa6 /* Hist AEC/AGC control 3 */ -#define OV7670_REG_HAECC4 0xa7 /* Hist AEC/AGC control 4 */ -#define OV7670_REG_HAECC5 0xa8 /* Hist AEC/AGC control 5 */ -#define OV7670_REG_HAECC6 0xa9 /* Hist AEC/AGC control 6 */ -#define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ -#define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */ +#define OV7670_REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ +#define OV7670_REG_BLUE 0x01 /* blue gain */ +#define OV7670_REG_RED 0x02 /* red gain */ +#define OV7670_REG_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ +#define OV7670_REG_COM1 0x04 /* Control 1 */ +/*#define OV7670_REG_AECHH 0x07 * AEC MS 5 bits */ +#define OV7670_REG_COM3 0x0c /* Control 3 */ +#define OV7670_REG_COM4 0x0d /* Control 4 */ +#define OV7670_REG_COM5 0x0e /* All "reserved" */ +#define OV7670_REG_COM6 0x0f /* Control 6 */ +#define OV7670_REG_AECH 0x10 /* More bits of AEC value */ +#define OV7670_REG_CLKRC 0x11 /* Clock control */ +#define OV7670_REG_COM7 0x12 /* Control 7 */ +#define OV7670_COM7_FMT_VGA 0x00 +/*#define OV7670_COM7_YUV 0x00 * YUV */ +#define OV7670_COM7_FMT_QVGA 0x10 /* QVGA format */ +#define OV7670_COM7_FMT_MASK 0x38 +#define OV7670_COM7_RESET 0x80 /* Register reset */ +#define OV7670_REG_COM8 0x13 /* Control 8 */ +#define OV7670_COM8_AEC 0x01 /* Auto exposure enable */ +#define OV7670_COM8_AWB 0x02 /* White balance enable */ +#define OV7670_COM8_AGC 0x04 /* Auto gain enable */ +#define OV7670_COM8_BFILT 0x20 /* Band filter enable */ +#define OV7670_COM8_AECSTEP 0x40 /* Unlimited AEC step size */ +#define OV7670_COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */ +#define OV7670_REG_COM9 0x14 /* Control 9 - gain ceiling */ +#define OV7670_REG_COM10 0x15 /* Control 10 */ +#define OV7670_REG_HSTART 0x17 /* Horiz start high bits */ +#define OV7670_REG_HSTOP 0x18 /* Horiz stop high bits */ +#define OV7670_REG_VSTART 0x19 /* Vert start high bits */ +#define OV7670_REG_VSTOP 0x1a /* Vert stop high bits */ +#define OV7670_REG_MVFP 0x1e /* Mirror / vflip */ +#define OV7670_MVFP_VFLIP 0x10 /* vertical flip */ +#define OV7670_MVFP_MIRROR 0x20 /* Mirror image */ +#define OV7670_REG_AEW 0x24 /* AGC upper limit */ +#define OV7670_REG_AEB 0x25 /* AGC lower limit */ +#define OV7670_REG_VPT 0x26 /* AGC/AEC fast mode op region */ +#define OV7670_REG_HREF 0x32 /* HREF pieces */ +#define OV7670_REG_TSLB 0x3a /* lots of stuff */ +#define OV7670_REG_COM11 0x3b /* Control 11 */ +#define OV7670_COM11_EXP 0x02 +#define OV7670_COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ +#define OV7670_REG_COM12 0x3c /* Control 12 */ +#define OV7670_REG_COM13 0x3d /* Control 13 */ +#define OV7670_COM13_GAMMA 0x80 /* Gamma enable */ +#define OV7670_COM13_UVSAT 0x40 /* UV saturation auto adjustment */ +#define OV7670_REG_COM14 0x3e /* Control 14 */ +#define OV7670_REG_EDGE 0x3f /* Edge enhancement factor */ +#define OV7670_REG_COM15 0x40 /* Control 15 */ +/*#define OV7670_COM15_R00FF 0xc0 * 00 to FF */ +#define OV7670_REG_COM16 0x41 /* Control 16 */ +#define OV7670_COM16_AWBGAIN 0x08 /* AWB gain enable */ +#define OV7670_REG_BRIGHT 0x55 /* Brightness */ +#define OV7670_REG_CONTRAS 0x56 /* Contrast control */ +#define OV7670_REG_GFIX 0x69 /* Fix gain control */ +#define OV7670_REG_RGB444 0x8c /* RGB 444 control */ +#define OV7670_REG_HAECC1 0x9f /* Hist AEC/AGC control 1 */ +#define OV7670_REG_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ +#define OV7670_REG_BD50MAX 0xa5 /* 50hz banding step limit */ +#define OV7670_REG_HAECC3 0xa6 /* Hist AEC/AGC control 3 */ +#define OV7670_REG_HAECC4 0xa7 /* Hist AEC/AGC control 4 */ +#define OV7670_REG_HAECC5 0xa8 /* Hist AEC/AGC control 5 */ +#define OV7670_REG_HAECC6 0xa9 /* Hist AEC/AGC control 6 */ +#define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ +#define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */ struct ov_regvals { u8 reg; @@ -618,7 +617,6 @@ static const struct ov_i2c_regvals norm_3620b[] = { * "wait 4096 external clock ... to make sure the sensor is * stable and ready to access registers" i.e. 160us at 24MHz */ - { 0x12, 0x80 }, /* COMH reset */ { 0x12, 0x00 }, /* QXGA, master */ @@ -651,7 +649,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * COMI[0] "Exposure control" * = 0 (0x00) .......0 "Manual" */ - { 0x13, 0xC0 }, + { 0x13, 0xc0 }, /* * 09 COMC "Common Control C" @@ -707,7 +705,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * COME[0] "Auto zero circuit select" * = 1 (0x01) .......1 "On" */ - { 0x0d, 0xA1 }, + { 0x0d, 0xa1 }, /* * 0E COMF "Common Control F" @@ -771,7 +769,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * COMJ[0] "Reserved" * = 0 (0x00) .......0 */ - { 0x14, 0xC6 }, + { 0x14, 0xc6 }, /* * 15 COMK "Common Control K" @@ -877,7 +875,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * FVOPT[7:0] "Range" * = 31 (0x1F) 00011111 */ - { 0x3c, 0x1F }, + { 0x3c, 0x1f }, /* * 44 Undocumented = 0 (0x00) 00000000 @@ -926,7 +924,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * 48[7:0] "It's a secret" * = 192 (0xC0) 11000000 */ - { 0x48, 0xC0 }, + { 0x48, 0xc0 }, /* * 49 Undocumented = 25 (0x19) 00011001 @@ -940,18 +938,18 @@ static const struct ov_i2c_regvals norm_3620b[] = { * 4B[7:0] "It's a secret" * = 128 (0x80) 10000000 */ - { 0x4B, 0x80 }, + { 0x4b, 0x80 }, /* * 4D Undocumented = 196 (0xC4) 11000100 * 4D[7:0] "It's a secret" * = 196 (0xC4) 11000100 */ - { 0x4D, 0xC4 }, + { 0x4d, 0xc4 }, /* * 35 VREF "Reference Voltage Control" - * = 76 (0x4C) 01001100 + * = 76 (0x4c) 01001100 * VREF[7:5] "Column high reference control" * = 2 (0x02) 010..... "higher voltage" * VREF[4:2] "Column low reference control" @@ -959,21 +957,21 @@ static const struct ov_i2c_regvals norm_3620b[] = { * VREF[1:0] "Reserved" * = 0 (0x00) ......00 */ - { 0x35, 0x4C }, + { 0x35, 0x4c }, /* * 3D Undocumented = 0 (0x00) 00000000 * 3D[7:0] "It's a secret" * = 0 (0x00) 00000000 */ - { 0x3D, 0x00 }, + { 0x3d, 0x00 }, /* * 3E Undocumented = 0 (0x00) 00000000 * 3E[7:0] "It's a secret" * = 0 (0x00) 00000000 */ - { 0x3E, 0x00 }, + { 0x3e, 0x00 }, /* * 3B FREFB "Internal Reference Adjustment" @@ -1013,7 +1011,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * VBLM[3:0] "Sensor current control" * = 10 (0x0A) ....1010 */ - { 0x34, 0x5A }, + { 0x34, 0x5a }, /* * 3B FREFB "Internal Reference Adjustment" @@ -1079,7 +1077,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * HREFST[7:0] "Horizontal window start, 8 MSBs" * = 31 (0x1F) 00011111 */ - { 0x17, 0x1F }, + { 0x17, 0x1f }, /* * 18 HREFEND "Horizontal window end" @@ -1087,7 +1085,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * HREFEND[7:0] "Horizontal Window End, 8 MSBs" * = 95 (0x5F) 01011111 */ - { 0x18, 0x5F }, + { 0x18, 0x5f }, /* * 19 VSTRT "Vertical window start" @@ -1127,7 +1125,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * COMA[1:0] "Vertical window start line control 2 LSBs" * = 2 (0x02) ......10 */ - { 0x03, 0x4A }, + { 0x03, 0x4a }, /* * 11 CLKRC "Clock Rate Control" @@ -1184,7 +1182,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * HREFST[7:0] "Horizontal window start, 8 MSBs" * = 31 (0x1F) 00011111 */ - { 0x17, 0x1F }, + { 0x17, 0x1f }, /* * 18 HREFEND "Horizontal window end" @@ -1192,7 +1190,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * HREFEND[7:0] "Horizontal Window End, 8 MSBs" * = 95 (0x5F) 01011111 */ - { 0x18, 0x5F }, + { 0x18, 0x5f }, /* * 19 VSTRT "Vertical window start" @@ -1232,7 +1230,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * COMA[1:0] "Vertical window start line control 2 LSBs" * = 2 (0x02) ......10 */ - { 0x03, 0x4A }, + { 0x03, 0x4a }, /* * 02 RED "Red Gain Control" @@ -1242,7 +1240,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * RED[6:0] "Value" * = 47 (0x2F) .0101111 */ - { 0x02, 0xAF }, + { 0x02, 0xaf }, /* * 2D ADDVSL "VSYNC Pulse Width" @@ -1250,7 +1248,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * ADDVSL[7:0] "VSYNC pulse width, LSB" * = 210 (0xD2) 11010010 */ - { 0x2d, 0xD2 }, + { 0x2d, 0xd2 }, /* * 00 GAIN = 24 (0x18) 00011000 @@ -1273,7 +1271,7 @@ static const struct ov_i2c_regvals norm_3620b[] = { * BLUE[6:0] "Value" * = 112 (0x70) .1110000 */ - { 0x01, 0xF0 }, + { 0x01, 0xf0 }, /* * 10 AEC "Automatic Exposure Control" @@ -1281,14 +1279,14 @@ static const struct ov_i2c_regvals norm_3620b[] = { * AEC[7:0] "Automatic Exposure Control, 8 MSBs" * = 10 (0x0A) 00001010 */ - { 0x10, 0x0A }, - - { 0xE1, 0x67 }, - { 0xE3, 0x03 }, - { 0xE4, 0x26 }, - { 0xE5, 0x3E }, - { 0xF8, 0x01 }, - { 0xFF, 0x01 }, + { 0x10, 0x0a }, + + { 0xe1, 0x67 }, + { 0xe3, 0x03 }, + { 0xe4, 0x26 }, + { 0xe5, 0x3e }, + { 0xf8, 0x01 }, + { 0xff, 0x01 }, }; static const struct ov_i2c_regvals norm_6x20[] = { @@ -1297,7 +1295,7 @@ static const struct ov_i2c_regvals norm_6x20[] = { { 0x03, 0x60 }, { 0x05, 0x7f }, /* For when autoadjust is off */ { 0x07, 0xa8 }, - /* The ratio of 0x0c and 0x0d controls the white point */ + /* The ratio of 0x0c and 0x0d controls the white point */ { 0x0c, 0x24 }, { 0x0d, 0x24 }, { 0x0f, 0x15 }, /* COMS */ @@ -2217,7 +2215,7 @@ static int i2c_w(struct sd *sd, u8 reg, u8 value) /* Up on sensor reset empty the register cache */ if (reg == 0x12 && (value & 0x80)) memset(sd->sensor_reg_cache, -1, - sizeof(sd->sensor_reg_cache)); + sizeof(sd->sensor_reg_cache)); else sd->sensor_reg_cache[reg] = value; } @@ -2366,6 +2364,7 @@ static int init_ov_sensor(struct sd *sd, u8 slave) return -EIO; /* Wait for it to initialize */ msleep(150); + /* Dummy read to sync I2C */ if (i2c_r(sd, 0x00) < 0) return -EIO; @@ -2457,7 +2456,7 @@ static int ov_hires_configure(struct sd *sd) sd->sensor = SEN_OV3610; } else { err("Error unknown sensor type: 0x%02x%02x", - high, low); + high, low); return -1; } @@ -2499,7 +2498,6 @@ static int ov7xx0_configure(struct sd *sd) { int rc, high, low; - PDEBUG(D_PROBE, "starting OV7xx0 configuration"); /* Detect sensor (sub)type */ @@ -2711,7 +2709,6 @@ static int ov51x_upload_quan_tables(struct sd *sd) 6, 6, 6, 6, 7, 7, 7, 8, 7, 7, 6, 7, 7, 7, 8, 8 }; - const unsigned char uvQuanTable518[] = { 6, 6, 6, 7, 7, 7, 7, 7, 6, 6, 6, 7, 7, 7, 7, 7, @@ -2728,11 +2725,11 @@ static int ov51x_upload_quan_tables(struct sd *sd) if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) { pYTable = yQuanTable511; pUVTable = uvQuanTable511; - size = 32; + size = 32; } else { pYTable = yQuanTable518; pUVTable = uvQuanTable518; - size = 16; + size = 16; } for (i = 0; i < size; i++) { @@ -2893,7 +2890,7 @@ static int ov518_configure(struct gspca_dev *gspca_dev) /* First 5 bits of custom ID reg are a revision ID on OV518 */ PDEBUG(D_PROBE, "Device revision %d", - 0x1F & reg_r(sd, R51x_SYS_CUST_ID)); + 0x1f & reg_r(sd, R51x_SYS_CUST_ID)); rc = write_regvals(sd, init_518, ARRAY_SIZE(init_518)); if (rc < 0) @@ -2933,18 +2930,18 @@ static int ov518_configure(struct gspca_dev *gspca_dev) static int ov519_configure(struct sd *sd) { static const struct ov_regvals init_519[] = { - { 0x5a, 0x6d }, /* EnableSystem */ - { 0x53, 0x9b }, - { 0x54, 0xff }, /* set bit2 to enable jpeg */ - { 0x5d, 0x03 }, - { 0x49, 0x01 }, - { 0x48, 0x00 }, + { 0x5a, 0x6d }, /* EnableSystem */ + { 0x53, 0x9b }, + { 0x54, 0xff }, /* set bit2 to enable jpeg */ + { 0x5d, 0x03 }, + { 0x49, 0x01 }, + { 0x48, 0x00 }, /* Set LED pin to output mode. Bit 4 must be cleared or sensor * detection will fail. This deserves further investigation. */ { OV519_GPIO_IO_CTRL0, 0xee }, - { 0x51, 0x0f }, /* SetUsbInit */ - { 0x51, 0x00 }, - { 0x22, 0x00 }, + { 0x51, 0x0f }, /* SetUsbInit */ + { 0x51, 0x00 }, + { 0x22, 0x00 }, /* windows reads 0x55 at this point*/ }; @@ -3335,7 +3332,6 @@ static int ov518_mode_init_regs(struct sd *sd) ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2); /******** Set the mode ********/ - reg_w(sd, 0x2b, 0); reg_w(sd, 0x2c, 0); reg_w(sd, 0x2d, 0); @@ -3369,7 +3365,7 @@ static int ov518_mode_init_regs(struct sd *sd) /* Windows driver does this here; who knows why */ reg_w(sd, 0x2f, 0x80); - /******** Set the framerate ********/ + /******** Set the framerate ********/ sd->clockdiv = 1; /* Mode independent, but framerate dependent, regs */ @@ -3436,7 +3432,6 @@ static int ov518_mode_init_regs(struct sd *sd) return 0; } - /* Sets up the OV519 with the given image parameters * * OV519 needs a completely different approach, until we can figure out what @@ -3609,7 +3604,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) u8 v; gspca_dev = &sd->gspca_dev; - qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; + qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1; /******** Mode (VGA/QVGA) and sensor specific regs ********/ switch (sd->sensor) { @@ -3777,8 +3772,8 @@ static int set_ov_sensor_window(struct sd *sd) return mode_init_ov_sensor_regs(sd); gspca_dev = &sd->gspca_dev; - qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; - crop = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 2; + qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1; + crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2; /* The different sensor ICs handle setting up of window differently. * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */ @@ -4458,14 +4453,14 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4064), - .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, + .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, {USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4068), - .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, + .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x054c, 0x0155), - .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, + .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 }, {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, @@ -4479,7 +4474,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 }, {USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 }, {USB_DEVICE(0x1046, 0x9967), .driver_info = BRIDGE_W9968CF }, - {USB_DEVICE(0x8020, 0xEF04), .driver_info = BRIDGE_OVFX2 }, + {USB_DEVICE(0x8020, 0xef04), .driver_info = BRIDGE_OVFX2 }, {} }; diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c index 5d73420..8bffde1 100644 --- a/drivers/media/video/gspca/w996Xcf.c +++ b/drivers/media/video/gspca/w996Xcf.c @@ -150,10 +150,10 @@ static int w9968cf_upload_quantizationtables(struct sd *sd) ret += reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */ for (i = 0, j = 0; i < 32; i++, j += 2) { - a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j+1]) << 8); - b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j+1]) << 8); - ret += reg_w(sd, 0x40+i, a); - ret += reg_w(sd, 0x60+i, b); + a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j + 1]) << 8); + b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j + 1]) << 8); + reg_w(sd, 0x40 + i, a); + reg_w(sd, 0x60 + i, b); } ret += reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */ @@ -351,7 +351,6 @@ static int w9968cf_i2c_r(struct sd *sd, u8 reg) return ret; } - /*-------------------------------------------------------------------------- Turn on the LED on some webcams. A beep should be heard too. Return 0 on success, a negative number otherwise. @@ -381,11 +380,11 @@ static int w9968cf_init(struct sd *sd) int ret = 0; unsigned long hw_bufsize = sd->sif ? (352 * 288 * 2) : (640 * 480 * 2), y0 = 0x0000, - u0 = y0 + hw_bufsize/2, - v0 = u0 + hw_bufsize/4, - y1 = v0 + hw_bufsize/4, - u1 = y1 + hw_bufsize/2, - v1 = u1 + hw_bufsize/4; + u0 = y0 + hw_bufsize / 2, + v0 = u0 + hw_bufsize / 4, + y1 = v0 + hw_bufsize / 4, + u1 = y1 + hw_bufsize / 2, + v1 = u1 + hw_bufsize / 4; ret += reg_w(sd, 0x00, 0xff00); /* power off */ ret += reg_w(sd, 0x00, 0xbf10); /* power on */ @@ -456,8 +455,8 @@ static int w9968cf_set_crop_window(struct sd *sd) fw = SC(sd->gspca_dev.width) / max_width; fh = SC(sd->gspca_dev.height) / max_height; - cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width)/fh; - ch = (fw >= fh) ? SC(sd->gspca_dev.height)/fw : max_height; + cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width) / fh; + ch = (fw >= fh) ? SC(sd->gspca_dev.height) / fw : max_height; sd->sensor_width = max_width; sd->sensor_height = max_height; @@ -489,8 +488,8 @@ static int w9968cf_mode_init_regs(struct sd *sd) /* Y & UV frame buffer strides (in WORD) */ if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == V4L2_PIX_FMT_JPEG) { - ret += reg_w(sd, 0x2c, sd->gspca_dev.width/2); - ret += reg_w(sd, 0x2d, sd->gspca_dev.width/4); + ret += reg_w(sd, 0x2c, sd->gspca_dev.width / 2); + ret += reg_w(sd, 0x2d, sd->gspca_dev.width / 4); } else ret += reg_w(sd, 0x2c, sd->gspca_dev.width); -- cgit v0.10.2 From 218678032589895f29f4ee01b9c330caaab44274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Fri, 12 Nov 2010 06:12:09 -0300 Subject: [media] gspca - ov519: Set their numbers in the ov519 and ov7670 register names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 85fc433..519dec9 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -466,8 +466,8 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define OV519_R25_FORMAT 0x25 /* OV519 System Controller register numbers */ -#define OV519_SYS_RESET1 0x51 -#define OV519_SYS_EN_CLK1 0x54 +#define OV519_R51_RESET1 0x51 +#define OV519_R54_EN_CLK1 0x54 #define OV519_GPIO_DATA_OUT0 0x71 #define OV519_GPIO_IO_CTRL0 0x72 @@ -527,71 +527,71 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define OV7610_REG_COM_I 0x29 /* misc settings */ /* OV7670 registers */ -#define OV7670_REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ -#define OV7670_REG_BLUE 0x01 /* blue gain */ -#define OV7670_REG_RED 0x02 /* red gain */ -#define OV7670_REG_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ -#define OV7670_REG_COM1 0x04 /* Control 1 */ -/*#define OV7670_REG_AECHH 0x07 * AEC MS 5 bits */ -#define OV7670_REG_COM3 0x0c /* Control 3 */ -#define OV7670_REG_COM4 0x0d /* Control 4 */ -#define OV7670_REG_COM5 0x0e /* All "reserved" */ -#define OV7670_REG_COM6 0x0f /* Control 6 */ -#define OV7670_REG_AECH 0x10 /* More bits of AEC value */ -#define OV7670_REG_CLKRC 0x11 /* Clock control */ -#define OV7670_REG_COM7 0x12 /* Control 7 */ +#define OV7670_R00_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ +#define OV7670_R01_BLUE 0x01 /* blue gain */ +#define OV7670_R02_RED 0x02 /* red gain */ +#define OV7670_R03_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ +#define OV7670_R04_COM1 0x04 /* Control 1 */ +/*#define OV7670_R07_AECHH 0x07 * AEC MS 5 bits */ +#define OV7670_R0C_COM3 0x0c /* Control 3 */ +#define OV7670_R0D_COM4 0x0d /* Control 4 */ +#define OV7670_R0E_COM5 0x0e /* All "reserved" */ +#define OV7670_R0F_COM6 0x0f /* Control 6 */ +#define OV7670_R10_AECH 0x10 /* More bits of AEC value */ +#define OV7670_R11_CLKRC 0x11 /* Clock control */ +#define OV7670_R12_COM7 0x12 /* Control 7 */ #define OV7670_COM7_FMT_VGA 0x00 /*#define OV7670_COM7_YUV 0x00 * YUV */ #define OV7670_COM7_FMT_QVGA 0x10 /* QVGA format */ #define OV7670_COM7_FMT_MASK 0x38 #define OV7670_COM7_RESET 0x80 /* Register reset */ -#define OV7670_REG_COM8 0x13 /* Control 8 */ +#define OV7670_R13_COM8 0x13 /* Control 8 */ #define OV7670_COM8_AEC 0x01 /* Auto exposure enable */ #define OV7670_COM8_AWB 0x02 /* White balance enable */ #define OV7670_COM8_AGC 0x04 /* Auto gain enable */ #define OV7670_COM8_BFILT 0x20 /* Band filter enable */ #define OV7670_COM8_AECSTEP 0x40 /* Unlimited AEC step size */ #define OV7670_COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */ -#define OV7670_REG_COM9 0x14 /* Control 9 - gain ceiling */ -#define OV7670_REG_COM10 0x15 /* Control 10 */ -#define OV7670_REG_HSTART 0x17 /* Horiz start high bits */ -#define OV7670_REG_HSTOP 0x18 /* Horiz stop high bits */ -#define OV7670_REG_VSTART 0x19 /* Vert start high bits */ -#define OV7670_REG_VSTOP 0x1a /* Vert stop high bits */ -#define OV7670_REG_MVFP 0x1e /* Mirror / vflip */ +#define OV7670_R14_COM9 0x14 /* Control 9 - gain ceiling */ +#define OV7670_R15_COM10 0x15 /* Control 10 */ +#define OV7670_R17_HSTART 0x17 /* Horiz start high bits */ +#define OV7670_R18_HSTOP 0x18 /* Horiz stop high bits */ +#define OV7670_R19_VSTART 0x19 /* Vert start high bits */ +#define OV7670_R1A_VSTOP 0x1a /* Vert stop high bits */ +#define OV7670_R1E_MVFP 0x1e /* Mirror / vflip */ #define OV7670_MVFP_VFLIP 0x10 /* vertical flip */ #define OV7670_MVFP_MIRROR 0x20 /* Mirror image */ -#define OV7670_REG_AEW 0x24 /* AGC upper limit */ -#define OV7670_REG_AEB 0x25 /* AGC lower limit */ -#define OV7670_REG_VPT 0x26 /* AGC/AEC fast mode op region */ -#define OV7670_REG_HREF 0x32 /* HREF pieces */ -#define OV7670_REG_TSLB 0x3a /* lots of stuff */ -#define OV7670_REG_COM11 0x3b /* Control 11 */ +#define OV7670_R24_AEW 0x24 /* AGC upper limit */ +#define OV7670_R25_AEB 0x25 /* AGC lower limit */ +#define OV7670_R26_VPT 0x26 /* AGC/AEC fast mode op region */ +#define OV7670_R32_HREF 0x32 /* HREF pieces */ +#define OV7670_R3A_TSLB 0x3a /* lots of stuff */ +#define OV7670_R3B_COM11 0x3b /* Control 11 */ #define OV7670_COM11_EXP 0x02 #define OV7670_COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ -#define OV7670_REG_COM12 0x3c /* Control 12 */ -#define OV7670_REG_COM13 0x3d /* Control 13 */ +#define OV7670_R3C_COM12 0x3c /* Control 12 */ +#define OV7670_R3D_COM13 0x3d /* Control 13 */ #define OV7670_COM13_GAMMA 0x80 /* Gamma enable */ #define OV7670_COM13_UVSAT 0x40 /* UV saturation auto adjustment */ -#define OV7670_REG_COM14 0x3e /* Control 14 */ -#define OV7670_REG_EDGE 0x3f /* Edge enhancement factor */ -#define OV7670_REG_COM15 0x40 /* Control 15 */ +#define OV7670_R3E_COM14 0x3e /* Control 14 */ +#define OV7670_R3F_EDGE 0x3f /* Edge enhancement factor */ +#define OV7670_R40_COM15 0x40 /* Control 15 */ /*#define OV7670_COM15_R00FF 0xc0 * 00 to FF */ -#define OV7670_REG_COM16 0x41 /* Control 16 */ +#define OV7670_R41_COM16 0x41 /* Control 16 */ #define OV7670_COM16_AWBGAIN 0x08 /* AWB gain enable */ -#define OV7670_REG_BRIGHT 0x55 /* Brightness */ -#define OV7670_REG_CONTRAS 0x56 /* Contrast control */ -#define OV7670_REG_GFIX 0x69 /* Fix gain control */ -#define OV7670_REG_RGB444 0x8c /* RGB 444 control */ -#define OV7670_REG_HAECC1 0x9f /* Hist AEC/AGC control 1 */ -#define OV7670_REG_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ -#define OV7670_REG_BD50MAX 0xa5 /* 50hz banding step limit */ -#define OV7670_REG_HAECC3 0xa6 /* Hist AEC/AGC control 3 */ -#define OV7670_REG_HAECC4 0xa7 /* Hist AEC/AGC control 4 */ -#define OV7670_REG_HAECC5 0xa8 /* Hist AEC/AGC control 5 */ -#define OV7670_REG_HAECC6 0xa9 /* Hist AEC/AGC control 6 */ -#define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ -#define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */ +#define OV7670_R55_BRIGHT 0x55 /* Brightness */ +#define OV7670_R56_CONTRAS 0x56 /* Contrast control */ +#define OV7670_R69_GFIX 0x69 /* Fix gain control */ +/*#define OV7670_R8C_RGB444 0x8c * RGB 444 control */ +#define OV7670_R9F_HAECC1 0x9f /* Hist AEC/AGC control 1 */ +#define OV7670_RA0_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ +#define OV7670_RA5_BD50MAX 0xa5 /* 50hz banding step limit */ +#define OV7670_RA6_HAECC3 0xa6 /* Hist AEC/AGC control 3 */ +#define OV7670_RA7_HAECC4 0xa7 /* Hist AEC/AGC control 4 */ +#define OV7670_RA8_HAECC5 0xa8 /* Hist AEC/AGC control 5 */ +#define OV7670_RA9_HAECC6 0xa9 /* Hist AEC/AGC control 6 */ +#define OV7670_RAA_HAECC7 0xaa /* Hist AEC/AGC control 7 */ +#define OV7670_RAB_BD60MAX 0xab /* 60hz banding step limit */ struct ov_regvals { u8 reg; @@ -1463,7 +1463,7 @@ static const struct ov_i2c_regvals norm_7620[] = { { 0x00, 0x00 }, /* gain */ { 0x01, 0x80 }, /* blue gain */ { 0x02, 0x80 }, /* red gain */ - { 0x03, 0xc0 }, /* OV7670_REG_VREF */ + { 0x03, 0xc0 }, /* OV7670_R03_VREF */ { 0x06, 0x60 }, { 0x07, 0x00 }, { 0x0c, 0x24 }, @@ -1534,30 +1534,30 @@ static const struct ov_i2c_regvals norm_7640[] = { /* 7670. Defaults taken from OmniVision provided data, * as provided by Jonathan Corbet of OLPC */ static const struct ov_i2c_regvals norm_7670[] = { - { OV7670_REG_COM7, OV7670_COM7_RESET }, - { OV7670_REG_TSLB, 0x04 }, /* OV */ - { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */ - { OV7670_REG_CLKRC, 0x01 }, + { OV7670_R12_COM7, OV7670_COM7_RESET }, + { OV7670_R3A_TSLB, 0x04 }, /* OV */ + { OV7670_R12_COM7, OV7670_COM7_FMT_VGA }, /* VGA */ + { OV7670_R11_CLKRC, 0x01 }, /* * Set the hardware window. These values from OV don't entirely * make sense - hstop is less than hstart. But they work... */ - { OV7670_REG_HSTART, 0x13 }, - { OV7670_REG_HSTOP, 0x01 }, - { OV7670_REG_HREF, 0xb6 }, - { OV7670_REG_VSTART, 0x02 }, - { OV7670_REG_VSTOP, 0x7a }, - { OV7670_REG_VREF, 0x0a }, - - { OV7670_REG_COM3, 0x00 }, - { OV7670_REG_COM14, 0x00 }, + { OV7670_R17_HSTART, 0x13 }, + { OV7670_R18_HSTOP, 0x01 }, + { OV7670_R32_HREF, 0xb6 }, + { OV7670_R19_VSTART, 0x02 }, + { OV7670_R1A_VSTOP, 0x7a }, + { OV7670_R03_VREF, 0x0a }, + + { OV7670_R0C_COM3, 0x00 }, + { OV7670_R3E_COM14, 0x00 }, /* Mystery scaling numbers */ { 0x70, 0x3a }, { 0x71, 0x35 }, { 0x72, 0x11 }, { 0x73, 0xf0 }, { 0xa2, 0x02 }, -/* { OV7670_REG_COM10, 0x0 }, */ +/* { OV7670_R15_COM10, 0x0 }, */ /* Gamma curve values */ { 0x7a, 0x20 }, @@ -1579,37 +1579,37 @@ static const struct ov_i2c_regvals norm_7670[] = { /* AGC and AEC parameters. Note we start by disabling those features, then turn them only after tweaking the values. */ - { OV7670_REG_COM8, OV7670_COM8_FASTAEC + { OV7670_R13_COM8, OV7670_COM8_FASTAEC | OV7670_COM8_AECSTEP | OV7670_COM8_BFILT }, - { OV7670_REG_GAIN, 0x00 }, - { OV7670_REG_AECH, 0x00 }, - { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */ - { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ - { OV7670_REG_BD50MAX, 0x05 }, - { OV7670_REG_BD60MAX, 0x07 }, - { OV7670_REG_AEW, 0x95 }, - { OV7670_REG_AEB, 0x33 }, - { OV7670_REG_VPT, 0xe3 }, - { OV7670_REG_HAECC1, 0x78 }, - { OV7670_REG_HAECC2, 0x68 }, + { OV7670_R00_GAIN, 0x00 }, + { OV7670_R10_AECH, 0x00 }, + { OV7670_R0D_COM4, 0x40 }, /* magic reserved bit */ + { OV7670_R14_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ + { OV7670_RA5_BD50MAX, 0x05 }, + { OV7670_RAB_BD60MAX, 0x07 }, + { OV7670_R24_AEW, 0x95 }, + { OV7670_R25_AEB, 0x33 }, + { OV7670_R26_VPT, 0xe3 }, + { OV7670_R9F_HAECC1, 0x78 }, + { OV7670_RA0_HAECC2, 0x68 }, { 0xa1, 0x03 }, /* magic */ - { OV7670_REG_HAECC3, 0xd8 }, - { OV7670_REG_HAECC4, 0xd8 }, - { OV7670_REG_HAECC5, 0xf0 }, - { OV7670_REG_HAECC6, 0x90 }, - { OV7670_REG_HAECC7, 0x94 }, - { OV7670_REG_COM8, OV7670_COM8_FASTAEC + { OV7670_RA6_HAECC3, 0xd8 }, + { OV7670_RA7_HAECC4, 0xd8 }, + { OV7670_RA8_HAECC5, 0xf0 }, + { OV7670_RA9_HAECC6, 0x90 }, + { OV7670_RAA_HAECC7, 0x94 }, + { OV7670_R13_COM8, OV7670_COM8_FASTAEC | OV7670_COM8_AECSTEP | OV7670_COM8_BFILT | OV7670_COM8_AGC | OV7670_COM8_AEC }, /* Almost all of these are magic "reserved" values. */ - { OV7670_REG_COM5, 0x61 }, - { OV7670_REG_COM6, 0x4b }, + { OV7670_R0E_COM5, 0x61 }, + { OV7670_R0F_COM6, 0x4b }, { 0x16, 0x02 }, - { OV7670_REG_MVFP, 0x07 }, + { OV7670_R1E_MVFP, 0x07 }, { 0x21, 0x02 }, { 0x22, 0x91 }, { 0x29, 0x07 }, @@ -1618,10 +1618,10 @@ static const struct ov_i2c_regvals norm_7670[] = { { 0x37, 0x1d }, { 0x38, 0x71 }, { 0x39, 0x2a }, - { OV7670_REG_COM12, 0x78 }, + { OV7670_R3C_COM12, 0x78 }, { 0x4d, 0x40 }, { 0x4e, 0x20 }, - { OV7670_REG_GFIX, 0x00 }, + { OV7670_R69_GFIX, 0x00 }, { 0x6b, 0x4a }, { 0x74, 0x10 }, { 0x8d, 0x4f }, @@ -1656,9 +1656,9 @@ static const struct ov_i2c_regvals norm_7670[] = { { 0x6f, 0x9f }, /* "9e for advance AWB" */ { 0x6a, 0x40 }, - { OV7670_REG_BLUE, 0x40 }, - { OV7670_REG_RED, 0x60 }, - { OV7670_REG_COM8, OV7670_COM8_FASTAEC + { OV7670_R01_BLUE, 0x40 }, + { OV7670_R02_RED, 0x60 }, + { OV7670_R13_COM8, OV7670_COM8_FASTAEC | OV7670_COM8_AECSTEP | OV7670_COM8_BFILT | OV7670_COM8_AGC @@ -1674,22 +1674,22 @@ static const struct ov_i2c_regvals norm_7670[] = { { 0x54, 0x80 }, { 0x58, 0x9e }, - { OV7670_REG_COM16, OV7670_COM16_AWBGAIN }, - { OV7670_REG_EDGE, 0x00 }, + { OV7670_R41_COM16, OV7670_COM16_AWBGAIN }, + { OV7670_R3F_EDGE, 0x00 }, { 0x75, 0x05 }, { 0x76, 0xe1 }, { 0x4c, 0x00 }, { 0x77, 0x01 }, - { OV7670_REG_COM13, OV7670_COM13_GAMMA + { OV7670_R3D_COM13, OV7670_COM13_GAMMA | OV7670_COM13_UVSAT | 2}, /* was 3 */ { 0x4b, 0x09 }, { 0xc9, 0x60 }, - { OV7670_REG_COM16, 0x38 }, + { OV7670_R41_COM16, 0x38 }, { 0x56, 0x40 }, { 0x34, 0x11 }, - { OV7670_REG_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO }, + { OV7670_R3B_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO }, { 0xa4, 0x88 }, { 0x96, 0x00 }, { 0x97, 0x30 }, @@ -2290,7 +2290,7 @@ static inline int ov51x_stop(struct sd *sd) case BRIDGE_OV518PLUS: return reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a); case BRIDGE_OV519: - return reg_w(sd, OV519_SYS_RESET1, 0x0f); + return reg_w(sd, OV519_R51_RESET1, 0x0f); case BRIDGE_OVFX2: return reg_w_mask(sd, 0x0f, 0x00, 0x02); case BRIDGE_W9968CF: @@ -2323,7 +2323,7 @@ static inline int ov51x_restart(struct sd *sd) return rc; return reg_w(sd, R51x_SYS_RESET, 0x00); case BRIDGE_OV519: - return reg_w(sd, OV519_SYS_RESET1, 0x00); + return reg_w(sd, OV519_R51_RESET1, 0x00); case BRIDGE_OVFX2: return reg_w_mask(sd, 0x0f, 0x02, 0x02); case BRIDGE_W9968CF: @@ -2932,15 +2932,15 @@ static int ov519_configure(struct sd *sd) static const struct ov_regvals init_519[] = { { 0x5a, 0x6d }, /* EnableSystem */ { 0x53, 0x9b }, - { 0x54, 0xff }, /* set bit2 to enable jpeg */ + { OV519_R54_EN_CLK1, 0xff }, /* set bit2 to enable jpeg */ { 0x5d, 0x03 }, { 0x49, 0x01 }, { 0x48, 0x00 }, /* Set LED pin to output mode. Bit 4 must be cleared or sensor * detection will fail. This deserves further investigation. */ { OV519_GPIO_IO_CTRL0, 0xee }, - { 0x51, 0x0f }, /* SetUsbInit */ - { 0x51, 0x00 }, + { OV519_R51_RESET1, 0x0f }, + { OV519_R51_RESET1, 0x00 }, { 0x22, 0x00 }, /* windows reads 0x55 at this point*/ }; @@ -3444,7 +3444,7 @@ static int ov519_mode_init_regs(struct sd *sd) static const struct ov_regvals mode_init_519_ov7670[] = { { 0x5d, 0x03 }, /* Turn off suspend mode */ { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */ - { 0x54, 0x0f }, /* bit2 (jpeg enable) */ + { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */ { 0xa2, 0x20 }, /* a2-a5 are undocumented */ { 0xa3, 0x18 }, { 0xa4, 0x04 }, @@ -3467,7 +3467,7 @@ static int ov519_mode_init_regs(struct sd *sd) static const struct ov_regvals mode_init_519[] = { { 0x5d, 0x03 }, /* Turn off suspend mode */ { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */ - { 0x54, 0x0f }, /* bit2 (jpeg enable) */ + { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */ { 0xa2, 0x20 }, /* a2-a5 are undocumented */ { 0xa3, 0x18 }, { 0xa4, 0x04 }, @@ -3687,11 +3687,11 @@ static int mode_init_ov_sensor_regs(struct sd *sd) /* set COM7_FMT_VGA or COM7_FMT_QVGA * do we need to set anything else? * HSTART etc are set in set_ov_sensor_window itself */ - i2c_w_mask(sd, OV7670_REG_COM7, + i2c_w_mask(sd, OV7670_R12_COM7, qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA, OV7670_COM7_FMT_MASK); i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ - i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_AWB, + i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_AWB, OV7670_COM8_AWB); if (qvga) { /* QVGA from ov7670.c by * Jonathan Corbet */ @@ -3707,21 +3707,21 @@ static int mode_init_ov_sensor_regs(struct sd *sd) } /* OV7670 hardware window registers are split across * multiple locations */ - i2c_w(sd, OV7670_REG_HSTART, xstart >> 3); - i2c_w(sd, OV7670_REG_HSTOP, xend >> 3); - v = i2c_r(sd, OV7670_REG_HREF); + i2c_w(sd, OV7670_R17_HSTART, xstart >> 3); + i2c_w(sd, OV7670_R18_HSTOP, xend >> 3); + v = i2c_r(sd, OV7670_R32_HREF); v = (v & 0xc0) | ((xend & 0x7) << 3) | (xstart & 0x07); msleep(10); /* need to sleep between read and write to * same reg! */ - i2c_w(sd, OV7670_REG_HREF, v); + i2c_w(sd, OV7670_R32_HREF, v); - i2c_w(sd, OV7670_REG_VSTART, ystart >> 2); - i2c_w(sd, OV7670_REG_VSTOP, yend >> 2); - v = i2c_r(sd, OV7670_REG_VREF); + i2c_w(sd, OV7670_R19_VSTART, ystart >> 2); + i2c_w(sd, OV7670_R1A_VSTOP, yend >> 2); + v = i2c_r(sd, OV7670_R03_VREF); v = (v & 0xc0) | ((yend & 0x3) << 2) | (ystart & 0x03); msleep(10); /* need to sleep between read and write to * same reg! */ - i2c_w(sd, OV7670_REG_VREF, v); + i2c_w(sd, OV7670_R03_VREF, v); break; case SEN_OV6620: i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); @@ -3751,7 +3751,7 @@ static void sethvflip(struct gspca_dev *gspca_dev) return; if (sd->gspca_dev.streaming) ov51x_stop(sd); - i2c_w_mask(sd, OV7670_REG_MVFP, + i2c_w_mask(sd, OV7670_R1E_MVFP, OV7670_MVFP_MIRROR * sd->ctrls[HFLIP].val | OV7670_MVFP_VFLIP * sd->ctrls[VFLIP].val, OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP); @@ -4191,8 +4191,8 @@ static void setbrightness(struct gspca_dev *gspca_dev) break; case SEN_OV7670: /*win trace - * i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_AEC); */ - i2c_w(sd, OV7670_REG_BRIGHT, ov7670_abs_to_sm(val)); + * i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_AEC); */ + i2c_w(sd, OV7670_R55_BRIGHT, ov7670_abs_to_sm(val)); break; } } @@ -4234,7 +4234,7 @@ static void setcontrast(struct gspca_dev *gspca_dev) } case SEN_OV7670: /* check that this isn't just the same as ov7610 */ - i2c_w(sd, OV7670_REG_CONTRAS, val >> 1); + i2c_w(sd, OV7670_R56_CONTRAS, val >> 1); break; } } @@ -4294,22 +4294,22 @@ static void setfreq_i(struct sd *sd) if (sd->sensor == SEN_OV7670) { switch (sd->ctrls[FREQ].val) { case 0: /* Banding filter disabled */ - i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_BFILT); + i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_BFILT); break; case 1: /* 50 hz */ - i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT, + i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT, OV7670_COM8_BFILT); - i2c_w_mask(sd, OV7670_REG_COM11, 0x08, 0x18); + i2c_w_mask(sd, OV7670_R3B_COM11, 0x08, 0x18); break; case 2: /* 60 hz */ - i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT, + i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT, OV7670_COM8_BFILT); - i2c_w_mask(sd, OV7670_REG_COM11, 0x00, 0x18); + i2c_w_mask(sd, OV7670_R3B_COM11, 0x00, 0x18); break; - case 3: /* Auto hz */ - i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT, + case 3: /* Auto hz - ov7670 only */ + i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT, OV7670_COM8_BFILT); - i2c_w_mask(sd, OV7670_REG_COM11, OV7670_COM11_HZAUTO, + i2c_w_mask(sd, OV7670_R3B_COM11, OV7670_COM11_HZAUTO, 0x18); break; } -- cgit v0.10.2 From 83db76886c0b0a32a0c8d35b4dc3dc1d8f1287d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Fri, 12 Nov 2010 07:14:08 -0300 Subject: [media] gspca - ov519: Define the disabled controls in a table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 519dec9..f6c62be 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -234,6 +234,51 @@ static const struct ctrl sd_ctrls[] = { }, }; +/* table of the disabled controls */ +static const unsigned ctrl_dis[] = { +[SEN_OV2610] = (1 << NCTRL) - 1, /* no control */ + +[SEN_OV3610] = (1 << NCTRL) - 1, /* no control */ + +[SEN_OV6620] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV6630] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV66308AF] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV7610] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV7620] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV7620AE] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV7640] = (1 << HFLIP) | + (1 << VFLIP) | + (1 << AUTOBRIGHT) | + (1 << CONTRAST), + +[SEN_OV7648] = (1 << HFLIP) | + (1 << VFLIP) | + (1 << AUTOBRIGHT) | + (1 << CONTRAST), + +[SEN_OV7670] = (1 << COLORS) | + (1 << AUTOBRIGHT), + +[SEN_OV76BE] = (1 << HFLIP) | + (1 << VFLIP), + +[SEN_OV8610] = (1 << HFLIP) | + (1 << VFLIP) | + (1 << FREQ), +}; + static const struct v4l2_pix_format ov519_vga_mode[] = { {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, @@ -3099,22 +3144,9 @@ static int sd_config(struct gspca_dev *gspca_dev, break; } gspca_dev->cam.ctrls = sd->ctrls; - if (sd->sensor == SEN_OV7670) - gspca_dev->ctrl_dis = 1 << COLORS; - else - gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP); sd->quality = QUALITY_DEF; - if (sd->sensor == SEN_OV7640 || - sd->sensor == SEN_OV7648) - gspca_dev->ctrl_dis |= (1 << AUTOBRIGHT) | (1 << CONTRAST); - if (sd->sensor == SEN_OV7670) - gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT; - /* OV8610 Frequency filter control should work but needs testing */ - if (sd->sensor == SEN_OV8610) - gspca_dev->ctrl_dis |= 1 << FREQ; - /* No controls for the OV2610/OV3610 */ - if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) - gspca_dev->ctrl_dis |= (1 << NCTRL) - 1; + + gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; return 0; error: -- cgit v0.10.2 From f8f20188e863dfb43ac53364da0b8865d37c97e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Fri, 12 Nov 2010 07:54:02 -0300 Subject: [media] gspca - ov519: Propagate errors to higher level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index f6c62be..0591ced 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -1869,10 +1869,13 @@ static unsigned char ov7670_abs_to_sm(unsigned char v) } /* Write a OV519 register */ -static int reg_w(struct sd *sd, u16 index, u16 value) +static void reg_w(struct sd *sd, u16 index, u16 value) { int ret, req = 0; + if (sd->gspca_dev.usb_err < 0) + return; + switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: @@ -1903,11 +1906,11 @@ leave: if (ret < 0) { err("Write reg 0x%04x -> [0x%02x] failed", value, index); - return ret; + sd->gspca_dev.usb_err = ret; + return; } PDEBUG(D_USBO, "Write reg 0x%04x -> [0x%02x]", value, index); - return 0; } /* Read from a OV519 register, note not valid for the w9968cf!! */ @@ -1917,6 +1920,9 @@ static int reg_r(struct sd *sd, u16 index) int ret; int req; + if (sd->gspca_dev.usb_err < 0) + return -1; + switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: @@ -1938,8 +1944,10 @@ static int reg_r(struct sd *sd, u16 index) if (ret >= 0) { ret = sd->gspca_dev.usb_buf[0]; PDEBUG(D_USBI, "Read reg [0x%02X] -> 0x%04X", index, ret); - } else + } else { err("Read reg [0x%02x] failed", index); + sd->gspca_dev.usb_err = ret; + } return ret; } @@ -1950,16 +1958,21 @@ static int reg_r8(struct sd *sd, { int ret; + if (sd->gspca_dev.usb_err < 0) + return -1; + ret = usb_control_msg(sd->gspca_dev.dev, usb_rcvctrlpipe(sd->gspca_dev.dev, 0), 1, /* REQ_IO */ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, index, sd->gspca_dev.usb_buf, 8, 500); - if (ret >= 0) + if (ret >= 0) { ret = sd->gspca_dev.usb_buf[0]; - else + } else { err("Read reg 8 [0x%02x] failed", index); + sd->gspca_dev.usb_err = ret; + } return ret; } @@ -1970,7 +1983,7 @@ static int reg_r8(struct sd *sd, * that are in the same position as 0's in "mask" are preserved, regardless * of their respective state in "value". */ -static int reg_w_mask(struct sd *sd, +static void reg_w_mask(struct sd *sd, u16 index, u8 value, u8 mask) @@ -1982,22 +1995,25 @@ static int reg_w_mask(struct sd *sd, value &= mask; /* Enforce mask on value */ ret = reg_r(sd, index); if (ret < 0) - return ret; + return; oldval = ret & ~mask; /* Clear the masked bits */ value |= oldval; /* Set the desired bits */ } - return reg_w(sd, index, value); + reg_w(sd, index, value); } /* * Writes multiple (n) byte value to a single register. Only valid with certain * registers (0x30 and 0xc4 - 0xce). */ -static int ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n) +static void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n) { int ret; + if (sd->gspca_dev.usb_err < 0) + return; + *((__le32 *) sd->gspca_dev.usb_buf) = __cpu_to_le32(value); ret = usb_control_msg(sd->gspca_dev.dev, @@ -2008,13 +2024,11 @@ static int ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n) sd->gspca_dev.usb_buf, n, 500); if (ret < 0) { err("Write reg32 [%02x] %08x failed", index, value); - return ret; + sd->gspca_dev.usb_err = ret; } - - return 0; } -static int ov511_i2c_w(struct sd *sd, u8 reg, u8 value) +static void ov511_i2c_w(struct sd *sd, u8 reg, u8 value) { int rc, retries; @@ -2023,36 +2037,28 @@ static int ov511_i2c_w(struct sd *sd, u8 reg, u8 value) /* Three byte write cycle */ for (retries = 6; ; ) { /* Select camera register */ - rc = reg_w(sd, R51x_I2C_SADDR_3, reg); - if (rc < 0) - return rc; + reg_w(sd, R51x_I2C_SADDR_3, reg); /* Write "value" to I2C data port of OV511 */ - rc = reg_w(sd, R51x_I2C_DATA, value); - if (rc < 0) - return rc; + reg_w(sd, R51x_I2C_DATA, value); /* Initiate 3-byte write cycle */ - rc = reg_w(sd, R511_I2C_CTL, 0x01); - if (rc < 0) - return rc; + reg_w(sd, R511_I2C_CTL, 0x01); do { rc = reg_r(sd, R511_I2C_CTL); } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ if (rc < 0) - return rc; + return; if ((rc & 2) == 0) /* Ack? */ break; if (--retries < 0) { PDEBUG(D_USBO, "i2c write retries exhausted"); - return -1; + return; } } - - return 0; } static int ov511_i2c_r(struct sd *sd, u8 reg) @@ -2062,14 +2068,10 @@ static int ov511_i2c_r(struct sd *sd, u8 reg) /* Two byte write cycle */ for (retries = 6; ; ) { /* Select camera register */ - rc = reg_w(sd, R51x_I2C_SADDR_2, reg); - if (rc < 0) - return rc; + reg_w(sd, R51x_I2C_SADDR_2, reg); /* Initiate 2-byte write cycle */ - rc = reg_w(sd, R511_I2C_CTL, 0x03); - if (rc < 0) - return rc; + reg_w(sd, R511_I2C_CTL, 0x03); do { rc = reg_r(sd, R511_I2C_CTL); @@ -2093,9 +2095,7 @@ static int ov511_i2c_r(struct sd *sd, u8 reg) /* Two byte read cycle */ for (retries = 6; ; ) { /* Initiate 2-byte read cycle */ - rc = reg_w(sd, R511_I2C_CTL, 0x05); - if (rc < 0) - return rc; + reg_w(sd, R511_I2C_CTL, 0x05); do { rc = reg_r(sd, R511_I2C_CTL); @@ -2108,9 +2108,7 @@ static int ov511_i2c_r(struct sd *sd, u8 reg) break; /* I2C abort */ - rc = reg_w(sd, R511_I2C_CTL, 0x10); - if (rc < 0) - return rc; + reg_w(sd, R511_I2C_CTL, 0x10); if (--retries < 0) { PDEBUG(D_USBI, "i2c read retries exhausted"); @@ -2123,9 +2121,7 @@ static int ov511_i2c_r(struct sd *sd, u8 reg) PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); /* This is needed to make i2c_w() work */ - rc = reg_w(sd, R511_I2C_CTL, 0x05); - if (rc < 0) - return rc; + reg_w(sd, R511_I2C_CTL, 0x05); return value; } @@ -2135,32 +2131,24 @@ static int ov511_i2c_r(struct sd *sd, u8 reg) * This is normally only called from i2c_w(). Note that this function * always succeeds regardless of whether the sensor is present and working. */ -static int ov518_i2c_w(struct sd *sd, +static void ov518_i2c_w(struct sd *sd, u8 reg, u8 value) { - int rc; - PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); /* Select camera register */ - rc = reg_w(sd, R51x_I2C_SADDR_3, reg); - if (rc < 0) - return rc; + reg_w(sd, R51x_I2C_SADDR_3, reg); /* Write "value" to I2C data port of OV511 */ - rc = reg_w(sd, R51x_I2C_DATA, value); - if (rc < 0) - return rc; + reg_w(sd, R51x_I2C_DATA, value); /* Initiate 3-byte write cycle */ - rc = reg_w(sd, R518_I2C_CTL, 0x01); - if (rc < 0) - return rc; + reg_w(sd, R518_I2C_CTL, 0x01); /* wait for write complete */ msleep(4); - return reg_r8(sd, R518_I2C_CTL); + reg_r8(sd, R518_I2C_CTL); } /* @@ -2172,31 +2160,28 @@ static int ov518_i2c_w(struct sd *sd, */ static int ov518_i2c_r(struct sd *sd, u8 reg) { - int rc, value; + int value; /* Select camera register */ - rc = reg_w(sd, R51x_I2C_SADDR_2, reg); - if (rc < 0) - return rc; + reg_w(sd, R51x_I2C_SADDR_2, reg); /* Initiate 2-byte write cycle */ - rc = reg_w(sd, R518_I2C_CTL, 0x03); - if (rc < 0) - return rc; + reg_w(sd, R518_I2C_CTL, 0x03); /* Initiate 2-byte read cycle */ - rc = reg_w(sd, R518_I2C_CTL, 0x05); - if (rc < 0) - return rc; + reg_w(sd, R518_I2C_CTL, 0x05); value = reg_r(sd, R51x_I2C_DATA); PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); return value; } -static int ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value) +static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value) { int ret; + if (sd->gspca_dev.usb_err < 0) + return; + ret = usb_control_msg(sd->gspca_dev.dev, usb_sndctrlpipe(sd->gspca_dev.dev, 0), 0x02, @@ -2205,17 +2190,19 @@ static int ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value) if (ret < 0) { err("i2c 0x%02x -> [0x%02x] failed", value, reg); - return ret; + sd->gspca_dev.usb_err = ret; } PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); - return 0; } static int ovfx2_i2c_r(struct sd *sd, u8 reg) { int ret; + if (sd->gspca_dev.usb_err < 0) + return -1; + ret = usb_control_msg(sd->gspca_dev.dev, usb_rcvctrlpipe(sd->gspca_dev.dev, 0), 0x03, @@ -2225,38 +2212,38 @@ static int ovfx2_i2c_r(struct sd *sd, u8 reg) if (ret >= 0) { ret = sd->gspca_dev.usb_buf[0]; PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, ret); - } else + } else { err("i2c read [0x%02x] failed", reg); + sd->gspca_dev.usb_err = ret; + } return ret; } -static int i2c_w(struct sd *sd, u8 reg, u8 value) +static void i2c_w(struct sd *sd, u8 reg, u8 value) { - int ret = -1; - if (sd->sensor_reg_cache[reg] == value) - return 0; + return; switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - ret = ov511_i2c_w(sd, reg, value); + ov511_i2c_w(sd, reg, value); break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: case BRIDGE_OV519: - ret = ov518_i2c_w(sd, reg, value); + ov518_i2c_w(sd, reg, value); break; case BRIDGE_OVFX2: - ret = ovfx2_i2c_w(sd, reg, value); + ovfx2_i2c_w(sd, reg, value); break; case BRIDGE_W9968CF: - ret = w9968cf_i2c_w(sd, reg, value); + w9968cf_i2c_w(sd, reg, value); break; } - if (ret >= 0) { + if (sd->gspca_dev.usb_err >= 0) { /* Up on sensor reset empty the register cache */ if (reg == 0x12 && (value & 0x80)) memset(sd->sensor_reg_cache, -1, @@ -2264,8 +2251,6 @@ static int i2c_w(struct sd *sd, u8 reg, u8 value) else sd->sensor_reg_cache[reg] = value; } - - return ret; } static int i2c_r(struct sd *sd, u8 reg) @@ -2304,7 +2289,7 @@ static int i2c_r(struct sd *sd, u8 reg) * that are in the same position as 0's in "mask" are preserved, regardless * of their respective state in "value". */ -static int i2c_w_mask(struct sd *sd, +static void i2c_w_mask(struct sd *sd, u8 reg, u8 value, u8 mask) @@ -2315,70 +2300,72 @@ static int i2c_w_mask(struct sd *sd, value &= mask; /* Enforce mask on value */ rc = i2c_r(sd, reg); if (rc < 0) - return rc; + return; oldval = rc & ~mask; /* Clear the masked bits */ value |= oldval; /* Set the desired bits */ - return i2c_w(sd, reg, value); + i2c_w(sd, reg, value); } /* Temporarily stops OV511 from functioning. Must do this before changing * registers while the camera is streaming */ -static inline int ov51x_stop(struct sd *sd) +static inline void ov51x_stop(struct sd *sd) { PDEBUG(D_STREAM, "stopping"); sd->stopped = 1; switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - return reg_w(sd, R51x_SYS_RESET, 0x3d); + reg_w(sd, R51x_SYS_RESET, 0x3d); + break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - return reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a); + reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a); + break; case BRIDGE_OV519: - return reg_w(sd, OV519_R51_RESET1, 0x0f); + reg_w(sd, OV519_R51_RESET1, 0x0f); + break; case BRIDGE_OVFX2: - return reg_w_mask(sd, 0x0f, 0x00, 0x02); + reg_w_mask(sd, 0x0f, 0x00, 0x02); + break; case BRIDGE_W9968CF: - return reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */ + reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */ + break; } - - return 0; } /* Restarts OV511 after ov511_stop() is called. Has no effect if it is not * actually stopped (for performance). */ -static inline int ov51x_restart(struct sd *sd) +static inline void ov51x_restart(struct sd *sd) { - int rc; - PDEBUG(D_STREAM, "restarting"); if (!sd->stopped) - return 0; + return; sd->stopped = 0; /* Reinitialize the stream */ switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - return reg_w(sd, R51x_SYS_RESET, 0x00); + reg_w(sd, R51x_SYS_RESET, 0x00); + break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - rc = reg_w(sd, 0x2f, 0x80); - if (rc < 0) - return rc; - return reg_w(sd, R51x_SYS_RESET, 0x00); + reg_w(sd, 0x2f, 0x80); + reg_w(sd, R51x_SYS_RESET, 0x00); + break; case BRIDGE_OV519: - return reg_w(sd, OV519_R51_RESET1, 0x00); + reg_w(sd, OV519_R51_RESET1, 0x00); + break; case BRIDGE_OVFX2: - return reg_w_mask(sd, 0x0f, 0x02, 0x02); + reg_w_mask(sd, 0x0f, 0x02, 0x02); + break; case BRIDGE_W9968CF: - return reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */ + reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */ + break; } - - return 0; } -static int ov51x_set_slave_ids(struct sd *sd, u8 slave); +static void ov51x_set_slave_ids(struct sd *sd, u8 slave); /* This does an initial reset of an OmniVision sensor and ensures that I2C * is synchronized. Returns <0 on failure. @@ -2387,12 +2374,10 @@ static int init_ov_sensor(struct sd *sd, u8 slave) { int i; - if (ov51x_set_slave_ids(sd, slave) < 0) - return -EIO; + ov51x_set_slave_ids(sd, slave); /* Reset the sensor */ - if (i2c_w(sd, 0x12, 0x80) < 0) - return -EIO; + i2c_w(sd, 0x12, 0x80); /* Wait for it to initialize */ msleep(150); @@ -2405,16 +2390,16 @@ static int init_ov_sensor(struct sd *sd, u8 slave) } /* Reset the sensor */ - if (i2c_w(sd, 0x12, 0x80) < 0) - return -EIO; + i2c_w(sd, 0x12, 0x80); + /* Wait for it to initialize */ msleep(150); /* Dummy read to sync I2C */ if (i2c_r(sd, 0x00) < 0) - return -EIO; + return -1; } - return -EIO; + return -1; } /* Set the read and write slave IDs. The "slave" argument is the write slave, @@ -2422,53 +2407,40 @@ static int init_ov_sensor(struct sd *sd, u8 slave) * This should not be called from outside the i2c I/O functions. * Sets I2C read and write slave IDs. Returns <0 for error */ -static int ov51x_set_slave_ids(struct sd *sd, +static void ov51x_set_slave_ids(struct sd *sd, u8 slave) { - int rc; - switch (sd->bridge) { case BRIDGE_OVFX2: - return reg_w(sd, OVFX2_I2C_ADDR, slave); + reg_w(sd, OVFX2_I2C_ADDR, slave); + return; case BRIDGE_W9968CF: sd->sensor_addr = slave; - return 0; + return; } - rc = reg_w(sd, R51x_I2C_W_SID, slave); - if (rc < 0) - return rc; - return reg_w(sd, R51x_I2C_R_SID, slave + 1); + reg_w(sd, R51x_I2C_W_SID, slave); + reg_w(sd, R51x_I2C_R_SID, slave + 1); } -static int write_regvals(struct sd *sd, +static void write_regvals(struct sd *sd, const struct ov_regvals *regvals, int n) { - int rc; - while (--n >= 0) { - rc = reg_w(sd, regvals->reg, regvals->val); - if (rc < 0) - return rc; + reg_w(sd, regvals->reg, regvals->val); regvals++; } - return 0; } -static int write_i2c_regvals(struct sd *sd, - const struct ov_i2c_regvals *regvals, - int n) +static void write_i2c_regvals(struct sd *sd, + const struct ov_i2c_regvals *regvals, + int n) { - int rc; - while (--n >= 0) { - rc = i2c_w(sd, regvals->reg, regvals->val); - if (rc < 0) - return rc; + i2c_w(sd, regvals->reg, regvals->val); regvals++; } - return 0; } /**************************************************************************** @@ -2478,13 +2450,13 @@ static int write_i2c_regvals(struct sd *sd, ***************************************************************************/ /* This initializes the OV2x10 / OV3610 / OV3620 */ -static int ov_hires_configure(struct sd *sd) +static void ov_hires_configure(struct sd *sd) { int high, low; if (sd->bridge != BRIDGE_OVFX2) { err("error hires sensors only supported with ovfx2"); - return -1; + return; } PDEBUG(D_PROBE, "starting ov hires configuration"); @@ -2502,18 +2474,13 @@ static int ov_hires_configure(struct sd *sd) } else { err("Error unknown sensor type: 0x%02x%02x", high, low); - return -1; } - - /* Set sensor-specific vars */ - return 0; } - /* This initializes the OV8110, OV8610 sensor. The OV8110 uses * the same register settings as the OV8610, since they are very similar. */ -static int ov8xx0_configure(struct sd *sd) +static void ov8xx0_configure(struct sd *sd) { int rc; @@ -2523,23 +2490,18 @@ static int ov8xx0_configure(struct sd *sd) rc = i2c_r(sd, OV7610_REG_COM_I); if (rc < 0) { PDEBUG(D_ERR, "Error detecting sensor type"); - return -1; + return; } - if ((rc & 3) == 1) { + if ((rc & 3) == 1) sd->sensor = SEN_OV8610; - } else { + else err("Unknown image sensor version: %d", rc & 3); - return -1; - } - - /* Set sensor-specific vars */ - return 0; } /* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses * the same register settings as the OV7610, since they are very similar. */ -static int ov7xx0_configure(struct sd *sd) +static void ov7xx0_configure(struct sd *sd) { int rc, high, low; @@ -2552,7 +2514,7 @@ static int ov7xx0_configure(struct sd *sd) * it appears to be wrongly detected as a 7610 by default */ if (rc < 0) { PDEBUG(D_ERR, "Error detecting sensor type"); - return -1; + return; } if ((rc & 3) == 3) { /* quick hack to make OV7670s work */ @@ -2580,19 +2542,19 @@ static int ov7xx0_configure(struct sd *sd) high = i2c_r(sd, 0x0a); if (high < 0) { PDEBUG(D_ERR, "Error detecting camera chip PID"); - return high; + return; } low = i2c_r(sd, 0x0b); if (low < 0) { PDEBUG(D_ERR, "Error detecting camera chip VER"); - return low; + return; } if (high == 0x76) { switch (low) { case 0x30: err("Sensor is an OV7630/OV7635"); err("7630 is not supported by this driver"); - return -1; + return; case 0x40: PDEBUG(D_PROBE, "Sensor is an OV7645"); sd->sensor = SEN_OV7640; /* FIXME */ @@ -2607,7 +2569,7 @@ static int ov7xx0_configure(struct sd *sd) break; default: PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low); - return -1; + return; } } else { PDEBUG(D_PROBE, "Sensor is an OV7620"); @@ -2615,15 +2577,11 @@ static int ov7xx0_configure(struct sd *sd) } } else { err("Unknown image sensor version: %d", rc & 3); - return -1; } - - /* Set sensor-specific vars */ - return 0; } /* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */ -static int ov6xx0_configure(struct sd *sd) +static void ov6xx0_configure(struct sd *sd) { int rc; PDEBUG(D_PROBE, "starting OV6xx0 configuration"); @@ -2632,7 +2590,7 @@ static int ov6xx0_configure(struct sd *sd) rc = i2c_r(sd, OV7610_REG_COM_I); if (rc < 0) { PDEBUG(D_ERR, "Error detecting sensor type"); - return -1; + return; } /* Ugh. The first two bits are the version bits, but @@ -2663,13 +2621,11 @@ static int ov6xx0_configure(struct sd *sd) break; default: err("FATAL: Unknown sensor version: 0x%02x", rc); - return -1; + return; } /* Set sensor-specific vars */ sd->sif = 1; - - return 0; } /* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */ @@ -2723,7 +2679,7 @@ static void sd_reset_snapshot(struct gspca_dev *gspca_dev) } } -static int ov51x_upload_quan_tables(struct sd *sd) +static void ov51x_upload_quan_tables(struct sd *sd) { const unsigned char yQuanTable511[] = { 0, 1, 1, 2, 2, 3, 3, 4, @@ -2763,7 +2719,7 @@ static int ov51x_upload_quan_tables(struct sd *sd) const unsigned char *pYTable, *pUVTable; unsigned char val0, val1; - int i, size, rc, reg = R51x_COMP_LUT_BEGIN; + int i, size, reg = R51x_COMP_LUT_BEGIN; PDEBUG(D_PROBE, "Uploading quantization tables"); @@ -2783,30 +2739,23 @@ static int ov51x_upload_quan_tables(struct sd *sd) val0 &= 0x0f; val1 &= 0x0f; val0 |= val1 << 4; - rc = reg_w(sd, reg, val0); - if (rc < 0) - return rc; + reg_w(sd, reg, val0); val0 = *pUVTable++; val1 = *pUVTable++; val0 &= 0x0f; val1 &= 0x0f; val0 |= val1 << 4; - rc = reg_w(sd, reg + size, val0); - if (rc < 0) - return rc; + reg_w(sd, reg + size, val0); reg++; } - - return 0; } /* This initializes the OV511/OV511+ and the sensor */ -static int ov511_configure(struct gspca_dev *gspca_dev) +static void ov511_configure(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int rc; /* For 511 and 511+ */ const struct ov_regvals init_511[] = { @@ -2852,42 +2801,27 @@ static int ov511_configure(struct gspca_dev *gspca_dev) PDEBUG(D_PROBE, "Device custom id %x", reg_r(sd, R51x_SYS_CUST_ID)); - rc = write_regvals(sd, init_511, ARRAY_SIZE(init_511)); - if (rc < 0) - return rc; + write_regvals(sd, init_511, ARRAY_SIZE(init_511)); switch (sd->bridge) { case BRIDGE_OV511: - rc = write_regvals(sd, norm_511, ARRAY_SIZE(norm_511)); - if (rc < 0) - return rc; + write_regvals(sd, norm_511, ARRAY_SIZE(norm_511)); break; case BRIDGE_OV511PLUS: - rc = write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p)); - if (rc < 0) - return rc; + write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p)); break; } /* Init compression */ - rc = write_regvals(sd, compress_511, ARRAY_SIZE(compress_511)); - if (rc < 0) - return rc; - - rc = ov51x_upload_quan_tables(sd); - if (rc < 0) { - PDEBUG(D_ERR, "Error uploading quantization tables"); - return rc; - } + write_regvals(sd, compress_511, ARRAY_SIZE(compress_511)); - return 0; + ov51x_upload_quan_tables(sd); } /* This initializes the OV518/OV518+ and the sensor */ -static int ov518_configure(struct gspca_dev *gspca_dev) +static void ov518_configure(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int rc; /* For 518 and 518+ */ const struct ov_regvals init_518[] = { @@ -2937,42 +2871,26 @@ static int ov518_configure(struct gspca_dev *gspca_dev) PDEBUG(D_PROBE, "Device revision %d", 0x1f & reg_r(sd, R51x_SYS_CUST_ID)); - rc = write_regvals(sd, init_518, ARRAY_SIZE(init_518)); - if (rc < 0) - return rc; + write_regvals(sd, init_518, ARRAY_SIZE(init_518)); /* Set LED GPIO pin to output mode */ - rc = reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02); - if (rc < 0) - return rc; + reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02); switch (sd->bridge) { case BRIDGE_OV518: - rc = write_regvals(sd, norm_518, ARRAY_SIZE(norm_518)); - if (rc < 0) - return rc; + write_regvals(sd, norm_518, ARRAY_SIZE(norm_518)); break; case BRIDGE_OV518PLUS: - rc = write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p)); - if (rc < 0) - return rc; + write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p)); break; } - rc = ov51x_upload_quan_tables(sd); - if (rc < 0) { - PDEBUG(D_ERR, "Error uploading quantization tables"); - return rc; - } - - rc = reg_w(sd, 0x2f, 0x80); - if (rc < 0) - return rc; + ov51x_upload_quan_tables(sd); - return 0; + reg_w(sd, 0x2f, 0x80); } -static int ov519_configure(struct sd *sd) +static void ov519_configure(struct sd *sd) { static const struct ov_regvals init_519[] = { { 0x5a, 0x6d }, /* EnableSystem */ @@ -2990,10 +2908,10 @@ static int ov519_configure(struct sd *sd) /* windows reads 0x55 at this point*/ }; - return write_regvals(sd, init_519, ARRAY_SIZE(init_519)); + write_regvals(sd, init_519, ARRAY_SIZE(init_519)); } -static int ovfx2_configure(struct sd *sd) +static void ovfx2_configure(struct sd *sd) { static const struct ov_regvals init_fx2[] = { { 0x00, 0x60 }, @@ -3007,7 +2925,7 @@ static int ovfx2_configure(struct sd *sd) sd->stopped = 1; - return write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2)); + write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2)); } /* this function is called at probe time */ @@ -3016,7 +2934,6 @@ static int sd_config(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; struct cam *cam = &gspca_dev->cam; - int ret = 0; sd->bridge = id->driver_info & BRIDGE_MASK; sd->invert_led = id->driver_info & BRIDGE_INVERT_LED; @@ -3024,30 +2941,27 @@ static int sd_config(struct gspca_dev *gspca_dev, switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - ret = ov511_configure(gspca_dev); + ov511_configure(gspca_dev); break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - ret = ov518_configure(gspca_dev); + ov518_configure(gspca_dev); break; case BRIDGE_OV519: - ret = ov519_configure(sd); + ov519_configure(sd); break; case BRIDGE_OVFX2: - ret = ovfx2_configure(sd); + ovfx2_configure(sd); cam->bulk_size = OVFX2_BULK_SIZE; cam->bulk_nurbs = MAX_NURBS; cam->bulk = 1; break; case BRIDGE_W9968CF: - ret = w9968cf_configure(sd); + w9968cf_configure(sd); cam->reverse_alts = 1; break; } - if (ret) - goto error; - ov51x_led_control(sd, 0); /* turn LED off */ /* The OV519 must be more aggressive about sensor detection since @@ -3057,28 +2971,19 @@ static int sd_config(struct gspca_dev *gspca_dev, /* Test for 76xx */ if (init_ov_sensor(sd, OV7xx0_SID) >= 0) { - if (ov7xx0_configure(sd) < 0) { - PDEBUG(D_ERR, "Failed to configure OV7xx0"); - goto error; - } + ov7xx0_configure(sd); + /* Test for 6xx0 */ } else if (init_ov_sensor(sd, OV6xx0_SID) >= 0) { - if (ov6xx0_configure(sd) < 0) { - PDEBUG(D_ERR, "Failed to configure OV6xx0"); - goto error; - } + ov6xx0_configure(sd); + /* Test for 8xx0 */ } else if (init_ov_sensor(sd, OV8xx0_SID) >= 0) { - if (ov8xx0_configure(sd) < 0) { - PDEBUG(D_ERR, "Failed to configure OV8xx0"); - goto error; - } + ov8xx0_configure(sd); + /* Test for 3xxx / 2xxx */ } else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) { - if (ov_hires_configure(sd) < 0) { - PDEBUG(D_ERR, "Failed to configure high res OV"); - goto error; - } + ov_hires_configure(sd); } else { err("Can't determine sensor slave IDs"); goto error; @@ -3139,8 +3044,7 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->nmodes--; /* w9968cf needs initialisation once the sensor is known */ - if (w9968cf_init(sd) < 0) - goto error; + w9968cf_init(sd); break; } gspca_dev->cam.ctrls = sd->ctrls; @@ -3148,7 +3052,7 @@ static int sd_config(struct gspca_dev *gspca_dev, gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; - return 0; + return gspca_dev->usb_err; error: PDEBUG(D_ERR, "OV519 Config failed"); return -EINVAL; @@ -3162,67 +3066,57 @@ static int sd_init(struct gspca_dev *gspca_dev) /* initialize the sensor */ switch (sd->sensor) { case SEN_OV2610: - if (write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610))) - return -EIO; + write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610)); + /* Enable autogain, autoexpo, awb, bandfilter */ - if (i2c_w_mask(sd, 0x13, 0x27, 0x27) < 0) - return -EIO; + i2c_w_mask(sd, 0x13, 0x27, 0x27); break; case SEN_OV3610: - if (write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b))) - return -EIO; + write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b)); + /* Enable autogain, autoexpo, awb, bandfilter */ - if (i2c_w_mask(sd, 0x13, 0x27, 0x27) < 0) - return -EIO; + i2c_w_mask(sd, 0x13, 0x27, 0x27); break; case SEN_OV6620: - if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20))) - return -EIO; + write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20)); break; case SEN_OV6630: case SEN_OV66308AF: sd->ctrls[CONTRAST].def = 200; /* The default is too low for the ov6630 */ - if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30))) - return -EIO; + write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)); break; default: /* case SEN_OV7610: */ /* case SEN_OV76BE: */ - if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610))) - return -EIO; - if (i2c_w_mask(sd, 0x0e, 0x00, 0x40)) - return -EIO; + write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)); + i2c_w_mask(sd, 0x0e, 0x00, 0x40); break; case SEN_OV7620: case SEN_OV7620AE: - if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620))) - return -EIO; + write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)); break; case SEN_OV7640: case SEN_OV7648: - if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640))) - return -EIO; + write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)); break; case SEN_OV7670: sd->ctrls[FREQ].max = 3; /* auto */ sd->ctrls[FREQ].def = 3; - if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670))) - return -EIO; + write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670)); break; case SEN_OV8610: - if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610))) - return -EIO; + write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610)); break; } - return 0; + return gspca_dev->usb_err; } /* Set up the OV511/OV511+ with the given image parameters. * * Do not put any sensor-specific code in here (including I2C I/O functions) */ -static int ov511_mode_init_regs(struct sd *sd) +static void ov511_mode_init_regs(struct sd *sd) { int hsegs, vsegs, packet_size, fps, needed; int interlaced = 0; @@ -3233,7 +3127,8 @@ static int ov511_mode_init_regs(struct sd *sd) alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); if (!alt) { err("Couldn't get altsetting"); - return -EIO; + sd->gspca_dev.usb_err = -EIO; + return; } packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); @@ -3336,8 +3231,6 @@ static int ov511_mode_init_regs(struct sd *sd) reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE); reg_w(sd, R51x_SYS_RESET, 0); - - return 0; } /* Sets up the OV518/OV518+ with the given image parameters @@ -3347,7 +3240,7 @@ static int ov511_mode_init_regs(struct sd *sd) * * Do not put any sensor-specific code in here (including I2C I/O functions) */ -static int ov518_mode_init_regs(struct sd *sd) +static void ov518_mode_init_regs(struct sd *sd) { int hsegs, vsegs, packet_size; struct usb_host_interface *alt; @@ -3357,7 +3250,8 @@ static int ov518_mode_init_regs(struct sd *sd) alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); if (!alt) { err("Couldn't get altsetting"); - return -EIO; + sd->gspca_dev.usb_err = -EIO; + return; } packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); @@ -3460,8 +3354,6 @@ static int ov518_mode_init_regs(struct sd *sd) } reg_w(sd, 0x2f, 0x80); - - return 0; } /* Sets up the OV519 with the given image parameters @@ -3471,7 +3363,7 @@ static int ov518_mode_init_regs(struct sd *sd) * * Do not put any sensor-specific code in here (including I2C I/O functions) */ -static int ov519_mode_init_regs(struct sd *sd) +static void ov519_mode_init_regs(struct sd *sd) { static const struct ov_regvals mode_init_519_ov7670[] = { { 0x5d, 0x03 }, /* Turn off suspend mode */ @@ -3519,18 +3411,15 @@ static int ov519_mode_init_regs(struct sd *sd) /******** Set the mode ********/ if (sd->sensor != SEN_OV7670) { - if (write_regvals(sd, mode_init_519, - ARRAY_SIZE(mode_init_519))) - return -EIO; + write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519)); if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7648) { /* Select 8-bit input mode */ reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10); } } else { - if (write_regvals(sd, mode_init_519_ov7670, - ARRAY_SIZE(mode_init_519_ov7670))) - return -EIO; + write_regvals(sd, mode_init_519_ov7670, + ARRAY_SIZE(mode_init_519_ov7670)); } reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.width >> 4); @@ -3626,10 +3515,9 @@ static int ov519_mode_init_regs(struct sd *sd) } break; } - return 0; } -static int mode_init_ov_sensor_regs(struct sd *sd) +static void mode_init_ov_sensor_regs(struct sd *sd) { struct gspca_dev *gspca_dev; int qvga, xstart, xend, ystart, yend; @@ -3648,7 +3536,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); - return 0; + return; case SEN_OV3610: if (qvga) { xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4); @@ -3672,7 +3560,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) i2c_w(sd, 0x18, xend >> 4); i2c_w(sd, 0x19, ystart >> 3); i2c_w(sd, 0x1a, yend >> 3); - return 0; + return; case SEN_OV8610: /* For OV8610 qvga means qsvga */ i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5); @@ -3766,13 +3654,11 @@ static int mode_init_ov_sensor_regs(struct sd *sd) i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ break; default: - return -EINVAL; + return; } /******** Clock programming ********/ i2c_w(sd, 0x11, sd->clockdiv); - - return 0; } static void sethvflip(struct gspca_dev *gspca_dev) @@ -3791,18 +3677,18 @@ static void sethvflip(struct gspca_dev *gspca_dev) ov51x_restart(sd); } -static int set_ov_sensor_window(struct sd *sd) +static void set_ov_sensor_window(struct sd *sd) { struct gspca_dev *gspca_dev; int qvga, crop; int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; - int ret; /* mode setup is fully handled in mode_init_ov_sensor_regs for these */ if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610 || - sd->sensor == SEN_OV7670) - return mode_init_ov_sensor_regs(sd); - + sd->sensor == SEN_OV7670) { + mode_init_ov_sensor_regs(sd); + return; + } gspca_dev = &sd->gspca_dev; qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1; crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2; @@ -3852,7 +3738,7 @@ static int set_ov_sensor_window(struct sd *sd) vwsbase = vwebase = 0x03; break; default: - return -EINVAL; + return; } switch (sd->sensor) { @@ -3887,23 +3773,18 @@ static int set_ov_sensor_window(struct sd *sd) } } - ret = mode_init_ov_sensor_regs(sd); - if (ret < 0) - return ret; + mode_init_ov_sensor_regs(sd); i2c_w(sd, 0x17, hwsbase); i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale)); i2c_w(sd, 0x19, vwsbase); i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale)); - - return 0; } /* -- start the camera -- */ static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int ret = 0; /* Default for most bridges, allow bridge_mode_init_regs to override */ sd->sensor_width = sd->gspca_dev.width; @@ -3912,26 +3793,22 @@ static int sd_start(struct gspca_dev *gspca_dev) switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - ret = ov511_mode_init_regs(sd); + ov511_mode_init_regs(sd); break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - ret = ov518_mode_init_regs(sd); + ov518_mode_init_regs(sd); break; case BRIDGE_OV519: - ret = ov519_mode_init_regs(sd); + ov519_mode_init_regs(sd); break; /* case BRIDGE_OVFX2: nothing to do */ case BRIDGE_W9968CF: - ret = w9968cf_mode_init_regs(sd); + w9968cf_mode_init_regs(sd); break; } - if (ret < 0) - goto out; - ret = set_ov_sensor_window(sd); - if (ret < 0) - goto out; + set_ov_sensor_window(sd); setcontrast(gspca_dev); setbrightness(gspca_dev); @@ -3947,14 +3824,9 @@ static int sd_start(struct gspca_dev *gspca_dev) sd->first_frame = 3; - ret = ov51x_restart(sd); - if (ret < 0) - goto out; + ov51x_restart(sd); ov51x_led_control(sd, 1); - return 0; -out: - PDEBUG(D_ERR, "camera start error:%d", ret); - return ret; + return gspca_dev->usb_err; } static void sd_stopN(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c index 8bffde1..4a9e622 100644 --- a/drivers/media/video/gspca/w996Xcf.c +++ b/drivers/media/video/gspca/w996Xcf.c @@ -59,18 +59,21 @@ static const struct v4l2_pix_format w9968cf_vga_mode[] = { .colorspace = V4L2_COLORSPACE_JPEG}, }; -static int reg_w(struct sd *sd, u16 index, u16 value); +static void reg_w(struct sd *sd, u16 index, u16 value); /*-------------------------------------------------------------------------- Write 64-bit data to the fast serial bus registers. Return 0 on success, -1 otherwise. --------------------------------------------------------------------------*/ -static int w9968cf_write_fsb(struct sd *sd, u16* data) +static void w9968cf_write_fsb(struct sd *sd, u16* data) { struct usb_device *udev = sd->gspca_dev.dev; u16 value; int ret; + if (sd->gspca_dev.usb_err < 0) + return; + value = *data++; memcpy(sd->gspca_dev.usb_buf, data, 6); @@ -79,20 +82,21 @@ static int w9968cf_write_fsb(struct sd *sd, u16* data) value, 0x06, sd->gspca_dev.usb_buf, 6, 500); if (ret < 0) { err("Write FSB registers failed (%d)", ret); - return ret; + sd->gspca_dev.usb_err = ret; } - - return 0; } /*-------------------------------------------------------------------------- Write data to the serial bus control register. Return 0 on success, a negative number otherwise. --------------------------------------------------------------------------*/ -static int w9968cf_write_sb(struct sd *sd, u16 value) +static void w9968cf_write_sb(struct sd *sd, u16 value) { int ret; + if (sd->gspca_dev.usb_err < 0) + return; + /* We don't use reg_w here, as that would cause all writes when bitbanging i2c to be logged, making the logs impossible to read */ ret = usb_control_msg(sd->gspca_dev.dev, @@ -105,10 +109,8 @@ static int w9968cf_write_sb(struct sd *sd, u16 value) if (ret < 0) { err("Write SB reg [01] %04x failed", value); - return ret; + sd->gspca_dev.usb_err = ret; } - - return 0; } /*-------------------------------------------------------------------------- @@ -119,6 +121,9 @@ static int w9968cf_read_sb(struct sd *sd) { int ret; + if (sd->gspca_dev.usb_err < 0) + return -1; + /* We don't use reg_r here, as the w9968cf is special and has 16 bit registers instead of 8 bit */ ret = usb_control_msg(sd->gspca_dev.dev, @@ -126,11 +131,13 @@ static int w9968cf_read_sb(struct sd *sd) 1, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, 0x01, sd->gspca_dev.usb_buf, 2, 500); - if (ret >= 0) + if (ret >= 0) { ret = sd->gspca_dev.usb_buf[0] | (sd->gspca_dev.usb_buf[1] << 8); - else + } else { err("Read SB reg [01] failed"); + sd->gspca_dev.usb_err = ret; + } udelay(W9968CF_I2C_BUS_DELAY); @@ -142,12 +149,12 @@ static int w9968cf_read_sb(struct sd *sd) This function is called by w9968cf_start_transfer(). Return 0 on success, a negative number otherwise. --------------------------------------------------------------------------*/ -static int w9968cf_upload_quantizationtables(struct sd *sd) +static void w9968cf_upload_quantizationtables(struct sd *sd) { u16 a, b; - int ret = 0, i, j; + int i, j; - ret += reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */ + reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */ for (i = 0, j = 0; i < 32; i++, j += 2) { a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j + 1]) << 8); @@ -155,9 +162,7 @@ static int w9968cf_upload_quantizationtables(struct sd *sd) reg_w(sd, 0x40 + i, a); reg_w(sd, 0x60 + i, b); } - ret += reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */ - - return ret; + reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */ } /**************************************************************************** @@ -168,50 +173,39 @@ static int w9968cf_upload_quantizationtables(struct sd *sd) * i2c_adap_read_byte() * ****************************************************************************/ -static int w9968cf_smbus_start(struct sd *sd) +static void w9968cf_smbus_start(struct sd *sd) { - int ret = 0; - - ret += w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ - ret += w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ - - return ret; + w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ + w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ } -static int w9968cf_smbus_stop(struct sd *sd) +static void w9968cf_smbus_stop(struct sd *sd) { - int ret = 0; - - ret += w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ - ret += w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ - ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ - - return ret; + w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ + w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ + w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ } -static int w9968cf_smbus_write_byte(struct sd *sd, u8 v) +static void w9968cf_smbus_write_byte(struct sd *sd, u8 v) { u8 bit; - int ret = 0, sda; + int sda; for (bit = 0 ; bit < 8 ; bit++) { sda = (v & 0x80) ? 2 : 0; v <<= 1; /* SDE=1, SDA=sda, SCL=0 */ - ret += w9968cf_write_sb(sd, 0x10 | sda); + w9968cf_write_sb(sd, 0x10 | sda); /* SDE=1, SDA=sda, SCL=1 */ - ret += w9968cf_write_sb(sd, 0x11 | sda); + w9968cf_write_sb(sd, 0x11 | sda); /* SDE=1, SDA=sda, SCL=0 */ - ret += w9968cf_write_sb(sd, 0x10 | sda); + w9968cf_write_sb(sd, 0x10 | sda); } - - return ret; } -static int w9968cf_smbus_read_byte(struct sd *sd, u8* v) +static void w9968cf_smbus_read_byte(struct sd *sd, u8 *v) { u8 bit; - int ret = 0; /* No need to ensure SDA is high as we are always called after read_ack which ends with SDA high */ @@ -219,51 +213,40 @@ static int w9968cf_smbus_read_byte(struct sd *sd, u8* v) for (bit = 0 ; bit < 8 ; bit++) { *v <<= 1; /* SDE=1, SDA=1, SCL=1 */ - ret += w9968cf_write_sb(sd, 0x0013); + w9968cf_write_sb(sd, 0x0013); *v |= (w9968cf_read_sb(sd) & 0x0008) ? 1 : 0; /* SDE=1, SDA=1, SCL=0 */ - ret += w9968cf_write_sb(sd, 0x0012); + w9968cf_write_sb(sd, 0x0012); } - - return ret; } -static int w9968cf_smbus_write_nack(struct sd *sd) +static void w9968cf_smbus_write_nack(struct sd *sd) { - int ret = 0; - /* No need to ensure SDA is high as we are always called after read_byte which ends with SDA high */ - ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ - ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ - - return ret; + w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ + w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ } -static int w9968cf_smbus_read_ack(struct sd *sd) +static void w9968cf_smbus_read_ack(struct sd *sd) { - int ret = 0, sda; + int sda; /* Ensure SDA is high before raising clock to avoid a spurious stop */ - ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ - ret += w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ + w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ + w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ sda = w9968cf_read_sb(sd); - ret += w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ - if (sda < 0) - ret += sda; - else if (sda & 0x08) { + w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ + if (sda >= 0 && (sda & 0x08)) { PDEBUG(D_USBI, "Did not receive i2c ACK"); - ret += -1; + sd->gspca_dev.usb_err = -EIO; } - - return ret; } /* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */ -static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) +static void w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) { u16* data = (u16 *)sd->gspca_dev.usb_buf; - int ret = 0; data[0] = 0x082f | ((sd->sensor_addr & 0x80) ? 0x1500 : 0x0); data[0] |= (sd->sensor_addr & 0x40) ? 0x4000 : 0x0; @@ -276,7 +259,7 @@ static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) data[3] = 0x1d20 | ((sd->sensor_addr & 0x02) ? 0x0001 : 0x0); data[3] |= (sd->sensor_addr & 0x01) ? 0x0054 : 0x0; - ret += w9968cf_write_fsb(sd, data); + w9968cf_write_fsb(sd, data); data[0] = 0x8208 | ((reg & 0x80) ? 0x0015 : 0x0); data[0] |= (reg & 0x40) ? 0x0540 : 0x0; @@ -290,7 +273,7 @@ static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) data[2] |= (reg & 0x01) ? 0x5400 : 0x0; data[3] = 0x001d; - ret += w9968cf_write_fsb(sd, data); + w9968cf_write_fsb(sd, data); data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0); data[0] |= (value & 0x40) ? 0x0540 : 0x0; @@ -304,14 +287,9 @@ static int w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) data[2] |= (value & 0x01) ? 0x5400 : 0x0; data[3] = 0xfe1d; - ret += w9968cf_write_fsb(sd, data); - - if (!ret) - PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); - else - PDEBUG(D_ERR, "i2c 0x%02x -> [0x%02x] failed", value, reg); + w9968cf_write_fsb(sd, data); - return ret; + PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); } /* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */ @@ -321,28 +299,28 @@ static int w9968cf_i2c_r(struct sd *sd, u8 reg) u8 value; /* Fast serial bus data control disable */ - ret += w9968cf_write_sb(sd, 0x0013); /* don't change ! */ - - ret += w9968cf_smbus_start(sd); - ret += w9968cf_smbus_write_byte(sd, sd->sensor_addr); - ret += w9968cf_smbus_read_ack(sd); - ret += w9968cf_smbus_write_byte(sd, reg); - ret += w9968cf_smbus_read_ack(sd); - ret += w9968cf_smbus_stop(sd); - ret += w9968cf_smbus_start(sd); - ret += w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1); - ret += w9968cf_smbus_read_ack(sd); - ret += w9968cf_smbus_read_byte(sd, &value); + w9968cf_write_sb(sd, 0x0013); /* don't change ! */ + + w9968cf_smbus_start(sd); + w9968cf_smbus_write_byte(sd, sd->sensor_addr); + w9968cf_smbus_read_ack(sd); + w9968cf_smbus_write_byte(sd, reg); + w9968cf_smbus_read_ack(sd); + w9968cf_smbus_stop(sd); + w9968cf_smbus_start(sd); + w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1); + w9968cf_smbus_read_ack(sd); + w9968cf_smbus_read_byte(sd, &value); /* signal we don't want to read anymore, the v4l1 driver used to send an ack here which is very wrong! (and then fixed the issues this gave by retrying reads) */ - ret += w9968cf_smbus_write_nack(sd); - ret += w9968cf_smbus_stop(sd); + w9968cf_smbus_write_nack(sd); + w9968cf_smbus_stop(sd); /* Fast serial bus data control re-enable */ - ret += w9968cf_write_sb(sd, 0x0030); + w9968cf_write_sb(sd, 0x0030); - if (!ret) { + if (sd->gspca_dev.usb_err >= 0) { ret = value; PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); } else @@ -355,29 +333,21 @@ static int w9968cf_i2c_r(struct sd *sd, u8 reg) Turn on the LED on some webcams. A beep should be heard too. Return 0 on success, a negative number otherwise. --------------------------------------------------------------------------*/ -static int w9968cf_configure(struct sd *sd) +static void w9968cf_configure(struct sd *sd) { - int ret = 0; - - ret += reg_w(sd, 0x00, 0xff00); /* power-down */ - ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */ - ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */ - ret += reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */ - ret += reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */ - ret += reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */ - ret += reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */ - - if (ret) - PDEBUG(D_ERR, "Couldn't turn on the LED"); + reg_w(sd, 0x00, 0xff00); /* power-down */ + reg_w(sd, 0x00, 0xbf17); /* reset everything */ + reg_w(sd, 0x00, 0xbf10); /* normal operation */ + reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */ + reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */ + reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */ + reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */ sd->stopped = 1; - - return ret; } -static int w9968cf_init(struct sd *sd) +static void w9968cf_init(struct sd *sd) { - int ret = 0; unsigned long hw_bufsize = sd->sif ? (352 * 288 * 2) : (640 * 480 * 2), y0 = 0x0000, u0 = y0 + hw_bufsize / 2, @@ -386,43 +356,41 @@ static int w9968cf_init(struct sd *sd) u1 = y1 + hw_bufsize / 2, v1 = u1 + hw_bufsize / 4; - ret += reg_w(sd, 0x00, 0xff00); /* power off */ - ret += reg_w(sd, 0x00, 0xbf10); /* power on */ - - ret += reg_w(sd, 0x03, 0x405d); /* DRAM timings */ - ret += reg_w(sd, 0x04, 0x0030); /* SDRAM timings */ + reg_w(sd, 0x00, 0xff00); /* power off */ + reg_w(sd, 0x00, 0xbf10); /* power on */ - ret += reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */ - ret += reg_w(sd, 0x21, y0 >> 16); /* Y buf.0, high */ - ret += reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */ - ret += reg_w(sd, 0x25, u0 >> 16); /* U buf.0, high */ - ret += reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */ - ret += reg_w(sd, 0x29, v0 >> 16); /* V buf.0, high */ + reg_w(sd, 0x03, 0x405d); /* DRAM timings */ + reg_w(sd, 0x04, 0x0030); /* SDRAM timings */ - ret += reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */ - ret += reg_w(sd, 0x23, y1 >> 16); /* Y buf.1, high */ - ret += reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */ - ret += reg_w(sd, 0x27, u1 >> 16); /* U buf.1, high */ - ret += reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */ - ret += reg_w(sd, 0x2b, v1 >> 16); /* V buf.1, high */ + reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */ + reg_w(sd, 0x21, y0 >> 16); /* Y buf.0, high */ + reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */ + reg_w(sd, 0x25, u0 >> 16); /* U buf.0, high */ + reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */ + reg_w(sd, 0x29, v0 >> 16); /* V buf.0, high */ - ret += reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */ - ret += reg_w(sd, 0x33, y1 >> 16); /* JPEG buf 0 high */ + reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */ + reg_w(sd, 0x23, y1 >> 16); /* Y buf.1, high */ + reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */ + reg_w(sd, 0x27, u1 >> 16); /* U buf.1, high */ + reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */ + reg_w(sd, 0x2b, v1 >> 16); /* V buf.1, high */ - ret += reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */ - ret += reg_w(sd, 0x35, y1 >> 16); /* JPEG bug 1 high */ + reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */ + reg_w(sd, 0x33, y1 >> 16); /* JPEG buf 0 high */ - ret += reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */ - ret += reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/ - ret += reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */ - ret += reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */ + reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */ + reg_w(sd, 0x35, y1 >> 16); /* JPEG bug 1 high */ - return ret; + reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */ + reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/ + reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */ + reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */ } -static int w9968cf_set_crop_window(struct sd *sd) +static void w9968cf_set_crop_window(struct sd *sd) { - int ret = 0, start_cropx, start_cropy, x, y, fw, fh, cw, ch, + int start_cropx, start_cropy, x, y, fw, fh, cw, ch, max_width, max_height; if (sd->sif) { @@ -464,42 +432,40 @@ static int w9968cf_set_crop_window(struct sd *sd) x = (max_width - cw) / 2; y = (max_height - ch) / 2; - ret += reg_w(sd, 0x10, start_cropx + x); - ret += reg_w(sd, 0x11, start_cropy + y); - ret += reg_w(sd, 0x12, start_cropx + x + cw); - ret += reg_w(sd, 0x13, start_cropy + y + ch); - - return ret; + reg_w(sd, 0x10, start_cropx + x); + reg_w(sd, 0x11, start_cropy + y); + reg_w(sd, 0x12, start_cropx + x + cw); + reg_w(sd, 0x13, start_cropy + y + ch); } -static int w9968cf_mode_init_regs(struct sd *sd) +static void w9968cf_mode_init_regs(struct sd *sd) { - int ret = 0, val, vs_polarity, hs_polarity; + int val, vs_polarity, hs_polarity; - ret += w9968cf_set_crop_window(sd); + w9968cf_set_crop_window(sd); - ret += reg_w(sd, 0x14, sd->gspca_dev.width); - ret += reg_w(sd, 0x15, sd->gspca_dev.height); + reg_w(sd, 0x14, sd->gspca_dev.width); + reg_w(sd, 0x15, sd->gspca_dev.height); /* JPEG width & height */ - ret += reg_w(sd, 0x30, sd->gspca_dev.width); - ret += reg_w(sd, 0x31, sd->gspca_dev.height); + reg_w(sd, 0x30, sd->gspca_dev.width); + reg_w(sd, 0x31, sd->gspca_dev.height); /* Y & UV frame buffer strides (in WORD) */ if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == V4L2_PIX_FMT_JPEG) { - ret += reg_w(sd, 0x2c, sd->gspca_dev.width / 2); - ret += reg_w(sd, 0x2d, sd->gspca_dev.width / 4); + reg_w(sd, 0x2c, sd->gspca_dev.width / 2); + reg_w(sd, 0x2d, sd->gspca_dev.width / 4); } else - ret += reg_w(sd, 0x2c, sd->gspca_dev.width); + reg_w(sd, 0x2c, sd->gspca_dev.width); - ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */ - ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */ + reg_w(sd, 0x00, 0xbf17); /* reset everything */ + reg_w(sd, 0x00, 0xbf10); /* normal operation */ /* Transfer size in WORDS (for UYVY format only) */ val = sd->gspca_dev.width * sd->gspca_dev.height; - ret += reg_w(sd, 0x3d, val & 0xffff); /* low bits */ - ret += reg_w(sd, 0x3e, val >> 16); /* high bits */ + reg_w(sd, 0x3d, val & 0xffff); /* low bits */ + reg_w(sd, 0x3e, val >> 16); /* high bits */ if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == V4L2_PIX_FMT_JPEG) { @@ -507,7 +473,7 @@ static int w9968cf_mode_init_regs(struct sd *sd) jpeg_define(sd->jpeg_hdr, sd->gspca_dev.height, sd->gspca_dev.width, 0x22); /* JPEG 420 */ jpeg_set_qual(sd->jpeg_hdr, sd->quality); - ret += w9968cf_upload_quantizationtables(sd); + w9968cf_upload_quantizationtables(sd); } /* Video Capture Control Register */ @@ -539,11 +505,9 @@ static int w9968cf_mode_init_regs(struct sd *sd) val |= 0x8000; /* capt. enable */ - ret += reg_w(sd, 0x16, val); + reg_w(sd, 0x16, val); sd->gspca_dev.empty_packet = 0; - - return ret; } static void w9968cf_stop0(struct sd *sd) -- cgit v0.10.2 From 858ea5e941fad6a2f38d0c9722bbb842d46662fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Fri, 12 Nov 2010 13:53:10 -0300 Subject: [media] gspca - ov519: Clearer debug and error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 0591ced..7ae304d 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -1885,6 +1885,8 @@ static void reg_w(struct sd *sd, u16 index, u16 value) req = 0x0a; /* fall through */ case BRIDGE_W9968CF: + PDEBUG(D_USBO, "SET %02x %04x %04x", + req, value, index); ret = usb_control_msg(sd->gspca_dev.dev, usb_sndctrlpipe(sd->gspca_dev.dev, 0), req, @@ -1895,6 +1897,8 @@ static void reg_w(struct sd *sd, u16 index, u16 value) req = 1; } + PDEBUG(D_USBO, "SET %02x 0000 %04x %02x", + req, index, value); sd->gspca_dev.usb_buf[0] = value; ret = usb_control_msg(sd->gspca_dev.dev, usb_sndctrlpipe(sd->gspca_dev.dev, 0), @@ -1904,13 +1908,10 @@ static void reg_w(struct sd *sd, u16 index, u16 value) sd->gspca_dev.usb_buf, 1, 500); leave: if (ret < 0) { - err("Write reg 0x%04x -> [0x%02x] failed", - value, index); + err("reg_w %02x failed %d", index, ret); sd->gspca_dev.usb_err = ret; return; } - - PDEBUG(D_USBO, "Write reg 0x%04x -> [0x%02x]", value, index); } /* Read from a OV519 register, note not valid for the w9968cf!! */ @@ -1943,9 +1944,10 @@ static int reg_r(struct sd *sd, u16 index) if (ret >= 0) { ret = sd->gspca_dev.usb_buf[0]; - PDEBUG(D_USBI, "Read reg [0x%02X] -> 0x%04X", index, ret); + PDEBUG(D_USBI, "GET %02x 0000 %04x %02x", + req, index, ret); } else { - err("Read reg [0x%02x] failed", index); + err("reg_r %02x failed %d", index, ret); sd->gspca_dev.usb_err = ret; } @@ -1970,7 +1972,7 @@ static int reg_r8(struct sd *sd, if (ret >= 0) { ret = sd->gspca_dev.usb_buf[0]; } else { - err("Read reg 8 [0x%02x] failed", index); + err("reg_r8 %02x failed %d", index, ret); sd->gspca_dev.usb_err = ret; } @@ -2023,7 +2025,7 @@ static void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n) 0, index, sd->gspca_dev.usb_buf, n, 500); if (ret < 0) { - err("Write reg32 [%02x] %08x failed", index, value); + err("reg_w32 %02x failed %d", index, ret); sd->gspca_dev.usb_err = ret; } } @@ -2032,7 +2034,7 @@ static void ov511_i2c_w(struct sd *sd, u8 reg, u8 value) { int rc, retries; - PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); + PDEBUG(D_USBO, "ov511_i2c_w %02x %02x", reg, value); /* Three byte write cycle */ for (retries = 6; ; ) { @@ -2118,7 +2120,7 @@ static int ov511_i2c_r(struct sd *sd, u8 reg) value = reg_r(sd, R51x_I2C_DATA); - PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); + PDEBUG(D_USBI, "ov511_i2c_r %02x %02x", reg, value); /* This is needed to make i2c_w() work */ reg_w(sd, R511_I2C_CTL, 0x05); @@ -2135,7 +2137,7 @@ static void ov518_i2c_w(struct sd *sd, u8 reg, u8 value) { - PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); + PDEBUG(D_USBO, "ov518_i2c_w %02x %02x", reg, value); /* Select camera register */ reg_w(sd, R51x_I2C_SADDR_3, reg); @@ -2171,7 +2173,7 @@ static int ov518_i2c_r(struct sd *sd, u8 reg) /* Initiate 2-byte read cycle */ reg_w(sd, R518_I2C_CTL, 0x05); value = reg_r(sd, R51x_I2C_DATA); - PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); + PDEBUG(D_USBI, "ov518_i2c_r %02x %02x", reg, value); return value; } @@ -2189,11 +2191,11 @@ static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value) (u16) value, (u16) reg, NULL, 0, 500); if (ret < 0) { - err("i2c 0x%02x -> [0x%02x] failed", value, reg); + err("ovfx2_i2c_w %02x failed %d", reg, ret); sd->gspca_dev.usb_err = ret; } - PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); + PDEBUG(D_USBO, "ovfx2_i2c_w %02x %02x", reg, value); } static int ovfx2_i2c_r(struct sd *sd, u8 reg) @@ -2211,9 +2213,9 @@ static int ovfx2_i2c_r(struct sd *sd, u8 reg) if (ret >= 0) { ret = sd->gspca_dev.usb_buf[0]; - PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, ret); + PDEBUG(D_USBI, "ovfx2_i2c_r %02x %02x", reg, ret); } else { - err("i2c read [0x%02x] failed", reg); + err("ovfx2_i2c_r %02x failed %d", reg, ret); sd->gspca_dev.usb_err = ret; } @@ -2472,7 +2474,7 @@ static void ov_hires_configure(struct sd *sd) PDEBUG(D_PROBE, "Sensor is an OV3610"); sd->sensor = SEN_OV3610; } else { - err("Error unknown sensor type: 0x%02x%02x", + err("Error unknown sensor type: %02x%02x", high, low); } } -- cgit v0.10.2 From e2817029b3f139bd85360536153467bd8f7f863b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Fri, 12 Nov 2010 13:59:48 -0300 Subject: [media] gspca - ov519: Check the disabled controls at start time only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 7ae304d..d603220 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -3667,8 +3667,6 @@ static void sethvflip(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - if (sd->sensor != SEN_OV7670) - return; if (sd->gspca_dev.streaming) ov51x_stop(sd); i2c_w_mask(sd, OV7670_R1E_MVFP, @@ -3812,12 +3810,18 @@ static int sd_start(struct gspca_dev *gspca_dev) set_ov_sensor_window(sd); - setcontrast(gspca_dev); - setbrightness(gspca_dev); - setcolors(gspca_dev); - sethvflip(gspca_dev); - setautobright(gspca_dev); - setfreq_i(sd); + if (!(sd->gspca_dev.ctrl_dis & (1 << CONTRAST))) + setcontrast(gspca_dev); + if (!(sd->gspca_dev.ctrl_dis & (1 << BRIGHTNESS))) + setbrightness(gspca_dev); + if (!(sd->gspca_dev.ctrl_dis & (1 << COLORS))) + setcolors(gspca_dev); + if (!(sd->gspca_dev.ctrl_dis & ((1 << HFLIP) | (1 << VFLIP)))) + sethvflip(gspca_dev); + if (!(sd->gspca_dev.ctrl_dis & (1 << AUTOBRIGHT))) + setautobright(gspca_dev); + if (!(sd->gspca_dev.ctrl_dis & (1 << FREQ))) + setfreq_i(sd); /* Force clear snapshot state in case the snapshot button was pressed while we weren't streaming */ @@ -4184,19 +4188,11 @@ static void setautobright(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7648 || - sd->sensor == SEN_OV7670 || - sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) - return; - i2c_w_mask(sd, 0x2d, sd->ctrls[AUTOBRIGHT].val ? 0x10 : 0x00, 0x10); } static void setfreq_i(struct sd *sd) { - if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) - return; - if (sd->sensor == SEN_OV7670) { switch (sd->ctrls[FREQ].val) { case 0: /* Banding filter disabled */ -- cgit v0.10.2 From a23acec4bca79f2168a5aeacc8d85386b70ae522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Fri, 12 Nov 2010 15:07:35 -0300 Subject: [media] gspca - ov519: Simplify the LED control functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index d603220..2484e52 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -2639,14 +2639,14 @@ static void ov51x_led_control(struct sd *sd, int on) switch (sd->bridge) { /* OV511 has no LED control */ case BRIDGE_OV511PLUS: - reg_w(sd, R511_SYS_LED_CTL, on ? 1 : 0); + reg_w(sd, R511_SYS_LED_CTL, on); break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - reg_w_mask(sd, R518_GPIO_OUT, on ? 0x02 : 0x00, 0x02); + reg_w_mask(sd, R518_GPIO_OUT, 0x02 * on, 0x02); break; case BRIDGE_OV519: - reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */ + reg_w_mask(sd, OV519_GPIO_DATA_OUT0, on, 1); break; } } @@ -2938,7 +2938,7 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam = &gspca_dev->cam; sd->bridge = id->driver_info & BRIDGE_MASK; - sd->invert_led = id->driver_info & BRIDGE_INVERT_LED; + sd->invert_led = (id->driver_info & BRIDGE_INVERT_LED) != 0; switch (sd->bridge) { case BRIDGE_OV511: -- cgit v0.10.2 From 5927abcb21d0dd10c960517453e37302acf2269e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Fri, 12 Nov 2010 15:32:29 -0300 Subject: [media] gspca - ov519: Change the ov519 start and stop sequences MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - start and stop streaming are done via the FRAR - streaming suspend (for control change) is done by video reset Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 2484e52..43b86b1 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -2325,6 +2325,8 @@ static inline void ov51x_stop(struct sd *sd) break; case BRIDGE_OV519: reg_w(sd, OV519_R51_RESET1, 0x0f); + reg_w(sd, OV519_R51_RESET1, 0x00); + reg_w(sd, 0x22, 0x00); /* FRAR */ break; case BRIDGE_OVFX2: reg_w_mask(sd, 0x0f, 0x00, 0x02); @@ -2356,7 +2358,9 @@ static inline void ov51x_restart(struct sd *sd) reg_w(sd, R51x_SYS_RESET, 0x00); break; case BRIDGE_OV519: + reg_w(sd, OV519_R51_RESET1, 0x0f); reg_w(sd, OV519_R51_RESET1, 0x00); + reg_w(sd, 0x22, 0x1d); /* FRAR */ break; case BRIDGE_OVFX2: reg_w_mask(sd, 0x0f, 0x02, 0x02); @@ -3668,13 +3672,13 @@ static void sethvflip(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; if (sd->gspca_dev.streaming) - ov51x_stop(sd); + reg_w(sd, OV519_R51_RESET1, 0x0f); /* block stream */ i2c_w_mask(sd, OV7670_R1E_MVFP, OV7670_MVFP_MIRROR * sd->ctrls[HFLIP].val | OV7670_MVFP_VFLIP * sd->ctrls[VFLIP].val, OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP); if (sd->gspca_dev.streaming) - ov51x_restart(sd); + reg_w(sd, OV519_R51_RESET1, 0x00); /* restart stream */ } static void set_ov_sensor_window(struct sd *sd) -- cgit v0.10.2 From b4e96ea30a211c0979e9e0ea10f39dfa50afb8fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Fri, 12 Nov 2010 16:13:17 -0300 Subject: [media] gspca - ov519: Initialize the ov519 snapshot register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 43b86b1..1d0fb4d 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -513,6 +513,7 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { /* OV519 System Controller register numbers */ #define OV519_R51_RESET1 0x51 #define OV519_R54_EN_CLK1 0x54 +#define OV519_R57_SNAPSHOT 0x57 #define OV519_GPIO_DATA_OUT0 0x71 #define OV519_GPIO_IO_CTRL0 0x72 @@ -3864,6 +3865,8 @@ static void sd_stop0(struct gspca_dev *gspca_dev) sd->snapshot_pressed = 0; } #endif + if (sd->bridge == BRIDGE_OV519) + reg_w(sd, OV519_R57_SNAPSHOT, 0x23); } static void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state) -- cgit v0.10.2 From 7491f785dd02bc35551e0463d798959b15644c1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Sat, 13 Nov 2010 03:56:41 -0300 Subject: [media] gspca - ov519: Re-initialize the webcam at resume time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 1d0fb4d..08f07c3 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -2948,28 +2948,64 @@ static int sd_config(struct gspca_dev *gspca_dev, switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - ov511_configure(gspca_dev); + cam->cam_mode = ov511_vga_mode; + cam->nmodes = ARRAY_SIZE(ov511_vga_mode); break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - ov518_configure(gspca_dev); + cam->cam_mode = ov518_vga_mode; + cam->nmodes = ARRAY_SIZE(ov518_vga_mode); break; case BRIDGE_OV519: - ov519_configure(sd); + cam->cam_mode = ov519_vga_mode; + cam->nmodes = ARRAY_SIZE(ov519_vga_mode); + sd->invert_led = !sd->invert_led; break; case BRIDGE_OVFX2: - ovfx2_configure(sd); + cam->cam_mode = ov519_vga_mode; + cam->nmodes = ARRAY_SIZE(ov519_vga_mode); cam->bulk_size = OVFX2_BULK_SIZE; cam->bulk_nurbs = MAX_NURBS; cam->bulk = 1; break; case BRIDGE_W9968CF: - w9968cf_configure(sd); + cam->cam_mode = w9968cf_vga_mode; + cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode); cam->reverse_alts = 1; break; } - ov51x_led_control(sd, 0); /* turn LED off */ + gspca_dev->cam.ctrls = sd->ctrls; + sd->quality = QUALITY_DEF; + + return 0; +} + +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct cam *cam = &gspca_dev->cam; + + switch (sd->bridge) { + case BRIDGE_OV511: + case BRIDGE_OV511PLUS: + ov511_configure(gspca_dev); + break; + case BRIDGE_OV518: + case BRIDGE_OV518PLUS: + ov518_configure(gspca_dev); + break; + case BRIDGE_OV519: + ov519_configure(sd); + break; + case BRIDGE_OVFX2: + ovfx2_configure(sd); + break; + case BRIDGE_W9968CF: + w9968cf_configure(sd); + break; + } /* The OV519 must be more aggressive about sensor detection since * I2C write will never fail if the sensor is not present. We have @@ -2999,32 +3035,25 @@ static int sd_config(struct gspca_dev *gspca_dev, if (sd->sensor < 0) goto error; + ov51x_led_control(sd, 0); /* turn LED off */ + switch (sd->bridge) { case BRIDGE_OV511: case BRIDGE_OV511PLUS: - if (!sd->sif) { - cam->cam_mode = ov511_vga_mode; - cam->nmodes = ARRAY_SIZE(ov511_vga_mode); - } else { + if (sd->sif) { cam->cam_mode = ov511_sif_mode; cam->nmodes = ARRAY_SIZE(ov511_sif_mode); } break; case BRIDGE_OV518: case BRIDGE_OV518PLUS: - if (!sd->sif) { - cam->cam_mode = ov518_vga_mode; - cam->nmodes = ARRAY_SIZE(ov518_vga_mode); - } else { + if (sd->sif) { cam->cam_mode = ov518_sif_mode; cam->nmodes = ARRAY_SIZE(ov518_sif_mode); } break; case BRIDGE_OV519: - if (!sd->sif) { - cam->cam_mode = ov519_vga_mode; - cam->nmodes = ARRAY_SIZE(ov519_vga_mode); - } else { + if (sd->sif) { cam->cam_mode = ov519_sif_mode; cam->nmodes = ARRAY_SIZE(ov519_sif_mode); } @@ -3036,40 +3065,22 @@ static int sd_config(struct gspca_dev *gspca_dev, } else if (sd->sensor == SEN_OV3610) { cam->cam_mode = ovfx2_ov3610_mode; cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode); - } else if (!sd->sif) { - cam->cam_mode = ov519_vga_mode; - cam->nmodes = ARRAY_SIZE(ov519_vga_mode); - } else { + } else if (sd->sif) { cam->cam_mode = ov519_sif_mode; cam->nmodes = ARRAY_SIZE(ov519_sif_mode); } break; case BRIDGE_W9968CF: - cam->cam_mode = w9968cf_vga_mode; - cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode); if (sd->sif) - cam->nmodes--; + cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode) - 1; /* w9968cf needs initialisation once the sensor is known */ w9968cf_init(sd); break; } - gspca_dev->cam.ctrls = sd->ctrls; - sd->quality = QUALITY_DEF; gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; - return gspca_dev->usb_err; -error: - PDEBUG(D_ERR, "OV519 Config failed"); - return -EINVAL; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - /* initialize the sensor */ switch (sd->sensor) { case SEN_OV2610: @@ -3117,6 +3128,9 @@ static int sd_init(struct gspca_dev *gspca_dev) break; } return gspca_dev->usb_err; +error: + PDEBUG(D_ERR, "OV519 Config failed"); + return -EINVAL; } /* Set up the OV511/OV511+ with the given image parameters. -- cgit v0.10.2 From 42e142f6b72493b5daec9950c4c83d20ccf56a0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Sat, 13 Nov 2010 05:10:27 -0300 Subject: [media] gspca - ov519: New sensor ov7660 with bridge ov530 (ov519) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [mchehab@redhat.com: Some CodingStyle fixes] Tested-by: Anca Emanuel Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 08f07c3..0ed21db 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -82,7 +82,7 @@ struct sd { #define BRIDGE_OV511PLUS 1 #define BRIDGE_OV518 2 #define BRIDGE_OV518PLUS 3 -#define BRIDGE_OV519 4 +#define BRIDGE_OV519 4 /* = ov530 */ #define BRIDGE_OVFX2 5 #define BRIDGE_W9968CF 6 #define BRIDGE_MASK 7 @@ -127,6 +127,7 @@ enum sensors { SEN_OV7620AE, SEN_OV7640, SEN_OV7648, + SEN_OV7660, SEN_OV7670, SEN_OV76BE, SEN_OV8610, @@ -183,7 +184,7 @@ static const struct ctrl sd_ctrls[] = { }, .set_control = setcolors, }, -/* The flip controls work with ov7670 only */ +/* The flip controls work for sensors ov7660 and ov7670 only */ [HFLIP] = { { .id = V4L2_CID_HFLIP, @@ -268,6 +269,8 @@ static const unsigned ctrl_dis[] = { (1 << AUTOBRIGHT) | (1 << CONTRAST), +[SEN_OV7660] = (1 << AUTOBRIGHT), + [SEN_OV7670] = (1 << COLORS) | (1 << AUTOBRIGHT), @@ -572,7 +575,7 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define OV7610_REG_ID_LOW 0x1d /* manufacturer ID LSB */ #define OV7610_REG_COM_I 0x29 /* misc settings */ -/* OV7670 registers */ +/* OV7660 and OV7670 registers */ #define OV7670_R00_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ #define OV7670_R01_BLUE 0x01 /* blue gain */ #define OV7670_R02_RED 0x02 /* red gain */ @@ -625,6 +628,7 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { /*#define OV7670_COM15_R00FF 0xc0 * 00 to FF */ #define OV7670_R41_COM16 0x41 /* Control 16 */ #define OV7670_COM16_AWBGAIN 0x08 /* AWB gain enable */ +/* end of ov7660 common registers */ #define OV7670_R55_BRIGHT 0x55 /* Brightness */ #define OV7670_R56_CONTRAS 0x56 /* Contrast control */ #define OV7670_R69_GFIX 0x69 /* Fix gain control */ @@ -1577,6 +1581,150 @@ static const struct ov_i2c_regvals norm_7640[] = { { 0x12, 0x14 }, }; +static const struct ov_regvals init_519_ov7660[] = { + { 0x5d, 0x03 }, /* Turn off suspend mode */ + { 0x53, 0x9b }, /* 0x9f enables the (unused) microcontroller */ + { 0x54, 0x0f }, /* bit2 (jpeg enable) */ + { 0xa2, 0x20 }, /* a2-a5 are undocumented */ + { 0xa3, 0x18 }, + { 0xa4, 0x04 }, + { 0xa5, 0x28 }, + { 0x37, 0x00 }, /* SetUsbInit */ + { 0x55, 0x02 }, /* 4.096 Mhz audio clock */ + /* Enable both fields, YUV Input, disable defect comp (why?) */ + { 0x20, 0x0c }, /* 0x0d does U <-> V swap */ + { 0x21, 0x38 }, + { 0x22, 0x1d }, + { 0x17, 0x50 }, /* undocumented */ + { 0x37, 0x00 }, /* undocumented */ + { 0x40, 0xff }, /* I2C timeout counter */ + { 0x46, 0x00 }, /* I2C clock prescaler */ +}; +static const struct ov_i2c_regvals norm_7660[] = { + {OV7670_R12_COM7, OV7670_COM7_RESET}, + {OV7670_R11_CLKRC, 0x81}, + {0x92, 0x00}, /* DM_LNL */ + {0x93, 0x00}, /* DM_LNH */ + {0x9d, 0x4c}, /* BD50ST */ + {0x9e, 0x3f}, /* BD60ST */ + {OV7670_R3B_COM11, 0x02}, + {OV7670_R13_COM8, 0xf5}, + {OV7670_R10_AECH, 0x00}, + {OV7670_R00_GAIN, 0x00}, + {OV7670_R01_BLUE, 0x7c}, + {OV7670_R02_RED, 0x9d}, + {OV7670_R12_COM7, 0x00}, + {OV7670_R04_COM1, 00}, + {OV7670_R18_HSTOP, 0x01}, + {OV7670_R17_HSTART, 0x13}, + {OV7670_R32_HREF, 0x92}, + {OV7670_R19_VSTART, 0x02}, + {OV7670_R1A_VSTOP, 0x7a}, + {OV7670_R03_VREF, 0x00}, + {OV7670_R0E_COM5, 0x04}, + {OV7670_R0F_COM6, 0x62}, + {OV7670_R15_COM10, 0x00}, + {0x16, 0x02}, /* RSVD */ + {0x1b, 0x00}, /* PSHFT */ + {OV7670_R1E_MVFP, 0x01}, + {0x29, 0x3c}, /* RSVD */ + {0x33, 0x00}, /* CHLF */ + {0x34, 0x07}, /* ARBLM */ + {0x35, 0x84}, /* RSVD */ + {0x36, 0x00}, /* RSVD */ + {0x37, 0x04}, /* ADC */ + {0x39, 0x43}, /* OFON */ + {OV7670_R3A_TSLB, 0x00}, + {OV7670_R3C_COM12, 0x6c}, + {OV7670_R3D_COM13, 0x98}, + {OV7670_R3F_EDGE, 0x23}, + {OV7670_R40_COM15, 0xc1}, + {OV7670_R41_COM16, 0x22}, + {0x6b, 0x0a}, /* DBLV */ + {0xa1, 0x08}, /* RSVD */ + {0x69, 0x80}, /* HV */ + {0x43, 0xf0}, /* RSVD.. */ + {0x44, 0x10}, + {0x45, 0x78}, + {0x46, 0xa8}, + {0x47, 0x60}, + {0x48, 0x80}, + {0x59, 0xba}, + {0x5a, 0x9a}, + {0x5b, 0x22}, + {0x5c, 0xb9}, + {0x5d, 0x9b}, + {0x5e, 0x10}, + {0x5f, 0xe0}, + {0x60, 0x85}, + {0x61, 0x60}, + {0x9f, 0x9d}, /* RSVD */ + {0xa0, 0xa0}, /* DSPC2 */ + {0x4f, 0x60}, /* matrix */ + {0x50, 0x64}, + {0x51, 0x04}, + {0x52, 0x18}, + {0x53, 0x3c}, + {0x54, 0x54}, + {0x55, 0x40}, + {0x56, 0x40}, + {0x57, 0x40}, + {0x58, 0x0d}, /* matrix sign */ + {0x8b, 0xcc}, /* RSVD */ + {0x8c, 0xcc}, + {0x8d, 0xcf}, + {0x6c, 0x40}, /* gamma curve */ + {0x6d, 0xe0}, + {0x6e, 0xa0}, + {0x6f, 0x80}, + {0x70, 0x70}, + {0x71, 0x80}, + {0x72, 0x60}, + {0x73, 0x60}, + {0x74, 0x50}, + {0x75, 0x40}, + {0x76, 0x38}, + {0x77, 0x3c}, + {0x78, 0x32}, + {0x79, 0x1a}, + {0x7a, 0x28}, + {0x7b, 0x24}, + {0x7c, 0x04}, /* gamma curve */ + {0x7d, 0x12}, + {0x7e, 0x26}, + {0x7f, 0x46}, + {0x80, 0x54}, + {0x81, 0x64}, + {0x82, 0x70}, + {0x83, 0x7c}, + {0x84, 0x86}, + {0x85, 0x8e}, + {0x86, 0x9c}, + {0x87, 0xab}, + {0x88, 0xc4}, + {0x89, 0xd1}, + {0x8a, 0xe5}, + {OV7670_R14_COM9, 0x1e}, + {OV7670_R24_AEW, 0x80}, + {OV7670_R25_AEB, 0x72}, + {OV7670_R26_VPT, 0xb3}, + {0x62, 0x80}, /* LCC1 */ + {0x63, 0x80}, /* LCC2 */ + {0x64, 0x06}, /* LCC3 */ + {0x65, 0x00}, /* LCC4 */ + {0x66, 0x01}, /* LCC5 */ + {0x94, 0x0e}, /* RSVD.. */ + {0x95, 0x14}, + {OV7670_R13_COM8, OV7670_COM8_FASTAEC + | OV7670_COM8_AECSTEP + | OV7670_COM8_BFILT + | 0x10 + | OV7670_COM8_AGC + | OV7670_COM8_AWB + | OV7670_COM8_AEC}, + {0xa1, 0xc8} +}; + /* 7670. Defaults taken from OmniVision provided data, * as provided by Jonathan Corbet of OLPC */ static const struct ov_i2c_regvals norm_7670[] = { @@ -2574,6 +2722,11 @@ static void ov7xx0_configure(struct sd *sd) PDEBUG(D_PROBE, "Sensor is an OV7648"); sd->sensor = SEN_OV7648; break; + case 0x60: + PDEBUG(D_PROBE, "Sensor is a OV7660"); + sd->sensor = SEN_OV7660; + sd->invert_led = 0; + break; default: PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low); return; @@ -2935,6 +3088,91 @@ static void ovfx2_configure(struct sd *sd) write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2)); } +/* set the mode */ +/* This function works for ov7660 only */ +static void ov519_set_mode(struct sd *sd) +{ + static const struct ov_regvals bridge_ov7660[2][10] = { + {{0x10, 0x14}, {0x11, 0x1e}, {0x12, 0x00}, {0x13, 0x00}, + {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c}, + {0x25, 0x01}, {0x26, 0x00}}, + {{0x10, 0x28}, {0x11, 0x3c}, {0x12, 0x00}, {0x13, 0x00}, + {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c}, + {0x25, 0x03}, {0x26, 0x00}} + }; + static const struct ov_i2c_regvals sensor_ov7660[2][3] = { + {{0x12, 0x00}, {0x24, 0x00}, {0x0c, 0x0c}}, + {{0x12, 0x00}, {0x04, 0x00}, {0x0c, 0x00}} + }; + static const struct ov_i2c_regvals sensor_ov7660_2[] = { + {OV7670_R17_HSTART, 0x13}, + {OV7670_R18_HSTOP, 0x01}, + {OV7670_R32_HREF, 0x92}, + {OV7670_R19_VSTART, 0x02}, + {OV7670_R1A_VSTOP, 0x7a}, + {OV7670_R03_VREF, 0x00}, +/* {0x33, 0x00}, */ +/* {0x34, 0x07}, */ +/* {0x36, 0x00}, */ +/* {0x6b, 0x0a}, */ + }; + + write_regvals(sd, bridge_ov7660[sd->gspca_dev.curr_mode], + ARRAY_SIZE(bridge_ov7660[0])); + write_i2c_regvals(sd, sensor_ov7660[sd->gspca_dev.curr_mode], + ARRAY_SIZE(sensor_ov7660[0])); + write_i2c_regvals(sd, sensor_ov7660_2, + ARRAY_SIZE(sensor_ov7660_2)); +} + +/* set the frame rate */ +/* This function works for sensors ov7640, ov7648 ov7660 and ov7670 only */ +static void ov519_set_fr(struct sd *sd) +{ + int fr; + u8 clock; + /* frame rate table with indices: + * - mode = 0: 320x240, 1: 640x480 + * - fr rate = 0: 30, 1: 25, 2: 20, 3: 15, 4: 10, 5: 5 + * - reg = 0: bridge a4, 1: bridge 23, 2: sensor 11 (clock) + */ + static const u8 fr_tb[2][6][3] = { + {{0x04, 0xff, 0x00}, + {0x04, 0x1f, 0x00}, + {0x04, 0x1b, 0x00}, + {0x04, 0x15, 0x00}, + {0x04, 0x09, 0x00}, + {0x04, 0x01, 0x00}}, + {{0x0c, 0xff, 0x00}, + {0x0c, 0x1f, 0x00}, + {0x0c, 0x1b, 0x00}, + {0x04, 0xff, 0x01}, + {0x04, 0x1f, 0x01}, + {0x04, 0x1b, 0x01}}, + }; + + if (frame_rate > 0) + sd->frame_rate = frame_rate; + if (sd->frame_rate >= 30) + fr = 0; + else if (sd->frame_rate >= 25) + fr = 1; + else if (sd->frame_rate >= 20) + fr = 2; + else if (sd->frame_rate >= 15) + fr = 3; + else if (sd->frame_rate >= 10) + fr = 4; + else + fr = 5; + reg_w(sd, 0xa4, fr_tb[sd->gspca_dev.curr_mode][fr][0]); + reg_w(sd, 0x23, fr_tb[sd->gspca_dev.curr_mode][fr][1]); + clock = fr_tb[sd->gspca_dev.curr_mode][fr][2]; + if (sd->sensor == SEN_OV7660) + clock |= 0x80; /* enable double clock */ + ov518_i2c_w(sd, OV7670_R11_CLKRC, clock); +} + /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) @@ -3118,6 +3356,34 @@ static int sd_init(struct gspca_dev *gspca_dev) case SEN_OV7648: write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)); break; + case SEN_OV7660: + i2c_w(sd, OV7670_R12_COM7, OV7670_COM7_RESET); + msleep(14); + reg_w(sd, OV519_R57_SNAPSHOT, 0x23); + write_regvals(sd, init_519_ov7660, + ARRAY_SIZE(init_519_ov7660)); + write_i2c_regvals(sd, norm_7660, ARRAY_SIZE(norm_7660)); + sd->gspca_dev.curr_mode = 1; /* 640x480 */ + sd->frame_rate = 15; + ov519_set_mode(sd); + ov519_set_fr(sd); + sd->ctrls[COLORS].max = 4; /* 0..4 */ + sd->ctrls[COLORS].val = + sd->ctrls[COLORS].def = 2; + setcolors(gspca_dev); + sd->ctrls[CONTRAST].max = 6; /* 0..6 */ + sd->ctrls[CONTRAST].val = + sd->ctrls[CONTRAST].def = 3; + setcontrast(gspca_dev); + sd->ctrls[BRIGHTNESS].max = 6; /* 0..6 */ + sd->ctrls[BRIGHTNESS].val = + sd->ctrls[BRIGHTNESS].def = 3; + setbrightness(gspca_dev); + sd_reset_snapshot(gspca_dev); + ov51x_restart(sd); + ov51x_stop(sd); /* not in win traces */ + ov51x_led_control(sd, 0); + break; case SEN_OV7670: sd->ctrls[FREQ].max = 3; /* auto */ sd->ctrls[FREQ].def = 3; @@ -3431,16 +3697,21 @@ static void ov519_mode_init_regs(struct sd *sd) }; /******** Set the mode ********/ - if (sd->sensor != SEN_OV7670) { + switch (sd->sensor) { + default: write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519)); if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7648) { /* Select 8-bit input mode */ reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10); } - } else { + break; + case SEN_OV7660: + return; /* done by ov519_set_mode/fr() */ + case SEN_OV7670: write_regvals(sd, mode_init_519_ov7670, ARRAY_SIZE(mode_init_519_ov7670)); + break; } reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.width >> 4); @@ -3682,6 +3953,7 @@ static void mode_init_ov_sensor_regs(struct sd *sd) i2c_w(sd, 0x11, sd->clockdiv); } +/* this function works for bridge ov519 and sensors ov7660 and ov7670 only */ static void sethvflip(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -3703,11 +3975,18 @@ static void set_ov_sensor_window(struct sd *sd) int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; /* mode setup is fully handled in mode_init_ov_sensor_regs for these */ - if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610 || - sd->sensor == SEN_OV7670) { + switch (sd->sensor) { + case SEN_OV2610: + case SEN_OV3610: + case SEN_OV7670: mode_init_ov_sensor_regs(sd); return; + case SEN_OV7660: + ov519_set_mode(sd); + ov519_set_fr(sd); + return; } + gspca_dev = &sd->gspca_dev; qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1; crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2; @@ -4101,6 +4380,22 @@ static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int val; + static const struct ov_i2c_regvals brit_7660[][7] = { + {{0x0f, 0x6a}, {0x24, 0x40}, {0x25, 0x2b}, {0x26, 0x90}, + {0x27, 0xe0}, {0x28, 0xe0}, {0x2c, 0xe0}}, + {{0x0f, 0x6a}, {0x24, 0x50}, {0x25, 0x40}, {0x26, 0xa1}, + {0x27, 0xc0}, {0x28, 0xc0}, {0x2c, 0xc0}}, + {{0x0f, 0x6a}, {0x24, 0x68}, {0x25, 0x58}, {0x26, 0xc2}, + {0x27, 0xa0}, {0x28, 0xa0}, {0x2c, 0xa0}}, + {{0x0f, 0x6a}, {0x24, 0x70}, {0x25, 0x68}, {0x26, 0xd3}, + {0x27, 0x80}, {0x28, 0x80}, {0x2c, 0x80}}, + {{0x0f, 0x6a}, {0x24, 0x80}, {0x25, 0x70}, {0x26, 0xd3}, + {0x27, 0x20}, {0x28, 0x20}, {0x2c, 0x20}}, + {{0x0f, 0x6a}, {0x24, 0x88}, {0x25, 0x78}, {0x26, 0xd3}, + {0x27, 0x40}, {0x28, 0x40}, {0x2c, 0x40}}, + {{0x0f, 0x6a}, {0x24, 0x90}, {0x25, 0x80}, {0x26, 0xd4}, + {0x27, 0x60}, {0x28, 0x60}, {0x2c, 0x60}} + }; val = sd->ctrls[BRIGHTNESS].val; switch (sd->sensor) { @@ -4120,6 +4415,10 @@ static void setbrightness(struct gspca_dev *gspca_dev) if (!sd->ctrls[AUTOBRIGHT].val) i2c_w(sd, OV7610_REG_BRT, val); break; + case SEN_OV7660: + write_i2c_regvals(sd, brit_7660[val], + ARRAY_SIZE(brit_7660[0])); + break; case SEN_OV7670: /*win trace * i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_AEC); */ @@ -4132,6 +4431,64 @@ static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int val; + static const struct ov_i2c_regvals contrast_7660[][31] = { + {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0xa0}, + {0x70, 0x58}, {0x71, 0x38}, {0x72, 0x30}, {0x73, 0x30}, + {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x24}, {0x77, 0x24}, + {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x34}, + {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x65}, + {0x80, 0x70}, {0x81, 0x77}, {0x82, 0x7d}, {0x83, 0x83}, + {0x84, 0x88}, {0x85, 0x8d}, {0x86, 0x96}, {0x87, 0x9f}, + {0x88, 0xb0}, {0x89, 0xc4}, {0x8a, 0xd9}}, + {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0x94}, + {0x70, 0x58}, {0x71, 0x40}, {0x72, 0x30}, {0x73, 0x30}, + {0x74, 0x30}, {0x75, 0x30}, {0x76, 0x2c}, {0x77, 0x24}, + {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x31}, + {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x62}, + {0x80, 0x6d}, {0x81, 0x75}, {0x82, 0x7b}, {0x83, 0x81}, + {0x84, 0x87}, {0x85, 0x8d}, {0x86, 0x98}, {0x87, 0xa1}, + {0x88, 0xb2}, {0x89, 0xc6}, {0x8a, 0xdb}}, + {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x84}, + {0x70, 0x58}, {0x71, 0x48}, {0x72, 0x40}, {0x73, 0x40}, + {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x28}, {0x77, 0x24}, + {0x78, 0x26}, {0x79, 0x28}, {0x7a, 0x28}, {0x7b, 0x34}, + {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x5d}, + {0x80, 0x68}, {0x81, 0x71}, {0x82, 0x79}, {0x83, 0x81}, + {0x84, 0x86}, {0x85, 0x8b}, {0x86, 0x95}, {0x87, 0x9e}, + {0x88, 0xb1}, {0x89, 0xc5}, {0x8a, 0xd9}}, + {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x70}, + {0x70, 0x58}, {0x71, 0x58}, {0x72, 0x48}, {0x73, 0x48}, + {0x74, 0x38}, {0x75, 0x40}, {0x76, 0x34}, {0x77, 0x34}, + {0x78, 0x2e}, {0x79, 0x28}, {0x7a, 0x24}, {0x7b, 0x22}, + {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x58}, + {0x80, 0x63}, {0x81, 0x6e}, {0x82, 0x77}, {0x83, 0x80}, + {0x84, 0x87}, {0x85, 0x8f}, {0x86, 0x9c}, {0x87, 0xa9}, + {0x88, 0xc0}, {0x89, 0xd4}, {0x8a, 0xe6}}, + {{0x6c, 0xa0}, {0x6d, 0xf0}, {0x6e, 0x90}, {0x6f, 0x80}, + {0x70, 0x70}, {0x71, 0x80}, {0x72, 0x60}, {0x73, 0x60}, + {0x74, 0x58}, {0x75, 0x60}, {0x76, 0x4c}, {0x77, 0x38}, + {0x78, 0x38}, {0x79, 0x2a}, {0x7a, 0x20}, {0x7b, 0x0e}, + {0x7c, 0x0a}, {0x7d, 0x14}, {0x7e, 0x26}, {0x7f, 0x46}, + {0x80, 0x54}, {0x81, 0x64}, {0x82, 0x70}, {0x83, 0x7c}, + {0x84, 0x87}, {0x85, 0x93}, {0x86, 0xa6}, {0x87, 0xb4}, + {0x88, 0xd0}, {0x89, 0xe5}, {0x8a, 0xf5}}, + {{0x6c, 0x60}, {0x6d, 0x80}, {0x6e, 0x60}, {0x6f, 0x80}, + {0x70, 0x80}, {0x71, 0x80}, {0x72, 0x88}, {0x73, 0x30}, + {0x74, 0x70}, {0x75, 0x68}, {0x76, 0x64}, {0x77, 0x50}, + {0x78, 0x3c}, {0x79, 0x22}, {0x7a, 0x10}, {0x7b, 0x08}, + {0x7c, 0x06}, {0x7d, 0x0e}, {0x7e, 0x1a}, {0x7f, 0x3a}, + {0x80, 0x4a}, {0x81, 0x5a}, {0x82, 0x6b}, {0x83, 0x7b}, + {0x84, 0x89}, {0x85, 0x96}, {0x86, 0xaf}, {0x87, 0xc3}, + {0x88, 0xe1}, {0x89, 0xf2}, {0x8a, 0xfa}}, + {{0x6c, 0x20}, {0x6d, 0x40}, {0x6e, 0x20}, {0x6f, 0x60}, + {0x70, 0x88}, {0x71, 0xc8}, {0x72, 0xc0}, {0x73, 0xb8}, + {0x74, 0xa8}, {0x75, 0xb8}, {0x76, 0x80}, {0x77, 0x5c}, + {0x78, 0x26}, {0x79, 0x10}, {0x7a, 0x08}, {0x7b, 0x04}, + {0x7c, 0x02}, {0x7d, 0x06}, {0x7e, 0x0a}, {0x7f, 0x22}, + {0x80, 0x33}, {0x81, 0x4c}, {0x82, 0x64}, {0x83, 0x7b}, + {0x84, 0x90}, {0x85, 0xa7}, {0x86, 0xc7}, {0x87, 0xde}, + {0x88, 0xf1}, {0x89, 0xf9}, {0x8a, 0xfd}}, + }; val = sd->ctrls[CONTRAST].val; switch (sd->sensor) { @@ -4163,6 +4520,10 @@ static void setcontrast(struct gspca_dev *gspca_dev) i2c_w(sd, 0x64, ctab[val >> 4]); break; } + case SEN_OV7660: + write_i2c_regvals(sd, contrast_7660[val], + ARRAY_SIZE(contrast_7660[0])); + break; case SEN_OV7670: /* check that this isn't just the same as ov7610 */ i2c_w(sd, OV7670_R56_CONTRAS, val >> 1); @@ -4174,6 +4535,18 @@ static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int val; + static const struct ov_i2c_regvals colors_7660[][6] = { + {{0x4f, 0x28}, {0x50, 0x2a}, {0x51, 0x02}, {0x52, 0x0a}, + {0x53, 0x19}, {0x54, 0x23}}, + {{0x4f, 0x47}, {0x50, 0x4a}, {0x51, 0x03}, {0x52, 0x11}, + {0x53, 0x2c}, {0x54, 0x3e}}, + {{0x4f, 0x66}, {0x50, 0x6b}, {0x51, 0x05}, {0x52, 0x19}, + {0x53, 0x40}, {0x54, 0x59}}, + {{0x4f, 0x84}, {0x50, 0x8b}, {0x51, 0x06}, {0x52, 0x20}, + {0x53, 0x53}, {0x54, 0x73}}, + {{0x4f, 0xa3}, {0x50, 0xab}, {0x51, 0x08}, {0x52, 0x28}, + {0x53, 0x66}, {0x54, 0x8e}}, + }; val = sd->ctrls[COLORS].val; switch (sd->sensor) { @@ -4197,6 +4570,10 @@ static void setcolors(struct gspca_dev *gspca_dev) case SEN_OV7648: i2c_w(sd, OV7610_REG_SAT, val & 0xf0); break; + case SEN_OV7660: + write_i2c_regvals(sd, colors_7660[val], + ARRAY_SIZE(colors_7660[0])); + break; case SEN_OV7670: /* supported later once I work out how to do it * transparently fail now! */ @@ -4214,7 +4591,8 @@ static void setautobright(struct gspca_dev *gspca_dev) static void setfreq_i(struct sd *sd) { - if (sd->sensor == SEN_OV7670) { + if (sd->sensor == SEN_OV7660 + || sd->sensor == SEN_OV7670) { switch (sd->ctrls[FREQ].val) { case 0: /* Banding filter disabled */ i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_BFILT); -- cgit v0.10.2 From 101b25b55ec48354bc40b9102b4f7922c9ad9eae Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 5 Nov 2010 00:07:39 -0300 Subject: [media] drivers/media: Use vzalloc Signed-off-by: Joe Perches Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index 3a7ef71..c7809f7 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -1536,12 +1536,11 @@ int __devinit ngene_probe(struct pci_dev *pci_dev, if (pci_enable_device(pci_dev) < 0) return -ENODEV; - dev = vmalloc(sizeof(struct ngene)); + dev = vzalloc(sizeof(struct ngene)); if (dev == NULL) { stat = -ENOMEM; goto fail0; } - memset(dev, 0, sizeof(struct ngene)); dev->pci_dev = pci_dev; dev->card_info = (struct ngene_info *)id->driver_data; diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index aa871c2..330d42e 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c @@ -1186,13 +1186,12 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev) goto egetres; } - mx3_cam = vmalloc(sizeof(*mx3_cam)); + mx3_cam = vzalloc(sizeof(*mx3_cam)); if (!mx3_cam) { dev_err(&pdev->dev, "Could not allocate mx3 camera object\n"); err = -ENOMEM; goto ealloc; } - memset(mx3_cam, 0, sizeof(*mx3_cam)); mx3_cam->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(mx3_cam->clk)) { diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index f3dc89d..b821065 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -287,14 +287,13 @@ static int pwc_allocate_buffers(struct pwc_device *pdev) /* create frame buffers, and make circular ring */ for (i = 0; i < default_fbufs; i++) { if (pdev->fbuf[i].data == NULL) { - kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */ + kbuf = vzalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */ if (kbuf == NULL) { PWC_ERROR("Failed to allocate frame buffer %d.\n", i); return -ENOMEM; } PWC_DEBUG_MEMORY("Allocated frame buffer %d at %p.\n", i, kbuf); pdev->fbuf[i].data = kbuf; - memset(kbuf, 0, PWC_FRAME_SIZE); } } diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 20f227e..ab684e8 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -69,10 +69,9 @@ static struct scatterlist *videobuf_vmalloc_to_sg(unsigned char *virt, struct page *pg; int i; - sglist = vmalloc(nr_pages * sizeof(*sglist)); + sglist = vzalloc(nr_pages * sizeof(*sglist)); if (NULL == sglist) return NULL; - memset(sglist, 0, nr_pages * sizeof(*sglist)); sg_init_table(sglist, nr_pages); for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) { pg = vmalloc_to_page(virt); -- cgit v0.10.2 From c1937f8e3490fedec2c75383df07cd8a7154c545 Mon Sep 17 00:00:00 2001 From: Stefan Ringel Date: Tue, 9 Nov 2010 13:50:28 -0300 Subject: [media] tm6000: add revision check adding chip revision check Signed-off-by: Stefan Ringel Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c index b143258..5a7946c 100644 --- a/drivers/staging/tm6000/tm6000-cards.c +++ b/drivers/staging/tm6000/tm6000-cards.c @@ -521,13 +521,6 @@ int tm6000_cards_setup(struct tm6000_core *dev) printk(KERN_ERR "Error %i doing tuner reset\n", rc); return rc; } - msleep(10); - - if (!i) { - rc = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0); - if (rc >= 0) - printk(KERN_DEBUG "board=0x%08x\n", rc); - } } } else { printk(KERN_ERR "Tuner reset is not configured\n"); diff --git a/drivers/staging/tm6000/tm6000-core.c b/drivers/staging/tm6000/tm6000-core.c index 40a0206..8c897d7 100644 --- a/drivers/staging/tm6000/tm6000-core.c +++ b/drivers/staging/tm6000/tm6000-core.c @@ -542,6 +542,26 @@ int tm6000_init(struct tm6000_core *dev) int board, rc = 0, i, size; struct reg_init *tab; + /* Check board revision */ + board = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0); + if (board >= 0) { + switch (board & 0xff) { + case 0xf3: + printk(KERN_INFO "Found tm6000\n"); + if (dev->dev_type != TM6000) + dev->dev_type = TM6000; + break; + case 0xf4: + printk(KERN_INFO "Found tm6010\n"); + if (dev->dev_type != TM6010) + dev->dev_type = TM6010; + break; + default: + printk(KERN_INFO "Unknown board version = 0x%08x\n", board); + } + } else + printk(KERN_ERR "Error %i while retrieving board version\n", board); + if (dev->dev_type == TM6010) { tab = tm6010_init_tab; size = ARRAY_SIZE(tm6010_init_tab); @@ -563,13 +583,6 @@ int tm6000_init(struct tm6000_core *dev) msleep(5); /* Just to be conservative */ - /* Check board version - maybe 10Moons specific */ - board = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0); - if (board >= 0) - printk(KERN_INFO "Board version = 0x%08x\n", board); - else - printk(KERN_ERR "Error %i while retrieving board version\n", board); - rc = tm6000_cards_setup(dev); return rc; -- cgit v0.10.2 From 70de39183a8b5ba0a0cd884ff46c1d81dbe939db Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 13 Nov 2010 16:23:06 -0300 Subject: [media] saa7134: use rc-core raw decoders for Encore FM 5.3 Acked-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index fbb2ff1..4878f46 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -767,9 +767,10 @@ int saa7134_input_init1(struct saa7134_dev *dev) break; case SAA7134_BOARD_ENCORE_ENLTV_FM53: ir_codes = RC_MAP_ENCORE_ENLTV_FM53; - mask_keydown = 0x0040000; - mask_keycode = 0x00007f; - nec_gpio = 1; + mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ + mask_keyup = 0x0040000; + mask_keycode = 0xffff; + raw_decode = 1; break; case SAA7134_BOARD_10MOONSTVMASTER3: ir_codes = RC_MAP_ENCORE_ENLTV; -- cgit v0.10.2 From 6c7e653ff668d939174aa7023736f4a40fd2be08 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 13 Nov 2010 16:19:54 -0300 Subject: [media] saa7134: Remove legacy IR decoding logic inside the module The only IR left still using the old raw decoders on saa7134 is ENCORE FM 5.3. As it is now using the standard rc-core raw decoders, lots of old code can be removed from saa7134. Acked-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 4878f46..72562b8 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -54,11 +54,8 @@ MODULE_PARM_DESC(disable_other_ir, "disable full codes of " #define i2cdprintk(fmt, arg...) if (ir_debug) \ printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg) -/* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */ -static int saa7134_rc5_irq(struct saa7134_dev *dev); -static int saa7134_nec_irq(struct saa7134_dev *dev); +/* Helper function for raw decoding at GPIO16 or GPIO18 */ static int saa7134_raw_decode_irq(struct saa7134_dev *dev); -static void nec_task(unsigned long data); /* -------------------- GPIO generic keycode builder -------------------- */ @@ -397,12 +394,8 @@ void saa7134_input_irq(struct saa7134_dev *dev) if (!ir->running) return; - if (ir->nec_gpio) { - saa7134_nec_irq(dev); - } else if (!ir->polling && !ir->rc5_gpio && !ir->raw_decode) { + if (!ir->polling && !ir->raw_decode) { build_key(dev); - } else if (ir->rc5_gpio) { - saa7134_rc5_irq(dev); } else if (ir->raw_decode) { saa7134_raw_decode_irq(dev); } @@ -448,17 +441,6 @@ static int __saa7134_ir_start(void *priv) (unsigned long)dev); ir->timer.expires = jiffies + HZ; add_timer(&ir->timer); - } else if (ir->rc5_gpio) { - /* set timer_end for code completion */ - init_timer(&ir->timer_end); - ir->timer_end.function = ir_rc5_timer_end; - ir->timer_end.data = (unsigned long)ir; - ir->shift_by = 2; - ir->start = 0x2; - ir->addr = 0x17; - ir->rc5_remote_gap = ir_rc5_remote_gap; - } else if (ir->nec_gpio) { - tasklet_init(&ir->tlet, nec_task, (unsigned long)dev); } else if (ir->raw_decode) { /* set timer_end for code completion */ init_timer(&ir->timer_end); @@ -486,10 +468,6 @@ static void __saa7134_ir_stop(void *priv) return; if (dev->remote->polling) del_timer_sync(&dev->remote->timer); - else if (ir->rc5_gpio) - del_timer_sync(&ir->timer_end); - else if (ir->nec_gpio) - tasklet_kill(&ir->tlet); else if (ir->raw_decode) { del_timer_sync(&ir->timer_end); ir->active = 0; @@ -531,40 +509,6 @@ static void saa7134_ir_close(struct rc_dev *rc) __saa7134_ir_stop(dev); } - -static int saa7134_ir_change_protocol(struct rc_dev *rc, u64 ir_type) -{ - struct saa7134_dev *dev = rc->priv; - struct card_ir *ir = dev->remote; - u32 nec_gpio, rc5_gpio; - - if (ir_type == IR_TYPE_RC5) { - dprintk("Changing protocol to RC5\n"); - nec_gpio = 0; - rc5_gpio = 1; - } else if (ir_type == IR_TYPE_NEC) { - dprintk("Changing protocol to NEC\n"); - nec_gpio = 1; - rc5_gpio = 0; - } else { - dprintk("IR protocol type %ud is not supported\n", - (unsigned)ir_type); - return -EINVAL; - } - - if (ir->running) { - saa7134_ir_stop(dev); - ir->nec_gpio = nec_gpio; - ir->rc5_gpio = rc5_gpio; - saa7134_ir_start(dev); - } else { - ir->nec_gpio = nec_gpio; - ir->rc5_gpio = rc5_gpio; - } - - return 0; -} - int saa7134_input_init1(struct saa7134_dev *dev) { struct card_ir *ir; @@ -574,10 +518,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) u32 mask_keydown = 0; u32 mask_keyup = 0; int polling = 0; - int rc5_gpio = 0; - int nec_gpio = 0; int raw_decode = 0; - int allow_protocol_change = 0; int err; if (dev->has_remote != SAA7134_REMOTE_GPIO) @@ -830,8 +771,6 @@ int saa7134_input_init1(struct saa7134_dev *dev) ir->mask_keydown = mask_keydown; ir->mask_keyup = mask_keyup; ir->polling = polling; - ir->rc5_gpio = rc5_gpio; - ir->nec_gpio = nec_gpio; ir->raw_decode = raw_decode; /* init input device */ @@ -846,11 +785,6 @@ int saa7134_input_init1(struct saa7134_dev *dev) if (raw_decode) rc->driver_type = RC_DRIVER_IR_RAW; - if (!raw_decode && allow_protocol_change) { - rc->allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; - rc->change_protocol = saa7134_ir_change_protocol; - } - rc->input_name = ir->name; rc->input_phys = ir->phys; rc->input_id.bustype = BUS_PCI; @@ -1024,152 +958,3 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev) return 1; } - -static int saa7134_rc5_irq(struct saa7134_dev *dev) -{ - struct card_ir *ir = dev->remote; - struct timeval tv; - u32 gap; - unsigned long current_jiffies, timeout; - - /* get time of bit */ - current_jiffies = jiffies; - do_gettimeofday(&tv); - - /* avoid overflow with gap >1s */ - if (tv.tv_sec - ir->base_time.tv_sec > 1) { - gap = 200000; - } else { - gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + - tv.tv_usec - ir->base_time.tv_usec; - } - - /* active code => add bit */ - if (ir->active) { - /* only if in the code (otherwise spurious IRQ or timer - late) */ - if (ir->last_bit < 28) { - ir->last_bit = (gap - ir_rc5_remote_gap / 2) / - ir_rc5_remote_gap; - ir->code |= 1 << ir->last_bit; - } - /* starting new code */ - } else { - ir->active = 1; - ir->code = 0; - ir->base_time = tv; - ir->last_bit = 0; - - timeout = current_jiffies + (500 + 30 * HZ) / 1000; - mod_timer(&ir->timer_end, timeout); - } - - return 1; -} - -static void nec_task(unsigned long data) -{ - struct saa7134_dev *dev = (struct saa7134_dev *) data; - struct card_ir *ir; - struct timeval tv; - int count, pulse, oldpulse, gap; - u32 ircode = 0, not_code = 0; - int ngap = 0; - - if (!data) { - printk(KERN_ERR "saa713x/ir: Can't recover dev struct\n"); - /* GPIO will be kept disabled */ - return; - } - - ir = dev->remote; - - /* rising SAA7134_GPIO_GPRESCAN reads the status */ - saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - - oldpulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; - pulse = oldpulse; - - do_gettimeofday(&tv); - ir->base_time = tv; - - /* Decode NEC pulsecode. This code can take up to 76.5 ms to run. - Unfortunately, using IRQ to decode pulse didn't work, since it uses - a pulse train of 38KHz. This means one pulse on each 52 us - */ - do { - /* Wait until the end of pulse/space or 5 ms */ - for (count = 0; count < 500; count++) { - udelay(10); - /* rising SAA7134_GPIO_GPRESCAN reads the status */ - saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) - & ir->mask_keydown; - if (pulse != oldpulse) - break; - } - - do_gettimeofday(&tv); - gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + - tv.tv_usec - ir->base_time.tv_usec; - - if (!pulse) { - /* Bit 0 has 560 us, while bit 1 has 1120 us. - Do something only if bit == 1 - */ - if (ngap && (gap > 560 + 280)) { - unsigned int shift = ngap - 1; - - /* Address first, then command */ - if (shift < 8) { - shift += 8; - ircode |= 1 << shift; - } else if (shift < 16) { - not_code |= 1 << shift; - } else if (shift < 24) { - shift -= 16; - ircode |= 1 << shift; - } else { - shift -= 24; - not_code |= 1 << shift; - } - } - ngap++; - } - - - ir->base_time = tv; - - /* TIMEOUT - Long pulse */ - if (gap >= 5000) - break; - oldpulse = pulse; - } while (ngap < 32); - - if (ngap == 32) { - /* FIXME: should check if not_code == ~ircode */ - ir->code = ir_extract_bits(ircode, ir->mask_keycode); - - dprintk("scancode = 0x%02x (code = 0x%02x, notcode= 0x%02x)\n", - ir->code, ircode, not_code); - - ir_keydown(ir->dev, ir->code, 0); - } else { - dprintk("Repeat last key\n"); - ir_repeat(ir->dev); - } - - saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P); -} - -static int saa7134_nec_irq(struct saa7134_dev *dev) -{ - struct card_ir *ir = dev->remote; - - saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P); - tasklet_schedule(&ir->tlet); - - return 1; -} diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 4e37b8b..a6c726f 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v0.10.2 From 8ea43d0a2f87b8460f46ddb7b42b5eb17c5385d2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 13 Nov 2010 16:49:10 -0300 Subject: [media] rc: Remove ir-common module Now, just one old bttv board uses the old RC5 raw decoding routines. Its conversion to rc-core requires the generation of IRQ data for both positive and negative transitions at the IRQ line. I'm not sure if bttv driver supports it or if the transitions will be reliable enough. So, due to the lack of hardware for testing, the better for now is to just move the legacy routines to bttv driver, and wait for someone with a Nebula Digi could help to port it to use also rc-core raw decoders. Acked-by: Hermann Pitton Acked-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 72562b8..fbb2ff1 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -54,8 +54,11 @@ MODULE_PARM_DESC(disable_other_ir, "disable full codes of " #define i2cdprintk(fmt, arg...) if (ir_debug) \ printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg) -/* Helper function for raw decoding at GPIO16 or GPIO18 */ +/* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */ +static int saa7134_rc5_irq(struct saa7134_dev *dev); +static int saa7134_nec_irq(struct saa7134_dev *dev); static int saa7134_raw_decode_irq(struct saa7134_dev *dev); +static void nec_task(unsigned long data); /* -------------------- GPIO generic keycode builder -------------------- */ @@ -394,8 +397,12 @@ void saa7134_input_irq(struct saa7134_dev *dev) if (!ir->running) return; - if (!ir->polling && !ir->raw_decode) { + if (ir->nec_gpio) { + saa7134_nec_irq(dev); + } else if (!ir->polling && !ir->rc5_gpio && !ir->raw_decode) { build_key(dev); + } else if (ir->rc5_gpio) { + saa7134_rc5_irq(dev); } else if (ir->raw_decode) { saa7134_raw_decode_irq(dev); } @@ -441,6 +448,17 @@ static int __saa7134_ir_start(void *priv) (unsigned long)dev); ir->timer.expires = jiffies + HZ; add_timer(&ir->timer); + } else if (ir->rc5_gpio) { + /* set timer_end for code completion */ + init_timer(&ir->timer_end); + ir->timer_end.function = ir_rc5_timer_end; + ir->timer_end.data = (unsigned long)ir; + ir->shift_by = 2; + ir->start = 0x2; + ir->addr = 0x17; + ir->rc5_remote_gap = ir_rc5_remote_gap; + } else if (ir->nec_gpio) { + tasklet_init(&ir->tlet, nec_task, (unsigned long)dev); } else if (ir->raw_decode) { /* set timer_end for code completion */ init_timer(&ir->timer_end); @@ -468,6 +486,10 @@ static void __saa7134_ir_stop(void *priv) return; if (dev->remote->polling) del_timer_sync(&dev->remote->timer); + else if (ir->rc5_gpio) + del_timer_sync(&ir->timer_end); + else if (ir->nec_gpio) + tasklet_kill(&ir->tlet); else if (ir->raw_decode) { del_timer_sync(&ir->timer_end); ir->active = 0; @@ -509,6 +531,40 @@ static void saa7134_ir_close(struct rc_dev *rc) __saa7134_ir_stop(dev); } + +static int saa7134_ir_change_protocol(struct rc_dev *rc, u64 ir_type) +{ + struct saa7134_dev *dev = rc->priv; + struct card_ir *ir = dev->remote; + u32 nec_gpio, rc5_gpio; + + if (ir_type == IR_TYPE_RC5) { + dprintk("Changing protocol to RC5\n"); + nec_gpio = 0; + rc5_gpio = 1; + } else if (ir_type == IR_TYPE_NEC) { + dprintk("Changing protocol to NEC\n"); + nec_gpio = 1; + rc5_gpio = 0; + } else { + dprintk("IR protocol type %ud is not supported\n", + (unsigned)ir_type); + return -EINVAL; + } + + if (ir->running) { + saa7134_ir_stop(dev); + ir->nec_gpio = nec_gpio; + ir->rc5_gpio = rc5_gpio; + saa7134_ir_start(dev); + } else { + ir->nec_gpio = nec_gpio; + ir->rc5_gpio = rc5_gpio; + } + + return 0; +} + int saa7134_input_init1(struct saa7134_dev *dev) { struct card_ir *ir; @@ -518,7 +574,10 @@ int saa7134_input_init1(struct saa7134_dev *dev) u32 mask_keydown = 0; u32 mask_keyup = 0; int polling = 0; + int rc5_gpio = 0; + int nec_gpio = 0; int raw_decode = 0; + int allow_protocol_change = 0; int err; if (dev->has_remote != SAA7134_REMOTE_GPIO) @@ -708,10 +767,9 @@ int saa7134_input_init1(struct saa7134_dev *dev) break; case SAA7134_BOARD_ENCORE_ENLTV_FM53: ir_codes = RC_MAP_ENCORE_ENLTV_FM53; - mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ - mask_keyup = 0x0040000; - mask_keycode = 0xffff; - raw_decode = 1; + mask_keydown = 0x0040000; + mask_keycode = 0x00007f; + nec_gpio = 1; break; case SAA7134_BOARD_10MOONSTVMASTER3: ir_codes = RC_MAP_ENCORE_ENLTV; @@ -771,6 +829,8 @@ int saa7134_input_init1(struct saa7134_dev *dev) ir->mask_keydown = mask_keydown; ir->mask_keyup = mask_keyup; ir->polling = polling; + ir->rc5_gpio = rc5_gpio; + ir->nec_gpio = nec_gpio; ir->raw_decode = raw_decode; /* init input device */ @@ -785,6 +845,11 @@ int saa7134_input_init1(struct saa7134_dev *dev) if (raw_decode) rc->driver_type = RC_DRIVER_IR_RAW; + if (!raw_decode && allow_protocol_change) { + rc->allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; + rc->change_protocol = saa7134_ir_change_protocol; + } + rc->input_name = ir->name; rc->input_phys = ir->phys; rc->input_id.bustype = BUS_PCI; @@ -958,3 +1023,152 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev) return 1; } + +static int saa7134_rc5_irq(struct saa7134_dev *dev) +{ + struct card_ir *ir = dev->remote; + struct timeval tv; + u32 gap; + unsigned long current_jiffies, timeout; + + /* get time of bit */ + current_jiffies = jiffies; + do_gettimeofday(&tv); + + /* avoid overflow with gap >1s */ + if (tv.tv_sec - ir->base_time.tv_sec > 1) { + gap = 200000; + } else { + gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + + tv.tv_usec - ir->base_time.tv_usec; + } + + /* active code => add bit */ + if (ir->active) { + /* only if in the code (otherwise spurious IRQ or timer + late) */ + if (ir->last_bit < 28) { + ir->last_bit = (gap - ir_rc5_remote_gap / 2) / + ir_rc5_remote_gap; + ir->code |= 1 << ir->last_bit; + } + /* starting new code */ + } else { + ir->active = 1; + ir->code = 0; + ir->base_time = tv; + ir->last_bit = 0; + + timeout = current_jiffies + (500 + 30 * HZ) / 1000; + mod_timer(&ir->timer_end, timeout); + } + + return 1; +} + +static void nec_task(unsigned long data) +{ + struct saa7134_dev *dev = (struct saa7134_dev *) data; + struct card_ir *ir; + struct timeval tv; + int count, pulse, oldpulse, gap; + u32 ircode = 0, not_code = 0; + int ngap = 0; + + if (!data) { + printk(KERN_ERR "saa713x/ir: Can't recover dev struct\n"); + /* GPIO will be kept disabled */ + return; + } + + ir = dev->remote; + + /* rising SAA7134_GPIO_GPRESCAN reads the status */ + saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + + oldpulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; + pulse = oldpulse; + + do_gettimeofday(&tv); + ir->base_time = tv; + + /* Decode NEC pulsecode. This code can take up to 76.5 ms to run. + Unfortunately, using IRQ to decode pulse didn't work, since it uses + a pulse train of 38KHz. This means one pulse on each 52 us + */ + do { + /* Wait until the end of pulse/space or 5 ms */ + for (count = 0; count < 500; count++) { + udelay(10); + /* rising SAA7134_GPIO_GPRESCAN reads the status */ + saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) + & ir->mask_keydown; + if (pulse != oldpulse) + break; + } + + do_gettimeofday(&tv); + gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + + tv.tv_usec - ir->base_time.tv_usec; + + if (!pulse) { + /* Bit 0 has 560 us, while bit 1 has 1120 us. + Do something only if bit == 1 + */ + if (ngap && (gap > 560 + 280)) { + unsigned int shift = ngap - 1; + + /* Address first, then command */ + if (shift < 8) { + shift += 8; + ircode |= 1 << shift; + } else if (shift < 16) { + not_code |= 1 << shift; + } else if (shift < 24) { + shift -= 16; + ircode |= 1 << shift; + } else { + shift -= 24; + not_code |= 1 << shift; + } + } + ngap++; + } + + + ir->base_time = tv; + + /* TIMEOUT - Long pulse */ + if (gap >= 5000) + break; + oldpulse = pulse; + } while (ngap < 32); + + if (ngap == 32) { + /* FIXME: should check if not_code == ~ircode */ + ir->code = ir_extract_bits(ircode, ir->mask_keycode); + + dprintk("scancode = 0x%02x (code = 0x%02x, notcode= 0x%02x)\n", + ir->code, ircode, not_code); + + ir_keydown(ir->dev, ir->code, 0); + } else { + dprintk("Repeat last key\n"); + ir_repeat(ir->dev); + } + + saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P); +} + +static int saa7134_nec_irq(struct saa7134_dev *dev) +{ + struct card_ir *ir = dev->remote; + + saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P); + tasklet_schedule(&ir->tlet); + + return 1; +} diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index a6c726f..4e37b8b 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v0.10.2 From 7bd444ede7285cad4ed5047ff954432325fe7f95 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 7 Nov 2010 12:53:44 -0300 Subject: [media] TM6000: Clean-up i2c initialization Usage of templates for large structures is a bad idea, as it wastes a lot of space. Manually initializing the few fields we need is way more efficient. Also set the algorithm data const, use strlcpy instead of strcpy, fix a small race (device data must always be set before registering said device) and properly return error on adapter registration failure. Signed-off-by: Jean Delvare Cc: Michel Ludwig Cc: Stefan Ringel Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/tm6000/tm6000-i2c.c b/drivers/staging/tm6000/tm6000-i2c.c index 93f625f..798087e 100644 --- a/drivers/staging/tm6000/tm6000-i2c.c +++ b/drivers/staging/tm6000/tm6000-i2c.c @@ -313,21 +313,11 @@ static u32 functionality(struct i2c_adapter *adap) msleep(10); \ } -static struct i2c_algorithm tm6000_algo = { +static const struct i2c_algorithm tm6000_algo = { .master_xfer = tm6000_i2c_xfer, .functionality = functionality, }; -static struct i2c_adapter tm6000_adap_template = { - .owner = THIS_MODULE, - .name = "tm6000", - .algo = &tm6000_algo, -}; - -static struct i2c_client tm6000_client_template = { - .name = "tm6000 internal", -}; - /* ----------------------------------------------------------- */ /* @@ -337,17 +327,20 @@ static struct i2c_client tm6000_client_template = { int tm6000_i2c_register(struct tm6000_core *dev) { unsigned char eedata[256]; + int rc; - dev->i2c_adap = tm6000_adap_template; + dev->i2c_adap.owner = THIS_MODULE; + dev->i2c_adap.algo = &tm6000_algo; dev->i2c_adap.dev.parent = &dev->udev->dev; - strcpy(dev->i2c_adap.name, dev->name); + strlcpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name)); dev->i2c_adap.algo_data = dev; - i2c_add_adapter(&dev->i2c_adap); + i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); + rc = i2c_add_adapter(&dev->i2c_adap); + if (rc) + return rc; - dev->i2c_client = tm6000_client_template; dev->i2c_client.adapter = &dev->i2c_adap; - - i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); + strlcpy(dev->i2c_client.name, "tm6000 internal", I2C_NAME_SIZE); tm6000_i2c_eeprom(dev, eedata, sizeof(eedata)); -- cgit v0.10.2 From 62c7cdd8a16025e4d5596b8e61352960745f3707 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 7 Nov 2010 12:54:39 -0300 Subject: [media] TM6000: Drop unused macro Signed-off-by: Jean Delvare Cc: Michel Ludwig Cc: Stefan Ringel Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/tm6000/tm6000-i2c.c b/drivers/staging/tm6000/tm6000-i2c.c index 798087e..18de474 100644 --- a/drivers/staging/tm6000/tm6000-i2c.c +++ b/drivers/staging/tm6000/tm6000-i2c.c @@ -301,18 +301,6 @@ static u32 functionality(struct i2c_adapter *adap) return I2C_FUNC_SMBUS_EMUL; } -#define mass_write(addr, reg, data...) \ - { static const u8 _val[] = data; \ - rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR, \ - REQ_16_SET_GET_I2C_WR1_RDN, (reg<<8)+addr, 0x00, (u8 *) _val, \ - ARRAY_SIZE(_val)); \ - if (rc < 0) { \ - printk(KERN_ERR "Error on line %d: %d\n", __LINE__, rc); \ - return rc; \ - } \ - msleep(10); \ - } - static const struct i2c_algorithm tm6000_algo = { .master_xfer = tm6000_i2c_xfer, .functionality = functionality, -- cgit v0.10.2 From 13d28e4917fb6cf6898e8998f01ab83b3f468aeb Mon Sep 17 00:00:00 2001 From: Matthias Schwarzott Date: Sun, 7 Nov 2010 10:57:13 -0300 Subject: [media] IX2505V: i2c transfer error code ignored It seems that ix2505v driver ignores a i2c error in ix2505v_read_status_reg. This looks like a typing error using (ret = 1) instead of correct (ret == 1). Acked-by: Malcolm Priestley Signed-off-by: Matthias Schwarzott Cc: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/ix2505v.c b/drivers/media/dvb/frontends/ix2505v.c index 55f2eba..6360c68 100644 --- a/drivers/media/dvb/frontends/ix2505v.c +++ b/drivers/media/dvb/frontends/ix2505v.c @@ -72,7 +72,7 @@ static int ix2505v_read_status_reg(struct ix2505v_state *state) ret = i2c_transfer(state->i2c, msg, 1); deb_i2c("Read %s ", __func__); - return (ret = 1) ? (int) b2[0] : -1; + return (ret == 1) ? (int) b2[0] : -1; } static int ix2505v_write(struct ix2505v_state *state, u8 buf[], u8 count) -- cgit v0.10.2 From 36d89f7de4a4937848de86d9b35cb03a9f0357e1 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 7 Nov 2010 17:48:21 -0300 Subject: [media] drivers/staging/cx25821: Use pr_fmt and pr_ Fix several defects with bad line continuation uses that introduce whitespace. Fix several defects with lines missing "\n". Standardize prefixes via pr_fmt. Remove internal cx25821 prefixes. Standardize :%s():" ... __func__ uses. Coalesce long formats. Add KERN_ prefixes via pr_ to printks. Signed-off-by: Joe Perches Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/cx25821/cx25821-alsa.c b/drivers/staging/cx25821/cx25821-alsa.c index 2a01dc0..9a205a3 100644 --- a/drivers/staging/cx25821/cx25821-alsa.c +++ b/drivers/staging/cx25821/cx25821-alsa.c @@ -20,6 +20,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -42,11 +44,16 @@ #define AUDIO_SRAM_CHANNEL SRAM_CH08 -#define dprintk(level, fmt, arg...) if (debug >= level) \ - printk(KERN_INFO "%s/1: " fmt, chip->dev->name , ## arg) - -#define dprintk_core(level, fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name , ## arg) +#define dprintk(level, fmt, arg...) \ +do { \ + if (debug >= level) \ + pr_info("%s/1: " fmt, chip->dev->name, ##arg); \ +} while (0) +#define dprintk_core(level, fmt, arg...) \ +do { \ + if (debug >= level) \ + printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name, ##arg); \ +} while (0) /**************************************************************************** Data type declarations - Can be moded to a header file later @@ -173,12 +180,11 @@ static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip) tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE | FLD_AUD_CLK_ENABLE); - /* printk(KERN_INFO "DEBUG: Start audio DMA, %d B/line," - "cmds_start(0x%x)= %d lines/FIFO, %d periods, " - "%d byte buffer\n", buf->bpl, - audio_ch->cmds_start, - cx_read(audio_ch->cmds_start + 12)>>1, - chip->num_periods, buf->bpl *chip->num_periods); + /* + pr_info("DEBUG: Start audio DMA, %d B/line, cmds_start(0x%x)= %d lines/FIFO, %d periods, %d byte buffer\n", + buf->bpl, audio_ch->cmds_start, + cx_read(audio_ch->cmds_start + 12)>>1, + chip->num_periods, buf->bpl * chip->num_periods); */ /* Enables corresponding bits at AUD_INT_STAT */ @@ -259,8 +265,7 @@ static void cx25821_aud_irq(struct cx25821_audio_dev *chip, u32 status, /* risc op code error */ if (status & AUD_INT_OPC_ERR) { - printk(KERN_WARNING "WARNING %s/1: Audio risc op code error\n", - dev->name); + pr_warn("WARNING %s/1: Audio risc op code error\n", dev->name); cx_clear(AUD_INT_DMA_CTL, FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN); @@ -269,8 +274,7 @@ static void cx25821_aud_irq(struct cx25821_audio_dev *chip, u32 status, [AUDIO_SRAM_CHANNEL]); } if (status & AUD_INT_DN_SYNC) { - printk(KERN_WARNING "WARNING %s: Downstream sync error!\n", - dev->name); + pr_warn("WARNING %s: Downstream sync error!\n", dev->name); cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET); return; } @@ -388,8 +392,7 @@ static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream) unsigned int bpl = 0; if (!chip) { - printk(KERN_ERR "DEBUG: cx25821 can't find device struct." - " Can't proceed with open\n"); + pr_err("DEBUG: cx25821 can't find device struct. Can't proceed with open\n"); return -ENODEV; } @@ -479,8 +482,7 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, chip->period_size, chip->num_periods, 1); if (ret < 0) { - printk(KERN_INFO - "DEBUG: ERROR after cx25821_risc_databuffer_audio()\n"); + pr_info("DEBUG: ERROR after cx25821_risc_databuffer_audio()\n"); goto error; } @@ -608,8 +610,7 @@ static int snd_cx25821_pcm(struct cx25821_audio_dev *chip, int device, err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); if (err < 0) { - printk(KERN_INFO "ERROR: FAILED snd_pcm_new() in %s\n", - __func__); + pr_info("ERROR: FAILED snd_pcm_new() in %s\n", __func__); return err; } pcm->private_data = chip; @@ -674,23 +675,21 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) int err; if (devno >= SNDRV_CARDS) { - printk(KERN_INFO "DEBUG ERROR: devno >= SNDRV_CARDS %s\n", - __func__); + pr_info("DEBUG ERROR: devno >= SNDRV_CARDS %s\n", __func__); return -ENODEV; } if (!enable[devno]) { ++devno; - printk(KERN_INFO "DEBUG ERROR: !enable[devno] %s\n", __func__); + pr_info("DEBUG ERROR: !enable[devno] %s\n", __func__); return -ENOENT; } err = snd_card_create(index[devno], id[devno], THIS_MODULE, sizeof(struct cx25821_audio_dev), &card); if (err < 0) { - printk(KERN_INFO - "DEBUG ERROR: cannot create snd_card_new in %s\n", - __func__); + pr_info("DEBUG ERROR: cannot create snd_card_new in %s\n", + __func__); return err; } @@ -712,16 +711,15 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) IRQF_SHARED | IRQF_DISABLED, chip->dev->name, chip); if (err < 0) { - printk(KERN_ERR "ERROR %s: can't get IRQ %d for ALSA\n", + pr_err("ERROR %s: can't get IRQ %d for ALSA\n", chip->dev->name, dev->pci->irq); goto error; } err = snd_cx25821_pcm(chip, 0, "cx25821 Digital"); if (err < 0) { - printk(KERN_INFO - "DEBUG ERROR: cannot create snd_cx25821_pcm %s\n", - __func__); + pr_info("DEBUG ERROR: cannot create snd_cx25821_pcm %s\n", + __func__); goto error; } @@ -732,13 +730,13 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) chip->iobase, chip->irq); strcpy(card->mixername, "CX25821"); - printk(KERN_INFO "%s/%i: ALSA support for cx25821 boards\n", - card->driver, devno); + pr_info("%s/%i: ALSA support for cx25821 boards\n", + card->driver, devno); err = snd_card_register(card); if (err < 0) { - printk(KERN_INFO "DEBUG ERROR: cannot register sound card %s\n", - __func__); + pr_info("DEBUG ERROR: cannot register sound card %s\n", + __func__); goto error; } @@ -778,8 +776,7 @@ static int cx25821_alsa_init(void) } if (dev == NULL) - printk(KERN_INFO - "cx25821 ERROR ALSA: no cx25821 cards found\n"); + pr_info("ERROR ALSA: no cx25821 cards found\n"); return 0; diff --git a/drivers/staging/cx25821/cx25821-audio-upstream.c b/drivers/staging/cx25821/cx25821-audio-upstream.c index 1607b0d..7992a3b 100644 --- a/drivers/staging/cx25821/cx25821-audio-upstream.c +++ b/drivers/staging/cx25821/cx25821-audio-upstream.c @@ -20,6 +20,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "cx25821-video.h" #include "cx25821-audio-upstream.h" @@ -221,7 +223,7 @@ void cx25821_stop_upstream_audio(struct cx25821_dev *dev) if (!dev->_audio_is_running) { printk(KERN_DEBUG - "cx25821: No audio file is currently running so return!\n"); + pr_fmt("No audio file is currently running so return!\n")); return; } /* Disable RISC interrupts */ @@ -281,19 +283,19 @@ int cx25821_get_audio_data(struct cx25821_dev *dev, if (IS_ERR(myfile)) { const int open_errno = -PTR_ERR(myfile); - printk(KERN_ERR "%s(): ERROR opening file(%s) with errno = %d!\n", + pr_err("%s(): ERROR opening file(%s) with errno = %d!\n", __func__, dev->_audiofilename, open_errno); return PTR_ERR(myfile); } else { if (!(myfile->f_op)) { - printk(KERN_ERR "%s: File has no file operations registered!\n", + pr_err("%s(): File has no file operations registered!\n", __func__); filp_close(myfile, NULL); return -EIO; } if (!myfile->f_op->read) { - printk(KERN_ERR "%s: File has no READ operations registered!\n", + pr_err("%s(): File has no READ operations registered!\n", __func__); filp_close(myfile, NULL); return -EIO; @@ -320,9 +322,8 @@ int cx25821_get_audio_data(struct cx25821_dev *dev, frame_offset += vfs_read_retval; if (vfs_read_retval < line_size) { - printk(KERN_INFO - "Done: exit %s() since no more bytes to read from Audio file.\n", - __func__); + pr_info("Done: exit %s() since no more bytes to read from Audio file\n", + __func__); break; } } @@ -346,7 +347,7 @@ static void cx25821_audioups_handler(struct work_struct *work) container_of(work, struct cx25821_dev, _audio_work_entry); if (!dev) { - printk(KERN_ERR "ERROR %s(): since container_of(work_struct) FAILED!\n", + pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n", __func__); return; } @@ -373,19 +374,19 @@ int cx25821_openfile_audio(struct cx25821_dev *dev, if (IS_ERR(myfile)) { const int open_errno = -PTR_ERR(myfile); - printk(KERN_ERR "%s(): ERROR opening file(%s) with errno = %d!\n", + pr_err("%s(): ERROR opening file(%s) with errno = %d!\n", __func__, dev->_audiofilename, open_errno); return PTR_ERR(myfile); } else { if (!(myfile->f_op)) { - printk(KERN_ERR "%s: File has no file operations registered!\n", + pr_err("%s(): File has no file operations registered!\n", __func__); filp_close(myfile, NULL); return -EIO; } if (!myfile->f_op->read) { - printk(KERN_ERR "%s: File has no READ operations registered!\n", + pr_err("%s(): File has no READ operations registered!\n", __func__); filp_close(myfile, NULL); return -EIO; @@ -414,9 +415,8 @@ int cx25821_openfile_audio(struct cx25821_dev *dev, offset += vfs_read_retval; if (vfs_read_retval < line_size) { - printk(KERN_INFO - "Done: exit %s() since no more bytes to read from Audio file.\n", - __func__); + pr_info("Done: exit %s() since no more bytes to read from Audio file\n", + __func__); break; } } @@ -459,7 +459,7 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, if (!dev->_risc_virt_addr) { printk(KERN_DEBUG - "cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning.\n"); + pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning\n")); return -ENOMEM; } /* Clear out memory at address */ @@ -474,7 +474,7 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, if (!dev->_audiodata_buf_virt_addr) { printk(KERN_DEBUG - "cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning.\n"); + pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning\n")); return -ENOMEM; } /* Clear out memory at address */ @@ -490,7 +490,7 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, dev->_audio_lines_count); if (ret < 0) { printk(KERN_DEBUG - "cx25821 ERROR creating audio upstream RISC programs!\n"); + pr_fmt("ERROR creating audio upstream RISC programs!\n")); goto error; } @@ -569,16 +569,16 @@ int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, spin_unlock(&dev->slock); } else { if (status & FLD_AUD_SRC_OF) - printk(KERN_WARNING "%s: Audio Received Overflow Error Interrupt!\n", - __func__); + pr_warn("%s(): Audio Received Overflow Error Interrupt!\n", + __func__); if (status & FLD_AUD_SRC_SYNC) - printk(KERN_WARNING "%s: Audio Received Sync Error Interrupt!\n", - __func__); + pr_warn("%s(): Audio Received Sync Error Interrupt!\n", + __func__); if (status & FLD_AUD_SRC_OPC_ERR) - printk(KERN_WARNING "%s: Audio Received OpCode Error Interrupt!\n", - __func__); + pr_warn("%s(): Audio Received OpCode Error Interrupt!\n", + __func__); /* Read and write back the interrupt status register to clear * our bits */ @@ -586,8 +586,8 @@ int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, } if (dev->_audiofile_status == END_OF_FILE) { - printk(KERN_WARNING "cx25821: EOF Channel Audio Framecount = %d\n", - dev->_audioframe_count); + pr_warn("EOF Channel Audio Framecount = %d\n", + dev->_audioframe_count); return -1; } /* ElSE, set the interrupt mask register, re-enable irq. */ @@ -644,9 +644,8 @@ static void cx25821_wait_fifo_enable(struct cx25821_dev *dev, /* 10 millisecond timeout */ if (count++ > 1000) { - printk(KERN_ERR - "cx25821 ERROR: %s() fifo is NOT turned on. Timeout!\n", - __func__); + pr_err("ERROR: %s() fifo is NOT turned on. Timeout!\n", + __func__); return; } @@ -696,8 +695,8 @@ int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev, request_irq(dev->pci->irq, cx25821_upstream_irq_audio, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); if (err < 0) { - printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, - dev->pci->irq); + pr_err("%s: can't get upstream IRQ %d\n", + dev->name, dev->pci->irq); goto fail_irq; } @@ -726,7 +725,7 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) int str_length = 0; if (dev->_audio_is_running) { - printk(KERN_WARNING "Audio Channel is still running so return!\n"); + pr_warn("Audio Channel is still running so return!\n"); return 0; } @@ -740,7 +739,7 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) if (!dev->_irq_audio_queues) { printk(KERN_DEBUG - "cx25821 ERROR: create_singlethread_workqueue() for Audio FAILED!\n"); + pr_fmt("ERROR: create_singlethread_workqueue() for Audio FAILED!\n")); return -ENOMEM; } @@ -787,8 +786,7 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) retval = cx25821_audio_upstream_buffer_prepare(dev, sram_ch, _line_size); if (retval < 0) { - printk(KERN_ERR - "%s: Failed to set up Audio upstream buffers!\n", + pr_err("%s: Failed to set up Audio upstream buffers!\n", dev->name); goto error; } diff --git a/drivers/staging/cx25821/cx25821-cards.c b/drivers/staging/cx25821/cx25821-cards.c index da0f56d..94e8d68 100644 --- a/drivers/staging/cx25821/cx25821-cards.c +++ b/drivers/staging/cx25821/cx25821-cards.c @@ -21,6 +21,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include diff --git a/drivers/staging/cx25821/cx25821-core.c b/drivers/staging/cx25821/cx25821-core.c index 300da31..a216b62 100644 --- a/drivers/staging/cx25821/cx25821-core.c +++ b/drivers/staging/cx25821/cx25821-core.c @@ -21,6 +21,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include "cx25821.h" @@ -332,7 +334,7 @@ struct cx25821_dmaqueue mpegq; static int cx25821_risc_decode(u32 risc) { - static char *instr[16] = { + static const char * const instr[16] = { [RISC_SYNC >> 28] = "sync", [RISC_WRITE >> 28] = "write", [RISC_WRITEC >> 28] = "writec", @@ -344,7 +346,7 @@ static int cx25821_risc_decode(u32 risc) [RISC_WRITECM >> 28] = "writecm", [RISC_WRITECR >> 28] = "writecr", }; - static int incr[16] = { + static const int incr[16] = { [RISC_WRITE >> 28] = 3, [RISC_JUMP >> 28] = 3, [RISC_SKIP >> 28] = 1, @@ -353,7 +355,7 @@ static int cx25821_risc_decode(u32 risc) [RISC_WRITECM >> 28] = 3, [RISC_WRITECR >> 28] = 4, }; - static char *bits[] = { + static const char * const bits[] = { "12", "13", "14", "resync", "cnt0", "cnt1", "18", "19", "20", "21", "22", "23", @@ -361,13 +363,13 @@ static int cx25821_risc_decode(u32 risc) }; int i; - printk("0x%08x [ %s", risc, - instr[risc >> 28] ? instr[risc >> 28] : "INVALID"); + pr_cont("0x%08x [ %s", + risc, instr[risc >> 28] ? instr[risc >> 28] : "INVALID"); for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--) { if (risc & (1 << (i + 12))) - printk(" %s", bits[i]); + pr_cont(" %s", bits[i]); } - printk(" count=%d ]\n", risc & 0xfff); + pr_cont(" count=%d ]\n", risc & 0xfff); return incr[risc >> 28] ? incr[risc >> 28] : 1; } @@ -620,16 +622,15 @@ void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch) u32 risc; unsigned int i, j, n; - printk(KERN_WARNING "%s: %s - dma channel status dump\n", dev->name, - ch->name); + pr_warn("%s: %s - dma channel status dump\n", dev->name, ch->name); for (i = 0; i < ARRAY_SIZE(name); i++) - printk(KERN_WARNING "cmds + 0x%2x: %-15s: 0x%08x\n", i * 4, - name[i], cx_read(ch->cmds_start + 4 * i)); + pr_warn("cmds + 0x%2x: %-15s: 0x%08x\n", + i * 4, name[i], cx_read(ch->cmds_start + 4 * i)); j = i * 4; for (i = 0; i < 4;) { risc = cx_read(ch->cmds_start + 4 * (i + 14)); - printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j + i * 4, i); + pr_warn("cmds + 0x%2x: risc%d: ", j + i * 4, i); i += cx25821_risc_decode(risc); } @@ -637,36 +638,35 @@ void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch) risc = cx_read(ch->ctrl_start + 4 * i); /* No consideration for bits 63-32 */ - printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i * 4, - ch->ctrl_start + 4 * i, i); + pr_warn("ctrl + 0x%2x (0x%08x): iq %x: ", + i * 4, ch->ctrl_start + 4 * i, i); n = cx25821_risc_decode(risc); for (j = 1; j < n; j++) { risc = cx_read(ch->ctrl_start + 4 * (i + j)); - printk(KERN_WARNING - "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n", - 4 * (i + j), i + j, risc, j); + pr_warn("ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n", + 4 * (i + j), i + j, risc, j); } } - printk(KERN_WARNING " : fifo: 0x%08x -> 0x%x\n", - ch->fifo_start, ch->fifo_start + ch->fifo_size); - printk(KERN_WARNING " : ctrl: 0x%08x -> 0x%x\n", - ch->ctrl_start, ch->ctrl_start + 6 * 16); - printk(KERN_WARNING " : ptr1_reg: 0x%08x\n", - cx_read(ch->ptr1_reg)); - printk(KERN_WARNING " : ptr2_reg: 0x%08x\n", - cx_read(ch->ptr2_reg)); - printk(KERN_WARNING " : cnt1_reg: 0x%08x\n", - cx_read(ch->cnt1_reg)); - printk(KERN_WARNING " : cnt2_reg: 0x%08x\n", - cx_read(ch->cnt2_reg)); + pr_warn(" : fifo: 0x%08x -> 0x%x\n", + ch->fifo_start, ch->fifo_start + ch->fifo_size); + pr_warn(" : ctrl: 0x%08x -> 0x%x\n", + ch->ctrl_start, ch->ctrl_start + 6 * 16); + pr_warn(" : ptr1_reg: 0x%08x\n", + cx_read(ch->ptr1_reg)); + pr_warn(" : ptr2_reg: 0x%08x\n", + cx_read(ch->ptr2_reg)); + pr_warn(" : cnt1_reg: 0x%08x\n", + cx_read(ch->cnt1_reg)); + pr_warn(" : cnt2_reg: 0x%08x\n", + cx_read(ch->cnt2_reg)); } EXPORT_SYMBOL(cx25821_sram_channel_dump); void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, struct sram_channel *ch) { - static char *name[] = { + static const char * const name[] = { "init risc lo", "init risc hi", "cdt base", @@ -686,18 +686,18 @@ void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, u32 risc, value, tmp; unsigned int i, j, n; - printk(KERN_INFO "\n%s: %s - dma Audio channel status dump\n", - dev->name, ch->name); + pr_info("\n%s: %s - dma Audio channel status dump\n", + dev->name, ch->name); for (i = 0; i < ARRAY_SIZE(name); i++) - printk(KERN_INFO "%s: cmds + 0x%2x: %-15s: 0x%08x\n", - dev->name, i * 4, name[i], - cx_read(ch->cmds_start + 4 * i)); + pr_info("%s: cmds + 0x%2x: %-15s: 0x%08x\n", + dev->name, i * 4, name[i], + cx_read(ch->cmds_start + 4 * i)); j = i * 4; for (i = 0; i < 4;) { risc = cx_read(ch->cmds_start + 4 * (i + 14)); - printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j + i * 4, i); + pr_warn("cmds + 0x%2x: risc%d: ", j + i * 4, i); i += cx25821_risc_decode(risc); } @@ -705,44 +705,43 @@ void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, risc = cx_read(ch->ctrl_start + 4 * i); /* No consideration for bits 63-32 */ - printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i * 4, - ch->ctrl_start + 4 * i, i); + pr_warn("ctrl + 0x%2x (0x%08x): iq %x: ", + i * 4, ch->ctrl_start + 4 * i, i); n = cx25821_risc_decode(risc); for (j = 1; j < n; j++) { risc = cx_read(ch->ctrl_start + 4 * (i + j)); - printk(KERN_WARNING - "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n", - 4 * (i + j), i + j, risc, j); + pr_warn("ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n", + 4 * (i + j), i + j, risc, j); } } - printk(KERN_WARNING " : fifo: 0x%08x -> 0x%x\n", - ch->fifo_start, ch->fifo_start + ch->fifo_size); - printk(KERN_WARNING " : ctrl: 0x%08x -> 0x%x\n", - ch->ctrl_start, ch->ctrl_start + 6 * 16); - printk(KERN_WARNING " : ptr1_reg: 0x%08x\n", - cx_read(ch->ptr1_reg)); - printk(KERN_WARNING " : ptr2_reg: 0x%08x\n", - cx_read(ch->ptr2_reg)); - printk(KERN_WARNING " : cnt1_reg: 0x%08x\n", - cx_read(ch->cnt1_reg)); - printk(KERN_WARNING " : cnt2_reg: 0x%08x\n", - cx_read(ch->cnt2_reg)); + pr_warn(" : fifo: 0x%08x -> 0x%x\n", + ch->fifo_start, ch->fifo_start + ch->fifo_size); + pr_warn(" : ctrl: 0x%08x -> 0x%x\n", + ch->ctrl_start, ch->ctrl_start + 6 * 16); + pr_warn(" : ptr1_reg: 0x%08x\n", + cx_read(ch->ptr1_reg)); + pr_warn(" : ptr2_reg: 0x%08x\n", + cx_read(ch->ptr2_reg)); + pr_warn(" : cnt1_reg: 0x%08x\n", + cx_read(ch->cnt1_reg)); + pr_warn(" : cnt2_reg: 0x%08x\n", + cx_read(ch->cnt2_reg)); for (i = 0; i < 4; i++) { risc = cx_read(ch->cmds_start + 56 + (i * 4)); - printk(KERN_WARNING "instruction %d = 0x%x\n", i, risc); + pr_warn("instruction %d = 0x%x\n", i, risc); } /* read data from the first cdt buffer */ risc = cx_read(AUD_A_CDT); - printk(KERN_WARNING "\nread cdt loc=0x%x\n", risc); + pr_warn("\nread cdt loc=0x%x\n", risc); for (i = 0; i < 8; i++) { n = cx_read(risc + i * 4); - printk(KERN_WARNING "0x%x ", n); + pr_cont("0x%x ", n); } - printk(KERN_WARNING "\n\n"); + pr_cont("\n\n"); value = cx_read(CLK_RST); CX25821_INFO(" CLK_RST = 0x%x\n\n", value); @@ -870,7 +869,7 @@ static int cx25821_get_resources(struct cx25821_dev *dev) dev->name)) return 0; - printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n", + pr_err("%s: can't get MMIO memory @ 0x%llx\n", dev->name, (unsigned long long)pci_resource_start(dev->pci, 0)); return -EBUSY; @@ -880,8 +879,8 @@ static void cx25821_dev_checkrevision(struct cx25821_dev *dev) { dev->hwrevision = cx_read(RDR_CFG2) & 0xff; - printk(KERN_INFO "%s() Hardware revision = 0x%02x\n", __func__, - dev->hwrevision); + pr_info("%s(): Hardware revision = 0x%02x\n", + __func__, dev->hwrevision); } static void cx25821_iounmap(struct cx25821_dev *dev) @@ -901,9 +900,9 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) { int io_size = 0, i; - printk(KERN_INFO "\n***********************************\n"); - printk(KERN_INFO "cx25821 set up\n"); - printk(KERN_INFO "***********************************\n\n"); + pr_info("\n***********************************\n"); + pr_info("cx25821 set up\n"); + pr_info("***********************************\n\n"); mutex_init(&dev->lock); @@ -920,13 +919,11 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821"); if (dev->pci->device != 0x8210) { - printk(KERN_INFO - "%s() Exiting. Incorrect Hardware device = 0x%02x\n", - __func__, dev->pci->device); + pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n", + __func__, dev->pci->device); return -1; } else { - printk(KERN_INFO "Athena Hardware device = 0x%02x\n", - dev->pci->device); + pr_info("Athena Hardware device = 0x%02x\n", dev->pci->device); } /* Apply a sensible clock frequency for the PCIe bridge */ @@ -956,8 +953,7 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) dev->i2c_bus[0].i2c_period = (0x07 << 24); /* 1.95MHz */ if (cx25821_get_resources(dev) < 0) { - printk(KERN_ERR "%s No more PCIe resources for " - "subsystem: %04x:%04x\n", + pr_err("%s: No more PCIe resources for subsystem: %04x:%04x\n", dev->name, dev->pci->subsystem_vendor, dev->pci->subsystem_device); @@ -985,11 +981,11 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) dev->bmmio = (u8 __iomem *) dev->lmmio; - printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", - dev->name, dev->pci->subsystem_vendor, - dev->pci->subsystem_device, cx25821_boards[dev->board].name, - dev->board, card[dev->nr] == dev->board ? - "insmod option" : "autodetected"); + pr_info("%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", + dev->name, dev->pci->subsystem_vendor, + dev->pci->subsystem_device, cx25821_boards[dev->board].name, + dev->board, card[dev->nr] == dev->board ? + "insmod option" : "autodetected"); /* init hardware */ cx25821_initialize(dev); @@ -1004,8 +1000,7 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) cx25821_card_setup(dev); if (medusa_video_init(dev) < 0) - CX25821_ERR("%s() Failed to initialize medusa!\n" - , __func__); + CX25821_ERR("%s(): Failed to initialize medusa!\n", __func__); cx25821_video_register(dev); @@ -1017,13 +1012,12 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) if (video_register_device (dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0) { cx25821_videoioctl_unregister(dev); - printk(KERN_ERR - "%s() Failed to register video adapter for IOCTL, so \ - unregistering videoioctl device.\n", __func__); + pr_err("%s(): Failed to register video adapter for IOCTL, so unregistering videoioctl device\n", + __func__); } cx25821_dev_checkrevision(dev); - CX25821_INFO("cx25821 setup done!\n"); + CX25821_INFO("setup done!\n"); return 0; } @@ -1362,20 +1356,20 @@ void cx25821_print_irqbits(char *name, char *tag, char **strings, { unsigned int i; - printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits); + printk(KERN_DEBUG pr_fmt("%s: %s [0x%x]"), name, tag, bits); for (i = 0; i < len; i++) { if (!(bits & (1 << i))) continue; if (strings[i]) - printk(" %s", strings[i]); + pr_cont(" %s", strings[i]); else - printk(" %d", i); + pr_cont(" %d", i); if (!(mask & (1 << i))) continue; - printk("*"); + pr_cont("*"); } - printk("\n"); + pr_cont("\n"); } EXPORT_SYMBOL(cx25821_print_irqbits); @@ -1405,12 +1399,12 @@ static int __devinit cx25821_initdev(struct pci_dev *pci_dev, if (pci_enable_device(pci_dev)) { err = -EIO; - printk(KERN_INFO "pci enable failed! "); + pr_info("pci enable failed!\n"); goto fail_unregister_device; } - printk(KERN_INFO "cx25821 Athena pci enable !\n"); + pr_info("Athena pci enable !\n"); err = cx25821_dev_setup(dev); if (err) { @@ -1423,14 +1417,13 @@ static int __devinit cx25821_initdev(struct pci_dev *pci_dev, /* print pci info */ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); - printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " - "latency: %d, mmio: 0x%llx\n", dev->name, - pci_name(pci_dev), dev->pci_rev, pci_dev->irq, - dev->pci_lat, (unsigned long long)dev->base_io_addr); + pr_info("%s/0: found at %s, rev: %d, irq: %d, latency: %d, mmio: 0x%llx\n", + dev->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq, + dev->pci_lat, (unsigned long long)dev->base_io_addr); pci_set_master(pci_dev); if (!pci_dma_supported(pci_dev, 0xffffffff)) { - printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name); + pr_err("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name); err = -EIO; goto fail_irq; } @@ -1440,15 +1433,14 @@ static int __devinit cx25821_initdev(struct pci_dev *pci_dev, dev->name, dev); if (err < 0) { - printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name, - pci_dev->irq); + pr_err("%s: can't get IRQ %d\n", dev->name, pci_dev->irq); goto fail_irq; } return 0; fail_irq: - printk(KERN_INFO "cx25821 cx25821_initdev() can't get IRQ !\n"); + pr_info("cx25821_initdev() can't get IRQ !\n"); cx25821_dev_unregister(dev); fail_unregister_pci: @@ -1510,9 +1502,10 @@ static struct pci_driver cx25821_pci_driver = { static int __init cx25821_init(void) { INIT_LIST_HEAD(&cx25821_devlist); - printk(KERN_INFO "cx25821 driver version %d.%d.%d loaded\n", - (CX25821_VERSION_CODE >> 16) & 0xff, - (CX25821_VERSION_CODE >> 8) & 0xff, CX25821_VERSION_CODE & 0xff); + pr_info("driver version %d.%d.%d loaded\n", + (CX25821_VERSION_CODE >> 16) & 0xff, + (CX25821_VERSION_CODE >> 8) & 0xff, + CX25821_VERSION_CODE & 0xff); return pci_register_driver(&cx25821_pci_driver); } diff --git a/drivers/staging/cx25821/cx25821-i2c.c b/drivers/staging/cx25821/cx25821-i2c.c index 2b14bcc..130dfeb 100644 --- a/drivers/staging/cx25821/cx25821-i2c.c +++ b/drivers/staging/cx25821/cx25821-i2c.c @@ -21,6 +21,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "cx25821.h" #include @@ -32,10 +34,11 @@ static unsigned int i2c_scan; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); -#define dprintk(level, fmt, arg...)\ - do { if (i2c_debug >= level)\ - printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ - } while (0) +#define dprintk(level, fmt, arg...) \ +do { \ + if (i2c_debug >= level) \ + printk(KERN_DEBUG "%s/0: " fmt, dev->name, ##arg); \ +} while (0) #define I2C_WAIT_DELAY 32 #define I2C_WAIT_RETRY 64 @@ -98,7 +101,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, if (!i2c_slave_did_ack(i2c_adap)) return -EIO; - dprintk(1, "%s() returns 0\n", __func__); + dprintk(1, "%s(): returns 0\n", __func__); return 0; } @@ -163,7 +166,7 @@ eio: retval = -EIO; err: if (i2c_debug) - printk(KERN_ERR " ERR: %d\n", retval); + pr_err(" ERR: %d\n", retval); return retval; } @@ -187,7 +190,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, if (!i2c_slave_did_ack(i2c_adap)) return -EIO; - dprintk(1, "%s() returns 0\n", __func__); + dprintk(1, "%s(): returns 0\n", __func__); return 0; } @@ -227,7 +230,7 @@ eio: retval = -EIO; err: if (i2c_debug) - printk(KERN_ERR " ERR: %d\n", retval); + pr_err(" ERR: %d\n", retval); return retval; } diff --git a/drivers/staging/cx25821/cx25821-medusa-video.c b/drivers/staging/cx25821/cx25821-medusa-video.c index 1e11e0c..fc780d0 100644 --- a/drivers/staging/cx25821/cx25821-medusa-video.c +++ b/drivers/staging/cx25821/cx25821-medusa-video.c @@ -20,6 +20,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "cx25821.h" #include "cx25821-medusa-video.h" #include "cx25821-biffuncs.h" @@ -499,9 +501,8 @@ void medusa_set_resolution(struct cx25821_dev *dev, int width, /* validate the width - cannot be negative */ if (width > MAX_WIDTH) { - printk - ("cx25821 %s() : width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n", - __func__, width, MAX_WIDTH); + pr_info("%s(): width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n", + __func__, width, MAX_WIDTH); width = MAX_WIDTH; } diff --git a/drivers/staging/cx25821/cx25821-video-upstream-ch2.c b/drivers/staging/cx25821/cx25821-video-upstream-ch2.c index 405e2db..e2efacd 100644 --- a/drivers/staging/cx25821/cx25821-video-upstream-ch2.c +++ b/drivers/staging/cx25821/cx25821-video-upstream-ch2.c @@ -20,6 +20,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "cx25821-video.h" #include "cx25821-video-upstream-ch2.h" @@ -211,8 +213,7 @@ void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev) u32 tmp = 0; if (!dev->_is_running_ch2) { - printk - ("cx25821: No video file is currently running so return!\n"); + pr_info("No video file is currently running so return!\n"); return; } /* Disable RISC interrupts */ @@ -301,19 +302,19 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0); if (IS_ERR(myfile)) { const int open_errno = -PTR_ERR(myfile); - printk("%s(): ERROR opening file(%s) with errno = %d!\n", - __func__, dev->_filename_ch2, open_errno); + pr_err("%s(): ERROR opening file(%s) with errno = %d!\n", + __func__, dev->_filename_ch2, open_errno); return PTR_ERR(myfile); } else { if (!(myfile->f_op)) { - printk("%s: File has no file operations registered!", + pr_err("%s(): File has no file operations registered!\n", __func__); filp_close(myfile, NULL); return -EIO; } if (!myfile->f_op->read) { - printk("%s: File has no READ operations registered!", + pr_err("%s(): File has no READ operations registered!\n", __func__); filp_close(myfile, NULL); return -EIO; @@ -340,9 +341,8 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) frame_offset += vfs_read_retval; if (vfs_read_retval < line_size) { - printk(KERN_INFO - "Done: exit %s() since no more bytes to read from Video file.\n", - __func__); + pr_info("Done: exit %s() since no more bytes to read from Video file\n", + __func__); break; } } @@ -366,8 +366,8 @@ static void cx25821_vidups_handler_ch2(struct work_struct *work) container_of(work, struct cx25821_dev, _irq_work_entry_ch2); if (!dev) { - printk("ERROR %s(): since container_of(work_struct) FAILED!\n", - __func__); + pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n", + __func__); return; } @@ -393,21 +393,20 @@ int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) if (IS_ERR(myfile)) { const int open_errno = -PTR_ERR(myfile); - printk("%s(): ERROR opening file(%s) with errno = %d!\n", - __func__, dev->_filename_ch2, open_errno); + pr_err("%s(): ERROR opening file(%s) with errno = %d!\n", + __func__, dev->_filename_ch2, open_errno); return PTR_ERR(myfile); } else { if (!(myfile->f_op)) { - printk("%s: File has no file operations registered!", + pr_err("%s(): File has no file operations registered!\n", __func__); filp_close(myfile, NULL); return -EIO; } if (!myfile->f_op->read) { - printk - ("%s: File has no READ operations registered! Returning.", - __func__); + pr_err("%s(): File has no READ operations registered! Returning\n", + __func__); filp_close(myfile, NULL); return -EIO; } @@ -435,9 +434,8 @@ int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) offset += vfs_read_retval; if (vfs_read_retval < line_size) { - printk(KERN_INFO - "Done: exit %s() since no more bytes to read from Video file.\n", - __func__); + pr_info("Done: exit %s() since no more bytes to read from Video file\n", + __func__); break; } } @@ -483,8 +481,7 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, dev->_risc_size_ch2 = dev->upstream_riscbuf_size_ch2; if (!dev->_dma_virt_addr_ch2) { - printk - ("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n"); + pr_err("FAILED to allocate memory for Risc buffer! Returning\n"); return -ENOMEM; } @@ -504,8 +501,7 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2; if (!dev->_data_buf_virt_addr_ch2) { - printk - ("cx25821: FAILED to allocate memory for data buffer! Returning.\n"); + pr_err("FAILED to allocate memory for data buffer! Returning\n"); return -ENOMEM; } @@ -521,8 +517,7 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, cx25821_risc_buffer_upstream_ch2(dev, dev->pci, 0, bpl, dev->_lines_count_ch2); if (ret < 0) { - printk(KERN_INFO - "cx25821: Failed creating Video Upstream Risc programs!\n"); + pr_info("Failed creating Video Upstream Risc programs!\n"); goto error; } @@ -602,8 +597,8 @@ int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num, } if (dev->_file_status_ch2 == END_OF_FILE) { - printk("cx25821: EOF Channel 2 Framecount = %d\n", - dev->_frame_count_ch2); + pr_info("EOF Channel 2 Framecount = %d\n", + dev->_frame_count_ch2); return -1; } /* ElSE, set the interrupt mask register, re-enable irq. */ @@ -714,8 +709,8 @@ int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev, request_irq(dev->pci->irq, cx25821_upstream_irq_ch2, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); if (err < 0) { - printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, - dev->pci->irq); + pr_err("%s: can't get upstream IRQ %d\n", + dev->name, dev->pci->irq); goto fail_irq; } /* Start the DMA engine */ @@ -744,7 +739,7 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, int str_length = 0; if (dev->_is_running_ch2) { - printk("Video Channel is still running so return!\n"); + pr_info("Video Channel is still running so return!\n"); return 0; } @@ -756,8 +751,7 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, create_singlethread_workqueue("cx25821_workqueue2"); if (!dev->_irq_queues_ch2) { - printk - ("cx25821: create_singlethread_workqueue() for Video FAILED!\n"); + pr_err("create_singlethread_workqueue() for Video FAILED!\n"); return -ENOMEM; } /* @@ -829,8 +823,7 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, cx25821_upstream_buffer_prepare_ch2(dev, sram_ch, dev->_line_size_ch2); if (retval < 0) { - printk(KERN_ERR - "%s: Failed to set up Video upstream buffers!\n", + pr_err("%s: Failed to set up Video upstream buffers!\n", dev->name); goto error; } diff --git a/drivers/staging/cx25821/cx25821-video-upstream.c b/drivers/staging/cx25821/cx25821-video-upstream.c index 16bf74d..31b4e3c 100644 --- a/drivers/staging/cx25821/cx25821-video-upstream.c +++ b/drivers/staging/cx25821/cx25821-video-upstream.c @@ -20,6 +20,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "cx25821-video.h" #include "cx25821-video-upstream.h" @@ -257,8 +259,7 @@ void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev) u32 tmp = 0; if (!dev->_is_running) { - printk - (KERN_INFO "cx25821: No video file is currently running so return!\n"); + pr_info("No video file is currently running so return!\n"); return; } /* Disable RISC interrupts */ @@ -346,23 +347,20 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) if (IS_ERR(myfile)) { const int open_errno = -PTR_ERR(myfile); - printk(KERN_ERR - "%s(): ERROR opening file(%s) with errno = %d!\n", - __func__, dev->_filename, open_errno); + pr_err("%s(): ERROR opening file(%s) with errno = %d!\n", + __func__, dev->_filename, open_errno); return PTR_ERR(myfile); } else { if (!(myfile->f_op)) { - printk(KERN_ERR - "%s: File has no file operations registered!", - __func__); + pr_err("%s(): File has no file operations registered!\n", + __func__); filp_close(myfile, NULL); return -EIO; } if (!myfile->f_op->read) { - printk(KERN_ERR - "%s: File has no READ operations registered!", - __func__); + pr_err("%s(): File has no READ operations registered!\n", + __func__); filp_close(myfile, NULL); return -EIO; } @@ -388,10 +386,8 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) frame_offset += vfs_read_retval; if (vfs_read_retval < line_size) { - printk(KERN_INFO - "Done: exit %s() since no more bytes to \ - read from Video file.\n", - __func__); + pr_info("Done: exit %s() since no more bytes to read from Video file\n", + __func__); break; } } @@ -415,9 +411,8 @@ static void cx25821_vidups_handler(struct work_struct *work) container_of(work, struct cx25821_dev, _irq_work_entry); if (!dev) { - printk(KERN_ERR - "ERROR %s(): since container_of(work_struct) FAILED!\n", - __func__); + pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n", + __func__); return; } @@ -443,23 +438,20 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) if (IS_ERR(myfile)) { const int open_errno = -PTR_ERR(myfile); - printk(KERN_ERR "%s(): ERROR opening file(%s) with errno = %d!\n", + pr_err("%s(): ERROR opening file(%s) with errno = %d!\n", __func__, dev->_filename, open_errno); return PTR_ERR(myfile); } else { if (!(myfile->f_op)) { - printk(KERN_ERR - "%s: File has no file operations registered!", - __func__); + pr_err("%s(): File has no file operations registered!\n", + __func__); filp_close(myfile, NULL); return -EIO; } if (!myfile->f_op->read) { - printk(KERN_ERR - "%s: File has no READ operations registered! \ - Returning.", - __func__); + pr_err("%s(): File has no READ operations registered! Returning\n", + __func__); filp_close(myfile, NULL); return -EIO; } @@ -487,10 +479,8 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) offset += vfs_read_retval; if (vfs_read_retval < line_size) { - printk(KERN_INFO - "Done: exit %s() since no more \ - bytes to read from Video file.\n", - __func__); + pr_info("Done: exit %s() since no more bytes to read from Video file\n", + __func__); break; } } @@ -534,9 +524,7 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, dev->_risc_size = dev->upstream_riscbuf_size; if (!dev->_dma_virt_addr) { - printk - (KERN_ERR "cx25821: FAILED to allocate memory for Risc \ - buffer! Returning.\n"); + pr_err("FAILED to allocate memory for Risc buffer! Returning\n"); return -ENOMEM; } @@ -556,9 +544,7 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, dev->_data_buf_size = dev->upstream_databuf_size; if (!dev->_data_buf_virt_addr) { - printk - (KERN_ERR "cx25821: FAILED to allocate memory for data \ - buffer! Returning.\n"); + pr_err("FAILED to allocate memory for data buffer! Returning\n"); return -ENOMEM; } @@ -574,8 +560,7 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl, dev->_lines_count); if (ret < 0) { - printk(KERN_INFO - "cx25821: Failed creating Video Upstream Risc programs!\n"); + pr_info("Failed creating Video Upstream Risc programs!\n"); goto error; } @@ -652,22 +637,20 @@ int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, spin_unlock(&dev->slock); } else { if (status & FLD_VID_SRC_UF) - printk - (KERN_ERR "%s: Video Received Underflow Error \ - Interrupt!\n", __func__); + pr_err("%s(): Video Received Underflow Error Interrupt!\n", + __func__); if (status & FLD_VID_SRC_SYNC) - printk(KERN_ERR "%s: Video Received Sync Error \ - Interrupt!\n", __func__); + pr_err("%s(): Video Received Sync Error Interrupt!\n", + __func__); if (status & FLD_VID_SRC_OPC_ERR) - printk(KERN_ERR "%s: Video Received OpCode Error \ - Interrupt!\n", __func__); + pr_err("%s(): Video Received OpCode Error Interrupt!\n", + __func__); } if (dev->_file_status == END_OF_FILE) { - printk(KERN_ERR "cx25821: EOF Channel 1 Framecount = %d\n", - dev->_frame_count); + pr_err("EOF Channel 1 Framecount = %d\n", dev->_frame_count); return -1; } /* ElSE, set the interrupt mask register, re-enable irq. */ @@ -775,8 +758,8 @@ int cx25821_start_video_dma_upstream(struct cx25821_dev *dev, request_irq(dev->pci->irq, cx25821_upstream_irq, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); if (err < 0) { - printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, - dev->pci->irq); + pr_err("%s: can't get upstream IRQ %d\n", + dev->name, dev->pci->irq); goto fail_irq; } @@ -806,7 +789,7 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, int str_length = 0; if (dev->_is_running) { - printk(KERN_INFO "Video Channel is still running so return!\n"); + pr_info("Video Channel is still running so return!\n"); return 0; } @@ -817,9 +800,7 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, dev->_irq_queues = create_singlethread_workqueue("cx25821_workqueue"); if (!dev->_irq_queues) { - printk - (KERN_ERR "cx25821: create_singlethread_workqueue() for \ - Video FAILED!\n"); + pr_err("create_singlethread_workqueue() for Video FAILED!\n"); return -ENOMEM; } /* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for @@ -895,8 +876,7 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, /* Allocating buffers and prepare RISC program */ retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size); if (retval < 0) { - printk(KERN_ERR - "%s: Failed to set up Video upstream buffers!\n", + pr_err("%s: Failed to set up Video upstream buffers!\n", dev->name); goto error; } diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c index 5238930..3c121fc 100644 --- a/drivers/staging/cx25821/cx25821-video.c +++ b/drivers/staging/cx25821/cx25821-video.c @@ -24,6 +24,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "cx25821-video.h" MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); @@ -104,7 +106,7 @@ struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc) if (formats[i].fourcc == fourcc) return formats + i; - printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc); + pr_err("%s(0x%08x) NOT FOUND\n", __func__, fourcc); return NULL; } @@ -159,15 +161,15 @@ void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, else mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); if (bc != 1) - printk(KERN_ERR "%s: %d buffers handled (should be 1)\n", + pr_err("%s: %d buffers handled (should be 1)\n", __func__, bc); } #ifdef TUNER_FLAG int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm) { - dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", __func__, - (unsigned int)norm, v4l2_norm_to_name(norm)); + dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", + __func__, (unsigned int)norm, v4l2_norm_to_name(norm)); dev->tvnorm = norm; @@ -267,7 +269,7 @@ int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input) struct v4l2_routing route; memset(&route, 0, sizeof(route)); - dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n", + dprintk(1, "%s(): video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n", __func__, input, INPUT(input)->vmux, INPUT(input)->gpio0, INPUT(input)->gpio1, INPUT(input)->gpio2, INPUT(input)->gpio3); dev->input = input; @@ -400,8 +402,8 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) /* risc op code error */ if (status & (1 << 16)) { - printk(KERN_WARNING "%s, %s: video risc op code error\n", - dev->name, channel->name); + pr_warn("%s, %s: video risc op code error\n", + dev->name, channel->name); cx_clear(channel->dma_ctl, 0x11); cx25821_sram_channel_dump(dev, channel); } @@ -458,7 +460,7 @@ void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num) btcx_riscmem_free(dev->pci, &dev->channels[chan_num].vidq.stopper); - printk(KERN_WARNING "device %d released!\n", chan_num); + pr_warn("device %d released!\n", chan_num); } } @@ -590,7 +592,7 @@ int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, init_buffer = 1; rc = videobuf_iolock(q, &buf->vb, NULL); if (0 != rc) { - printk(KERN_DEBUG "videobuf_iolock failed!\n"); + printk(KERN_DEBUG pr_fmt("videobuf_iolock failed!\n")); goto fail; } } @@ -1038,8 +1040,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, dev->channels[fh->channel_id].cif_width = fh->width; medusa_set_resolution(dev, fh->width, SRAM_CH00); - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, - fh->height, fh->vidq.field); + dprintk(2, "%s(): width=%d height=%d field=%d\n", __func__, fh->width, + fh->height, fh->vidq.field); v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED); cx25821_call_all(dev, video, s_mbus_fmt, &mbus_fmt); @@ -1070,14 +1072,14 @@ static int vidioc_log_status(struct file *file, void *priv) u32 tmp = 0; snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", - dev->name); + pr_info("%s/2: ============ START LOG STATUS ============\n", + dev->name); cx25821_call_all(dev, core, log_status); tmp = cx_read(sram_ch->dma_ctl); - printk(KERN_INFO "Video input 0 is %s\n", - (tmp & 0x11) ? "streaming" : "stopped"); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", - dev->name); + pr_info("Video input 0 is %s\n", + (tmp & 0x11) ? "streaming" : "stopped"); + pr_info("%s/2: ============= END LOG STATUS =============\n", + dev->name); return 0; } @@ -1319,7 +1321,7 @@ int cx25821_vidioc_g_input(struct file *file, void *priv, unsigned int *i) struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; *i = dev->input; - dprintk(1, "%s() returns %d\n", __func__, *i); + dprintk(1, "%s(): returns %d\n", __func__, *i); return 0; } @@ -1339,7 +1341,7 @@ int cx25821_vidioc_s_input(struct file *file, void *priv, unsigned int i) } if (i > 2) { - dprintk(1, "%s() -EINVAL\n", __func__); + dprintk(1, "%s(): -EINVAL\n", __func__); return -EINVAL; } @@ -1390,7 +1392,7 @@ int cx25821_vidioc_s_frequency(struct file *file, void *priv, struct v4l2_freque if (0 != err) return err; } else { - printk(KERN_ERR "Invalid fh pointer!\n"); + pr_err("Invalid fh pointer!\n"); return -EINVAL; } @@ -1733,12 +1735,10 @@ static long video_ioctl_upstream9(struct file *file, unsigned int cmd, data_from_user = (struct upstream_user_struct *)arg; - if (!data_from_user) { - printk - ("cx25821 in %s(): Upstream data is INVALID. Returning.\n", - __func__); - return 0; - } + if (!data_from_user) { + pr_err("%s(): Upstream data is INVALID. Returning\n", __func__); + return 0; + } command = data_from_user->command; @@ -1776,12 +1776,10 @@ static long video_ioctl_upstream10(struct file *file, unsigned int cmd, data_from_user = (struct upstream_user_struct *)arg; - if (!data_from_user) { - printk - ("cx25821 in %s(): Upstream data is INVALID. Returning.\n", - __func__); - return 0; - } + if (!data_from_user) { + pr_err("%s(): Upstream data is INVALID. Returning\n", __func__); + return 0; + } command = data_from_user->command; @@ -1819,12 +1817,10 @@ static long video_ioctl_upstream11(struct file *file, unsigned int cmd, data_from_user = (struct upstream_user_struct *)arg; - if (!data_from_user) { - printk - ("cx25821 in %s(): Upstream data is INVALID. Returning.\n", - __func__); - return 0; - } + if (!data_from_user) { + pr_err("%s(): Upstream data is INVALID. Returning\n", __func__); + return 0; + } command = data_from_user->command; @@ -1866,12 +1862,10 @@ static long video_ioctl_set(struct file *file, unsigned int cmd, data_from_user = (struct downstream_user_struct *)arg; - if (!data_from_user) { - printk( - "cx25821 in %s(): User data is INVALID. Returning.\n", - __func__); - return 0; - } + if (!data_from_user) { + pr_err("%s(): User data is INVALID. Returning\n", __func__); + return 0; + } command = data_from_user->command; diff --git a/drivers/staging/cx25821/cx25821-video.h b/drivers/staging/cx25821/cx25821-video.h index a2415d3..213f37c 100644 --- a/drivers/staging/cx25821/cx25821-video.h +++ b/drivers/staging/cx25821/cx25821-video.h @@ -49,10 +49,11 @@ #define VIDEO_DEBUG 0 -#define dprintk(level, fmt, arg...)\ - do { if (VIDEO_DEBUG >= level)\ - printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ - } while (0) +#define dprintk(level, fmt, arg...) \ +do { \ + if (VIDEO_DEBUG >= level) \ + printk(KERN_DEBUG "%s/0: " fmt, dev->name, ##arg); \ +} while (0) /* For IOCTL to identify running upstream */ #define UPSTREAM_START_VIDEO 700 diff --git a/drivers/staging/cx25821/cx25821.h b/drivers/staging/cx25821/cx25821.h index c940001..5511523 100644 --- a/drivers/staging/cx25821/cx25821.h +++ b/drivers/staging/cx25821/cx25821.h @@ -519,9 +519,12 @@ extern struct sram_channel cx25821_sram_channels[]; #define Set_GPIO_Bit(Bit) (1 << Bit) #define Clear_GPIO_Bit(Bit) (~(1 << Bit)) -#define CX25821_ERR(fmt, args...) printk(KERN_ERR "cx25821(%d): " fmt, dev->board, ## args) -#define CX25821_WARN(fmt, args...) printk(KERN_WARNING "cx25821(%d): " fmt, dev->board , ## args) -#define CX25821_INFO(fmt, args...) printk(KERN_INFO "cx25821(%d): " fmt, dev->board , ## args) +#define CX25821_ERR(fmt, args...) \ + pr_err("(%d): " fmt, dev->board, ##args) +#define CX25821_WARN(fmt, args...) \ + pr_warn("(%d): " fmt, dev->board, ##args) +#define CX25821_INFO(fmt, args...) \ + pr_info("(%d): " fmt, dev->board, ##args) extern int cx25821_i2c_register(struct cx25821_i2c *bus); extern void cx25821_card_setup(struct cx25821_dev *dev); -- cgit v0.10.2 From 9eae42e5a216059a146b3fbbe24b4fdc0b10c723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Mon, 8 Nov 2010 10:45:44 -0300 Subject: [media] media: Add timberdale video-in driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds the timberdale video-in driver. The video IP of timberdale delivers the video data via DMA. The driver uses the DMA api to handle DMA transfers, and make use of the V4L2 video buffers to handle buffers against user space. If available the driver uses an encoder to get/set the video standard Signed-off-by: Richard Röjfors Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 22feac4..73962d6 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -666,6 +666,15 @@ config VIDEO_HEXIUM_GEMINI To compile this driver as a module, choose M here: the module will be called hexium_gemini. +config VIDEO_TIMBERDALE + tristate "Support for timberdale Video In/LogiWIN" + depends on VIDEO_V4L2 && I2C + select TIMB_DMA + select VIDEO_ADV7180 + select VIDEOBUF_DMA_CONTIG + ---help--- + Add support for the Video In peripherial of the timberdale FPGA. + source "drivers/media/video/cx88/Kconfig" source "drivers/media/video/cx23885/Kconfig" diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index af79d47..482f14b 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -106,6 +106,7 @@ obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ obj-$(CONFIG_VIDEO_MXB) += mxb.o obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o +obj-$(CONFIG_VIDEO_TIMBERDALE) += timblogiw.o obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o diff --git a/drivers/media/video/timblogiw.c b/drivers/media/video/timblogiw.c new file mode 100644 index 0000000..bddcdb6 --- /dev/null +++ b/drivers/media/video/timblogiw.c @@ -0,0 +1,894 @@ +/* + * timblogiw.c timberdale FPGA LogiWin Video In driver + * Copyright (c) 2009-2010 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supports: + * Timberdale FPGA LogiWin Video In + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "timb-video" + +#define TIMBLOGIWIN_NAME "Timberdale Video-In" +#define TIMBLOGIW_VERSION_CODE 0x04 + +#define TIMBLOGIW_LINES_PER_DESC 44 +#define TIMBLOGIW_MAX_VIDEO_MEM 16 + +#define TIMBLOGIW_HAS_DECODER(lw) (lw->pdata.encoder.module_name) + + +struct timblogiw { + struct video_device video_dev; + struct v4l2_device v4l2_dev; /* mutual exclusion */ + struct mutex lock; + struct device *dev; + struct timb_video_platform_data pdata; + struct v4l2_subdev *sd_enc; /* encoder */ + bool opened; +}; + +struct timblogiw_tvnorm { + v4l2_std_id std; + u16 width; + u16 height; + u8 fps; +}; + +struct timblogiw_fh { + struct videobuf_queue vb_vidq; + struct timblogiw_tvnorm const *cur_norm; + struct list_head capture; + struct dma_chan *chan; + spinlock_t queue_lock; /* mutual exclusion */ + unsigned int frame_count; +}; + +struct timblogiw_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + struct scatterlist sg[16]; + dma_cookie_t cookie; + struct timblogiw_fh *fh; +}; + +const struct timblogiw_tvnorm timblogiw_tvnorms[] = { + { + .std = V4L2_STD_PAL, + .width = 720, + .height = 576, + .fps = 25 + }, + { + .std = V4L2_STD_NTSC, + .width = 720, + .height = 480, + .fps = 30 + } +}; + +static int timblogiw_bytes_per_line(const struct timblogiw_tvnorm *norm) +{ + return norm->width * 2; +} + + +static int timblogiw_frame_size(const struct timblogiw_tvnorm *norm) +{ + return norm->height * timblogiw_bytes_per_line(norm); +} + +static const struct timblogiw_tvnorm *timblogiw_get_norm(const v4l2_std_id std) +{ + int i; + for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++) + if (timblogiw_tvnorms[i].std & std) + return timblogiw_tvnorms + i; + + /* default to first element */ + return timblogiw_tvnorms; +} + +static void timblogiw_dma_cb(void *data) +{ + struct timblogiw_buffer *buf = data; + struct timblogiw_fh *fh = buf->fh; + struct videobuf_buffer *vb = &buf->vb; + + spin_lock(&fh->queue_lock); + + /* mark the transfer done */ + buf->cookie = -1; + + fh->frame_count++; + + if (vb->state != VIDEOBUF_ERROR) { + list_del(&vb->queue); + do_gettimeofday(&vb->ts); + vb->field_count = fh->frame_count * 2; + vb->state = VIDEOBUF_DONE; + + wake_up(&vb->done); + } + + if (!list_empty(&fh->capture)) { + vb = list_entry(fh->capture.next, struct videobuf_buffer, + queue); + vb->state = VIDEOBUF_ACTIVE; + } + + spin_unlock(&fh->queue_lock); +} + +static bool timblogiw_dma_filter_fn(struct dma_chan *chan, void *filter_param) +{ + return chan->chan_id == (int)filter_param; +} + +/* IOCTL functions */ + +static int timblogiw_g_fmt(struct file *file, void *priv, + struct v4l2_format *format) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw *lw = video_get_drvdata(vdev); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s entry\n", __func__); + + if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + mutex_lock(&lw->lock); + + format->fmt.pix.width = fh->cur_norm->width; + format->fmt.pix.height = fh->cur_norm->height; + format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; + format->fmt.pix.bytesperline = timblogiw_bytes_per_line(fh->cur_norm); + format->fmt.pix.sizeimage = timblogiw_frame_size(fh->cur_norm); + format->fmt.pix.field = V4L2_FIELD_NONE; + + mutex_unlock(&lw->lock); + + return 0; +} + +static int timblogiw_try_fmt(struct file *file, void *priv, + struct v4l2_format *format) +{ + struct video_device *vdev = video_devdata(file); + struct v4l2_pix_format *pix = &format->fmt.pix; + + dev_dbg(&vdev->dev, + "%s - width=%d, height=%d, pixelformat=%d, field=%d\n" + "bytes per line %d, size image: %d, colorspace: %d\n", + __func__, + pix->width, pix->height, pix->pixelformat, pix->field, + pix->bytesperline, pix->sizeimage, pix->colorspace); + + if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (pix->field != V4L2_FIELD_NONE) + return -EINVAL; + + if (pix->pixelformat != V4L2_PIX_FMT_UYVY) + return -EINVAL; + + return 0; +} + +static int timblogiw_s_fmt(struct file *file, void *priv, + struct v4l2_format *format) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw *lw = video_get_drvdata(vdev); + struct timblogiw_fh *fh = priv; + struct v4l2_pix_format *pix = &format->fmt.pix; + int err; + + mutex_lock(&lw->lock); + + err = timblogiw_try_fmt(file, priv, format); + if (err) + goto out; + + if (videobuf_queue_is_busy(&fh->vb_vidq)) { + dev_err(&vdev->dev, "%s queue busy\n", __func__); + err = -EBUSY; + goto out; + } + + pix->width = fh->cur_norm->width; + pix->height = fh->cur_norm->height; + +out: + mutex_unlock(&lw->lock); + return err; +} + +static int timblogiw_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct video_device *vdev = video_devdata(file); + + dev_dbg(&vdev->dev, "%s: Entry\n", __func__); + memset(cap, 0, sizeof(*cap)); + strncpy(cap->card, TIMBLOGIWIN_NAME, sizeof(cap->card)-1); + strncpy(cap->driver, DRIVER_NAME, sizeof(cap->card)-1); + strlcpy(cap->bus_info, vdev->name, sizeof(cap->bus_info)); + cap->version = TIMBLOGIW_VERSION_CODE; + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE; + + return 0; +} + +static int timblogiw_enum_fmt(struct file *file, void *priv, + struct v4l2_fmtdesc *fmt) +{ + struct video_device *vdev = video_devdata(file); + + dev_dbg(&vdev->dev, "%s, index: %d\n", __func__, fmt->index); + + if (fmt->index != 0) + return -EINVAL; + memset(fmt, 0, sizeof(*fmt)); + fmt->index = 0; + fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + strncpy(fmt->description, "4:2:2, packed, YUYV", + sizeof(fmt->description)-1); + fmt->pixelformat = V4L2_PIX_FMT_UYVY; + + return 0; +} + +static int timblogiw_g_parm(struct file *file, void *priv, + struct v4l2_streamparm *sp) +{ + struct timblogiw_fh *fh = priv; + struct v4l2_captureparm *cp = &sp->parm.capture; + + cp->capability = V4L2_CAP_TIMEPERFRAME; + cp->timeperframe.numerator = 1; + cp->timeperframe.denominator = fh->cur_norm->fps; + + return 0; +} + +static int timblogiw_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *rb) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_reqbufs(&fh->vb_vidq, rb); +} + +static int timblogiw_querybuf(struct file *file, void *priv, + struct v4l2_buffer *b) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_querybuf(&fh->vb_vidq, b); +} + +static int timblogiw_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_qbuf(&fh->vb_vidq, b); +} + +static int timblogiw_dqbuf(struct file *file, void *priv, + struct v4l2_buffer *b) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); +} + +static int timblogiw_g_std(struct file *file, void *priv, v4l2_std_id *std) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + *std = fh->cur_norm->std; + return 0; +} + +static int timblogiw_s_std(struct file *file, void *priv, v4l2_std_id *std) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw *lw = video_get_drvdata(vdev); + struct timblogiw_fh *fh = priv; + int err = 0; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + mutex_lock(&lw->lock); + + if (TIMBLOGIW_HAS_DECODER(lw)) + err = v4l2_subdev_call(lw->sd_enc, core, s_std, *std); + + if (!err) + fh->cur_norm = timblogiw_get_norm(*std); + + mutex_unlock(&lw->lock); + + return err; +} + +static int timblogiw_enuminput(struct file *file, void *priv, + struct v4l2_input *inp) +{ + struct video_device *vdev = video_devdata(file); + int i; + + dev_dbg(&vdev->dev, "%s: Entry\n", __func__); + + if (inp->index != 0) + return -EINVAL; + + memset(inp, 0, sizeof(*inp)); + inp->index = 0; + + strncpy(inp->name, "Timb input 1", sizeof(inp->name) - 1); + inp->type = V4L2_INPUT_TYPE_CAMERA; + + inp->std = 0; + for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++) + inp->std |= timblogiw_tvnorms[i].std; + + return 0; +} + +static int timblogiw_g_input(struct file *file, void *priv, + unsigned int *input) +{ + struct video_device *vdev = video_devdata(file); + + dev_dbg(&vdev->dev, "%s: Entry\n", __func__); + + *input = 0; + + return 0; +} + +static int timblogiw_s_input(struct file *file, void *priv, unsigned int input) +{ + struct video_device *vdev = video_devdata(file); + + dev_dbg(&vdev->dev, "%s: Entry\n", __func__); + + if (input != 0) + return -EINVAL; + return 0; +} + +static int timblogiw_streamon(struct file *file, void *priv, unsigned int type) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + dev_dbg(&vdev->dev, "%s - No capture device\n", __func__); + return -EINVAL; + } + + fh->frame_count = 0; + return videobuf_streamon(&fh->vb_vidq); +} + +static int timblogiw_streamoff(struct file *file, void *priv, + unsigned int type) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s entry\n", __func__); + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + return videobuf_streamoff(&fh->vb_vidq); +} + +static int timblogiw_querystd(struct file *file, void *priv, v4l2_std_id *std) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw *lw = video_get_drvdata(vdev); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s entry\n", __func__); + + if (TIMBLOGIW_HAS_DECODER(lw)) + return v4l2_subdev_call(lw->sd_enc, video, querystd, std); + else { + *std = fh->cur_norm->std; + return 0; + } +} + +static int timblogiw_enum_framesizes(struct file *file, void *priv, + struct v4l2_frmsizeenum *fsize) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = priv; + + dev_dbg(&vdev->dev, "%s - index: %d, format: %d\n", __func__, + fsize->index, fsize->pixel_format); + + if ((fsize->index != 0) || + (fsize->pixel_format != V4L2_PIX_FMT_UYVY)) + return -EINVAL; + + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = fh->cur_norm->width; + fsize->discrete.height = fh->cur_norm->height; + + return 0; +} + +/* Video buffer functions */ + +static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) +{ + struct timblogiw_fh *fh = vq->priv_data; + + *size = timblogiw_frame_size(fh->cur_norm); + + if (!*count) + *count = 32; + + while (*size * *count > TIMBLOGIW_MAX_VIDEO_MEM * 1024 * 1024) + (*count)--; + + return 0; +} + +static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct timblogiw_fh *fh = vq->priv_data; + struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer, + vb); + unsigned int data_size = timblogiw_frame_size(fh->cur_norm); + int err = 0; + + if (vb->baddr && vb->bsize < data_size) + /* User provided buffer, but it is too small */ + return -ENOMEM; + + vb->size = data_size; + vb->width = fh->cur_norm->width; + vb->height = fh->cur_norm->height; + vb->field = field; + + if (vb->state == VIDEOBUF_NEEDS_INIT) { + int i; + unsigned int size; + unsigned int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC * + timblogiw_bytes_per_line(fh->cur_norm); + dma_addr_t addr; + + sg_init_table(buf->sg, ARRAY_SIZE(buf->sg)); + + err = videobuf_iolock(vq, vb, NULL); + if (err) + goto err; + + addr = videobuf_to_dma_contig(vb); + for (i = 0, size = 0; size < data_size; i++) { + sg_dma_address(buf->sg + i) = addr + size; + size += bytes_per_desc; + sg_dma_len(buf->sg + i) = (size > data_size) ? + (bytes_per_desc - (size - data_size)) : + bytes_per_desc; + } + + vb->state = VIDEOBUF_PREPARED; + buf->cookie = -1; + buf->fh = fh; + } + + return 0; + +err: + videobuf_dma_contig_free(vq, vb); + vb->state = VIDEOBUF_NEEDS_INIT; + return err; +} + +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct timblogiw_fh *fh = vq->priv_data; + struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer, + vb); + struct dma_async_tx_descriptor *desc; + int sg_elems; + int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC * + timblogiw_bytes_per_line(fh->cur_norm); + + sg_elems = timblogiw_frame_size(fh->cur_norm) / bytes_per_desc; + sg_elems += + (timblogiw_frame_size(fh->cur_norm) % bytes_per_desc) ? 1 : 0; + + if (list_empty(&fh->capture)) + vb->state = VIDEOBUF_ACTIVE; + else + vb->state = VIDEOBUF_QUEUED; + + list_add_tail(&vb->queue, &fh->capture); + + spin_unlock_irq(&fh->queue_lock); + + desc = fh->chan->device->device_prep_slave_sg(fh->chan, + buf->sg, sg_elems, DMA_FROM_DEVICE, + DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP); + if (!desc) { + spin_lock_irq(&fh->queue_lock); + list_del_init(&vb->queue); + vb->state = VIDEOBUF_PREPARED; + return; + } + + desc->callback_param = buf; + desc->callback = timblogiw_dma_cb; + + buf->cookie = desc->tx_submit(desc); + + spin_lock_irq(&fh->queue_lock); +} + +static void buffer_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct timblogiw_fh *fh = vq->priv_data; + struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer, + vb); + + videobuf_waiton(vq, vb, 0, 0); + if (buf->cookie >= 0) + dma_sync_wait(fh->chan, buf->cookie); + + videobuf_dma_contig_free(vq, vb); + vb->state = VIDEOBUF_NEEDS_INIT; +} + +static struct videobuf_queue_ops timblogiw_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + +/* Device Operations functions */ + +static int timblogiw_open(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw *lw = video_get_drvdata(vdev); + struct timblogiw_fh *fh; + v4l2_std_id std; + dma_cap_mask_t mask; + int err = 0; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + mutex_lock(&lw->lock); + if (lw->opened) { + err = -EBUSY; + goto out; + } + + if (TIMBLOGIW_HAS_DECODER(lw) && !lw->sd_enc) { + struct i2c_adapter *adapt; + + /* find the video decoder */ + adapt = i2c_get_adapter(lw->pdata.i2c_adapter); + if (!adapt) { + dev_err(&vdev->dev, "No I2C bus #%d\n", + lw->pdata.i2c_adapter); + err = -ENODEV; + goto out; + } + + /* now find the encoder */ + lw->sd_enc = v4l2_i2c_new_subdev_board(&lw->v4l2_dev, adapt, + lw->pdata.encoder.info, NULL); + + i2c_put_adapter(adapt); + + if (!lw->sd_enc) { + dev_err(&vdev->dev, "Failed to get encoder: %s\n", + lw->pdata.encoder.module_name); + err = -ENODEV; + goto out; + } + } + + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (!fh) { + err = -ENOMEM; + goto out; + } + + fh->cur_norm = timblogiw_tvnorms; + timblogiw_querystd(file, fh, &std); + fh->cur_norm = timblogiw_get_norm(std); + + INIT_LIST_HEAD(&fh->capture); + spin_lock_init(&fh->queue_lock); + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_PRIVATE, mask); + + /* find the DMA channel */ + fh->chan = dma_request_channel(mask, timblogiw_dma_filter_fn, + (void *)lw->pdata.dma_channel); + if (!fh->chan) { + dev_err(&vdev->dev, "Failed to get DMA channel\n"); + kfree(fh); + err = -ENODEV; + goto out; + } + + file->private_data = fh; + videobuf_queue_dma_contig_init(&fh->vb_vidq, + &timblogiw_video_qops, lw->dev, &fh->queue_lock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, + sizeof(struct timblogiw_buffer), fh, NULL); + + lw->opened = true; +out: + mutex_unlock(&lw->lock); + + return err; +} + +static int timblogiw_close(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw *lw = video_get_drvdata(vdev); + struct timblogiw_fh *fh = file->private_data; + + dev_dbg(&vdev->dev, "%s: Entry\n", __func__); + + videobuf_stop(&fh->vb_vidq); + videobuf_mmap_free(&fh->vb_vidq); + + dma_release_channel(fh->chan); + + kfree(fh); + + mutex_lock(&lw->lock); + lw->opened = false; + mutex_unlock(&lw->lock); + return 0; +} + +static ssize_t timblogiw_read(struct file *file, char __user *data, + size_t count, loff_t *ppos) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = file->private_data; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0, + file->f_flags & O_NONBLOCK); +} + +static unsigned int timblogiw_poll(struct file *file, + struct poll_table_struct *wait) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = file->private_data; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_poll_stream(file, &fh->vb_vidq, wait); +} + +static int timblogiw_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct video_device *vdev = video_devdata(file); + struct timblogiw_fh *fh = file->private_data; + + dev_dbg(&vdev->dev, "%s: entry\n", __func__); + + return videobuf_mmap_mapper(&fh->vb_vidq, vma); +} + +/* Platform device functions */ + +static const __devinitdata struct v4l2_ioctl_ops timblogiw_ioctl_ops = { + .vidioc_querycap = timblogiw_querycap, + .vidioc_enum_fmt_vid_cap = timblogiw_enum_fmt, + .vidioc_g_fmt_vid_cap = timblogiw_g_fmt, + .vidioc_try_fmt_vid_cap = timblogiw_try_fmt, + .vidioc_s_fmt_vid_cap = timblogiw_s_fmt, + .vidioc_g_parm = timblogiw_g_parm, + .vidioc_reqbufs = timblogiw_reqbufs, + .vidioc_querybuf = timblogiw_querybuf, + .vidioc_qbuf = timblogiw_qbuf, + .vidioc_dqbuf = timblogiw_dqbuf, + .vidioc_g_std = timblogiw_g_std, + .vidioc_s_std = timblogiw_s_std, + .vidioc_enum_input = timblogiw_enuminput, + .vidioc_g_input = timblogiw_g_input, + .vidioc_s_input = timblogiw_s_input, + .vidioc_streamon = timblogiw_streamon, + .vidioc_streamoff = timblogiw_streamoff, + .vidioc_querystd = timblogiw_querystd, + .vidioc_enum_framesizes = timblogiw_enum_framesizes, +}; + +static const __devinitdata struct v4l2_file_operations timblogiw_fops = { + .owner = THIS_MODULE, + .open = timblogiw_open, + .release = timblogiw_close, + .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ + .mmap = timblogiw_mmap, + .read = timblogiw_read, + .poll = timblogiw_poll, +}; + +static const __devinitdata struct video_device timblogiw_template = { + .name = TIMBLOGIWIN_NAME, + .fops = &timblogiw_fops, + .ioctl_ops = &timblogiw_ioctl_ops, + .release = video_device_release_empty, + .minor = -1, + .tvnorms = V4L2_STD_PAL | V4L2_STD_NTSC +}; + +static int __devinit timblogiw_probe(struct platform_device *pdev) +{ + int err; + struct timblogiw *lw = NULL; + struct timb_video_platform_data *pdata = pdev->dev.platform_data; + + if (!pdata) { + dev_err(&pdev->dev, "No platform data\n"); + err = -EINVAL; + goto err; + } + + if (!pdata->encoder.module_name) + dev_info(&pdev->dev, "Running without decoder\n"); + + lw = kzalloc(sizeof(*lw), GFP_KERNEL); + if (!lw) { + err = -ENOMEM; + goto err; + } + + if (pdev->dev.parent) + lw->dev = pdev->dev.parent; + else + lw->dev = &pdev->dev; + + memcpy(&lw->pdata, pdata, sizeof(lw->pdata)); + + mutex_init(&lw->lock); + + lw->video_dev = timblogiw_template; + + strlcpy(lw->v4l2_dev.name, DRIVER_NAME, sizeof(lw->v4l2_dev.name)); + err = v4l2_device_register(NULL, &lw->v4l2_dev); + if (err) + goto err_register; + + lw->video_dev.v4l2_dev = &lw->v4l2_dev; + + platform_set_drvdata(pdev, lw); + video_set_drvdata(&lw->video_dev, lw); + + err = video_register_device(&lw->video_dev, VFL_TYPE_GRABBER, 0); + if (err) { + dev_err(&pdev->dev, "Error reg video: %d\n", err); + goto err_request; + } + + + return 0; + +err_request: + platform_set_drvdata(pdev, NULL); + v4l2_device_unregister(&lw->v4l2_dev); +err_register: + kfree(lw); +err: + dev_err(&pdev->dev, "Failed to register: %d\n", err); + + return err; +} + +static int __devexit timblogiw_remove(struct platform_device *pdev) +{ + struct timblogiw *lw = platform_get_drvdata(pdev); + + video_unregister_device(&lw->video_dev); + + v4l2_device_unregister(&lw->v4l2_dev); + + kfree(lw); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver timblogiw_platform_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, + .probe = timblogiw_probe, + .remove = __devexit_p(timblogiw_remove), +}; + +/* Module functions */ + +static int __init timblogiw_init(void) +{ + return platform_driver_register(&timblogiw_platform_driver); +} + +static void __exit timblogiw_exit(void) +{ + platform_driver_unregister(&timblogiw_platform_driver); +} + +module_init(timblogiw_init); +module_exit(timblogiw_exit); + +MODULE_DESCRIPTION(TIMBLOGIWIN_NAME); +MODULE_AUTHOR("Pelagicore AB "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:"DRIVER_NAME); diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c index 727f62c..e948a2b 100644 --- a/drivers/mfd/timberdale.c +++ b/drivers/mfd/timberdale.c @@ -271,11 +271,9 @@ static __devinitdata struct timb_radio_platform_data timberdale_radio_platform_data = { .i2c_adapter = 0, .tuner = { - .module_name = "tef6862", .info = &timberdale_tef6868_i2c_board_info }, .dsp = { - .module_name = "saa7706h", .info = &timberdale_saa7706_i2c_board_info } }; diff --git a/include/media/timb_radio.h b/include/media/timb_radio.h index fcd32a3..a59a848 100644 --- a/include/media/timb_radio.h +++ b/include/media/timb_radio.h @@ -24,7 +24,6 @@ struct timb_radio_platform_data { int i2c_adapter; /* I2C adapter where the tuner and dsp are attached */ struct { - const char *module_name; struct i2c_board_info *info; } tuner; struct { diff --git a/include/media/timb_video.h b/include/media/timb_video.h new file mode 100644 index 0000000..70ae439 --- /dev/null +++ b/include/media/timb_video.h @@ -0,0 +1,33 @@ +/* + * timb_video.h Platform struct for the Timberdale video driver + * Copyright (c) 2009-2010 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _TIMB_VIDEO_ +#define _TIMB_VIDEO_ 1 + +#include + +struct timb_video_platform_data { + int dma_channel; + int i2c_adapter; /* The I2C adapter where the encoder is attached */ + struct { + const char *module_name; + struct i2c_board_info *info; + } encoder; +}; + +#endif -- cgit v0.10.2 From c091575c8b35b39b8f271e0d4b692329a705240a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=83=C2=B6jfors?= Date: Mon, 8 Nov 2010 10:45:48 -0300 Subject: [media] mfd: Add timberdale video-in driver to timberdale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch defines platform data for the video-in driver and adds it to all configurations of timberdale. Signed-off-by: Richard Röjfors Acked-by: Samuel Ortiz Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c index e948a2b..6ad8a7f 100644 --- a/drivers/mfd/timberdale.c +++ b/drivers/mfd/timberdale.c @@ -40,6 +40,7 @@ #include #include +#include #include @@ -246,7 +247,23 @@ static const __devinitconst struct resource timberdale_uartlite_resources[] = { }, }; -static const __devinitconst struct resource timberdale_radio_resources[] = { +static __devinitdata struct i2c_board_info timberdale_adv7180_i2c_board_info = { + /* Requires jumper JP9 to be off */ + I2C_BOARD_INFO("adv7180", 0x42 >> 1), + .irq = IRQ_TIMBERDALE_ADV7180 +}; + +static __devinitdata struct timb_video_platform_data + timberdale_video_platform_data = { + .dma_channel = DMA_VIDEO_RX, + .i2c_adapter = 0, + .encoder = { + .info = &timberdale_adv7180_i2c_board_info + } +}; + +static const __devinitconst struct resource +timberdale_radio_resources[] = { { .start = RDSOFFSET, .end = RDSEND, @@ -278,6 +295,18 @@ static __devinitdata struct timb_radio_platform_data } }; +static const __devinitconst struct resource timberdale_video_resources[] = { + { + .start = LOGIWOFFSET, + .end = LOGIWEND, + .flags = IORESOURCE_MEM, + }, + /* + note that the "frame buffer" is located in DMA area + starting at 0x1200000 + */ +}; + static __devinitdata struct timb_dma_platform_data timb_dma_platform_data = { .nr_channels = 10, .channels = { @@ -378,6 +407,13 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = { .data_size = sizeof(timberdale_gpio_platform_data), }, { + .name = "timb-video", + .num_resources = ARRAY_SIZE(timberdale_video_resources), + .resources = timberdale_video_resources, + .platform_data = &timberdale_video_platform_data, + .data_size = sizeof(timberdale_video_platform_data), + }, + { .name = "timb-radio", .num_resources = ARRAY_SIZE(timberdale_radio_resources), .resources = timberdale_radio_resources, @@ -438,6 +474,13 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { .resources = timberdale_mlogicore_resources, }, { + .name = "timb-video", + .num_resources = ARRAY_SIZE(timberdale_video_resources), + .resources = timberdale_video_resources, + .platform_data = &timberdale_video_platform_data, + .data_size = sizeof(timberdale_video_platform_data), + }, + { .name = "timb-radio", .num_resources = ARRAY_SIZE(timberdale_radio_resources), .resources = timberdale_radio_resources, @@ -488,6 +531,13 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = { .data_size = sizeof(timberdale_gpio_platform_data), }, { + .name = "timb-video", + .num_resources = ARRAY_SIZE(timberdale_video_resources), + .resources = timberdale_video_resources, + .platform_data = &timberdale_video_platform_data, + .data_size = sizeof(timberdale_video_platform_data), + }, + { .name = "timb-radio", .num_resources = ARRAY_SIZE(timberdale_radio_resources), .resources = timberdale_radio_resources, @@ -531,6 +581,13 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = { .data_size = sizeof(timberdale_gpio_platform_data), }, { + .name = "timb-video", + .num_resources = ARRAY_SIZE(timberdale_video_resources), + .resources = timberdale_video_resources, + .platform_data = &timberdale_video_platform_data, + .data_size = sizeof(timberdale_video_platform_data), + }, + { .name = "timb-radio", .num_resources = ARRAY_SIZE(timberdale_radio_resources), .resources = timberdale_radio_resources, diff --git a/drivers/mfd/timberdale.h b/drivers/mfd/timberdale.h index c11bf6e..4412acd 100644 --- a/drivers/mfd/timberdale.h +++ b/drivers/mfd/timberdale.h @@ -23,7 +23,7 @@ #ifndef MFD_TIMBERDALE_H #define MFD_TIMBERDALE_H -#define DRV_VERSION "0.2" +#define DRV_VERSION "0.3" /* This driver only support versions >= 3.8 and < 4.0 */ #define TIMB_SUPPORTED_MAJOR 3 -- cgit v0.10.2 From 9c0147b6941e082f52dcbb9688d0e6e5f359744f Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 24 Nov 2010 16:41:09 -0300 Subject: [media] timblogiw: fix kconfig & build error timblogiw uses dma() interfaces and it selects TIMB_DMA for that support. However, drivers/dma/ is not built unless CONFIG_DMA_ENGINE is enabled, so select/enable that symbol also. drivers/built-in.o: In function `timblogiw_close': timblogiw.c:(.text+0x4419fe): undefined reference to `dma_release_channel' drivers/built-in.o: In function `buffer_release': timblogiw.c:(.text+0x441a8d): undefined reference to `dma_sync_wait' drivers/built-in.o: In function `timblogiw_open': timblogiw.c:(.text+0x44212b): undefined reference to `__dma_request_channel' Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 73962d6..963b3e6 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -669,6 +669,7 @@ config VIDEO_HEXIUM_GEMINI config VIDEO_TIMBERDALE tristate "Support for timberdale Video In/LogiWIN" depends on VIDEO_V4L2 && I2C + select DMA_ENGINE select TIMB_DMA select VIDEO_ADV7180 select VIDEOBUF_DMA_CONTIG -- cgit v0.10.2 From 9a9dcb4a19c29ec01e7d249e3dae2d589af86480 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 8 Nov 2010 20:08:41 -0300 Subject: [media] cx231xx-417: Remove unnecessary casts of void ptr returning alloc function return values Hi, The [vk][cmz]alloc(_node) family of functions return void pointers which it's completely unnecessary/pointless to cast to other pointer types since that happens implicitly. This patch removes such casts from drivers/media/ Signed-off-by: Jesper Juhl Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx231xx/cx231xx-417.c b/drivers/media/video/cx231xx/cx231xx-417.c index 4c7cac3..fc9526a 100644 --- a/drivers/media/video/cx231xx/cx231xx-417.c +++ b/drivers/media/video/cx231xx/cx231xx-417.c @@ -940,14 +940,14 @@ static int cx231xx_load_firmware(struct cx231xx *dev) u16 _buffer_size = 4096; u8 *p_buffer; - p_current_fw = (u32 *)vmalloc(1884180*4); + p_current_fw = vmalloc(1884180 * 4); p_fw = p_current_fw; if (p_current_fw == 0) { dprintk(2, "FAIL!!!\n"); return -1; } - p_buffer = (u8 *)vmalloc(4096); + p_buffer = vmalloc(4096); if (p_buffer == 0) { dprintk(2, "FAIL!!!\n"); return -1; -- cgit v0.10.2 From c0ff9f4c24a2571943c0d0991c2cb9ac90dc1915 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 10 Nov 2010 11:14:13 -0300 Subject: [media] media: video: do not clear 'driver' from an i2c_client The i2c-core does this already. Reported-by: Jean Delvare Signed-off-by: Wolfram Sang Acked-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/imx074.c b/drivers/media/video/imx074.c index 27b5dfd..b9c91c1 100644 --- a/drivers/media/video/imx074.c +++ b/drivers/media/video/imx074.c @@ -467,7 +467,7 @@ static int imx074_remove(struct i2c_client *client) icd->ops = NULL; if (icl->free_bus) icl->free_bus(icl); - client->driver = NULL; + i2c_set_clientdata(client, NULL); kfree(priv); return 0; diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index fcb4cd9..f7fc88d 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -798,7 +798,6 @@ static int mt9m001_remove(struct i2c_client *client) icd->ops = NULL; mt9m001_video_remove(icd); - client->driver = NULL; kfree(mt9m001); return 0; diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index 525a16e..53fa2a7 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c @@ -1092,7 +1092,6 @@ static int mt9m111_remove(struct i2c_client *client) struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; - client->driver = NULL; kfree(mt9m111); return 0; diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index 9bd44a8..7ce279c 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c @@ -896,7 +896,6 @@ static int mt9t031_remove(struct i2c_client *client) if (icd) icd->ops = NULL; - client->driver = NULL; kfree(mt9t031); return 0; diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index b96171c..6a784c8 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -930,7 +930,6 @@ static int mt9v022_remove(struct i2c_client *client) icd->ops = NULL; mt9v022_video_remove(icd); - client->driver = NULL; kfree(mt9v022); return 0; diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c index d2fa2d4..57e11b6 100644 --- a/drivers/media/video/rj54n1cb0c.c +++ b/drivers/media/video/rj54n1cb0c.c @@ -1460,7 +1460,6 @@ static int rj54n1_remove(struct i2c_client *client) icd->ops = NULL; if (icl->free_bus) icl->free_bus(icl); - client->driver = NULL; kfree(rj54n1); return 0; -- cgit v0.10.2 From e6f199f3e7e10112adfa80700ecc00b056b5a62e Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 10 Nov 2010 09:28:19 -0300 Subject: [media] i2c: Remove obsolete cleanup for clientdata A few new i2c-drivers came into the kernel which clear the clientdata-pointer on exit. This is obsolete meanwhile, so fix it and hope the word will spread. Signed-off-by: Wolfram Sang Acked-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/imx074.c b/drivers/media/video/imx074.c index b9c91c1..1a11691 100644 --- a/drivers/media/video/imx074.c +++ b/drivers/media/video/imx074.c @@ -467,7 +467,6 @@ static int imx074_remove(struct i2c_client *client) icd->ops = NULL; if (icl->free_bus) icl->free_bus(icl); - i2c_set_clientdata(client, NULL); kfree(priv); return 0; -- cgit v0.10.2 From 116d588ea21cf0278a4de1e3272e9c3220a647e7 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 11 Feb 2010 04:11:05 -0300 Subject: [media] Mantis, hopper: use MODULE_DEVICE_TABLE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use the macro to make modules auto-loadable Thanks to Ozan ÇaÄŸlayan for pointing it out Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c index 09e9fc7..70e73af 100644 --- a/drivers/media/dvb/mantis/hopper_cards.c +++ b/drivers/media/dvb/mantis/hopper_cards.c @@ -251,6 +251,8 @@ static struct pci_device_id hopper_pci_table[] = { { } }; +MODULE_DEVICE_TABLE(pci, hopper_pci_table); + static struct pci_driver hopper_pci_driver = { .name = DRIVER_NAME, .id_table = hopper_pci_table, diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c index cf4b39f..40da225 100644 --- a/drivers/media/dvb/mantis/mantis_cards.c +++ b/drivers/media/dvb/mantis/mantis_cards.c @@ -281,6 +281,8 @@ static struct pci_device_id mantis_pci_table[] = { { } }; +MODULE_DEVICE_TABLE(pci, mantis_pci_table); + static struct pci_driver mantis_pci_driver = { .name = DRIVER_NAME, .id_table = mantis_pci_table, -- cgit v0.10.2 From 9c81496a88b04206d0607b23b298b6529da1fcb0 Mon Sep 17 00:00:00 2001 From: Marko Ristola Date: Sun, 14 Nov 2010 14:09:04 -0300 Subject: [media] Mantis: append tasklet maintenance for DVB stream delivery After dvb-core has called mantis-fe->stop_feed(dvbdmxfeed) the last time (count to zero), no data should ever be copied with dvb_dmx_swfilter() by a tasklet: the target structure might be in an unusable state. Caller of mantis_fe->stop_feed() assumes that feeding is stopped after stop_feed() has been called, ie. dvb_dmx_swfilter() isn't running, and won't be called. There is a risk that dvb_dmx_swfilter() references freed resources (memory or spinlocks or ???) causing instabilities. Thus tasklet_disable(&mantis->tasklet) must be called inside of mantis-fe->stop_feed(dvbdmxfeed) when necessary. Signed-off-by: Marko Ristola Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 99d82ee..a9864f7 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -117,6 +117,7 @@ static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) if (mantis->feeds == 1) { dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma"); mantis_dma_start(mantis); + tasklet_enable(&mantis->tasklet); } return mantis->feeds; @@ -136,6 +137,7 @@ static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) mantis->feeds--; if (mantis->feeds == 0) { dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma"); + tasklet_disable(&mantis->tasklet); mantis_dma_stop(mantis); } @@ -216,6 +218,7 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis) dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx); tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis); + tasklet_disable(&mantis->tasklet); if (mantis->hwconfig) { result = config->frontend_init(mantis, mantis->fe); if (result < 0) { -- cgit v0.10.2 From a22407faba57c3624beea1a9fad7cbdcf5a19a1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Sun, 14 Nov 2010 14:24:36 -0300 Subject: [media] Mantis: use dvb_attach to avoid double dereferencing on module removal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert the driver to use the dvb_attach macro to avoid the hard dependency on the frontend drivers. The hard dependecy will result in loading a number of unused frontends, and unwanted automatic dereferencing. This fixes a bug where unloading the mantis driver will derefence any attached frontend twice, which will cause an oops if the same frontend is used by another driver. Signed-off-by: Bjørn Mork Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/mantis/hopper_vp3028.c b/drivers/media/dvb/mantis/hopper_vp3028.c index 96674c7..567ed24 100644 --- a/drivers/media/dvb/mantis/hopper_vp3028.c +++ b/drivers/media/dvb/mantis/hopper_vp3028.c @@ -57,7 +57,7 @@ static int vp3028_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * if (err == 0) { msleep(250); dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); - fe = zl10353_attach(&hopper_vp3028_config, adapter); + fe = dvb_attach(zl10353_attach, &hopper_vp3028_config, adapter); if (!fe) return -1; diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index 4a723bd..deec927 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -173,7 +173,7 @@ static int vp1033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * msleep(250); dprintk(MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)"); - fe = stv0299_attach(&lgtdqcs001f_config, adapter); + fe = dvb_attach(stv0299_attach, &lgtdqcs001f_config, adapter); if (fe) { fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set; diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index 8e6ae55..bf62338 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -82,7 +82,7 @@ static int vp1034_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * msleep(250); dprintk(MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); - fe = mb86a16_attach(&vp1034_mb86a16_config, adapter); + fe = dvb_attach(mb86a16_attach, &vp1034_mb86a16_config, adapter); if (fe) { dprintk(MANTIS_ERROR, 1, "found MB86A16 DVB-S/DSS frontend @0x%02x", diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c index d1aa2bc..38a436c 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.c +++ b/drivers/media/dvb/mantis/mantis_vp1041.c @@ -316,14 +316,14 @@ static int vp1041_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * if (err == 0) { mantis_frontend_soft_reset(mantis); msleep(250); - mantis->fe = stb0899_attach(&vp1041_stb0899_config, adapter); + mantis->fe = dvb_attach(stb0899_attach, &vp1041_stb0899_config, adapter); if (mantis->fe) { dprintk(MANTIS_ERROR, 1, "found STB0899 DVB-S/DVB-S2 frontend @0x%02x", vp1041_stb0899_config.demod_address); - if (stb6100_attach(mantis->fe, &vp1041_stb6100_config, adapter)) { - if (!lnbp21_attach(mantis->fe, adapter, 0, 0)) + if (dvb_attach(stb6100_attach, mantis->fe, &vp1041_stb6100_config, adapter)) { + if (!dvb_attach(lnbp21_attach, mantis->fe, adapter, 0, 0)) dprintk(MANTIS_ERROR, 1, "No LNBP21 found!"); } } else { diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index 10ce817..06da0dd 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -132,7 +132,7 @@ static int vp2033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * msleep(250); dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); - fe = tda10021_attach(&vp2033_tda1002x_cu1216_config, + fe = dvb_attach(tda10021_attach, &vp2033_tda1002x_cu1216_config, adapter, read_pwm(mantis)); @@ -141,7 +141,7 @@ static int vp2033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", vp2033_tda1002x_cu1216_config.demod_address); } else { - fe = tda10023_attach(&vp2033_tda10023_cu1216_config, + fe = dvb_attach(tda10023_attach, &vp2033_tda10023_cu1216_config, adapter, read_pwm(mantis)); diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c index a7ca233e8..f72b137 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.c +++ b/drivers/media/dvb/mantis/mantis_vp2040.c @@ -132,7 +132,7 @@ static int vp2040_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * msleep(250); dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); - fe = tda10021_attach(&vp2040_tda1002x_cu1216_config, + fe = dvb_attach(tda10021_attach, &vp2040_tda1002x_cu1216_config, adapter, read_pwm(mantis)); @@ -141,7 +141,7 @@ static int vp2040_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", vp2040_tda1002x_cu1216_config.demod_address); } else { - fe = tda10023_attach(&vp2040_tda10023_cu1216_config, + fe = dvb_attach(tda10023_attach, &vp2040_tda10023_cu1216_config, adapter, read_pwm(mantis)); diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c index 1f43342..be4d87c 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -68,12 +68,12 @@ static int vp3030_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * if (err == 0) { msleep(250); dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); - fe = zl10353_attach(&mantis_vp3030_config, adapter); + fe = dvb_attach(zl10353_attach, &mantis_vp3030_config, adapter); if (!fe) return -1; - tda665x_attach(fe, &env57h12d5_config, adapter); + dvb_attach(tda665x_attach, fe, &env57h12d5_config, adapter); } else { dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", adapter->name, -- cgit v0.10.2 From 3037fd14302d635426996fb7f6fcf7cb98dc15b9 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 14 Nov 2010 14:56:00 -0300 Subject: [media] Mantis: Rename gpio_set_bits to mantis_gpio_set_bits This function is declared extern and exported, and should not be given a generic name which may conflict with gpiolib in future. Signed-off-by: Ben Hutchings Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/mantis/hopper_vp3028.c b/drivers/media/dvb/mantis/hopper_vp3028.c index 567ed24..68a29f8 100644 --- a/drivers/media/dvb/mantis/hopper_vp3028.c +++ b/drivers/media/dvb/mantis/hopper_vp3028.c @@ -47,11 +47,11 @@ static int vp3028_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * struct mantis_hwconfig *config = mantis->hwconfig; int err = 0; - gpio_set_bits(mantis, config->reset, 0); + mantis_gpio_set_bits(mantis, config->reset, 0); msleep(100); err = mantis_frontend_power(mantis, POWER_ON); msleep(100); - gpio_set_bits(mantis, config->reset, 1); + mantis_gpio_set_bits(mantis, config->reset, 1); err = mantis_frontend_power(mantis, POWER_ON); if (err == 0) { diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index a9864f7..e5180e4 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -47,15 +47,15 @@ int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power) switch (power) { case POWER_ON: dprintk(MANTIS_DEBUG, 1, "Power ON"); - gpio_set_bits(mantis, config->power, POWER_ON); + mantis_gpio_set_bits(mantis, config->power, POWER_ON); msleep(100); - gpio_set_bits(mantis, config->power, POWER_ON); + mantis_gpio_set_bits(mantis, config->power, POWER_ON); msleep(100); break; case POWER_OFF: dprintk(MANTIS_DEBUG, 1, "Power OFF"); - gpio_set_bits(mantis, config->power, POWER_OFF); + mantis_gpio_set_bits(mantis, config->power, POWER_OFF); msleep(100); break; @@ -73,13 +73,13 @@ void mantis_frontend_soft_reset(struct mantis_pci *mantis) struct mantis_hwconfig *config = mantis->hwconfig; dprintk(MANTIS_DEBUG, 1, "Frontend RESET"); - gpio_set_bits(mantis, config->reset, 0); + mantis_gpio_set_bits(mantis, config->reset, 0); msleep(100); - gpio_set_bits(mantis, config->reset, 0); + mantis_gpio_set_bits(mantis, config->reset, 0); msleep(100); - gpio_set_bits(mantis, config->reset, 1); + mantis_gpio_set_bits(mantis, config->reset, 1); msleep(100); - gpio_set_bits(mantis, config->reset, 1); + mantis_gpio_set_bits(mantis, config->reset, 1); msleep(100); return; diff --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/dvb/mantis/mantis_ioc.c index fe31cfb..479086d 100644 --- a/drivers/media/dvb/mantis/mantis_ioc.c +++ b/drivers/media/dvb/mantis/mantis_ioc.c @@ -75,7 +75,7 @@ int mantis_get_mac(struct mantis_pci *mantis) EXPORT_SYMBOL_GPL(mantis_get_mac); /* Turn the given bit on or off. */ -void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) +void mantis_gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) { u32 cur; @@ -90,7 +90,7 @@ void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR); mmwrite(0x00, MANTIS_GPIF_DOUT); } -EXPORT_SYMBOL_GPL(gpio_set_bits); +EXPORT_SYMBOL_GPL(mantis_gpio_set_bits); int mantis_stream_control(struct mantis_pci *mantis, enum mantis_stream_control stream_ctl) { diff --git a/drivers/media/dvb/mantis/mantis_ioc.h b/drivers/media/dvb/mantis/mantis_ioc.h index 188fe5a..d56e002 100644 --- a/drivers/media/dvb/mantis/mantis_ioc.h +++ b/drivers/media/dvb/mantis/mantis_ioc.h @@ -44,7 +44,7 @@ enum mantis_stream_control { }; extern int mantis_get_mac(struct mantis_pci *mantis); -extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value); +extern void mantis_gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value); extern int mantis_stream_control(struct mantis_pci *mantis, enum mantis_stream_control stream_ctl); diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index bf62338..26bc0cb 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -50,13 +50,13 @@ int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) switch (voltage) { case SEC_VOLTAGE_13: dprintk(MANTIS_ERROR, 1, "Polarization=[13V]"); - gpio_set_bits(mantis, 13, 1); - gpio_set_bits(mantis, 14, 0); + mantis_gpio_set_bits(mantis, 13, 1); + mantis_gpio_set_bits(mantis, 14, 0); break; case SEC_VOLTAGE_18: dprintk(MANTIS_ERROR, 1, "Polarization=[18V]"); - gpio_set_bits(mantis, 13, 1); - gpio_set_bits(mantis, 14, 1); + mantis_gpio_set_bits(mantis, 13, 1); + mantis_gpio_set_bits(mantis, 14, 1); break; case SEC_VOLTAGE_OFF: dprintk(MANTIS_ERROR, 1, "Frontend (dummy) POWERDOWN"); diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c index be4d87c..c09308cd 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -59,11 +59,11 @@ static int vp3030_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * struct mantis_hwconfig *config = mantis->hwconfig; int err = 0; - gpio_set_bits(mantis, config->reset, 0); + mantis_gpio_set_bits(mantis, config->reset, 0); msleep(100); err = mantis_frontend_power(mantis, POWER_ON); msleep(100); - gpio_set_bits(mantis, config->reset, 1); + mantis_gpio_set_bits(mantis, config->reset, 1); if (err == 0) { msleep(250); -- cgit v0.10.2 From f14bfe94e459cb070a489e1786f26d54e9e7b5de Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sun, 14 Nov 2010 15:52:10 -0300 Subject: [media] stb6100: Improve tuner performance - Reduce the amount of white noise present, which causes the demodulator a significant time to acquire a frontend lock on a whole. Frontend shows a large significant improvement in performance. Thanks to Peter Nayler for helping to identify the potential hotspots and fixing them. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/stb6100.c b/drivers/media/dvb/frontends/stb6100.c index 80a9e4c..db66248 100644 --- a/drivers/media/dvb/frontends/stb6100.c +++ b/drivers/media/dvb/frontends/stb6100.c @@ -51,7 +51,7 @@ module_param(verbose, int, 0644); if (x > y) \ printk(format, ##arg); \ } \ -} while(0) +} while (0) struct stb6100_lkup { u32 val_low; @@ -157,13 +157,25 @@ static int stb6100_read_reg(struct stb6100_state *state, u8 reg) u8 regs[STB6100_NUMREGS]; int rc; + struct i2c_msg msg = { + .addr = state->config->tuner_address + reg, + .flags = I2C_M_RD, + .buf = regs, + .len = 1 + }; + + rc = i2c_transfer(state->i2c, &msg, 1); + if (unlikely(reg >= STB6100_NUMREGS)) { dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg); return -EINVAL; } - if ((rc = stb6100_read_regs(state, regs)) < 0) - return rc; - return (unsigned int)regs[reg]; + if (unlikely(verbose > FE_DEBUG)) { + dprintk(verbose, FE_DEBUG, 1, " Read from 0x%02x", state->config->tuner_address); + dprintk(verbose, FE_DEBUG, 1, " %s: 0x%02x", stb6100_regnames[reg], regs[0]); + } + + return (unsigned int)regs[0]; } static int stb6100_write_reg_range(struct stb6100_state *state, u8 buf[], int start, int len) @@ -211,20 +223,17 @@ static int stb6100_write_reg(struct stb6100_state *state, u8 reg, u8 data) return stb6100_write_reg_range(state, &data, reg, 1); } -static int stb6100_write_regs(struct stb6100_state *state, u8 regs[]) -{ - stb6100_normalise_regs(regs); - return stb6100_write_reg_range(state, ®s[1], 1, STB6100_NUMREGS - 1); -} static int stb6100_get_status(struct dvb_frontend *fe, u32 *status) { int rc; struct stb6100_state *state = fe->tuner_priv; - if ((rc = stb6100_read_reg(state, STB6100_LD)) < 0) + rc = stb6100_read_reg(state, STB6100_LD); + if (rc < 0) { + dprintk(verbose, FE_ERROR, 1, "%s failed", __func__); return rc; - + } return (rc & STB6100_LD_LOCK) ? TUNER_STATUS_LOCKED : 0; } @@ -234,7 +243,8 @@ static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) u8 f; struct stb6100_state *state = fe->tuner_priv; - if ((rc = stb6100_read_reg(state, STB6100_F)) < 0) + rc = stb6100_read_reg(state, STB6100_F); + if (rc < 0) return rc; f = rc & STB6100_F_F; @@ -265,14 +275,21 @@ static int stb6100_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth) /* Turn on LPF bandwidth setting clock control, * set bandwidth, wait 10ms, turn off. */ - if ((rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d | STB6100_FCCK_FCCK)) < 0) + rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d | STB6100_FCCK_FCCK); + if (rc < 0) return rc; - if ((rc = stb6100_write_reg(state, STB6100_F, 0xc0 | tmp)) < 0) + rc = stb6100_write_reg(state, STB6100_F, 0xc0 | tmp); + if (rc < 0) return rc; - msleep(1); - if ((rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d)) < 0) + + msleep(5); /* This is dangerous as another (related) thread may start */ + + rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d); + if (rc < 0) return rc; + msleep(10); /* This is dangerous as another (related) thread may start */ + return 0; } @@ -284,7 +301,8 @@ static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency) struct stb6100_state *state = fe->tuner_priv; u8 regs[STB6100_NUMREGS]; - if ((rc = stb6100_read_regs(state, regs)) < 0) + rc = stb6100_read_regs(state, regs); + if (rc < 0) return rc; odiv = (regs[STB6100_VCO] & STB6100_VCO_ODIV) >> STB6100_VCO_ODIV_SHIFT; @@ -312,8 +330,7 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency) u8 regs[STB6100_NUMREGS]; u8 g, psd2, odiv; - if ((rc = stb6100_read_regs(state, regs)) < 0) - return rc; + dprintk(verbose, FE_DEBUG, 1, "Version 2010-8-14 13:51"); if (fe->ops.get_frontend) { dprintk(verbose, FE_DEBUG, 1, "Get frontend parameters"); @@ -321,96 +338,140 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency) } srate = p.u.qpsk.symbol_rate; - regs[STB6100_DLB] = 0xdc; - /* Disable LPEN */ - regs[STB6100_LPEN] &= ~STB6100_LPEN_LPEN; /* PLL Loop disabled */ + /* Set up tuner cleanly, LPF calibration on */ + rc = stb6100_write_reg(state, STB6100_FCCK, 0x4d | STB6100_FCCK_FCCK); + if (rc < 0) + return rc; /* allow LPF calibration */ - if ((rc = stb6100_write_regs(state, regs)) < 0) + /* PLL Loop disabled, bias on, VCO on, synth on */ + regs[STB6100_LPEN] = 0xeb; + rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN]); + if (rc < 0) return rc; - /* Baseband gain. */ - if (srate >= 15000000) - g = 9; // +4 dB - else if (srate >= 5000000) - g = 11; // +8 dB - else - g = 14; // +14 dB - - regs[STB6100_G] = (regs[STB6100_G] & ~STB6100_G_G) | g; - regs[STB6100_G] &= ~STB6100_G_GCT; /* mask GCT */ - regs[STB6100_G] |= (1 << 5); /* 2Vp-p Mode */ + /* Program the registers with their data values */ /* VCO divide ratio (LO divide ratio, VCO prescaler enable). */ if (frequency <= 1075000) odiv = 1; else odiv = 0; - regs[STB6100_VCO] = (regs[STB6100_VCO] & ~STB6100_VCO_ODIV) | (odiv << STB6100_VCO_ODIV_SHIFT); - if ((frequency > 1075000) && (frequency <= 1325000)) - psd2 = 0; - else - psd2 = 1; - regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_PSD2) | (psd2 << STB6100_K_PSD2_SHIFT); + /* VCO enabled, seach clock off as per LL3.7, 3.4.1 */ + regs[STB6100_VCO] = 0xe0 | (odiv << STB6100_VCO_ODIV_SHIFT); /* OSM */ for (ptr = lkup; (ptr->val_high != 0) && !CHKRANGE(frequency, ptr->val_low, ptr->val_high); ptr++); + if (ptr->val_high == 0) { printk(KERN_ERR "%s: frequency out of range: %u kHz\n", __func__, frequency); return -EINVAL; } regs[STB6100_VCO] = (regs[STB6100_VCO] & ~STB6100_VCO_OSM) | ptr->reg; + rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO]); + if (rc < 0) + return rc; + if ((frequency > 1075000) && (frequency <= 1325000)) + psd2 = 0; + else + psd2 = 1; /* F(VCO) = F(LO) * (ODIV == 0 ? 2 : 4) */ fvco = frequency << (1 + odiv); /* N(I) = floor(f(VCO) / (f(XTAL) * (PSD2 ? 2 : 1))) */ nint = fvco / (state->reference << psd2); /* N(F) = round(f(VCO) / f(XTAL) * (PSD2 ? 2 : 1) - N(I)) * 2 ^ 9 */ nfrac = DIV_ROUND_CLOSEST((fvco - (nint * state->reference << psd2)) - << (9 - psd2), - state->reference); + << (9 - psd2), state->reference); + + /* NI */ + regs[STB6100_NI] = nint; + rc = stb6100_write_reg(state, STB6100_NI, regs[STB6100_NI]); + if (rc < 0) + return rc; + + /* NF */ + regs[STB6100_NF_LSB] = nfrac; + rc = stb6100_write_reg(state, STB6100_NF_LSB, regs[STB6100_NF_LSB]); + if (rc < 0) + return rc; + + /* K */ + regs[STB6100_K] = (0x38 & ~STB6100_K_PSD2) | (psd2 << STB6100_K_PSD2_SHIFT); + regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_NF_MSB) | ((nfrac >> 8) & STB6100_K_NF_MSB); + rc = stb6100_write_reg(state, STB6100_K, regs[STB6100_K]); + if (rc < 0) + return rc; + + /* G Baseband gain. */ + if (srate >= 15000000) + g = 9; /* +4 dB */ + else if (srate >= 5000000) + g = 11; /* +8 dB */ + else + g = 14; /* +14 dB */ + + regs[STB6100_G] = (0x10 & ~STB6100_G_G) | g; + regs[STB6100_G] &= ~STB6100_G_GCT; /* mask GCT */ + regs[STB6100_G] |= (1 << 5); /* 2Vp-p Mode */ + rc = stb6100_write_reg(state, STB6100_G, regs[STB6100_G]); + if (rc < 0) + return rc; + + /* F we don't write as it is set up in BW set */ + + /* DLB set DC servo loop BW to 160Hz (LLA 3.8 / 2.1) */ + regs[STB6100_DLB] = 0xcc; + rc = stb6100_write_reg(state, STB6100_DLB, regs[STB6100_DLB]); + if (rc < 0) + return rc; + dprintk(verbose, FE_DEBUG, 1, "frequency = %u, srate = %u, g = %u, odiv = %u, psd2 = %u, fxtal = %u, osm = %u, fvco = %u, N(I) = %u, N(F) = %u", frequency, srate, (unsigned int)g, (unsigned int)odiv, (unsigned int)psd2, state->reference, ptr->reg, fvco, nint, nfrac); - regs[STB6100_NI] = nint; - regs[STB6100_NF_LSB] = nfrac; - regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_NF_MSB) | ((nfrac >> 8) & STB6100_K_NF_MSB); - regs[STB6100_VCO] |= STB6100_VCO_OSCH; /* VCO search enabled */ - regs[STB6100_VCO] |= STB6100_VCO_OCK; /* VCO search clock off */ - regs[STB6100_FCCK] |= STB6100_FCCK_FCCK; /* LPF BW setting clock enabled */ - regs[STB6100_LPEN] &= ~STB6100_LPEN_LPEN; /* PLL loop disabled */ - /* Power up. */ - regs[STB6100_LPEN] |= STB6100_LPEN_SYNP | STB6100_LPEN_OSCP | STB6100_LPEN_BEN; - msleep(2); - if ((rc = stb6100_write_regs(state, regs)) < 0) + /* Set up the test registers */ + regs[STB6100_TEST1] = 0x8f; + rc = stb6100_write_reg(state, STB6100_TEST1, regs[STB6100_TEST1]); + if (rc < 0) + return rc; + regs[STB6100_TEST3] = 0xde; + rc = stb6100_write_reg(state, STB6100_TEST3, regs[STB6100_TEST3]); + if (rc < 0) return rc; - msleep(2); - regs[STB6100_LPEN] |= STB6100_LPEN_LPEN; /* PLL loop enabled */ - if ((rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN])) < 0) + /* Bring up tuner according to LLA 3.7 3.4.1, step 2 */ + regs[STB6100_LPEN] = 0xfb; /* PLL Loop enabled, bias on, VCO on, synth on */ + rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN]); + if (rc < 0) return rc; + msleep(2); + + /* Bring up tuner according to LLA 3.7 3.4.1, step 3 */ regs[STB6100_VCO] &= ~STB6100_VCO_OCK; /* VCO fast search */ - if ((rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO])) < 0) + rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO]); + if (rc < 0) return rc; - msleep(10); /* wait for LO to lock */ + msleep(10); /* This is dangerous as another (related) thread may start */ /* wait for LO to lock */ + regs[STB6100_VCO] &= ~STB6100_VCO_OSCH; /* vco search disabled */ regs[STB6100_VCO] |= STB6100_VCO_OCK; /* search clock off */ - if ((rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO])) < 0) - return rc; - regs[STB6100_FCCK] &= ~STB6100_FCCK_FCCK; /* LPF BW clock disabled */ - stb6100_normalise_regs(regs); - if ((rc = stb6100_write_reg_range(state, ®s[1], 1, STB6100_NUMREGS - 3)) < 0) + rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO]); + if (rc < 0) return rc; - msleep(100); + rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d); + if (rc < 0) + return rc; /* Stop LPF calibration */ + msleep(10); /* This is dangerous as another (related) thread may start */ + /* wait for stabilisation, (should not be necessary) */ return 0; } @@ -433,8 +494,8 @@ static int stb6100_init(struct dvb_frontend *fe) state->bandwidth = status->bandwidth * 1000; /* Hz */ state->reference = status->refclock / 1000; /* kHz */ - /* Set default bandwidth. */ - return stb6100_set_bandwidth(fe, state->bandwidth); + /* Set default bandwidth. Modified, PN 13-May-10 */ + return 0; } static int stb6100_get_state(struct dvb_frontend *fe, -- cgit v0.10.2 From 1697c8dfba72fd182d670a68dca157f64dd3b1f2 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sun, 14 Nov 2010 16:01:47 -0300 Subject: [media] stb0899: fix diseqc messages getting lost - Some badly written applications in conjuction with certain SEC devices do send too many messages causing the DiSEqC bus to get congested. As a result, the end devices do get confused and hence do not respond. The issue was found by Julian Scheel. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb/frontends/stb0899_drv.c index 8e38fce..37a222d 100644 --- a/drivers/media/dvb/frontends/stb0899_drv.c +++ b/drivers/media/dvb/frontends/stb0899_drv.c @@ -714,7 +714,7 @@ static int stb0899_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_ma reg = stb0899_read_reg(state, STB0899_DISCNTRL1); STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0); stb0899_write_reg(state, STB0899_DISCNTRL1, reg); - + msleep(100); return 0; } -- cgit v0.10.2 From bce8d0fe4af4b3a1e46e66cd6116d6389ad0cc22 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2010 09:58:09 -0300 Subject: [media] rc: remove ir-common module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Something weird happened with commit 740069e6e043403199dbe2b42256722fb814f6ae. Instead of dong the right thing, it got somehow corrupted and reverted the rc changes. Thanks to David Härdeman for pointing me about the problem. This patch should be merged with 740069e6e04 before sending upstream. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 2d15468..ef193758 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -10,11 +10,6 @@ menuconfig IR_CORE if you don't need IR, as otherwise, you may not be able to compile the driver for your adapter. -config IR_LEGACY - tristate - depends on IR_CORE - default IR_CORE - if IR_CORE config LIRC diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 859c12c..8c0e4cb 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -1,10 +1,8 @@ -ir-common-objs := ir-functions.o rc-core-objs := rc-main.o rc-raw.o obj-y += keymaps/ obj-$(CONFIG_IR_CORE) += rc-core.o -obj-$(CONFIG_IR_LEGACY) += ir-common.o obj-$(CONFIG_LIRC) += lirc_dev.o obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o diff --git a/drivers/media/rc/ir-functions.c b/drivers/media/rc/ir-functions.c deleted file mode 100644 index 14397d0..0000000 --- a/drivers/media/rc/ir-functions.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * some common functions to handle infrared remote protocol decoding for - * drivers which have not yet been (or can't be) converted to use the - * regular protocol decoders... - * - * (c) 2003 Gerd Knorr [SuSE Labs] - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include "rc-core-priv.h" - -/* -------------------------------------------------------------------------- */ - -MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); -MODULE_LICENSE("GPL"); - -/* RC5 decoding stuff, moved from bttv-input.c to share it with - * saa7134 */ - -/* decode raw bit pattern to RC5 code */ -static u32 ir_rc5_decode(unsigned int code) -{ - unsigned int org_code = code; - unsigned int pair; - unsigned int rc5 = 0; - int i; - - for (i = 0; i < 14; ++i) { - pair = code & 0x3; - code >>= 2; - - rc5 <<= 1; - switch (pair) { - case 0: - case 2: - break; - case 1: - rc5 |= 1; - break; - case 3: - IR_dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code); - return 0; - } - } - IR_dprintk(1, "ir-common: code=%x, rc5=%x, start=%x, toggle=%x, address=%x, " - "instr=%x\n", rc5, org_code, RC5_START(rc5), - RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); - return rc5; -} - -void ir_rc5_timer_end(unsigned long data) -{ - struct card_ir *ir = (struct card_ir *)data; - struct timeval tv; - unsigned long current_jiffies; - u32 gap; - u32 rc5 = 0; - - /* get time */ - current_jiffies = jiffies; - do_gettimeofday(&tv); - - /* avoid overflow with gap >1s */ - if (tv.tv_sec - ir->base_time.tv_sec > 1) { - gap = 200000; - } else { - gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + - tv.tv_usec - ir->base_time.tv_usec; - } - - /* signal we're ready to start a new code */ - ir->active = 0; - - /* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */ - if (gap < 28000) { - IR_dprintk(1, "ir-common: spurious timer_end\n"); - return; - } - - if (ir->last_bit < 20) { - /* ignore spurious codes (caused by light/other remotes) */ - IR_dprintk(1, "ir-common: short code: %x\n", ir->code); - } else { - ir->code = (ir->code << ir->shift_by) | 1; - rc5 = ir_rc5_decode(ir->code); - - /* two start bits? */ - if (RC5_START(rc5) != ir->start) { - IR_dprintk(1, "ir-common: rc5 start bits invalid: %u\n", RC5_START(rc5)); - - /* right address? */ - } else if (RC5_ADDR(rc5) == ir->addr) { - u32 toggle = RC5_TOGGLE(rc5); - u32 instr = RC5_INSTR(rc5); - - /* Good code */ - ir_keydown(ir->dev, instr, toggle); - IR_dprintk(1, "ir-common: instruction %x, toggle %x\n", - instr, toggle); - } - } -} -EXPORT_SYMBOL_GPL(ir_rc5_timer_end); diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig index 659e448..3c7c0a5 100644 --- a/drivers/media/video/bt8xx/Kconfig +++ b/drivers/media/video/bt8xx/Kconfig @@ -4,7 +4,7 @@ config VIDEO_BT848 select I2C_ALGOBIT select VIDEO_BTCX select VIDEOBUF_DMA_SG - depends on IR_LEGACY + depends on IR_CORE select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 4b4f613..e8f60ab 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -140,7 +140,100 @@ static void bttv_input_timer(unsigned long data) mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); } -/* ---------------------------------------------------------------*/ +/* + * FIXME: Nebula digi uses the legacy way to decode RC5, instead of relying + * on the rc-core way. As we need to be sure that both IRQ transitions are + * properly triggered, Better to touch it only with this hardware for + * testing. + */ + +/* decode raw bit pattern to RC5 code */ +static u32 bttv_rc5_decode(unsigned int code) +{ + unsigned int org_code = code; + unsigned int pair; + unsigned int rc5 = 0; + int i; + + for (i = 0; i < 14; ++i) { + pair = code & 0x3; + code >>= 2; + + rc5 <<= 1; + switch (pair) { + case 0: + case 2: + break; + case 1: + rc5 |= 1; + break; + case 3: + dprintk(KERN_INFO DEVNAME ":rc5_decode(%x) bad code\n", + org_code); + return 0; + } + } + dprintk(KERN_INFO DEVNAME ":" + "code=%x, rc5=%x, start=%x, toggle=%x, address=%x, " + "instr=%x\n", rc5, org_code, RC5_START(rc5), + RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); + return rc5; +} + +void bttv_rc5_timer_end(unsigned long data) +{ + struct card_ir *ir = (struct card_ir *)data; + struct timeval tv; + unsigned long current_jiffies; + u32 gap; + u32 rc5 = 0; + + /* get time */ + current_jiffies = jiffies; + do_gettimeofday(&tv); + + /* avoid overflow with gap >1s */ + if (tv.tv_sec - ir->base_time.tv_sec > 1) { + gap = 200000; + } else { + gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + + tv.tv_usec - ir->base_time.tv_usec; + } + + /* signal we're ready to start a new code */ + ir->active = 0; + + /* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */ + if (gap < 28000) { + dprintk(KERN_INFO DEVNAME ": spurious timer_end\n"); + return; + } + + if (ir->last_bit < 20) { + /* ignore spurious codes (caused by light/other remotes) */ + dprintk(KERN_INFO DEVNAME ": short code: %x\n", ir->code); + } else { + ir->code = (ir->code << ir->shift_by) | 1; + rc5 = bttv_rc5_decode(ir->code); + + /* two start bits? */ + if (RC5_START(rc5) != ir->start) { + printk(KERN_INFO DEVNAME ":" + " rc5 start bits invalid: %u\n", RC5_START(rc5)); + + /* right address? */ + } else if (RC5_ADDR(rc5) == ir->addr) { + u32 toggle = RC5_TOGGLE(rc5); + u32 instr = RC5_INSTR(rc5); + + /* Good code */ + ir_keydown(ir->dev, instr, toggle); + dprintk(KERN_INFO DEVNAME ":" + " instruction %x, toggle %x\n", + instr, toggle); + } + } +} static int bttv_rc5_irq(struct bttv *btv) { @@ -206,7 +299,7 @@ static void bttv_ir_start(struct bttv *btv, struct card_ir *ir) } else if (ir->rc5_gpio) { /* set timer_end for code completion */ init_timer(&ir->timer_end); - ir->timer_end.function = ir_rc5_timer_end; + ir->timer_end.function = bttv_rc5_timer_end; ir->timer_end.data = (unsigned long)ir; ir->shift_by = 1; ir->start = 3; @@ -283,10 +376,10 @@ void __devinit init_bttv_i2c_ir(struct bttv *btv) default: /* * The external IR receiver is at i2c address 0x34 (0x35 for - * reads). Future Hauppauge cards will have an internal - * receiver at 0x30 (0x31 for reads). In theory, both can be - * fitted, and Hauppauge suggest an external overrides an - * internal. + * reads). Future Hauppauge cards will have an internal + * receiver at 0x30 (0x31 for reads). In theory, both can be + * fitted, and Hauppauge suggest an external overrides an + * internal. * That's why we probe 0x1a (~0x34) first. CB */ diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index 32a95a2..e03bff9 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig @@ -26,7 +26,7 @@ config VIDEO_SAA7134_ALSA config VIDEO_SAA7134_RC bool "Philips SAA7134 Remote Controller support" - depends on IR_LEGACY + depends on IR_CORE depends on VIDEO_SAA7134 default y ---help--- diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index fbb2ff1..72562b8 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -54,11 +54,8 @@ MODULE_PARM_DESC(disable_other_ir, "disable full codes of " #define i2cdprintk(fmt, arg...) if (ir_debug) \ printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg) -/* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */ -static int saa7134_rc5_irq(struct saa7134_dev *dev); -static int saa7134_nec_irq(struct saa7134_dev *dev); +/* Helper function for raw decoding at GPIO16 or GPIO18 */ static int saa7134_raw_decode_irq(struct saa7134_dev *dev); -static void nec_task(unsigned long data); /* -------------------- GPIO generic keycode builder -------------------- */ @@ -397,12 +394,8 @@ void saa7134_input_irq(struct saa7134_dev *dev) if (!ir->running) return; - if (ir->nec_gpio) { - saa7134_nec_irq(dev); - } else if (!ir->polling && !ir->rc5_gpio && !ir->raw_decode) { + if (!ir->polling && !ir->raw_decode) { build_key(dev); - } else if (ir->rc5_gpio) { - saa7134_rc5_irq(dev); } else if (ir->raw_decode) { saa7134_raw_decode_irq(dev); } @@ -448,17 +441,6 @@ static int __saa7134_ir_start(void *priv) (unsigned long)dev); ir->timer.expires = jiffies + HZ; add_timer(&ir->timer); - } else if (ir->rc5_gpio) { - /* set timer_end for code completion */ - init_timer(&ir->timer_end); - ir->timer_end.function = ir_rc5_timer_end; - ir->timer_end.data = (unsigned long)ir; - ir->shift_by = 2; - ir->start = 0x2; - ir->addr = 0x17; - ir->rc5_remote_gap = ir_rc5_remote_gap; - } else if (ir->nec_gpio) { - tasklet_init(&ir->tlet, nec_task, (unsigned long)dev); } else if (ir->raw_decode) { /* set timer_end for code completion */ init_timer(&ir->timer_end); @@ -486,10 +468,6 @@ static void __saa7134_ir_stop(void *priv) return; if (dev->remote->polling) del_timer_sync(&dev->remote->timer); - else if (ir->rc5_gpio) - del_timer_sync(&ir->timer_end); - else if (ir->nec_gpio) - tasklet_kill(&ir->tlet); else if (ir->raw_decode) { del_timer_sync(&ir->timer_end); ir->active = 0; @@ -531,40 +509,6 @@ static void saa7134_ir_close(struct rc_dev *rc) __saa7134_ir_stop(dev); } - -static int saa7134_ir_change_protocol(struct rc_dev *rc, u64 ir_type) -{ - struct saa7134_dev *dev = rc->priv; - struct card_ir *ir = dev->remote; - u32 nec_gpio, rc5_gpio; - - if (ir_type == IR_TYPE_RC5) { - dprintk("Changing protocol to RC5\n"); - nec_gpio = 0; - rc5_gpio = 1; - } else if (ir_type == IR_TYPE_NEC) { - dprintk("Changing protocol to NEC\n"); - nec_gpio = 1; - rc5_gpio = 0; - } else { - dprintk("IR protocol type %ud is not supported\n", - (unsigned)ir_type); - return -EINVAL; - } - - if (ir->running) { - saa7134_ir_stop(dev); - ir->nec_gpio = nec_gpio; - ir->rc5_gpio = rc5_gpio; - saa7134_ir_start(dev); - } else { - ir->nec_gpio = nec_gpio; - ir->rc5_gpio = rc5_gpio; - } - - return 0; -} - int saa7134_input_init1(struct saa7134_dev *dev) { struct card_ir *ir; @@ -574,10 +518,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) u32 mask_keydown = 0; u32 mask_keyup = 0; int polling = 0; - int rc5_gpio = 0; - int nec_gpio = 0; int raw_decode = 0; - int allow_protocol_change = 0; int err; if (dev->has_remote != SAA7134_REMOTE_GPIO) @@ -767,9 +708,10 @@ int saa7134_input_init1(struct saa7134_dev *dev) break; case SAA7134_BOARD_ENCORE_ENLTV_FM53: ir_codes = RC_MAP_ENCORE_ENLTV_FM53; - mask_keydown = 0x0040000; - mask_keycode = 0x00007f; - nec_gpio = 1; + mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ + mask_keyup = 0x0040000; + mask_keycode = 0xffff; + raw_decode = 1; break; case SAA7134_BOARD_10MOONSTVMASTER3: ir_codes = RC_MAP_ENCORE_ENLTV; @@ -829,8 +771,6 @@ int saa7134_input_init1(struct saa7134_dev *dev) ir->mask_keydown = mask_keydown; ir->mask_keyup = mask_keyup; ir->polling = polling; - ir->rc5_gpio = rc5_gpio; - ir->nec_gpio = nec_gpio; ir->raw_decode = raw_decode; /* init input device */ @@ -845,11 +785,6 @@ int saa7134_input_init1(struct saa7134_dev *dev) if (raw_decode) rc->driver_type = RC_DRIVER_IR_RAW; - if (!raw_decode && allow_protocol_change) { - rc->allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; - rc->change_protocol = saa7134_ir_change_protocol; - } - rc->input_name = ir->name; rc->input_phys = ir->phys; rc->input_id.bustype = BUS_PCI; @@ -1023,152 +958,3 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev) return 1; } - -static int saa7134_rc5_irq(struct saa7134_dev *dev) -{ - struct card_ir *ir = dev->remote; - struct timeval tv; - u32 gap; - unsigned long current_jiffies, timeout; - - /* get time of bit */ - current_jiffies = jiffies; - do_gettimeofday(&tv); - - /* avoid overflow with gap >1s */ - if (tv.tv_sec - ir->base_time.tv_sec > 1) { - gap = 200000; - } else { - gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + - tv.tv_usec - ir->base_time.tv_usec; - } - - /* active code => add bit */ - if (ir->active) { - /* only if in the code (otherwise spurious IRQ or timer - late) */ - if (ir->last_bit < 28) { - ir->last_bit = (gap - ir_rc5_remote_gap / 2) / - ir_rc5_remote_gap; - ir->code |= 1 << ir->last_bit; - } - /* starting new code */ - } else { - ir->active = 1; - ir->code = 0; - ir->base_time = tv; - ir->last_bit = 0; - - timeout = current_jiffies + (500 + 30 * HZ) / 1000; - mod_timer(&ir->timer_end, timeout); - } - - return 1; -} - -static void nec_task(unsigned long data) -{ - struct saa7134_dev *dev = (struct saa7134_dev *) data; - struct card_ir *ir; - struct timeval tv; - int count, pulse, oldpulse, gap; - u32 ircode = 0, not_code = 0; - int ngap = 0; - - if (!data) { - printk(KERN_ERR "saa713x/ir: Can't recover dev struct\n"); - /* GPIO will be kept disabled */ - return; - } - - ir = dev->remote; - - /* rising SAA7134_GPIO_GPRESCAN reads the status */ - saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - - oldpulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; - pulse = oldpulse; - - do_gettimeofday(&tv); - ir->base_time = tv; - - /* Decode NEC pulsecode. This code can take up to 76.5 ms to run. - Unfortunately, using IRQ to decode pulse didn't work, since it uses - a pulse train of 38KHz. This means one pulse on each 52 us - */ - do { - /* Wait until the end of pulse/space or 5 ms */ - for (count = 0; count < 500; count++) { - udelay(10); - /* rising SAA7134_GPIO_GPRESCAN reads the status */ - saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); - pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) - & ir->mask_keydown; - if (pulse != oldpulse) - break; - } - - do_gettimeofday(&tv); - gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + - tv.tv_usec - ir->base_time.tv_usec; - - if (!pulse) { - /* Bit 0 has 560 us, while bit 1 has 1120 us. - Do something only if bit == 1 - */ - if (ngap && (gap > 560 + 280)) { - unsigned int shift = ngap - 1; - - /* Address first, then command */ - if (shift < 8) { - shift += 8; - ircode |= 1 << shift; - } else if (shift < 16) { - not_code |= 1 << shift; - } else if (shift < 24) { - shift -= 16; - ircode |= 1 << shift; - } else { - shift -= 24; - not_code |= 1 << shift; - } - } - ngap++; - } - - - ir->base_time = tv; - - /* TIMEOUT - Long pulse */ - if (gap >= 5000) - break; - oldpulse = pulse; - } while (ngap < 32); - - if (ngap == 32) { - /* FIXME: should check if not_code == ~ircode */ - ir->code = ir_extract_bits(ircode, ir->mask_keycode); - - dprintk("scancode = 0x%02x (code = 0x%02x, notcode= 0x%02x)\n", - ir->code, ircode, not_code); - - ir_keydown(ir->dev, ir->code, 0); - } else { - dprintk("Repeat last key\n"); - ir_repeat(ir->dev); - } - - saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P); -} - -static int saa7134_nec_irq(struct saa7134_dev *dev) -{ - struct card_ir *ir = dev->remote; - - saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P); - tasklet_schedule(&ir->tlet); - - return 1; -} diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 4e37b8b..a6c726f 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v0.10.2 From a6e3b81f6198654207c4e972e7ed91931e53e93c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2010 10:05:29 -0300 Subject: [media] rc: Remove ir-common.h Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index e8f60ab..e4df7f8 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -147,6 +147,11 @@ static void bttv_input_timer(unsigned long data) * testing. */ +#define RC5_START(x) (((x) >> 12) & 3) +#define RC5_TOGGLE(x) (((x) >> 11) & 1) +#define RC5_ADDR(x) (((x) >> 6) & 31) +#define RC5_INSTR(x) ((x) & 63) + /* decode raw bit pattern to RC5 code */ static u32 bttv_rc5_decode(unsigned int code) { diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index 6fd2a8e..fd62bf1 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -17,7 +17,6 @@ #include #include #include -#include #include #include diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index 157285b..0bbdd48 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include "bt848.h" @@ -120,6 +120,47 @@ struct bttv_format { int hshift,vshift; /* for planar modes */ }; +struct card_ir { + struct rc_dev *dev; + + char name[32]; + char phys[32]; +#if 0 + int users; + u32 running:1; +#endif + /* Usual gpio signalling */ + u32 mask_keycode; + u32 mask_keydown; + u32 mask_keyup; + u32 polling; + u32 last_gpio; + int shift_by; + int start; // What should RC5_START() be + int addr; // What RC5_ADDR() should be. + int rc5_remote_gap; + struct work_struct work; + struct timer_list timer; + + /* RC5 gpio */ + u32 rc5_gpio; + struct timer_list timer_end; /* timer_end for code completion */ + u32 last_bit; /* last raw bit seen */ + u32 code; /* raw code under construction */ + struct timeval base_time; /* time of last seen code */ + int active; /* building raw code */ + +#if 0 + /* NEC decoding */ + u32 nec_gpio; + struct tasklet_struct tlet; + + /* IR core raw decoding */ + u32 raw_decode; +#endif +}; + + /* ---------------------------------------------------------- */ struct bttv_geometry { diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 72562b8..900e798 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -61,7 +61,7 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev); static int build_key(struct saa7134_dev *dev) { - struct card_ir *ir = dev->remote; + struct saa7134_card_ir *ir = dev->remote; u32 gpio, data; /* here comes the additional handshake steps for some cards */ @@ -385,7 +385,7 @@ static int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) void saa7134_input_irq(struct saa7134_dev *dev) { - struct card_ir *ir; + struct saa7134_card_ir *ir; if (!dev || !dev->remote) return; @@ -404,7 +404,7 @@ void saa7134_input_irq(struct saa7134_dev *dev) static void saa7134_input_timer(unsigned long data) { struct saa7134_dev *dev = (struct saa7134_dev *)data; - struct card_ir *ir = dev->remote; + struct saa7134_card_ir *ir = dev->remote; build_key(dev); mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); @@ -413,17 +413,17 @@ static void saa7134_input_timer(unsigned long data) static void ir_raw_decode_timer_end(unsigned long data) { struct saa7134_dev *dev = (struct saa7134_dev *)data; - struct card_ir *ir = dev->remote; + struct saa7134_card_ir *ir = dev->remote; ir_raw_event_handle(dev->remote->dev); - ir->active = 0; + ir->active = false; } static int __saa7134_ir_start(void *priv) { struct saa7134_dev *dev = priv; - struct card_ir *ir; + struct saa7134_card_ir *ir; if (!dev) return -EINVAL; @@ -435,7 +435,7 @@ static int __saa7134_ir_start(void *priv) if (ir->running) return 0; - ir->running = 1; + ir->running = true; if (ir->polling) { setup_timer(&ir->timer, saa7134_input_timer, (unsigned long)dev); @@ -446,7 +446,7 @@ static int __saa7134_ir_start(void *priv) init_timer(&ir->timer_end); ir->timer_end.function = ir_raw_decode_timer_end; ir->timer_end.data = (unsigned long)dev; - ir->active = 0; + ir->active = false; } return 0; @@ -455,7 +455,7 @@ static int __saa7134_ir_start(void *priv) static void __saa7134_ir_stop(void *priv) { struct saa7134_dev *dev = priv; - struct card_ir *ir; + struct saa7134_card_ir *ir; if (!dev) return; @@ -470,10 +470,10 @@ static void __saa7134_ir_stop(void *priv) del_timer_sync(&dev->remote->timer); else if (ir->raw_decode) { del_timer_sync(&ir->timer_end); - ir->active = 0; + ir->active = false; } - ir->running = 0; + ir->running = false; return; } @@ -511,7 +511,7 @@ static void saa7134_ir_close(struct rc_dev *rc) int saa7134_input_init1(struct saa7134_dev *dev) { - struct card_ir *ir; + struct saa7134_card_ir *ir; struct rc_dev *rc; char *ir_codes = NULL; u32 mask_keycode = 0; @@ -764,7 +764,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) ir->dev = rc; dev->remote = ir; - ir->running = 0; + ir->running = false; /* init hardware-specific stuff */ ir->mask_keycode = mask_keycode; @@ -934,7 +934,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) static int saa7134_raw_decode_irq(struct saa7134_dev *dev) { - struct card_ir *ir = dev->remote; + struct saa7134_card_ir *ir = dev->remote; unsigned long timeout; int space; @@ -953,7 +953,7 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev) if (!ir->active) { timeout = jiffies + jiffies_to_msecs(15); mod_timer(&ir->timer_end, timeout); - ir->active = 1; + ir->active = true; } return 1; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index a6c726f..c6ef95e 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -119,6 +119,27 @@ struct saa7134_format { unsigned int uvswap:1; }; +struct saa7134_card_ir { + struct rc_dev *dev; + + char name[32]; + char phys[32]; + int users; + + u32 polling; + u32 last_gpio; + u32 mask_keycode, mask_keydown, mask_keyup; + + bool running; + bool active; + + struct timer_list timer; + struct timer_list timer_end; /* timer_end for code completion */ + + /* IR core raw decoding */ + u32 raw_decode; +}; + /* ----------------------------------------------------------- */ /* card configuration */ @@ -530,7 +551,7 @@ struct saa7134_dev { /* infrared remote */ int has_remote; - struct card_ir *remote; + struct saa7134_card_ir *remote; /* pci i/o */ char name[32]; diff --git a/include/media/ir-common.h b/include/media/ir-common.h deleted file mode 100644 index 41fefd9..0000000 --- a/include/media/ir-common.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * some common functions to handle infrared remote protocol decoding for - * drivers which have not yet been (or can't be) converted to use the - * regular protocol decoders... - * - * (c) 2003 Gerd Knorr [SuSE Labs] - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _IR_COMMON -#define _IR_COMMON - -#include -#include -#include -#include - -#define RC5_START(x) (((x)>>12)&3) -#define RC5_TOGGLE(x) (((x)>>11)&1) -#define RC5_ADDR(x) (((x)>>6)&31) -#define RC5_INSTR(x) ((x)&63) - -/* this was saa7134_ir and bttv_ir, moved here for - * rc5 decoding. */ -struct card_ir { - struct rc_dev *dev; - char name[32]; - char phys[32]; - int users; - u32 running:1; - - /* Usual gpio signalling */ - u32 mask_keycode; - u32 mask_keydown; - u32 mask_keyup; - u32 polling; - u32 last_gpio; - int shift_by; - int start; // What should RC5_START() be - int addr; // What RC5_ADDR() should be. - int rc5_remote_gap; - struct work_struct work; - struct timer_list timer; - - /* RC5 gpio */ - u32 rc5_gpio; - struct timer_list timer_end; /* timer_end for code completion */ - u32 last_bit; /* last raw bit seen */ - u32 code; /* raw code under construction */ - struct timeval base_time; /* time of last seen code */ - int active; /* building raw code */ - - /* NEC decoding */ - u32 nec_gpio; - struct tasklet_struct tlet; - - /* IR core raw decoding */ - u32 raw_decode; -}; - -/* Routines from ir-functions.c */ -void ir_rc5_timer_end(unsigned long data); - -#endif diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h index aca015e..d27505f 100644 --- a/include/media/ir-kbd-i2c.h +++ b/include/media/ir-kbd-i2c.h @@ -1,7 +1,7 @@ #ifndef _IR_I2C #define _IR_I2C -#include +#include #define DEFAULT_POLLING_INTERVAL 100 /* ms */ -- cgit v0.10.2 From 6bda96447cef24fbf97a798b1ea664224d5fdc25 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2010 13:28:38 -0300 Subject: [media] rc: rename the remaining things to rc_core The Remote Controller subsystem is meant to be used not only by Infra Red but also for similar types of Remote Controllers. The core is not specific to Infra Red. As such, rename: - ir-core.h to rc-core.h - IR_CORE to RC_CORE - namespace inside rc-core.c/rc-core.h To be consistent with the other changes. No functional change on this patch. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/dvb/dm1105/Kconfig index 576f3b7..f3de0a4 100644 --- a/drivers/media/dvb/dm1105/Kconfig +++ b/drivers/media/dvb/dm1105/Kconfig @@ -8,7 +8,7 @@ config DVB_DM1105 select DVB_CX24116 if !DVB_FE_CUSTOMISE select DVB_SI21XX if !DVB_FE_CUSTOMISE select DVB_DS3000 if !DVB_FE_CUSTOMISE - depends on IR_CORE + depends on RC_CORE help Support for cards based on the SDMC DM1105 PCI chip like DvbWorld 2002 diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index d1a4385..e9cacf6 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include "demux.h" #include "dmxdev.h" diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 2525d3b..3d48ba0 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -1,6 +1,6 @@ config DVB_USB tristate "Support for various USB DVB devices" - depends on DVB_CORE && USB && I2C && IR_CORE + depends on DVB_CORE && USB && I2C && RC_CORE help By enabling this you will be able to choose the various supported USB1.1 and USB2.0 DVB devices. diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index 83aa982..18828cb 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include "dvb_frontend.h" #include "dvb_demux.h" diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c index d8f1b15..f0c0308 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/drivers/media/dvb/dvb-usb/lmedm04.c @@ -61,7 +61,7 @@ #define DVB_USB_LOG_PREFIX "LME2510(C)" #include #include -#include +#include #include "dvb-usb.h" #include "lmedm04.h" diff --git a/drivers/media/dvb/mantis/Kconfig b/drivers/media/dvb/mantis/Kconfig index fd0830e..a13a505 100644 --- a/drivers/media/dvb/mantis/Kconfig +++ b/drivers/media/dvb/mantis/Kconfig @@ -1,6 +1,6 @@ config MANTIS_CORE tristate "Mantis/Hopper PCI bridge based devices" - depends on PCI && I2C && INPUT && IR_CORE + depends on PCI && I2C && INPUT && RC_CORE help Support for PCI cards based on the Mantis and Hopper PCi bridge. diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c index 209f211..e030b18 100644 --- a/drivers/media/dvb/mantis/mantis_input.c +++ b/drivers/media/dvb/mantis/mantis_input.c @@ -18,7 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include +#include #include #include "dmxdev.h" diff --git a/drivers/media/dvb/siano/Kconfig b/drivers/media/dvb/siano/Kconfig index e520bce..bc6456e 100644 --- a/drivers/media/dvb/siano/Kconfig +++ b/drivers/media/dvb/siano/Kconfig @@ -4,7 +4,7 @@ config SMS_SIANO_MDTV tristate "Siano SMS1xxx based MDTV receiver" - depends on DVB_CORE && IR_CORE && HAS_DMA + depends on DVB_CORE && RC_CORE && HAS_DMA ---help--- Choose Y or M here if you have MDTV receiver with a Siano chipset. diff --git a/drivers/media/dvb/siano/smsir.h b/drivers/media/dvb/siano/smsir.h index c2f68a4..ae92b3a 100644 --- a/drivers/media/dvb/siano/smsir.h +++ b/drivers/media/dvb/siano/smsir.h @@ -28,7 +28,7 @@ along with this program. If not, see . #define __SMS_IR_H__ #include -#include +#include #define IR_DEFAULT_TIMEOUT 100 diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 0ffd694..44afab2 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -97,7 +97,7 @@ config DVB_BUDGET_CI select DVB_LNBP21 if !DVB_FE_CUSTOMISE select DVB_TDA10023 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE - depends on IR_CORE + depends on RC_CORE help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 9aca0f3..32caa9b 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include "budget.h" diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index ef193758..42b4feb 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -1,16 +1,17 @@ -menuconfig IR_CORE - tristate "Infrared remote controller adapters" +menuconfig RC_CORE + tristate "Remote Controller adapters" depends on INPUT default INPUT ---help--- Enable support for Remote Controllers on Linux. This is needed in order to support several video capture adapters. + Currently, all supported devices use InfraRed. Enable this option if you have a video capture board even if you don't need IR, as otherwise, you may not be able to compile the driver for your adapter. -if IR_CORE +if RC_CORE config LIRC tristate @@ -27,7 +28,7 @@ source "drivers/media/rc/keymaps/Kconfig" config IR_NEC_DECODER tristate "Enable IR raw decoder for the NEC protocol" - depends on IR_CORE + depends on RC_CORE select BITREVERSE default y @@ -37,7 +38,7 @@ config IR_NEC_DECODER config IR_RC5_DECODER tristate "Enable IR raw decoder for the RC-5 protocol" - depends on IR_CORE + depends on RC_CORE select BITREVERSE default y @@ -47,7 +48,7 @@ config IR_RC5_DECODER config IR_RC6_DECODER tristate "Enable IR raw decoder for the RC6 protocol" - depends on IR_CORE + depends on RC_CORE select BITREVERSE default y @@ -57,7 +58,7 @@ config IR_RC6_DECODER config IR_JVC_DECODER tristate "Enable IR raw decoder for the JVC protocol" - depends on IR_CORE + depends on RC_CORE select BITREVERSE default y @@ -67,7 +68,7 @@ config IR_JVC_DECODER config IR_SONY_DECODER tristate "Enable IR raw decoder for the Sony protocol" - depends on IR_CORE + depends on RC_CORE default y ---help--- @@ -76,7 +77,7 @@ config IR_SONY_DECODER config IR_RC5_SZ_DECODER tristate "Enable IR raw decoder for the RC-5 (streamzap) protocol" - depends on IR_CORE + depends on RC_CORE select BITREVERSE default y @@ -88,7 +89,7 @@ config IR_RC5_SZ_DECODER config IR_LIRC_CODEC tristate "Enable IR to LIRC bridge" - depends on IR_CORE + depends on RC_CORE depends on LIRC default y @@ -99,7 +100,7 @@ config IR_LIRC_CODEC config IR_ENE tristate "ENE eHome Receiver/Transceiver (pnp id: ENE0100/ENE02xxx)" depends on PNP - depends on IR_CORE + depends on RC_CORE ---help--- Say Y here to enable support for integrated infrared receiver /transceiver made by ENE. @@ -113,7 +114,7 @@ config IR_ENE config IR_IMON tristate "SoundGraph iMON Receiver and Display" depends on USB_ARCH_HAS_HCD - depends on IR_CORE + depends on RC_CORE select USB ---help--- Say Y here if you want to use a SoundGraph iMON (aka Antec Veris) @@ -125,7 +126,7 @@ config IR_IMON config IR_MCEUSB tristate "Windows Media Center Ed. eHome Infrared Transceiver" depends on USB_ARCH_HAS_HCD - depends on IR_CORE + depends on RC_CORE select USB ---help--- Say Y here if you want to use a Windows Media Center Edition @@ -137,7 +138,7 @@ config IR_MCEUSB config IR_NUVOTON tristate "Nuvoton w836x7hg Consumer Infrared Transceiver" depends on PNP - depends on IR_CORE + depends on RC_CORE ---help--- Say Y here to enable support for integrated infrared receiver /transciever made by Nuvoton (formerly Winbond). This chip is @@ -150,7 +151,7 @@ config IR_NUVOTON config IR_STREAMZAP tristate "Streamzap PC Remote IR Receiver" depends on USB_ARCH_HAS_HCD - depends on IR_CORE + depends on RC_CORE select USB ---help--- Say Y here if you want to use a Streamzap PC Remote @@ -162,7 +163,7 @@ config IR_STREAMZAP config IR_WINBOND_CIR tristate "Winbond IR remote control" depends on X86 && PNP - depends on IR_CORE + depends on RC_CORE select NEW_LEDS select LEDS_CLASS select LEDS_TRIGGERS @@ -176,4 +177,4 @@ config IR_WINBOND_CIR To compile this driver as a module, choose M here: the module will be called winbond_cir. -endif #IR_CORE +endif #RC_CORE diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 8c0e4cb..21251ba 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -2,7 +2,7 @@ rc-core-objs := rc-main.o rc-raw.o obj-y += keymaps/ -obj-$(CONFIG_IR_CORE) += rc-core.o +obj-$(CONFIG_RC_CORE) += rc-core.o obj-$(CONFIG_LIRC) += lirc_dev.o obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c index 0a4151f..1ace458 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include "ene_ir.h" static int sample_period; diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 8d4b35d..b6ba3c7 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index ceabea6..f9086c5 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include "rc-core-priv.h" #define LIRCBUF_SIZE 256 diff --git a/drivers/media/rc/keymaps/Kconfig b/drivers/media/rc/keymaps/Kconfig index 14b22f5..8e615fd 100644 --- a/drivers/media/rc/keymaps/Kconfig +++ b/drivers/media/rc/keymaps/Kconfig @@ -1,6 +1,6 @@ config RC_MAP tristate "Compile Remote Controller keymap modules" - depends on IR_CORE + depends on RC_CORE default y ---help--- diff --git a/drivers/media/rc/keymaps/rc-lirc.c b/drivers/media/rc/keymaps/rc-lirc.c index 43fcf90..9c8577d 100644 --- a/drivers/media/rc/keymaps/rc-lirc.c +++ b/drivers/media/rc/keymaps/rc-lirc.c @@ -9,7 +9,7 @@ * (at your option) any later version. */ -#include +#include static struct ir_scancode lirc[] = { { }, diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 539bec2..db7787a 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #define DRIVER_VERSION "1.91" #define DRIVER_AUTHOR "Jarod Wilson " diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 0ce328f..bf3f58f 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include "nuvoton-cir.h" diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index 3616c32..48065b7 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h @@ -18,7 +18,7 @@ #include #include -#include +#include struct ir_raw_handler { struct list_head list; diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 5b67eea..d91b62c 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -12,7 +12,7 @@ * GNU General Public License for more details. */ -#include +#include #include #include #include @@ -1103,11 +1103,11 @@ EXPORT_SYMBOL_GPL(rc_unregister_device); * Init/exit code for the module. Basically, creates/removes /sys/class/rc */ -static int __init ir_core_init(void) +static int __init rc_core_init(void) { int rc = class_register(&ir_input_class); if (rc) { - printk(KERN_ERR "ir_core: unable to register rc class\n"); + printk(KERN_ERR "rc_core: unable to register rc class\n"); return rc; } @@ -1118,18 +1118,18 @@ static int __init ir_core_init(void) return 0; } -static void __exit ir_core_exit(void) +static void __exit rc_core_exit(void) { class_unregister(&ir_input_class); ir_unregister_map(&empty_map); } -module_init(ir_core_init); -module_exit(ir_core_exit); +module_init(rc_core_init); +module_exit(rc_core_exit); -int ir_core_debug; /* ir_debug level (0,1,2) */ -EXPORT_SYMBOL_GPL(ir_core_debug); -module_param_named(debug, ir_core_debug, int, 0644); +int rc_core_debug; /* ir_debug level (0,1,2) */ +EXPORT_SYMBOL_GPL(rc_core_debug); +module_param_named(debug, rc_core_debug, int, 0644); MODULE_AUTHOR("Mauro Carvalho Chehab "); MODULE_LICENSE("GPL"); diff --git a/drivers/media/rc/rc-raw.c b/drivers/media/rc/rc-raw.c index ab9b1e4..165412f 100644 --- a/drivers/media/rc/rc-raw.c +++ b/drivers/media/rc/rc-raw.c @@ -357,7 +357,7 @@ static void init_decoders(struct work_struct *work) load_lirc_codec(); /* If needed, we may later add some init code. In this case, - it is needed to change the CONFIG_MODULE test at ir-core.h + it is needed to change the CONFIG_MODULE test at rc-core.h */ } #endif diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c index f05f5c1..ea2cb63 100644 --- a/drivers/media/rc/streamzap.c +++ b/drivers/media/rc/streamzap.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #define DRIVER_VERSION "1.61" #define DRIVER_NAME "streamzap" diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c index 0ee16ec..186de55 100644 --- a/drivers/media/rc/winbond-cir.c +++ b/drivers/media/rc/winbond-cir.c @@ -50,7 +50,7 @@ #include #include #include -#include +#include #define DRVNAME "winbond-cir" diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 963b3e6..4b751ef 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -96,7 +96,7 @@ config VIDEO_HELPER_CHIPS_AUTO config VIDEO_IR_I2C tristate "I2C module for IR" if !VIDEO_HELPER_CHIPS_AUTO - depends on I2C && IR_CORE + depends on I2C && RC_CORE default y ---help--- Most boards have an IR chip directly connected via GPIO. However, diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig index 3c7c0a5..7da5c2e 100644 --- a/drivers/media/video/bt8xx/Kconfig +++ b/drivers/media/video/bt8xx/Kconfig @@ -4,7 +4,7 @@ config VIDEO_BT848 select I2C_ALGOBIT select VIDEO_BTCX select VIDEOBUF_DMA_SG - depends on IR_CORE + depends on RC_CORE select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index 0bbdd48..b71d04d 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include "bt848.h" diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig index f3c3ccb..d9d2f6a 100644 --- a/drivers/media/video/cx18/Kconfig +++ b/drivers/media/video/cx18/Kconfig @@ -2,7 +2,7 @@ config VIDEO_CX18 tristate "Conexant cx23418 MPEG encoder support" depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL select I2C_ALGOBIT - depends on IR_CORE + depends on RC_CORE select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_CX2341X diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/video/cx231xx/Kconfig index d6a2350..ae85a7a 100644 --- a/drivers/media/video/cx231xx/Kconfig +++ b/drivers/media/video/cx231xx/Kconfig @@ -3,7 +3,7 @@ config VIDEO_CX231XX depends on VIDEO_DEV && I2C select VIDEO_TUNER select VIDEO_TVEEPROM - depends on IR_CORE + depends on RC_CORE select VIDEOBUF_VMALLOC select VIDEO_CX25840 select VIDEO_CX2341X @@ -16,7 +16,7 @@ config VIDEO_CX231XX config VIDEO_CX231XX_RC bool "Conexant cx231xx Remote Controller additional support" - depends on IR_CORE + depends on RC_CORE depends on VIDEO_CX231XX default y ---help--- diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h index fcccc9d..87a20ae 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/video/cx231xx/cx231xx.h @@ -34,7 +34,7 @@ #include #include -#include +#include #include #include diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index e1367b3..6b4a516 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig @@ -5,7 +5,7 @@ config VIDEO_CX23885 select VIDEO_BTCX select VIDEO_TUNER select VIDEO_TVEEPROM - depends on IR_CORE + depends on RC_CORE select VIDEOBUF_DVB select VIDEOBUF_DMA_SG select VIDEO_CX25840 diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index f1bb3a8..e824ba6 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c @@ -36,7 +36,7 @@ */ #include -#include +#include #include #include "cx23885.h" diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index f350d88..fd38722 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include "btcx-risc.h" #include "cx23885-reg.h" diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c index e78e3e4..e37be6f 100644 --- a/drivers/media/video/cx23885/cx23888-ir.c +++ b/drivers/media/video/cx23885/cx23888-ir.c @@ -26,7 +26,7 @@ #include #include -#include +#include #include "cx23885.h" diff --git a/drivers/media/video/cx25840/cx25840-ir.c b/drivers/media/video/cx25840/cx25840-ir.c index 97a4e9b..627926f 100644 --- a/drivers/media/video/cx25840/cx25840-ir.c +++ b/drivers/media/video/cx25840/cx25840-ir.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include "cx25840-core.h" diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index dbae629..5c42abd 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -1,6 +1,6 @@ config VIDEO_CX88 tristate "Conexant 2388x (bt878 successor) support" - depends on VIDEO_DEV && PCI && I2C && IR_CORE + depends on VIDEO_DEV && PCI && I2C && RC_CORE select I2C_ALGOBIT select VIDEO_BTCX select VIDEOBUF_DMA_SG diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 3b2ef45..a730338 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -29,7 +29,7 @@ #include #include "cx88.h" -#include +#include #define MODULE_NAME "cx88xx" diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 72ea2ba..985100e 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -3,7 +3,7 @@ config VIDEO_EM28XX depends on VIDEO_DEV && I2C select VIDEO_TUNER select VIDEO_TVEEPROM - depends on IR_CORE + depends on RC_CORE select VIDEOBUF_VMALLOC select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 6a48043..6f2795a 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -33,7 +33,7 @@ #include #include #include -#include +#include #if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE) #include #endif diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index de0060f..83662a4 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -46,7 +46,7 @@ #include #include -#include +#include #include /* ----------------------------------------------------------------------- */ diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig index c4f1980..89f6591 100644 --- a/drivers/media/video/ivtv/Kconfig +++ b/drivers/media/video/ivtv/Kconfig @@ -2,7 +2,7 @@ config VIDEO_IVTV tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support" depends on VIDEO_V4L2 && PCI && I2C select I2C_ALGOBIT - depends on IR_CORE + depends on RC_CORE select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_CX2341X diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index e03bff9..380f1b2 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig @@ -26,7 +26,7 @@ config VIDEO_SAA7134_ALSA config VIDEO_SAA7134_RC bool "Philips SAA7134 Remote Controller support" - depends on IR_CORE + depends on RC_CORE depends on VIDEO_SAA7134 default y ---help--- diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index c6ef95e..1923f3c 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/media/video/tlg2300/Kconfig b/drivers/media/video/tlg2300/Kconfig index 580580e..645d915 100644 --- a/drivers/media/video/tlg2300/Kconfig +++ b/drivers/media/video/tlg2300/Kconfig @@ -3,7 +3,7 @@ config VIDEO_TLG2300 depends on VIDEO_DEV && I2C && SND && DVB_CORE select VIDEO_TUNER select VIDEO_TVEEPROM - depends on IR_CORE + depends on RC_CORE select VIDEOBUF_VMALLOC select SND_PCM select VIDEOBUF_DVB diff --git a/drivers/staging/cx25821/Kconfig b/drivers/staging/cx25821/Kconfig index f8f2bb0..b265695 100644 --- a/drivers/staging/cx25821/Kconfig +++ b/drivers/staging/cx25821/Kconfig @@ -5,7 +5,7 @@ config VIDEO_CX25821 select I2C_ALGOBIT select VIDEO_BTCX select VIDEO_TVEEPROM - depends on IR_CORE + depends on RC_CORE select VIDEOBUF_DVB select VIDEOBUF_DMA_SG select VIDEO_CX25840 diff --git a/drivers/staging/go7007/Kconfig b/drivers/staging/go7007/Kconfig index edc9091..1da57df 100644 --- a/drivers/staging/go7007/Kconfig +++ b/drivers/staging/go7007/Kconfig @@ -4,7 +4,7 @@ config VIDEO_GO7007 depends on BKL # please fix depends on SND select VIDEOBUF_DMA_SG - depends on IR_CORE + depends on RC_CORE select VIDEO_TUNER select VIDEO_TVEEPROM select SND_PCM diff --git a/drivers/staging/tm6000/Kconfig b/drivers/staging/tm6000/Kconfig index de7ebb9..114eec8 100644 --- a/drivers/staging/tm6000/Kconfig +++ b/drivers/staging/tm6000/Kconfig @@ -1,6 +1,6 @@ config VIDEO_TM6000 tristate "TV Master TM5600/6000/6010 driver" - depends on VIDEO_DEV && I2C && INPUT && IR_CORE && USB && EXPERIMENTAL + depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB && EXPERIMENTAL select VIDEO_TUNER select MEDIA_TUNER_XC2028 select MEDIA_TUNER_XC5000 diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/staging/tm6000/tm6000-input.c index 3517d20..58e93d0 100644 --- a/drivers/staging/tm6000/tm6000-input.c +++ b/drivers/staging/tm6000/tm6000-input.c @@ -24,7 +24,7 @@ #include #include -#include +#include #include "tm6000.h" #include "tm6000-regs.h" diff --git a/include/media/ir-core.h b/include/media/ir-core.h deleted file mode 100644 index c590998..0000000 --- a/include/media/ir-core.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Remote Controller core header - * - * Copyright (C) 2009-2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _IR_CORE -#define _IR_CORE - -#include -#include -#include -#include -#include - -extern int ir_core_debug; -#define IR_dprintk(level, fmt, arg...) if (ir_core_debug >= level) \ - printk(KERN_DEBUG "%s: " fmt , __func__, ## arg) - -enum rc_driver_type { - RC_DRIVER_SCANCODE = 0, /* Driver or hardware generates a scancode */ - RC_DRIVER_IR_RAW, /* Needs a Infra-Red pulse/space decoder */ -}; - -/** - * struct rc_dev - represents a remote control device - * @dev: driver model's view of this device - * @input_name: name of the input child device - * @input_phys: physical path to the input child device - * @input_id: id of the input child device (struct input_id) - * @driver_name: name of the hardware driver which registered this device - * @map_name: name of the default keymap - * @rc_tab: current scan/key table - * @devno: unique remote control device number - * @raw: additional data for raw pulse/space devices - * @input_dev: the input child device used to communicate events to userspace - * @driver_type: specifies if protocol decoding is done in hardware or software - * @idle: used to keep track of RX state - * @allowed_protos: bitmask with the supported IR_TYPE_* protocols - * @scanmask: some hardware decoders are not capable of providing the full - * scancode to the application. As this is a hardware limit, we can't do - * anything with it. Yet, as the same keycode table can be used with other - * devices, a mask is provided to allow its usage. Drivers should generally - * leave this field in blank - * @priv: driver-specific data - * @keylock: protects the remaining members of the struct - * @keypressed: whether a key is currently pressed - * @keyup_jiffies: time (in jiffies) when the current keypress should be released - * @timer_keyup: timer for releasing a keypress - * @last_keycode: keycode of last keypress - * @last_scancode: scancode of last keypress - * @last_toggle: toggle value of last command - * @timeout: optional time after which device stops sending data - * @min_timeout: minimum timeout supported by device - * @max_timeout: maximum timeout supported by device - * @rx_resolution : resolution (in ns) of input sampler - * @tx_resolution: resolution (in ns) of output sampler - * @change_protocol: allow changing the protocol used on hardware decoders - * @open: callback to allow drivers to enable polling/irq when IR input device - * is opened. - * @close: callback to allow drivers to disable polling/irq when IR input device - * is opened. - * @s_tx_mask: set transmitter mask (for devices with multiple tx outputs) - * @s_tx_carrier: set transmit carrier frequency - * @s_tx_duty_cycle: set transmit duty cycle (0% - 100%) - * @s_rx_carrier: inform driver about carrier it is expected to handle - * @tx_ir: transmit IR - * @s_idle: enable/disable hardware idle mode, upon which, - * device doesn't interrupt host until it sees IR pulses - * @s_learning_mode: enable wide band receiver used for learning - * @s_carrier_report: enable carrier reports - */ -struct rc_dev { - struct device dev; - const char *input_name; - const char *input_phys; - struct input_id input_id; - char *driver_name; - const char *map_name; - struct ir_scancode_table rc_tab; - unsigned long devno; - struct ir_raw_event_ctrl *raw; - struct input_dev *input_dev; - enum rc_driver_type driver_type; - bool idle; - u64 allowed_protos; - u32 scanmask; - void *priv; - spinlock_t keylock; - bool keypressed; - unsigned long keyup_jiffies; - struct timer_list timer_keyup; - u32 last_keycode; - u32 last_scancode; - u8 last_toggle; - u32 timeout; - u32 min_timeout; - u32 max_timeout; - u32 rx_resolution; - u32 tx_resolution; - int (*change_protocol)(struct rc_dev *dev, u64 ir_type); - int (*open)(struct rc_dev *dev); - void (*close)(struct rc_dev *dev); - int (*s_tx_mask)(struct rc_dev *dev, u32 mask); - int (*s_tx_carrier)(struct rc_dev *dev, u32 carrier); - int (*s_tx_duty_cycle)(struct rc_dev *dev, u32 duty_cycle); - int (*s_rx_carrier_range)(struct rc_dev *dev, u32 min, u32 max); - int (*tx_ir)(struct rc_dev *dev, int *txbuf, u32 n); - void (*s_idle)(struct rc_dev *dev, bool enable); - int (*s_learning_mode)(struct rc_dev *dev, int enable); - int (*s_carrier_report) (struct rc_dev *dev, int enable); -}; - -enum raw_event_type { - IR_SPACE = (1 << 0), - IR_PULSE = (1 << 1), - IR_START_EVENT = (1 << 2), - IR_STOP_EVENT = (1 << 3), -}; - -#define to_rc_dev(d) container_of(d, struct rc_dev, dev) - - -void ir_repeat(struct rc_dev *dev); -void ir_keydown(struct rc_dev *dev, int scancode, u8 toggle); -void ir_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle); -void ir_keyup(struct rc_dev *dev); -u32 ir_g_keycode_from_table(struct rc_dev *dev, u32 scancode); - -/* From ir-raw-event.c */ -struct ir_raw_event { - union { - u32 duration; - - struct { - u32 carrier; - u8 duty_cycle; - }; - }; - - unsigned pulse:1; - unsigned reset:1; - unsigned timeout:1; - unsigned carrier_report:1; -}; - -#define DEFINE_IR_RAW_EVENT(event) \ - struct ir_raw_event event = { \ - { .duration = 0 } , \ - .pulse = 0, \ - .reset = 0, \ - .timeout = 0, \ - .carrier_report = 0 } - -static inline void init_ir_raw_event(struct ir_raw_event *ev) -{ - memset(ev, 0, sizeof(*ev)); -} - -#define IR_MAX_DURATION 0xFFFFFFFF /* a bit more than 4 seconds */ - -struct rc_dev *rc_allocate_device(void); -void rc_free_device(struct rc_dev *dev); -int rc_register_device(struct rc_dev *dev); -void rc_unregister_device(struct rc_dev *dev); - -void ir_raw_event_handle(struct rc_dev *dev); -int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev); -int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type); -int ir_raw_event_store_with_filter(struct rc_dev *dev, - struct ir_raw_event *ev); -void ir_raw_event_set_idle(struct rc_dev *dev, bool idle); - -static inline void ir_raw_event_reset(struct rc_dev *dev) -{ - DEFINE_IR_RAW_EVENT(ev); - ev.reset = true; - - ir_raw_event_store(dev, &ev); - ir_raw_event_handle(dev); -} - - -/* extract mask bits out of data and pack them into the result */ -static inline u32 ir_extract_bits(u32 data, u32 mask) -{ - u32 vbit = 1, value = 0; - - do { - if (mask & 1) { - if (data & 1) - value |= vbit; - vbit <<= 1; - } - data >>= 1; - } while (mask >>= 1); - - return value; -} - - -#endif /* _IR_CORE */ diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h index d27505f..f22b359 100644 --- a/include/media/ir-kbd-i2c.h +++ b/include/media/ir-kbd-i2c.h @@ -1,7 +1,7 @@ #ifndef _IR_I2C #define _IR_I2C -#include +#include #define DEFAULT_POLLING_INTERVAL 100 /* ms */ diff --git a/include/media/rc-core.h b/include/media/rc-core.h new file mode 100644 index 0000000..eedb2f0 --- /dev/null +++ b/include/media/rc-core.h @@ -0,0 +1,211 @@ +/* + * Remote Controller core header + * + * Copyright (C) 2009-2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _IR_CORE +#define _IR_CORE + +#include +#include +#include +#include +#include + +extern int rc_core_debug; +#define IR_dprintk(level, fmt, arg...) if (rc_core_debug >= level) \ + printk(KERN_DEBUG "%s: " fmt , __func__, ## arg) + +enum rc_driver_type { + RC_DRIVER_SCANCODE = 0, /* Driver or hardware generates a scancode */ + RC_DRIVER_IR_RAW, /* Needs a Infra-Red pulse/space decoder */ +}; + +/** + * struct rc_dev - represents a remote control device + * @dev: driver model's view of this device + * @input_name: name of the input child device + * @input_phys: physical path to the input child device + * @input_id: id of the input child device (struct input_id) + * @driver_name: name of the hardware driver which registered this device + * @map_name: name of the default keymap + * @rc_tab: current scan/key table + * @devno: unique remote control device number + * @raw: additional data for raw pulse/space devices + * @input_dev: the input child device used to communicate events to userspace + * @driver_type: specifies if protocol decoding is done in hardware or software + * @idle: used to keep track of RX state + * @allowed_protos: bitmask with the supported IR_TYPE_* protocols + * @scanmask: some hardware decoders are not capable of providing the full + * scancode to the application. As this is a hardware limit, we can't do + * anything with it. Yet, as the same keycode table can be used with other + * devices, a mask is provided to allow its usage. Drivers should generally + * leave this field in blank + * @priv: driver-specific data + * @keylock: protects the remaining members of the struct + * @keypressed: whether a key is currently pressed + * @keyup_jiffies: time (in jiffies) when the current keypress should be released + * @timer_keyup: timer for releasing a keypress + * @last_keycode: keycode of last keypress + * @last_scancode: scancode of last keypress + * @last_toggle: toggle value of last command + * @timeout: optional time after which device stops sending data + * @min_timeout: minimum timeout supported by device + * @max_timeout: maximum timeout supported by device + * @rx_resolution : resolution (in ns) of input sampler + * @tx_resolution: resolution (in ns) of output sampler + * @change_protocol: allow changing the protocol used on hardware decoders + * @open: callback to allow drivers to enable polling/irq when IR input device + * is opened. + * @close: callback to allow drivers to disable polling/irq when IR input device + * is opened. + * @s_tx_mask: set transmitter mask (for devices with multiple tx outputs) + * @s_tx_carrier: set transmit carrier frequency + * @s_tx_duty_cycle: set transmit duty cycle (0% - 100%) + * @s_rx_carrier: inform driver about carrier it is expected to handle + * @tx_ir: transmit IR + * @s_idle: enable/disable hardware idle mode, upon which, + * device doesn't interrupt host until it sees IR pulses + * @s_learning_mode: enable wide band receiver used for learning + * @s_carrier_report: enable carrier reports + */ +struct rc_dev { + struct device dev; + const char *input_name; + const char *input_phys; + struct input_id input_id; + char *driver_name; + const char *map_name; + struct ir_scancode_table rc_tab; + unsigned long devno; + struct ir_raw_event_ctrl *raw; + struct input_dev *input_dev; + enum rc_driver_type driver_type; + bool idle; + u64 allowed_protos; + u32 scanmask; + void *priv; + spinlock_t keylock; + bool keypressed; + unsigned long keyup_jiffies; + struct timer_list timer_keyup; + u32 last_keycode; + u32 last_scancode; + u8 last_toggle; + u32 timeout; + u32 min_timeout; + u32 max_timeout; + u32 rx_resolution; + u32 tx_resolution; + int (*change_protocol)(struct rc_dev *dev, u64 ir_type); + int (*open)(struct rc_dev *dev); + void (*close)(struct rc_dev *dev); + int (*s_tx_mask)(struct rc_dev *dev, u32 mask); + int (*s_tx_carrier)(struct rc_dev *dev, u32 carrier); + int (*s_tx_duty_cycle)(struct rc_dev *dev, u32 duty_cycle); + int (*s_rx_carrier_range)(struct rc_dev *dev, u32 min, u32 max); + int (*tx_ir)(struct rc_dev *dev, int *txbuf, u32 n); + void (*s_idle)(struct rc_dev *dev, bool enable); + int (*s_learning_mode)(struct rc_dev *dev, int enable); + int (*s_carrier_report) (struct rc_dev *dev, int enable); +}; + +enum raw_event_type { + IR_SPACE = (1 << 0), + IR_PULSE = (1 << 1), + IR_START_EVENT = (1 << 2), + IR_STOP_EVENT = (1 << 3), +}; + +#define to_rc_dev(d) container_of(d, struct rc_dev, dev) + + +void ir_repeat(struct rc_dev *dev); +void ir_keydown(struct rc_dev *dev, int scancode, u8 toggle); +void ir_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle); +void ir_keyup(struct rc_dev *dev); +u32 ir_g_keycode_from_table(struct rc_dev *dev, u32 scancode); + +/* From ir-raw-event.c */ +struct ir_raw_event { + union { + u32 duration; + + struct { + u32 carrier; + u8 duty_cycle; + }; + }; + + unsigned pulse:1; + unsigned reset:1; + unsigned timeout:1; + unsigned carrier_report:1; +}; + +#define DEFINE_IR_RAW_EVENT(event) \ + struct ir_raw_event event = { \ + { .duration = 0 } , \ + .pulse = 0, \ + .reset = 0, \ + .timeout = 0, \ + .carrier_report = 0 } + +static inline void init_ir_raw_event(struct ir_raw_event *ev) +{ + memset(ev, 0, sizeof(*ev)); +} + +#define IR_MAX_DURATION 0xFFFFFFFF /* a bit more than 4 seconds */ + +struct rc_dev *rc_allocate_device(void); +void rc_free_device(struct rc_dev *dev); +int rc_register_device(struct rc_dev *dev); +void rc_unregister_device(struct rc_dev *dev); + +void ir_raw_event_handle(struct rc_dev *dev); +int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev); +int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type); +int ir_raw_event_store_with_filter(struct rc_dev *dev, + struct ir_raw_event *ev); +void ir_raw_event_set_idle(struct rc_dev *dev, bool idle); + +static inline void ir_raw_event_reset(struct rc_dev *dev) +{ + DEFINE_IR_RAW_EVENT(ev); + ev.reset = true; + + ir_raw_event_store(dev, &ev); + ir_raw_event_handle(dev); +} + + +/* extract mask bits out of data and pack them into the result */ +static inline u32 ir_extract_bits(u32 data, u32 mask) +{ + u32 vbit = 1, value = 0; + + do { + if (mask & 1) { + if (data & 1) + value |= vbit; + vbit <<= 1; + } + data >>= 1; + } while (mask >>= 1); + + return value; +} + + +#endif /* _IR_CORE */ -- cgit v0.10.2 From ca86674b8a93ea11c4bb6f4dd0113b1adf1fa841 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2010 13:53:11 -0300 Subject: [media] Rename all public generic RC functions from ir_ to rc_ Those functions are not InfraRed specific. So, rename them to properly reflect it. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index e9cacf6..2d8b404 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -531,7 +531,7 @@ static void dm1105_emit_key(struct work_struct *work) data = (ircom >> 8) & 0x7f; - ir_keydown(ir->dev, data, 0); + rc_keydown(ir->dev, data, 0); } /* work handler */ diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 8b9ab30..bc2a6e4 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -1041,13 +1041,13 @@ static int af9015_rc_query(struct dvb_usb_device *d) priv->rc_keycode = buf[12] << 16 | buf[13] << 8 | buf[14]; } - ir_keydown(d->rc_dev, priv->rc_keycode, 0); + rc_keydown(d->rc_dev, priv->rc_keycode, 0); } else { priv->rc_keycode = 0; /* clear just for sure */ } } else if (priv->rc_repeat != buf[6] || buf[0]) { deb_rc("%s: key repeated\n", __func__); - ir_keydown(d->rc_dev, priv->rc_keycode, 0); + rc_keydown(d->rc_dev, priv->rc_keycode, 0); } else { deb_rc("%s: no key press\n", __func__); } diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index c6e4ba5..5e12488 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c @@ -394,7 +394,7 @@ static int anysee_rc_query(struct dvb_usb_device *d) if (ircode[0]) { deb_rc("%s: key pressed %02x\n", __func__, ircode[1]); - ir_keydown(d->rc_dev, 0x08 << 8 | ircode[1], 0); + rc_keydown(d->rc_dev, 0x08 << 8 | ircode[1], 0); } return 0; diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index 3b58f45..1dd119e 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -600,7 +600,7 @@ static void dib0700_rc_urb_completion(struct urb *purb) goto resubmit; } - ir_keydown(d->rc_dev, keycode, toggle); + rc_keydown(d->rc_dev, keycode, toggle); resubmit: /* Clean the buffer before we requeue */ diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index be167f2..9ac920d 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -520,13 +520,13 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d) d->last_event = keycode; } - ir_keydown(d->rc_dev, keycode, 0); + rc_keydown(d->rc_dev, keycode, 0); break; default: /* RC-5 protocol changes toggle bit on new keypress */ keycode = key[3-2] << 8 | key[3-3]; toggle = key[3-1]; - ir_keydown(d->rc_dev, keycode, toggle); + rc_keydown(d->rc_dev, keycode, toggle); break; } diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c index f0c0308..1455c23 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/drivers/media/dvb/dvb-usb/lmedm04.c @@ -198,7 +198,7 @@ static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u16 keypress) deb_info(1, "INT Key Keypress =%04x", keypress); if (keypress > 0) - ir_keydown(d->rc_dev, keypress, 0); + rc_keydown(d->rc_dev, keypress, 0); return 0; } diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 32caa9b..8ae67c1 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -159,7 +159,7 @@ static void msp430_ir_interrupt(unsigned long data) budget_ci->ir.rc5_device != (command & 0x1f)) return; - ir_keydown(dev, budget_ci->ir.ir_key, (command & 0x20) ? 1 : 0); + rc_keydown(dev, budget_ci->ir.ir_key, (command & 0x20) ? 1 : 0); } static int msp430_ir_init(struct budget_ci *budget_ci) diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index b6ba3c7..d67573e 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -1146,14 +1146,14 @@ static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 scancode) bool is_release_code = false; /* Look for the initial press of a button */ - keycode = ir_g_keycode_from_table(ictx->rdev, scancode); + keycode = rc_g_keycode_from_table(ictx->rdev, scancode); ictx->rc_toggle = 0x0; ictx->rc_scancode = scancode; /* Look for the release of a button */ if (keycode == KEY_RESERVED) { release = scancode & ~0x4000; - keycode = ir_g_keycode_from_table(ictx->rdev, release); + keycode = rc_g_keycode_from_table(ictx->rdev, release); if (keycode != KEY_RESERVED) is_release_code = true; } @@ -1182,7 +1182,7 @@ static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 scancode) scancode = scancode | MCE_KEY_MASK | MCE_TOGGLE_BIT; ictx->rc_scancode = scancode; - keycode = ir_g_keycode_from_table(ictx->rdev, scancode); + keycode = rc_g_keycode_from_table(ictx->rdev, scancode); /* not used in mce mode, but make sure we know its false */ ictx->release_code = false; @@ -1564,9 +1564,9 @@ static void imon_incoming_packet(struct imon_context *ictx, if (ktype != IMON_KEY_PANEL) { if (press_type == 0) - ir_keyup(ictx->rdev); + rc_keyup(ictx->rdev); else { - ir_keydown(ictx->rdev, ictx->rc_scancode, ictx->rc_toggle); + rc_keydown(ictx->rdev, ictx->rc_scancode, ictx->rc_toggle); spin_lock_irqsave(&ictx->kc_lock, flags); ictx->last_keycode = ictx->kc; spin_unlock_irqrestore(&ictx->kc_lock, flags); diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c index cfe0e70..09c143f 100644 --- a/drivers/media/rc/ir-jvc-decoder.c +++ b/drivers/media/rc/ir-jvc-decoder.c @@ -139,12 +139,12 @@ again: scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) | (bitrev8((data->bits >> 0) & 0xff) << 0); IR_dprintk(1, "JVC scancode 0x%04x\n", scancode); - ir_keydown(dev, scancode, data->toggle); + rc_keydown(dev, scancode, data->toggle); data->first = false; data->old_bits = data->bits; } else if (data->bits == data->old_bits) { IR_dprintk(1, "JVC repeat\n"); - ir_repeat(dev); + rc_repeat(dev); } else { IR_dprintk(1, "JVC invalid repeat msg\n"); break; diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c index 8ff157a..235d774 100644 --- a/drivers/media/rc/ir-nec-decoder.c +++ b/drivers/media/rc/ir-nec-decoder.c @@ -88,7 +88,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) data->state = STATE_BIT_PULSE; return 0; } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) { - ir_repeat(dev); + rc_repeat(dev); IR_dprintk(1, "Repeat last key\n"); data->state = STATE_TRAILER_PULSE; return 0; @@ -114,7 +114,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2)) { IR_dprintk(1, "Repeat last key\n"); - ir_repeat(dev); + rc_repeat(dev); data->state = STATE_INACTIVE; return 0; @@ -178,7 +178,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) if (data->is_nec_x) data->necx_repeat = true; - ir_keydown(dev, scancode, 0); + rc_keydown(dev, scancode, 0); data->state = STATE_INACTIVE; return 0; } diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c index dae6f9a..779ab0d 100644 --- a/drivers/media/rc/ir-rc5-decoder.c +++ b/drivers/media/rc/ir-rc5-decoder.c @@ -150,7 +150,7 @@ again: scancode, toggle); } - ir_keydown(dev, scancode, toggle); + rc_keydown(dev, scancode, toggle); data->state = STATE_INACTIVE; return 0; } diff --git a/drivers/media/rc/ir-rc5-sz-decoder.c b/drivers/media/rc/ir-rc5-sz-decoder.c index d8a53c0..5586bf2 100644 --- a/drivers/media/rc/ir-rc5-sz-decoder.c +++ b/drivers/media/rc/ir-rc5-sz-decoder.c @@ -114,7 +114,7 @@ again: IR_dprintk(1, "RC5-sz scancode 0x%04x (toggle: %u)\n", scancode, toggle); - ir_keydown(dev, scancode, toggle); + rc_keydown(dev, scancode, toggle); data->state = STATE_INACTIVE; return 0; } diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c index 2435bbd..88d9487 100644 --- a/drivers/media/rc/ir-rc6-decoder.c +++ b/drivers/media/rc/ir-rc6-decoder.c @@ -242,7 +242,7 @@ again: goto out; } - ir_keydown(dev, scancode, toggle); + rc_keydown(dev, scancode, toggle); data->state = STATE_INACTIVE; return 0; } diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c index 3138520..5292b89 100644 --- a/drivers/media/rc/ir-sony-decoder.c +++ b/drivers/media/rc/ir-sony-decoder.c @@ -143,7 +143,7 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev) scancode = device << 16 | subdevice << 8 | function; IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode); - ir_keydown(dev, scancode, 0); + rc_keydown(dev, scancode, 0); data->state = STATE_INACTIVE; return 0; } diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index d91b62c..11e2703 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -481,7 +481,7 @@ out: } /** - * ir_g_keycode_from_table() - gets the keycode that corresponds to a scancode + * rc_g_keycode_from_table() - gets the keycode that corresponds to a scancode * @dev: the struct rc_dev descriptor of the device * @scancode: the scancode to look for * @return: the corresponding keycode, or KEY_RESERVED @@ -490,7 +490,7 @@ out: * keycode. Normally it should not be used since drivers should have no * interest in keycodes. */ -u32 ir_g_keycode_from_table(struct rc_dev *dev, u32 scancode) +u32 rc_g_keycode_from_table(struct rc_dev *dev, u32 scancode) { struct ir_scancode_table *rc_tab = &dev->rc_tab; unsigned int keycode; @@ -511,7 +511,7 @@ u32 ir_g_keycode_from_table(struct rc_dev *dev, u32 scancode) return keycode; } -EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); +EXPORT_SYMBOL_GPL(rc_g_keycode_from_table); /** * ir_do_keyup() - internal function to signal the release of a keypress @@ -532,13 +532,13 @@ static void ir_do_keyup(struct rc_dev *dev) } /** - * ir_keyup() - signals the release of a keypress + * rc_keyup() - signals the release of a keypress * @dev: the struct rc_dev descriptor of the device * * This routine is used to signal that a key has been released on the * remote control. */ -void ir_keyup(struct rc_dev *dev) +void rc_keyup(struct rc_dev *dev) { unsigned long flags; @@ -546,7 +546,7 @@ void ir_keyup(struct rc_dev *dev) ir_do_keyup(dev); spin_unlock_irqrestore(&dev->keylock, flags); } -EXPORT_SYMBOL_GPL(ir_keyup); +EXPORT_SYMBOL_GPL(rc_keyup); /** * ir_timer_keyup() - generates a keyup event after a timeout @@ -577,14 +577,14 @@ static void ir_timer_keyup(unsigned long cookie) } /** - * ir_repeat() - signals that a key is still pressed + * rc_repeat() - signals that a key is still pressed * @dev: the struct rc_dev descriptor of the device * * This routine is used by IR decoders when a repeat message which does * not include the necessary bits to reproduce the scancode has been * received. */ -void ir_repeat(struct rc_dev *dev) +void rc_repeat(struct rc_dev *dev) { unsigned long flags; @@ -601,7 +601,7 @@ void ir_repeat(struct rc_dev *dev) out: spin_unlock_irqrestore(&dev->keylock, flags); } -EXPORT_SYMBOL_GPL(ir_repeat); +EXPORT_SYMBOL_GPL(rc_repeat); /** * ir_do_keydown() - internal function to process a keypress @@ -643,7 +643,7 @@ static void ir_do_keydown(struct rc_dev *dev, int scancode, } /** - * ir_keydown() - generates input event for a key press + * rc_keydown() - generates input event for a key press * @dev: the struct rc_dev descriptor of the device * @scancode: the scancode that we're seeking * @toggle: the toggle value (protocol dependent, if the protocol doesn't @@ -652,10 +652,10 @@ static void ir_do_keydown(struct rc_dev *dev, int scancode, * This routine is used to signal that a key has been pressed on the * remote control. */ -void ir_keydown(struct rc_dev *dev, int scancode, u8 toggle) +void rc_keydown(struct rc_dev *dev, int scancode, u8 toggle) { unsigned long flags; - u32 keycode = ir_g_keycode_from_table(dev, scancode); + u32 keycode = rc_g_keycode_from_table(dev, scancode); spin_lock_irqsave(&dev->keylock, flags); ir_do_keydown(dev, scancode, keycode, toggle); @@ -666,10 +666,10 @@ void ir_keydown(struct rc_dev *dev, int scancode, u8 toggle) } spin_unlock_irqrestore(&dev->keylock, flags); } -EXPORT_SYMBOL_GPL(ir_keydown); +EXPORT_SYMBOL_GPL(rc_keydown); /** - * ir_keydown_notimeout() - generates input event for a key press without + * rc_keydown_notimeout() - generates input event for a key press without * an automatic keyup event at a later time * @dev: the struct rc_dev descriptor of the device * @scancode: the scancode that we're seeking @@ -677,18 +677,18 @@ EXPORT_SYMBOL_GPL(ir_keydown); * support toggle values, this should be set to zero) * * This routine is used to signal that a key has been pressed on the - * remote control. The driver must manually call ir_keyup() at a later stage. + * remote control. The driver must manually call rc_keyup() at a later stage. */ -void ir_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle) +void rc_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle) { unsigned long flags; - u32 keycode = ir_g_keycode_from_table(dev, scancode); + u32 keycode = rc_g_keycode_from_table(dev, scancode); spin_lock_irqsave(&dev->keylock, flags); ir_do_keydown(dev, scancode, keycode, toggle); spin_unlock_irqrestore(&dev->keylock, flags); } -EXPORT_SYMBOL_GPL(ir_keydown_notimeout); +EXPORT_SYMBOL_GPL(rc_keydown_notimeout); static int ir_open(struct input_dev *idev) { diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index e4df7f8..773ee6a 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -70,14 +70,14 @@ static void ir_handle_key(struct bttv *btv) if ((ir->mask_keydown && (gpio & ir->mask_keydown)) || (ir->mask_keyup && !(gpio & ir->mask_keyup))) { - ir_keydown_notimeout(ir->dev, data, 0); + rc_keydown_notimeout(ir->dev, data, 0); } else { /* HACK: Probably, ir->mask_keydown is missing for this board */ if (btv->c.type == BTTV_BOARD_WINFAST2000) - ir_keydown_notimeout(ir->dev, data, 0); + rc_keydown_notimeout(ir->dev, data, 0); - ir_keyup(ir->dev); + rc_keyup(ir->dev); } } @@ -100,9 +100,9 @@ static void ir_enltv_handle_key(struct bttv *btv) gpio, data, (gpio & ir->mask_keyup) ? " up" : "up/down"); - ir_keydown_notimeout(ir->dev, data, 0); + rc_keydown_notimeout(ir->dev, data, 0); if (keyup) - ir_keyup(ir->dev); + rc_keyup(ir->dev); } else { if ((ir->last_gpio & 1 << 31) == keyup) return; @@ -112,9 +112,9 @@ static void ir_enltv_handle_key(struct bttv *btv) (gpio & ir->mask_keyup) ? " up" : "down"); if (keyup) - ir_keyup(ir->dev); + rc_keyup(ir->dev); else - ir_keydown_notimeout(ir->dev, data, 0); + rc_keydown_notimeout(ir->dev, data, 0); } ir->last_gpio = data | keyup; @@ -232,7 +232,7 @@ void bttv_rc5_timer_end(unsigned long data) u32 instr = RC5_INSTR(rc5); /* Good code */ - ir_keydown(ir->dev, instr, toggle); + rc_keydown(ir->dev, instr, toggle); dprintk(KERN_INFO DEVNAME ":" " instruction %x, toggle %x\n", instr, toggle); diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index a730338..cfeba4c 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -123,26 +123,26 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) data = (data << 4) | ((gpio_key & 0xf0) >> 4); - ir_keydown(ir->dev, data, 0); + rc_keydown(ir->dev, data, 0); } else if (ir->mask_keydown) { /* bit set on keydown */ if (gpio & ir->mask_keydown) - ir_keydown_notimeout(ir->dev, data, 0); + rc_keydown_notimeout(ir->dev, data, 0); else - ir_keyup(ir->dev); + rc_keyup(ir->dev); } else if (ir->mask_keyup) { /* bit cleared on keydown */ if (0 == (gpio & ir->mask_keyup)) - ir_keydown_notimeout(ir->dev, data, 0); + rc_keydown_notimeout(ir->dev, data, 0); else - ir_keyup(ir->dev); + rc_keyup(ir->dev); } else { /* can't distinguish keydown/up :-/ */ - ir_keydown_notimeout(ir->dev, data, 0); - ir_keyup(ir->dev); + rc_keydown_notimeout(ir->dev, data, 0); + rc_keyup(ir->dev); } } diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index b7d3999..e32eb38 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -297,12 +297,12 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) poll_result.toggle_bit, poll_result.read_count, poll_result.rc_address, poll_result.rc_data[0]); if (ir->full_code) - ir_keydown(ir->rc, + rc_keydown(ir->rc, poll_result.rc_address << 8 | poll_result.rc_data[0], poll_result.toggle_bit); else - ir_keydown(ir->rc, + rc_keydown(ir->rc, poll_result.rc_data[0], poll_result.toggle_bit); diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 83662a4..c77ea53 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -252,7 +252,7 @@ static void ir_key_poll(struct IR_i2c *ir) } if (rc) - ir_keydown(ir->rc, ir_key, 0); + rc_keydown(ir->rc, ir_key, 0); } static void ir_work(struct work_struct *work) diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 900e798..cd39aea 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -89,25 +89,25 @@ static int build_key(struct saa7134_dev *dev) switch (dev->board) { case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: if (data == ir->mask_keycode) - ir_keyup(ir->dev); + rc_keyup(ir->dev); else - ir_keydown_notimeout(ir->dev, data, 0); + rc_keydown_notimeout(ir->dev, data, 0); return 0; } if (ir->polling) { if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { - ir_keydown_notimeout(ir->dev, data, 0); + rc_keydown_notimeout(ir->dev, data, 0); } else { - ir_keyup(ir->dev); + rc_keyup(ir->dev); } } else { /* IRQ driven mode - handle key press and release in one go */ if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) || (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) { - ir_keydown_notimeout(ir->dev, data, 0); - ir_keyup(ir->dev); + rc_keydown_notimeout(ir->dev, data, 0); + rc_keyup(ir->dev); } } diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/staging/tm6000/tm6000-input.c index 58e93d0..02b9829 100644 --- a/drivers/staging/tm6000/tm6000-input.c +++ b/drivers/staging/tm6000/tm6000-input.c @@ -199,7 +199,7 @@ static void tm6000_ir_handle_key(struct tm6000_IR *ir) dprintk("ir->get_key result data=%04x\n", poll_result.rc_data); if (ir->key) { - ir_keydown(ir->rc, poll_result.rc_data, 0); + rc_keydown(ir->rc, poll_result.rc_data, 0); ir->key = 0; } return; diff --git a/include/media/rc-core.h b/include/media/rc-core.h index eedb2f0..170581b4 100644 --- a/include/media/rc-core.h +++ b/include/media/rc-core.h @@ -13,8 +13,8 @@ * GNU General Public License for more details. */ -#ifndef _IR_CORE -#define _IR_CORE +#ifndef _RC_CORE +#define _RC_CORE #include #include @@ -120,6 +120,32 @@ struct rc_dev { int (*s_carrier_report) (struct rc_dev *dev, int enable); }; +#define to_rc_dev(d) container_of(d, struct rc_dev, dev) + +/* + * From rc-main.c + * Those functions can be used on any type of Remote Controller. They + * basically creates an input_dev and properly reports the device as a + * Remote Controller, at sys/class/rc. + */ + +struct rc_dev *rc_allocate_device(void); +void rc_free_device(struct rc_dev *dev); +int rc_register_device(struct rc_dev *dev); +void rc_unregister_device(struct rc_dev *dev); + +void rc_repeat(struct rc_dev *dev); +void rc_keydown(struct rc_dev *dev, int scancode, u8 toggle); +void rc_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle); +void rc_keyup(struct rc_dev *dev); +u32 rc_g_keycode_from_table(struct rc_dev *dev, u32 scancode); + +/* + * From rc-raw.c + * The Raw interface is specific to InfraRed. It may be a good idea to + * split it later into a separate header. + */ + enum raw_event_type { IR_SPACE = (1 << 0), IR_PULSE = (1 << 1), @@ -127,16 +153,6 @@ enum raw_event_type { IR_STOP_EVENT = (1 << 3), }; -#define to_rc_dev(d) container_of(d, struct rc_dev, dev) - - -void ir_repeat(struct rc_dev *dev); -void ir_keydown(struct rc_dev *dev, int scancode, u8 toggle); -void ir_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle); -void ir_keyup(struct rc_dev *dev); -u32 ir_g_keycode_from_table(struct rc_dev *dev, u32 scancode); - -/* From ir-raw-event.c */ struct ir_raw_event { union { u32 duration; @@ -168,11 +184,6 @@ static inline void init_ir_raw_event(struct ir_raw_event *ev) #define IR_MAX_DURATION 0xFFFFFFFF /* a bit more than 4 seconds */ -struct rc_dev *rc_allocate_device(void); -void rc_free_device(struct rc_dev *dev); -int rc_register_device(struct rc_dev *dev); -void rc_unregister_device(struct rc_dev *dev); - void ir_raw_event_handle(struct rc_dev *dev); int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev); int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type); @@ -189,7 +200,6 @@ static inline void ir_raw_event_reset(struct rc_dev *dev) ir_raw_event_handle(dev); } - /* extract mask bits out of data and pack them into the result */ static inline u32 ir_extract_bits(u32 data, u32 mask) { @@ -207,5 +217,4 @@ static inline u32 ir_extract_bits(u32 data, u32 mask) return value; } - -#endif /* _IR_CORE */ +#endif /* _RC_CORE */ -- cgit v0.10.2 From 29e3ec19d5c88d534ced219d3962d67243e4d310 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2010 14:12:46 -0300 Subject: [media] cx231xx: Properly name rc_map name rc_map is confusing, as it may be understood as another thing. Properly rename the field to indicate its usage. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 83772eb..2b61017 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c @@ -412,7 +412,7 @@ struct cx231xx_board cx231xx_boards[] = { .tuner_i2c_master = 2, .demod_i2c_master = 1, .ir_i2c_master = 2, - .rc_map = RC_MAP_PIXELVIEW_NEW, + .rc_map_name = RC_MAP_PIXELVIEW_NEW, .has_dvb = 1, .demod_addr = 0x10, .norm = V4L2_STD_PAL_M, diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c index 65d951e..1d043ed 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/video/cx231xx/cx231xx-input.c @@ -57,7 +57,7 @@ int cx231xx_ir_init(struct cx231xx *dev) dev_dbg(&dev->udev->dev, "%s\n", __func__); /* Only initialize if a rc keycode map is defined */ - if (!cx231xx_boards[dev->model].rc_map) + if (!cx231xx_boards[dev->model].rc_map_name) return -ENODEV; request_module("ir-kbd-i2c"); @@ -80,7 +80,7 @@ int cx231xx_ir_init(struct cx231xx *dev) * an i2c device. */ dev->init_data.get_key = get_key_isdbt; - dev->init_data.ir_codes = cx231xx_boards[dev->model].rc_map; + dev->init_data.ir_codes = cx231xx_boards[dev->model].rc_map_name; /* The i2c micro-controller only outputs the cmd part of NEC protocol */ dev->init_data.rc_dev->scanmask = 0xff; dev->init_data.rc_dev->driver_name = "cx231xx"; diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h index 87a20ae..709cb87 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/video/cx231xx/cx231xx.h @@ -349,7 +349,7 @@ struct cx231xx_board { u8 ir_i2c_master; /* for devices with I2C chips for IR */ - char *rc_map; + char *rc_map_name; unsigned int max_range_640_480:1; unsigned int has_dvb:1; -- cgit v0.10.2 From 52b661449aecc47e652a164c0d8078b31e10aca0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2010 14:20:52 -0300 Subject: [media] rc: Rename remote controller type to rc_type instead of ir_type for i in `find drivers/staging -type f -name *.[ch]` `find include/media -type f -name *.[ch]` `find drivers/media -type f -name *.[ch]`; do sed s,IR_TYPE,RC_TYPE,g <$i >a && mv a $i; done for i in `find drivers/staging -type f -name *.[ch]` `find include/media -type f -name *.[ch]` `find drivers/media -type f -name *.[ch]`; do sed s,ir_type,rc_type,g <$i >a && mv a $i; done Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index bc2a6e4..8671ca3 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -1344,11 +1344,11 @@ static struct dvb_usb_device_properties af9015_properties[] = { .identify_state = af9015_identify_state, .rc.core = { - .protocol = IR_TYPE_NEC, + .protocol = RC_TYPE_NEC, .module_name = "af9015", .rc_query = af9015_rc_query, .rc_interval = AF9015_RC_INTERVAL, - .allowed_protos = IR_TYPE_NEC, + .allowed_protos = RC_TYPE_NEC, }, .i2c_algo = &af9015_i2c_algo, @@ -1472,11 +1472,11 @@ static struct dvb_usb_device_properties af9015_properties[] = { .identify_state = af9015_identify_state, .rc.core = { - .protocol = IR_TYPE_NEC, + .protocol = RC_TYPE_NEC, .module_name = "af9015", .rc_query = af9015_rc_query, .rc_interval = AF9015_RC_INTERVAL, - .allowed_protos = IR_TYPE_NEC, + .allowed_protos = RC_TYPE_NEC, }, .i2c_algo = &af9015_i2c_algo, @@ -1584,11 +1584,11 @@ static struct dvb_usb_device_properties af9015_properties[] = { .identify_state = af9015_identify_state, .rc.core = { - .protocol = IR_TYPE_NEC, + .protocol = RC_TYPE_NEC, .module_name = "af9015", .rc_query = af9015_rc_query, .rc_interval = AF9015_RC_INTERVAL, - .allowed_protos = IR_TYPE_NEC, + .allowed_protos = RC_TYPE_NEC, }, .i2c_algo = &af9015_i2c_algo, diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index 5e12488..6b402e9 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c @@ -476,7 +476,7 @@ static struct dvb_usb_device_properties anysee_properties = { .rc.core = { .rc_codes = RC_MAP_ANYSEE, - .protocol = IR_TYPE_OTHER, + .protocol = RC_TYPE_OTHER, .module_name = "anysee", .rc_query = anysee_rc_query, .rc_interval = 250, /* windows driver uses 500ms */ diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h index 1e7d780..3537d65 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/dvb/dvb-usb/dib0700.h @@ -60,7 +60,7 @@ extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff); extern struct i2c_algorithm dib0700_i2c_algo; extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, int *cold); -extern int dib0700_change_protocol(struct rc_dev *dev, u64 ir_type); +extern int dib0700_change_protocol(struct rc_dev *dev, u64 rc_type); extern int dib0700_device_count; extern int dvb_usb_dib0700_ir_proto; diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index 1dd119e..8ca48f7 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -471,7 +471,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) return dib0700_ctrl_wr(adap->dev, b, 4); } -int dib0700_change_protocol(struct rc_dev *rc, u64 ir_type) +int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) { struct dvb_usb_device *d = rc->priv; struct dib0700_state *st = d->priv; @@ -479,11 +479,11 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 ir_type) int new_proto, ret; /* Set the IR mode */ - if (ir_type == IR_TYPE_RC5) + if (rc_type == RC_TYPE_RC5) new_proto = 1; - else if (ir_type == IR_TYPE_NEC) + else if (rc_type == RC_TYPE_NEC) new_proto = 0; - else if (ir_type == IR_TYPE_RC6) { + else if (rc_type == RC_TYPE_RC6) { if (st->fw_version < 0x10200) return -EINVAL; @@ -499,7 +499,7 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 ir_type) return ret; } - d->props.rc.core.protocol = ir_type; + d->props.rc.core.protocol = rc_type; return ret; } @@ -562,7 +562,7 @@ static void dib0700_rc_urb_completion(struct urb *purb) purb->actual_length); switch (d->props.rc.core.protocol) { - case IR_TYPE_NEC: + case RC_TYPE_NEC: toggle = 0; /* NEC protocol sends repeat code as 0 0 0 FF */ diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 9ac920d..defd839 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -510,7 +510,7 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d) d->last_event = 0; switch (d->props.rc.core.protocol) { - case IR_TYPE_NEC: + case RC_TYPE_NEC: /* NEC protocol sends repeat code as 0 0 0 FF */ if ((key[3-2] == 0x00) && (key[3-3] == 0x00) && (key[3] == 0xff)) @@ -1924,9 +1924,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_interval = DEFAULT_RC_INTERVAL, .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .rc_query = dib0700_rc_query_old_firmware, - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, + .allowed_protos = RC_TYPE_RC5 | + RC_TYPE_RC6 | + RC_TYPE_NEC, .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -1958,9 +1958,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_interval = DEFAULT_RC_INTERVAL, .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .rc_query = dib0700_rc_query_old_firmware, - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, + .allowed_protos = RC_TYPE_RC5 | + RC_TYPE_RC6 | + RC_TYPE_NEC, .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2017,9 +2017,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_interval = DEFAULT_RC_INTERVAL, .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .rc_query = dib0700_rc_query_old_firmware, - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, + .allowed_protos = RC_TYPE_RC5 | + RC_TYPE_RC6 | + RC_TYPE_NEC, .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2059,9 +2059,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, + .allowed_protos = RC_TYPE_RC5 | + RC_TYPE_RC6 | + RC_TYPE_NEC, .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2135,9 +2135,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, + .allowed_protos = RC_TYPE_RC5 | + RC_TYPE_RC6 | + RC_TYPE_NEC, .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2179,9 +2179,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, + .allowed_protos = RC_TYPE_RC5 | + RC_TYPE_RC6 | + RC_TYPE_NEC, .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2247,9 +2247,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, + .allowed_protos = RC_TYPE_RC5 | + RC_TYPE_RC6 | + RC_TYPE_NEC, .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2294,9 +2294,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_NEC_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, + .allowed_protos = RC_TYPE_RC5 | + RC_TYPE_RC6 | + RC_TYPE_NEC, .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2363,9 +2363,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, + .allowed_protos = RC_TYPE_RC5 | + RC_TYPE_RC6 | + RC_TYPE_NEC, .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2399,9 +2399,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, + .allowed_protos = RC_TYPE_RC5 | + RC_TYPE_RC6 | + RC_TYPE_NEC, .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2467,9 +2467,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, + .allowed_protos = RC_TYPE_RC5 | + RC_TYPE_RC6 | + RC_TYPE_NEC, .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2511,9 +2511,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_NEC_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, + .allowed_protos = RC_TYPE_RC5 | + RC_TYPE_RC6 | + RC_TYPE_NEC, .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2560,9 +2560,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, + .allowed_protos = RC_TYPE_RC5 | + RC_TYPE_RC6 | + RC_TYPE_NEC, .change_protocol = dib0700_change_protocol, }, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -2597,9 +2597,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, .module_name = "dib0700", .rc_query = dib0700_rc_query_old_firmware, - .allowed_protos = IR_TYPE_RC5 | - IR_TYPE_RC6 | - IR_TYPE_NEC, + .allowed_protos = RC_TYPE_RC5 | + RC_TYPE_RC6 | + RC_TYPE_NEC, .change_protocol = dib0700_change_protocol, }, }, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index 18828cb..95b1603 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -190,7 +190,7 @@ struct dvb_rc { char *rc_codes; u64 protocol; u64 allowed_protos; - int (*change_protocol)(struct rc_dev *dev, u64 ir_type); + int (*change_protocol)(struct rc_dev *dev, u64 rc_type); char *module_name; int (*rc_query) (struct dvb_usb_device *d); int rc_interval; diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c index e030b18..cf5f8ca 100644 --- a/drivers/media/dvb/mantis/mantis_input.c +++ b/drivers/media/dvb/mantis/mantis_input.c @@ -99,7 +99,7 @@ static struct rc_keymap ir_mantis_map = { .map = { .scan = mantis_ir_table, .size = ARRAY_SIZE(mantis_ir_table), - .ir_type = IR_TYPE_UNKNOWN, + .rc_type = RC_TYPE_UNKNOWN, .name = RC_MAP_MANTIS, } }; diff --git a/drivers/media/dvb/siano/smsir.c b/drivers/media/dvb/siano/smsir.c index ebd7305..37bc5c4 100644 --- a/drivers/media/dvb/siano/smsir.c +++ b/drivers/media/dvb/siano/smsir.c @@ -88,7 +88,7 @@ int sms_ir_init(struct smscore_device_t *coredev) dev->priv = coredev; dev->driver_type = RC_DRIVER_IR_RAW; - dev->allowed_protos = IR_TYPE_ALL; + dev->allowed_protos = RC_TYPE_ALL; dev->map_name = sms_get_board(board_id)->rc_codes; dev->driver_name = MODULE_NAME; diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c index 1ace458..80b3c31 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c @@ -1052,7 +1052,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) learning_mode_force = false; rdev->driver_type = RC_DRIVER_IR_RAW; - rdev->allowed_protos = IR_TYPE_ALL; + rdev->allowed_protos = RC_TYPE_ALL; rdev->priv = dev; rdev->open = ene_open; rdev->close = ene_close; diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index d67573e..de9dc0e 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -131,7 +131,7 @@ struct imon_context { u32 last_keycode; /* last reported input keycode */ u32 rc_scancode; /* the computed remote scancode */ u8 rc_toggle; /* the computed remote toggle bit */ - u64 ir_type; /* iMON or MCE (RC6) IR protocol? */ + u64 rc_type; /* iMON or MCE (RC6) IR protocol? */ bool release_code; /* some keys send a release code */ u8 display_type; /* store the display type */ @@ -983,7 +983,7 @@ static void imon_touch_display_timeout(unsigned long data) * really just RC-6), but only one or the other at a time, as the signals * are decoded onboard the receiver. */ -static int imon_ir_change_protocol(struct rc_dev *rc, u64 ir_type) +static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type) { int retval; struct imon_context *ictx = rc->priv; @@ -992,18 +992,18 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 ir_type) unsigned char ir_proto_packet[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 }; - if (ir_type && !(ir_type & rc->allowed_protos)) + if (rc_type && !(rc_type & rc->allowed_protos)) dev_warn(dev, "Looks like you're trying to use an IR protocol " "this device does not support\n"); - switch (ir_type) { - case IR_TYPE_RC6: + switch (rc_type) { + case RC_TYPE_RC6: dev_dbg(dev, "Configuring IR receiver for MCE protocol\n"); ir_proto_packet[0] = 0x01; pad_mouse = false; break; - case IR_TYPE_UNKNOWN: - case IR_TYPE_OTHER: + case RC_TYPE_UNKNOWN: + case RC_TYPE_OTHER: dev_dbg(dev, "Configuring IR receiver for iMON protocol\n"); if (pad_stabilize && !nomouse) pad_mouse = true; @@ -1012,7 +1012,7 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 ir_type) pad_mouse = false; } /* ir_proto_packet[0] = 0x00; // already the default */ - ir_type = IR_TYPE_OTHER; + rc_type = RC_TYPE_OTHER; break; default: dev_warn(dev, "Unsupported IR protocol specified, overriding " @@ -1024,7 +1024,7 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 ir_type) pad_mouse = false; } /* ir_proto_packet[0] = 0x00; // already the default */ - ir_type = IR_TYPE_OTHER; + rc_type = RC_TYPE_OTHER; break; } @@ -1034,7 +1034,7 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 ir_type) if (retval) goto out; - ictx->ir_type = ir_type; + ictx->rc_type = rc_type; ictx->pad_mouse = pad_mouse; out: @@ -1306,7 +1306,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) rel_x = buf[2]; rel_y = buf[3]; - if (ictx->ir_type == IR_TYPE_OTHER && pad_stabilize) { + if (ictx->rc_type == RC_TYPE_OTHER && pad_stabilize) { if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) { dir = stabilize((int)rel_x, (int)rel_y, timeout, threshold); @@ -1373,7 +1373,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) buf[0] = 0x01; buf[1] = buf[4] = buf[5] = buf[6] = buf[7] = 0; - if (ictx->ir_type == IR_TYPE_OTHER && pad_stabilize) { + if (ictx->rc_type == RC_TYPE_OTHER && pad_stabilize) { dir = stabilize((int)rel_x, (int)rel_y, timeout, threshold); if (!dir) { @@ -1495,7 +1495,7 @@ static void imon_incoming_packet(struct imon_context *ictx, kc = imon_panel_key_lookup(scancode); } else { scancode = be32_to_cpu(*((u32 *)buf)); - if (ictx->ir_type == IR_TYPE_RC6) { + if (ictx->rc_type == RC_TYPE_RC6) { ktype = IMON_KEY_IMON; if (buf[0] == 0x80) ktype = IMON_KEY_MCE; @@ -1709,7 +1709,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx) { u8 ffdc_cfg_byte = ictx->usb_rx_buf[6]; u8 detected_display_type = IMON_DISPLAY_TYPE_NONE; - u64 allowed_protos = IR_TYPE_OTHER; + u64 allowed_protos = RC_TYPE_OTHER; switch (ffdc_cfg_byte) { /* iMON Knob, no display, iMON IR + vol knob */ @@ -1738,13 +1738,13 @@ static void imon_get_ffdc_type(struct imon_context *ictx) case 0x9e: dev_info(ictx->dev, "0xffdc iMON VFD, MCE IR"); detected_display_type = IMON_DISPLAY_TYPE_VFD; - allowed_protos = IR_TYPE_RC6; + allowed_protos = RC_TYPE_RC6; break; /* iMON LCD, MCE IR */ case 0x9f: dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR"); detected_display_type = IMON_DISPLAY_TYPE_LCD; - allowed_protos = IR_TYPE_RC6; + allowed_protos = RC_TYPE_RC6; break; default: dev_info(ictx->dev, "Unknown 0xffdc device, " @@ -1757,7 +1757,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx) ictx->display_type = detected_display_type; ictx->rdev->allowed_protos = allowed_protos; - ictx->ir_type = allowed_protos; + ictx->rc_type = allowed_protos; } static void imon_set_display_type(struct imon_context *ictx) @@ -1836,10 +1836,10 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx) rdev->priv = ictx; rdev->driver_type = RC_DRIVER_SCANCODE; - rdev->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6; /* iMON PAD or MCE */ + rdev->allowed_protos = RC_TYPE_OTHER | RC_TYPE_RC6; /* iMON PAD or MCE */ rdev->change_protocol = imon_ir_change_protocol; rdev->driver_name = MOD_NAME; - if (ictx->ir_type == IR_TYPE_RC6) + if (ictx->rc_type == RC_TYPE_RC6) rdev->map_name = RC_MAP_IMON_MCE; else rdev->map_name = RC_MAP_IMON_PAD; diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c index 09c143f..624449a 100644 --- a/drivers/media/rc/ir-jvc-decoder.c +++ b/drivers/media/rc/ir-jvc-decoder.c @@ -46,7 +46,7 @@ static int ir_jvc_decode(struct rc_dev *dev, struct ir_raw_event ev) { struct jvc_dec *data = &dev->raw->jvc; - if (!(dev->raw->enabled_protocols & IR_TYPE_JVC)) + if (!(dev->raw->enabled_protocols & RC_TYPE_JVC)) return 0; if (!is_timing_event(ev)) { @@ -173,7 +173,7 @@ out: } static struct ir_raw_handler jvc_handler = { - .protocols = IR_TYPE_JVC, + .protocols = RC_TYPE_JVC, .decode = ir_jvc_decode, }; diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index f9086c5..1e87ee8 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -34,7 +34,7 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) struct lirc_codec *lirc = &dev->raw->lirc; int sample; - if (!(dev->raw->enabled_protocols & IR_TYPE_LIRC)) + if (!(dev->raw->enabled_protocols & RC_TYPE_LIRC)) return 0; if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf) @@ -373,7 +373,7 @@ static int ir_lirc_unregister(struct rc_dev *dev) } static struct ir_raw_handler lirc_handler = { - .protocols = IR_TYPE_LIRC, + .protocols = RC_TYPE_LIRC, .decode = ir_lirc_decode, .raw_register = ir_lirc_register, .raw_unregister = ir_lirc_unregister, diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c index 235d774..5d15c31 100644 --- a/drivers/media/rc/ir-nec-decoder.c +++ b/drivers/media/rc/ir-nec-decoder.c @@ -50,7 +50,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) u32 scancode; u8 address, not_address, command, not_command; - if (!(dev->raw->enabled_protocols & IR_TYPE_NEC)) + if (!(dev->raw->enabled_protocols & RC_TYPE_NEC)) return 0; if (!is_timing_event(ev)) { @@ -190,7 +190,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) } static struct ir_raw_handler nec_handler = { - .protocols = IR_TYPE_NEC, + .protocols = RC_TYPE_NEC, .decode = ir_nec_decode, }; diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c index 779ab0d..ebdba55 100644 --- a/drivers/media/rc/ir-rc5-decoder.c +++ b/drivers/media/rc/ir-rc5-decoder.c @@ -51,7 +51,7 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev) u8 toggle; u32 scancode; - if (!(dev->raw->enabled_protocols & IR_TYPE_RC5)) + if (!(dev->raw->enabled_protocols & RC_TYPE_RC5)) return 0; if (!is_timing_event(ev)) { @@ -163,7 +163,7 @@ out: } static struct ir_raw_handler rc5_handler = { - .protocols = IR_TYPE_RC5, + .protocols = RC_TYPE_RC5, .decode = ir_rc5_decode, }; diff --git a/drivers/media/rc/ir-rc5-sz-decoder.c b/drivers/media/rc/ir-rc5-sz-decoder.c index 5586bf2..90aa886 100644 --- a/drivers/media/rc/ir-rc5-sz-decoder.c +++ b/drivers/media/rc/ir-rc5-sz-decoder.c @@ -47,7 +47,7 @@ static int ir_rc5_sz_decode(struct rc_dev *dev, struct ir_raw_event ev) u8 toggle, command, system; u32 scancode; - if (!(dev->raw->enabled_protocols & IR_TYPE_RC5_SZ)) + if (!(dev->raw->enabled_protocols & RC_TYPE_RC5_SZ)) return 0; if (!is_timing_event(ev)) { @@ -127,7 +127,7 @@ out: } static struct ir_raw_handler rc5_sz_handler = { - .protocols = IR_TYPE_RC5_SZ, + .protocols = RC_TYPE_RC5_SZ, .decode = ir_rc5_sz_decode, }; diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c index 88d9487..755dafa 100644 --- a/drivers/media/rc/ir-rc6-decoder.c +++ b/drivers/media/rc/ir-rc6-decoder.c @@ -81,7 +81,7 @@ static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev) u32 scancode; u8 toggle; - if (!(dev->raw->enabled_protocols & IR_TYPE_RC6)) + if (!(dev->raw->enabled_protocols & RC_TYPE_RC6)) return 0; if (!is_timing_event(ev)) { @@ -255,7 +255,7 @@ out: } static struct ir_raw_handler rc6_handler = { - .protocols = IR_TYPE_RC6, + .protocols = RC_TYPE_RC6, .decode = ir_rc6_decode, }; diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c index 5292b89..a92de80 100644 --- a/drivers/media/rc/ir-sony-decoder.c +++ b/drivers/media/rc/ir-sony-decoder.c @@ -44,7 +44,7 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev) u32 scancode; u8 device, subdevice, function; - if (!(dev->raw->enabled_protocols & IR_TYPE_SONY)) + if (!(dev->raw->enabled_protocols & RC_TYPE_SONY)) return 0; if (!is_timing_event(ev)) { @@ -156,7 +156,7 @@ out: } static struct ir_raw_handler sony_handler = { - .protocols = IR_TYPE_SONY, + .protocols = RC_TYPE_SONY, .decode = ir_sony_decode, }; diff --git a/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c b/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c index b172831..0ea0aee 100644 --- a/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c +++ b/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c @@ -67,7 +67,7 @@ static struct rc_keymap adstech_dvb_t_pci_map = { .map = { .scan = adstech_dvb_t_pci, .size = ARRAY_SIZE(adstech_dvb_t_pci), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_ADSTECH_DVB_T_PCI, } }; diff --git a/drivers/media/rc/keymaps/rc-alink-dtu-m.c b/drivers/media/rc/keymaps/rc-alink-dtu-m.c index ddfee7f..b0ec1c8 100644 --- a/drivers/media/rc/keymaps/rc-alink-dtu-m.c +++ b/drivers/media/rc/keymaps/rc-alink-dtu-m.c @@ -46,7 +46,7 @@ static struct rc_keymap alink_dtu_m_map = { .map = { .scan = alink_dtu_m, .size = ARRAY_SIZE(alink_dtu_m), - .ir_type = IR_TYPE_NEC, + .rc_type = RC_TYPE_NEC, .name = RC_MAP_ALINK_DTU_M, } }; diff --git a/drivers/media/rc/keymaps/rc-anysee.c b/drivers/media/rc/keymaps/rc-anysee.c index 30d7049..9bfe60e 100644 --- a/drivers/media/rc/keymaps/rc-anysee.c +++ b/drivers/media/rc/keymaps/rc-anysee.c @@ -71,7 +71,7 @@ static struct rc_keymap anysee_map = { .map = { .scan = anysee, .size = ARRAY_SIZE(anysee), - .ir_type = IR_TYPE_NEC, + .rc_type = RC_TYPE_NEC, .name = RC_MAP_ANYSEE, } }; diff --git a/drivers/media/rc/keymaps/rc-apac-viewcomp.c b/drivers/media/rc/keymaps/rc-apac-viewcomp.c index 0ef2b56..a32840d 100644 --- a/drivers/media/rc/keymaps/rc-apac-viewcomp.c +++ b/drivers/media/rc/keymaps/rc-apac-viewcomp.c @@ -58,7 +58,7 @@ static struct rc_keymap apac_viewcomp_map = { .map = { .scan = apac_viewcomp, .size = ARRAY_SIZE(apac_viewcomp), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_APAC_VIEWCOMP, } }; diff --git a/drivers/media/rc/keymaps/rc-asus-pc39.c b/drivers/media/rc/keymaps/rc-asus-pc39.c index 2996e0a..f86bfb7 100644 --- a/drivers/media/rc/keymaps/rc-asus-pc39.c +++ b/drivers/media/rc/keymaps/rc-asus-pc39.c @@ -69,7 +69,7 @@ static struct rc_keymap asus_pc39_map = { .map = { .scan = asus_pc39, .size = ARRAY_SIZE(asus_pc39), - .ir_type = IR_TYPE_RC5, + .rc_type = RC_TYPE_RC5, .name = RC_MAP_ASUS_PC39, } }; diff --git a/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c b/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c index 8edfd29..0cefe1c 100644 --- a/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c +++ b/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c @@ -47,7 +47,7 @@ static struct rc_keymap ati_tv_wonder_hd_600_map = { .map = { .scan = ati_tv_wonder_hd_600, .size = ARRAY_SIZE(ati_tv_wonder_hd_600), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_ATI_TV_WONDER_HD_600, } }; diff --git a/drivers/media/rc/keymaps/rc-avermedia-a16d.c b/drivers/media/rc/keymaps/rc-avermedia-a16d.c index 12f0435..43525c8 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-a16d.c +++ b/drivers/media/rc/keymaps/rc-avermedia-a16d.c @@ -53,7 +53,7 @@ static struct rc_keymap avermedia_a16d_map = { .map = { .scan = avermedia_a16d, .size = ARRAY_SIZE(avermedia_a16d), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_AVERMEDIA_A16D, } }; diff --git a/drivers/media/rc/keymaps/rc-avermedia-cardbus.c b/drivers/media/rc/keymaps/rc-avermedia-cardbus.c index 2a945b0..2d528ca 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-cardbus.c +++ b/drivers/media/rc/keymaps/rc-avermedia-cardbus.c @@ -75,7 +75,7 @@ static struct rc_keymap avermedia_cardbus_map = { .map = { .scan = avermedia_cardbus, .size = ARRAY_SIZE(avermedia_cardbus), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_AVERMEDIA_CARDBUS, } }; diff --git a/drivers/media/rc/keymaps/rc-avermedia-dvbt.c b/drivers/media/rc/keymaps/rc-avermedia-dvbt.c index 39dde62..e45b67f 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-dvbt.c +++ b/drivers/media/rc/keymaps/rc-avermedia-dvbt.c @@ -56,7 +56,7 @@ static struct rc_keymap avermedia_dvbt_map = { .map = { .scan = avermedia_dvbt, .size = ARRAY_SIZE(avermedia_dvbt), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_AVERMEDIA_DVBT, } }; diff --git a/drivers/media/rc/keymaps/rc-avermedia-m135a.c b/drivers/media/rc/keymaps/rc-avermedia-m135a.c index e4471fb..d5622c5 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-m135a.c +++ b/drivers/media/rc/keymaps/rc-avermedia-m135a.c @@ -125,7 +125,7 @@ static struct rc_keymap avermedia_m135a_map = { .map = { .scan = avermedia_m135a, .size = ARRAY_SIZE(avermedia_m135a), - .ir_type = IR_TYPE_NEC, + .rc_type = RC_TYPE_NEC, .name = RC_MAP_AVERMEDIA_M135A, } }; diff --git a/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c b/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c index cf8d457..b0e10be 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c +++ b/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c @@ -73,7 +73,7 @@ static struct rc_keymap avermedia_m733a_rm_k6_map = { .map = { .scan = avermedia_m733a_rm_k6, .size = ARRAY_SIZE(avermedia_m733a_rm_k6), - .ir_type = IR_TYPE_NEC, + .rc_type = RC_TYPE_NEC, .name = RC_MAP_AVERMEDIA_M733A_RM_K6, } }; diff --git a/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c b/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c index 9ee6090..3348466 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c +++ b/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c @@ -57,7 +57,7 @@ static struct rc_keymap avermedia_rm_ks_map = { .map = { .scan = avermedia_rm_ks, .size = ARRAY_SIZE(avermedia_rm_ks), - .ir_type = IR_TYPE_NEC, + .rc_type = RC_TYPE_NEC, .name = RC_MAP_AVERMEDIA_RM_KS, } }; diff --git a/drivers/media/rc/keymaps/rc-avermedia.c b/drivers/media/rc/keymaps/rc-avermedia.c index 21effd5..cfde54e 100644 --- a/drivers/media/rc/keymaps/rc-avermedia.c +++ b/drivers/media/rc/keymaps/rc-avermedia.c @@ -64,7 +64,7 @@ static struct rc_keymap avermedia_map = { .map = { .scan = avermedia, .size = ARRAY_SIZE(avermedia), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_AVERMEDIA, } }; diff --git a/drivers/media/rc/keymaps/rc-avertv-303.c b/drivers/media/rc/keymaps/rc-avertv-303.c index 971c59d..ae58663 100644 --- a/drivers/media/rc/keymaps/rc-avertv-303.c +++ b/drivers/media/rc/keymaps/rc-avertv-303.c @@ -63,7 +63,7 @@ static struct rc_keymap avertv_303_map = { .map = { .scan = avertv_303, .size = ARRAY_SIZE(avertv_303), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_AVERTV_303, } }; diff --git a/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c b/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c index e087614..579fafe 100644 --- a/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c +++ b/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c @@ -80,7 +80,7 @@ static struct rc_keymap azurewave_ad_tu700_map = { .map = { .scan = azurewave_ad_tu700, .size = ARRAY_SIZE(azurewave_ad_tu700), - .ir_type = IR_TYPE_NEC, + .rc_type = RC_TYPE_NEC, .name = RC_MAP_AZUREWAVE_AD_TU700, } }; diff --git a/drivers/media/rc/keymaps/rc-behold-columbus.c b/drivers/media/rc/keymaps/rc-behold-columbus.c index 9f56c98..6abb712 100644 --- a/drivers/media/rc/keymaps/rc-behold-columbus.c +++ b/drivers/media/rc/keymaps/rc-behold-columbus.c @@ -86,7 +86,7 @@ static struct rc_keymap behold_columbus_map = { .map = { .scan = behold_columbus, .size = ARRAY_SIZE(behold_columbus), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_BEHOLD_COLUMBUS, } }; diff --git a/drivers/media/rc/keymaps/rc-behold.c b/drivers/media/rc/keymaps/rc-behold.c index abc140b..5694185 100644 --- a/drivers/media/rc/keymaps/rc-behold.c +++ b/drivers/media/rc/keymaps/rc-behold.c @@ -119,7 +119,7 @@ static struct rc_keymap behold_map = { .map = { .scan = behold, .size = ARRAY_SIZE(behold), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_BEHOLD, } }; diff --git a/drivers/media/rc/keymaps/rc-budget-ci-old.c b/drivers/media/rc/keymaps/rc-budget-ci-old.c index 64c2ac9..99f7323 100644 --- a/drivers/media/rc/keymaps/rc-budget-ci-old.c +++ b/drivers/media/rc/keymaps/rc-budget-ci-old.c @@ -70,7 +70,7 @@ static struct rc_keymap budget_ci_old_map = { .map = { .scan = budget_ci_old, .size = ARRAY_SIZE(budget_ci_old), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_BUDGET_CI_OLD, } }; diff --git a/drivers/media/rc/keymaps/rc-cinergy-1400.c b/drivers/media/rc/keymaps/rc-cinergy-1400.c index 074f2c2..b504ddd 100644 --- a/drivers/media/rc/keymaps/rc-cinergy-1400.c +++ b/drivers/media/rc/keymaps/rc-cinergy-1400.c @@ -62,7 +62,7 @@ static struct rc_keymap cinergy_1400_map = { .map = { .scan = cinergy_1400, .size = ARRAY_SIZE(cinergy_1400), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_CINERGY_1400, } }; diff --git a/drivers/media/rc/keymaps/rc-cinergy.c b/drivers/media/rc/keymaps/rc-cinergy.c index cf84c3d..8bf02f1 100644 --- a/drivers/media/rc/keymaps/rc-cinergy.c +++ b/drivers/media/rc/keymaps/rc-cinergy.c @@ -56,7 +56,7 @@ static struct rc_keymap cinergy_map = { .map = { .scan = cinergy, .size = ARRAY_SIZE(cinergy), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_CINERGY, } }; diff --git a/drivers/media/rc/keymaps/rc-dib0700-nec.c b/drivers/media/rc/keymaps/rc-dib0700-nec.c index ae18320..47d5476 100644 --- a/drivers/media/rc/keymaps/rc-dib0700-nec.c +++ b/drivers/media/rc/keymaps/rc-dib0700-nec.c @@ -102,7 +102,7 @@ static struct rc_keymap dib0700_nec_map = { .map = { .scan = dib0700_nec_table, .size = ARRAY_SIZE(dib0700_nec_table), - .ir_type = IR_TYPE_NEC, + .rc_type = RC_TYPE_NEC, .name = RC_MAP_DIB0700_NEC_TABLE, } }; diff --git a/drivers/media/rc/keymaps/rc-dib0700-rc5.c b/drivers/media/rc/keymaps/rc-dib0700-rc5.c index 4a4797c..1d09921 100644 --- a/drivers/media/rc/keymaps/rc-dib0700-rc5.c +++ b/drivers/media/rc/keymaps/rc-dib0700-rc5.c @@ -213,7 +213,7 @@ static struct rc_keymap dib0700_rc5_map = { .map = { .scan = dib0700_rc5_table, .size = ARRAY_SIZE(dib0700_rc5_table), - .ir_type = IR_TYPE_RC5, + .rc_type = RC_TYPE_RC5, .name = RC_MAP_DIB0700_RC5_TABLE, } }; diff --git a/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c b/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c index 63e469e..8ae726b 100644 --- a/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c +++ b/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c @@ -76,7 +76,7 @@ static struct rc_keymap digitalnow_tinytwin_map = { .map = { .scan = digitalnow_tinytwin, .size = ARRAY_SIZE(digitalnow_tinytwin), - .ir_type = IR_TYPE_NEC, + .rc_type = RC_TYPE_NEC, .name = RC_MAP_DIGITALNOW_TINYTWIN, } }; diff --git a/drivers/media/rc/keymaps/rc-digittrade.c b/drivers/media/rc/keymaps/rc-digittrade.c index 5dece78..206469f 100644 --- a/drivers/media/rc/keymaps/rc-digittrade.c +++ b/drivers/media/rc/keymaps/rc-digittrade.c @@ -60,7 +60,7 @@ static struct rc_keymap digittrade_map = { .map = { .scan = digittrade, .size = ARRAY_SIZE(digittrade), - .ir_type = IR_TYPE_NEC, + .rc_type = RC_TYPE_NEC, .name = RC_MAP_DIGITTRADE, } }; diff --git a/drivers/media/rc/keymaps/rc-dm1105-nec.c b/drivers/media/rc/keymaps/rc-dm1105-nec.c index 90684d0..ba6fb0b 100644 --- a/drivers/media/rc/keymaps/rc-dm1105-nec.c +++ b/drivers/media/rc/keymaps/rc-dm1105-nec.c @@ -54,7 +54,7 @@ static struct rc_keymap dm1105_nec_map = { .map = { .scan = dm1105_nec, .size = ARRAY_SIZE(dm1105_nec), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_DM1105_NEC, } }; diff --git a/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c b/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c index 8a4027a..b703937 100644 --- a/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c +++ b/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c @@ -56,7 +56,7 @@ static struct rc_keymap dntv_live_dvb_t_map = { .map = { .scan = dntv_live_dvb_t, .size = ARRAY_SIZE(dntv_live_dvb_t), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_DNTV_LIVE_DVB_T, } }; diff --git a/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c b/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c index 6f4d607..b0126b2 100644 --- a/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c +++ b/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c @@ -75,7 +75,7 @@ static struct rc_keymap dntv_live_dvbt_pro_map = { .map = { .scan = dntv_live_dvbt_pro, .size = ARRAY_SIZE(dntv_live_dvbt_pro), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_DNTV_LIVE_DVBT_PRO, } }; diff --git a/drivers/media/rc/keymaps/rc-em-terratec.c b/drivers/media/rc/keymaps/rc-em-terratec.c index 3130c9c..57bcd55 100644 --- a/drivers/media/rc/keymaps/rc-em-terratec.c +++ b/drivers/media/rc/keymaps/rc-em-terratec.c @@ -47,7 +47,7 @@ static struct rc_keymap em_terratec_map = { .map = { .scan = em_terratec, .size = ARRAY_SIZE(em_terratec), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_EM_TERRATEC, } }; diff --git a/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c b/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c index 4b81696..97e01f4 100644 --- a/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c +++ b/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c @@ -59,7 +59,7 @@ static struct rc_keymap encore_enltv_fm53_map = { .map = { .scan = encore_enltv_fm53, .size = ARRAY_SIZE(encore_enltv_fm53), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_ENCORE_ENLTV_FM53, } }; diff --git a/drivers/media/rc/keymaps/rc-encore-enltv.c b/drivers/media/rc/keymaps/rc-encore-enltv.c index 9fabffd..d3030cf 100644 --- a/drivers/media/rc/keymaps/rc-encore-enltv.c +++ b/drivers/media/rc/keymaps/rc-encore-enltv.c @@ -90,7 +90,7 @@ static struct rc_keymap encore_enltv_map = { .map = { .scan = encore_enltv, .size = ARRAY_SIZE(encore_enltv), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_ENCORE_ENLTV, } }; diff --git a/drivers/media/rc/keymaps/rc-encore-enltv2.c b/drivers/media/rc/keymaps/rc-encore-enltv2.c index efefd51..1871b32 100644 --- a/drivers/media/rc/keymaps/rc-encore-enltv2.c +++ b/drivers/media/rc/keymaps/rc-encore-enltv2.c @@ -68,7 +68,7 @@ static struct rc_keymap encore_enltv2_map = { .map = { .scan = encore_enltv2, .size = ARRAY_SIZE(encore_enltv2), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_ENCORE_ENLTV2, } }; diff --git a/drivers/media/rc/keymaps/rc-evga-indtube.c b/drivers/media/rc/keymaps/rc-evga-indtube.c index 3f3fb13..192d7f8 100644 --- a/drivers/media/rc/keymaps/rc-evga-indtube.c +++ b/drivers/media/rc/keymaps/rc-evga-indtube.c @@ -39,7 +39,7 @@ static struct rc_keymap evga_indtube_map = { .map = { .scan = evga_indtube, .size = ARRAY_SIZE(evga_indtube), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_EVGA_INDTUBE, } }; diff --git a/drivers/media/rc/keymaps/rc-eztv.c b/drivers/media/rc/keymaps/rc-eztv.c index 660907a..fe3ab5e 100644 --- a/drivers/media/rc/keymaps/rc-eztv.c +++ b/drivers/media/rc/keymaps/rc-eztv.c @@ -74,7 +74,7 @@ static struct rc_keymap eztv_map = { .map = { .scan = eztv, .size = ARRAY_SIZE(eztv), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_EZTV, } }; diff --git a/drivers/media/rc/keymaps/rc-flydvb.c b/drivers/media/rc/keymaps/rc-flydvb.c index a173c81..f48249e 100644 --- a/drivers/media/rc/keymaps/rc-flydvb.c +++ b/drivers/media/rc/keymaps/rc-flydvb.c @@ -55,7 +55,7 @@ static struct rc_keymap flydvb_map = { .map = { .scan = flydvb, .size = ARRAY_SIZE(flydvb), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_FLYDVB, } }; diff --git a/drivers/media/rc/keymaps/rc-flyvideo.c b/drivers/media/rc/keymaps/rc-flyvideo.c index 9c73043..59713fb4 100644 --- a/drivers/media/rc/keymaps/rc-flyvideo.c +++ b/drivers/media/rc/keymaps/rc-flyvideo.c @@ -48,7 +48,7 @@ static struct rc_keymap flyvideo_map = { .map = { .scan = flyvideo, .size = ARRAY_SIZE(flyvideo), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_FLYVIDEO, } }; diff --git a/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c b/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c index cdb1038..e69458d 100644 --- a/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c +++ b/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c @@ -76,7 +76,7 @@ static struct rc_keymap fusionhdtv_mce_map = { .map = { .scan = fusionhdtv_mce, .size = ARRAY_SIZE(fusionhdtv_mce), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_FUSIONHDTV_MCE, } }; diff --git a/drivers/media/rc/keymaps/rc-gadmei-rm008z.c b/drivers/media/rc/keymaps/rc-gadmei-rm008z.c index c16c0d1..13587b8 100644 --- a/drivers/media/rc/keymaps/rc-gadmei-rm008z.c +++ b/drivers/media/rc/keymaps/rc-gadmei-rm008z.c @@ -59,7 +59,7 @@ static struct rc_keymap gadmei_rm008z_map = { .map = { .scan = gadmei_rm008z, .size = ARRAY_SIZE(gadmei_rm008z), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_GADMEI_RM008Z, } }; diff --git a/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c b/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c index 89f8e38..2304bf6 100644 --- a/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c +++ b/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c @@ -62,7 +62,7 @@ static struct rc_keymap genius_tvgo_a11mce_map = { .map = { .scan = genius_tvgo_a11mce, .size = ARRAY_SIZE(genius_tvgo_a11mce), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_GENIUS_TVGO_A11MCE, } }; diff --git a/drivers/media/rc/keymaps/rc-gotview7135.c b/drivers/media/rc/keymaps/rc-gotview7135.c index 52f025b..b5be7bf 100644 --- a/drivers/media/rc/keymaps/rc-gotview7135.c +++ b/drivers/media/rc/keymaps/rc-gotview7135.c @@ -57,7 +57,7 @@ static struct rc_keymap gotview7135_map = { .map = { .scan = gotview7135, .size = ARRAY_SIZE(gotview7135), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_GOTVIEW7135, } }; diff --git a/drivers/media/rc/keymaps/rc-hauppauge-new.c b/drivers/media/rc/keymaps/rc-hauppauge-new.c index c6f8cd7..c60f845 100644 --- a/drivers/media/rc/keymaps/rc-hauppauge-new.c +++ b/drivers/media/rc/keymaps/rc-hauppauge-new.c @@ -78,7 +78,7 @@ static struct rc_keymap hauppauge_new_map = { .map = { .scan = hauppauge_new, .size = ARRAY_SIZE(hauppauge_new), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_HAUPPAUGE_NEW, } }; diff --git a/drivers/media/rc/keymaps/rc-imon-mce.c b/drivers/media/rc/keymaps/rc-imon-mce.c index e49f350..4ce902f 100644 --- a/drivers/media/rc/keymaps/rc-imon-mce.c +++ b/drivers/media/rc/keymaps/rc-imon-mce.c @@ -120,7 +120,7 @@ static struct rc_keymap imon_mce_map = { .scan = imon_mce, .size = ARRAY_SIZE(imon_mce), /* its RC6, but w/a hardware decoder */ - .ir_type = IR_TYPE_RC6, + .rc_type = RC_TYPE_RC6, .name = RC_MAP_IMON_MCE, } }; diff --git a/drivers/media/rc/keymaps/rc-imon-pad.c b/drivers/media/rc/keymaps/rc-imon-pad.c index bc4db72..6d4633af 100644 --- a/drivers/media/rc/keymaps/rc-imon-pad.c +++ b/drivers/media/rc/keymaps/rc-imon-pad.c @@ -134,7 +134,7 @@ static struct rc_keymap imon_pad_map = { .scan = imon_pad, .size = ARRAY_SIZE(imon_pad), /* actual protocol details unknown, hardware decoder */ - .ir_type = IR_TYPE_OTHER, + .rc_type = RC_TYPE_OTHER, .name = RC_MAP_IMON_PAD, } }; diff --git a/drivers/media/rc/keymaps/rc-iodata-bctv7e.c b/drivers/media/rc/keymaps/rc-iodata-bctv7e.c index ef66002..c5208f1 100644 --- a/drivers/media/rc/keymaps/rc-iodata-bctv7e.c +++ b/drivers/media/rc/keymaps/rc-iodata-bctv7e.c @@ -66,7 +66,7 @@ static struct rc_keymap iodata_bctv7e_map = { .map = { .scan = iodata_bctv7e, .size = ARRAY_SIZE(iodata_bctv7e), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_IODATA_BCTV7E, } }; diff --git a/drivers/media/rc/keymaps/rc-kaiomy.c b/drivers/media/rc/keymaps/rc-kaiomy.c index 4c7883b..1b6da7f 100644 --- a/drivers/media/rc/keymaps/rc-kaiomy.c +++ b/drivers/media/rc/keymaps/rc-kaiomy.c @@ -65,7 +65,7 @@ static struct rc_keymap kaiomy_map = { .map = { .scan = kaiomy, .size = ARRAY_SIZE(kaiomy), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_KAIOMY, } }; diff --git a/drivers/media/rc/keymaps/rc-kworld-315u.c b/drivers/media/rc/keymaps/rc-kworld-315u.c index 618c817..3418e07 100644 --- a/drivers/media/rc/keymaps/rc-kworld-315u.c +++ b/drivers/media/rc/keymaps/rc-kworld-315u.c @@ -61,7 +61,7 @@ static struct rc_keymap kworld_315u_map = { .map = { .scan = kworld_315u, .size = ARRAY_SIZE(kworld_315u), - .ir_type = IR_TYPE_NEC, + .rc_type = RC_TYPE_NEC, .name = RC_MAP_KWORLD_315U, } }; diff --git a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c index 366732f..4d681eb 100644 --- a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c +++ b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c @@ -77,7 +77,7 @@ static struct rc_keymap kworld_plus_tv_analog_map = { .map = { .scan = kworld_plus_tv_analog, .size = ARRAY_SIZE(kworld_plus_tv_analog), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_KWORLD_PLUS_TV_ANALOG, } }; diff --git a/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c b/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c index 7521315..ebdd122 100644 --- a/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c +++ b/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c @@ -77,7 +77,7 @@ static struct rc_keymap leadtek_y04g0051_map = { .map = { .scan = leadtek_y04g0051, .size = ARRAY_SIZE(leadtek_y04g0051), - .ir_type = IR_TYPE_NEC, + .rc_type = RC_TYPE_NEC, .name = RC_MAP_LEADTEK_Y04G0051, } }; diff --git a/drivers/media/rc/keymaps/rc-lirc.c b/drivers/media/rc/keymaps/rc-lirc.c index 9c8577d..6d8a641 100644 --- a/drivers/media/rc/keymaps/rc-lirc.c +++ b/drivers/media/rc/keymaps/rc-lirc.c @@ -19,7 +19,7 @@ static struct rc_keymap lirc_map = { .map = { .scan = lirc, .size = ARRAY_SIZE(lirc), - .ir_type = IR_TYPE_LIRC, + .rc_type = RC_TYPE_LIRC, .name = RC_MAP_LIRC, } }; diff --git a/drivers/media/rc/keymaps/rc-lme2510.c b/drivers/media/rc/keymaps/rc-lme2510.c index 40dcf0b..ca7e2ac 100644 --- a/drivers/media/rc/keymaps/rc-lme2510.c +++ b/drivers/media/rc/keymaps/rc-lme2510.c @@ -46,7 +46,7 @@ static struct rc_keymap lme2510_map = { .map = { .scan = lme2510_rc, .size = ARRAY_SIZE(lme2510_rc), - .ir_type = IR_TYPE_UNKNOWN, + .rc_type = RC_TYPE_UNKNOWN, .name = RC_MAP_LME2510, } }; diff --git a/drivers/media/rc/keymaps/rc-manli.c b/drivers/media/rc/keymaps/rc-manli.c index 0f590b3..056cf52 100644 --- a/drivers/media/rc/keymaps/rc-manli.c +++ b/drivers/media/rc/keymaps/rc-manli.c @@ -112,7 +112,7 @@ static struct rc_keymap manli_map = { .map = { .scan = manli, .size = ARRAY_SIZE(manli), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_MANLI, } }; diff --git a/drivers/media/rc/keymaps/rc-msi-digivox-ii.c b/drivers/media/rc/keymaps/rc-msi-digivox-ii.c index 67237fb..3a14d31 100644 --- a/drivers/media/rc/keymaps/rc-msi-digivox-ii.c +++ b/drivers/media/rc/keymaps/rc-msi-digivox-ii.c @@ -45,7 +45,7 @@ static struct rc_keymap msi_digivox_ii_map = { .map = { .scan = msi_digivox_ii, .size = ARRAY_SIZE(msi_digivox_ii), - .ir_type = IR_TYPE_NEC, + .rc_type = RC_TYPE_NEC, .name = RC_MAP_MSI_DIGIVOX_II, } }; diff --git a/drivers/media/rc/keymaps/rc-msi-digivox-iii.c b/drivers/media/rc/keymaps/rc-msi-digivox-iii.c index 882056e..16c5b0a 100644 --- a/drivers/media/rc/keymaps/rc-msi-digivox-iii.c +++ b/drivers/media/rc/keymaps/rc-msi-digivox-iii.c @@ -63,7 +63,7 @@ static struct rc_keymap msi_digivox_iii_map = { .map = { .scan = msi_digivox_iii, .size = ARRAY_SIZE(msi_digivox_iii), - .ir_type = IR_TYPE_NEC, + .rc_type = RC_TYPE_NEC, .name = RC_MAP_MSI_DIGIVOX_III, } }; diff --git a/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c b/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c index eb8e42c..d4c9102 100644 --- a/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c +++ b/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c @@ -101,7 +101,7 @@ static struct rc_keymap msi_tvanywhere_plus_map = { .map = { .scan = msi_tvanywhere_plus, .size = ARRAY_SIZE(msi_tvanywhere_plus), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_MSI_TVANYWHERE_PLUS, } }; diff --git a/drivers/media/rc/keymaps/rc-msi-tvanywhere.c b/drivers/media/rc/keymaps/rc-msi-tvanywhere.c index ef41185..aec064c 100644 --- a/drivers/media/rc/keymaps/rc-msi-tvanywhere.c +++ b/drivers/media/rc/keymaps/rc-msi-tvanywhere.c @@ -47,7 +47,7 @@ static struct rc_keymap msi_tvanywhere_map = { .map = { .scan = msi_tvanywhere, .size = ARRAY_SIZE(msi_tvanywhere), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_MSI_TVANYWHERE, } }; diff --git a/drivers/media/rc/keymaps/rc-nebula.c b/drivers/media/rc/keymaps/rc-nebula.c index ccc50eb..2c44b90 100644 --- a/drivers/media/rc/keymaps/rc-nebula.c +++ b/drivers/media/rc/keymaps/rc-nebula.c @@ -74,7 +74,7 @@ static struct rc_keymap nebula_map = { .map = { .scan = nebula, .size = ARRAY_SIZE(nebula), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_NEBULA, } }; diff --git a/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c b/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c index e1b54d2..929084b 100644 --- a/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c +++ b/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c @@ -83,7 +83,7 @@ static struct rc_keymap nec_terratec_cinergy_xs_map = { .map = { .scan = nec_terratec_cinergy_xs, .size = ARRAY_SIZE(nec_terratec_cinergy_xs), - .ir_type = IR_TYPE_NEC, + .rc_type = RC_TYPE_NEC, .name = RC_MAP_NEC_TERRATEC_CINERGY_XS, } }; diff --git a/drivers/media/rc/keymaps/rc-norwood.c b/drivers/media/rc/keymaps/rc-norwood.c index e5849a6..7fe7746 100644 --- a/drivers/media/rc/keymaps/rc-norwood.c +++ b/drivers/media/rc/keymaps/rc-norwood.c @@ -63,7 +63,7 @@ static struct rc_keymap norwood_map = { .map = { .scan = norwood, .size = ARRAY_SIZE(norwood), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_NORWOOD, } }; diff --git a/drivers/media/rc/keymaps/rc-npgtech.c b/drivers/media/rc/keymaps/rc-npgtech.c index b9ece1e..a9cbcde 100644 --- a/drivers/media/rc/keymaps/rc-npgtech.c +++ b/drivers/media/rc/keymaps/rc-npgtech.c @@ -58,7 +58,7 @@ static struct rc_keymap npgtech_map = { .map = { .scan = npgtech, .size = ARRAY_SIZE(npgtech), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_NPGTECH, } }; diff --git a/drivers/media/rc/keymaps/rc-pctv-sedna.c b/drivers/media/rc/keymaps/rc-pctv-sedna.c index 4129bb4..68b33b3 100644 --- a/drivers/media/rc/keymaps/rc-pctv-sedna.c +++ b/drivers/media/rc/keymaps/rc-pctv-sedna.c @@ -58,7 +58,7 @@ static struct rc_keymap pctv_sedna_map = { .map = { .scan = pctv_sedna, .size = ARRAY_SIZE(pctv_sedna), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_PCTV_SEDNA, } }; diff --git a/drivers/media/rc/keymaps/rc-pinnacle-color.c b/drivers/media/rc/keymaps/rc-pinnacle-color.c index 326e023..364ccde 100644 --- a/drivers/media/rc/keymaps/rc-pinnacle-color.c +++ b/drivers/media/rc/keymaps/rc-pinnacle-color.c @@ -72,7 +72,7 @@ static struct rc_keymap pinnacle_color_map = { .map = { .scan = pinnacle_color, .size = ARRAY_SIZE(pinnacle_color), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_PINNACLE_COLOR, } }; diff --git a/drivers/media/rc/keymaps/rc-pinnacle-grey.c b/drivers/media/rc/keymaps/rc-pinnacle-grey.c index 14cb772..993eff7 100644 --- a/drivers/media/rc/keymaps/rc-pinnacle-grey.c +++ b/drivers/media/rc/keymaps/rc-pinnacle-grey.c @@ -67,7 +67,7 @@ static struct rc_keymap pinnacle_grey_map = { .map = { .scan = pinnacle_grey, .size = ARRAY_SIZE(pinnacle_grey), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_PINNACLE_GREY, } }; diff --git a/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c index 835bf4e..56e6a7e 100644 --- a/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c +++ b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c @@ -51,7 +51,7 @@ static struct rc_keymap pinnacle_pctv_hd_map = { .map = { .scan = pinnacle_pctv_hd, .size = ARRAY_SIZE(pinnacle_pctv_hd), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_PINNACLE_PCTV_HD, } }; diff --git a/drivers/media/rc/keymaps/rc-pixelview-mk12.c b/drivers/media/rc/keymaps/rc-pixelview-mk12.c index 5a735d5..84f89eb 100644 --- a/drivers/media/rc/keymaps/rc-pixelview-mk12.c +++ b/drivers/media/rc/keymaps/rc-pixelview-mk12.c @@ -61,7 +61,7 @@ static struct rc_keymap pixelview_map = { .map = { .scan = pixelview_mk12, .size = ARRAY_SIZE(pixelview_mk12), - .ir_type = IR_TYPE_NEC, + .rc_type = RC_TYPE_NEC, .name = RC_MAP_PIXELVIEW_MK12, } }; diff --git a/drivers/media/rc/keymaps/rc-pixelview-new.c b/drivers/media/rc/keymaps/rc-pixelview-new.c index 7bbbbf5..703f86b 100644 --- a/drivers/media/rc/keymaps/rc-pixelview-new.c +++ b/drivers/media/rc/keymaps/rc-pixelview-new.c @@ -61,7 +61,7 @@ static struct rc_keymap pixelview_new_map = { .map = { .scan = pixelview_new, .size = ARRAY_SIZE(pixelview_new), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_PIXELVIEW_NEW, } }; diff --git a/drivers/media/rc/keymaps/rc-pixelview.c b/drivers/media/rc/keymaps/rc-pixelview.c index 82ff12e..5a50aa7 100644 --- a/drivers/media/rc/keymaps/rc-pixelview.c +++ b/drivers/media/rc/keymaps/rc-pixelview.c @@ -60,7 +60,7 @@ static struct rc_keymap pixelview_map = { .map = { .scan = pixelview, .size = ARRAY_SIZE(pixelview), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_PIXELVIEW, } }; diff --git a/drivers/media/rc/keymaps/rc-powercolor-real-angel.c b/drivers/media/rc/keymaps/rc-powercolor-real-angel.c index 7cef819..4eec437 100644 --- a/drivers/media/rc/keymaps/rc-powercolor-real-angel.c +++ b/drivers/media/rc/keymaps/rc-powercolor-real-angel.c @@ -59,7 +59,7 @@ static struct rc_keymap powercolor_real_angel_map = { .map = { .scan = powercolor_real_angel, .size = ARRAY_SIZE(powercolor_real_angel), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_POWERCOLOR_REAL_ANGEL, } }; diff --git a/drivers/media/rc/keymaps/rc-proteus-2309.c b/drivers/media/rc/keymaps/rc-proteus-2309.c index 22e92d3..802c58a 100644 --- a/drivers/media/rc/keymaps/rc-proteus-2309.c +++ b/drivers/media/rc/keymaps/rc-proteus-2309.c @@ -47,7 +47,7 @@ static struct rc_keymap proteus_2309_map = { .map = { .scan = proteus_2309, .size = ARRAY_SIZE(proteus_2309), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_PROTEUS_2309, } }; diff --git a/drivers/media/rc/keymaps/rc-purpletv.c b/drivers/media/rc/keymaps/rc-purpletv.c index 4e20fc2..f3e9709 100644 --- a/drivers/media/rc/keymaps/rc-purpletv.c +++ b/drivers/media/rc/keymaps/rc-purpletv.c @@ -59,7 +59,7 @@ static struct rc_keymap purpletv_map = { .map = { .scan = purpletv, .size = ARRAY_SIZE(purpletv), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_PURPLETV, } }; diff --git a/drivers/media/rc/keymaps/rc-pv951.c b/drivers/media/rc/keymaps/rc-pv951.c index 36679e7..e301ff0 100644 --- a/drivers/media/rc/keymaps/rc-pv951.c +++ b/drivers/media/rc/keymaps/rc-pv951.c @@ -56,7 +56,7 @@ static struct rc_keymap pv951_map = { .map = { .scan = pv951, .size = ARRAY_SIZE(pv951), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_PV951, } }; diff --git a/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c b/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c index cc6b8f5..91bcab8 100644 --- a/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c +++ b/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c @@ -81,7 +81,7 @@ static struct rc_keymap rc5_hauppauge_new_map = { .map = { .scan = rc5_hauppauge_new, .size = ARRAY_SIZE(rc5_hauppauge_new), - .ir_type = IR_TYPE_RC5, + .rc_type = RC_TYPE_RC5, .name = RC_MAP_RC5_HAUPPAUGE_NEW, } }; diff --git a/drivers/media/rc/keymaps/rc-rc5-tv.c b/drivers/media/rc/keymaps/rc-rc5-tv.c index 73cce2f..cda2a2f 100644 --- a/drivers/media/rc/keymaps/rc-rc5-tv.c +++ b/drivers/media/rc/keymaps/rc-rc5-tv.c @@ -59,7 +59,7 @@ static struct rc_keymap rc5_tv_map = { .map = { .scan = rc5_tv, .size = ARRAY_SIZE(rc5_tv), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_RC5_TV, } }; diff --git a/drivers/media/rc/keymaps/rc-rc6-mce.c b/drivers/media/rc/keymaps/rc-rc6-mce.c index 6da955d..f926477 100644 --- a/drivers/media/rc/keymaps/rc-rc6-mce.c +++ b/drivers/media/rc/keymaps/rc-rc6-mce.c @@ -91,7 +91,7 @@ static struct rc_keymap rc6_mce_map = { .map = { .scan = rc6_mce, .size = ARRAY_SIZE(rc6_mce), - .ir_type = IR_TYPE_RC6, + .rc_type = RC_TYPE_RC6, .name = RC_MAP_RC6_MCE, } }; diff --git a/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c b/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c index ab1a6d2..6781426 100644 --- a/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c +++ b/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c @@ -56,7 +56,7 @@ static struct rc_keymap real_audio_220_32_keys_map = { .map = { .scan = real_audio_220_32_keys, .size = ARRAY_SIZE(real_audio_220_32_keys), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_REAL_AUDIO_220_32_KEYS, } }; diff --git a/drivers/media/rc/keymaps/rc-streamzap.c b/drivers/media/rc/keymaps/rc-streamzap.c index df32013..bafe5b8 100644 --- a/drivers/media/rc/keymaps/rc-streamzap.c +++ b/drivers/media/rc/keymaps/rc-streamzap.c @@ -60,7 +60,7 @@ static struct rc_keymap streamzap_map = { .map = { .scan = streamzap, .size = ARRAY_SIZE(streamzap), - .ir_type = IR_TYPE_RC5_SZ, + .rc_type = RC_TYPE_RC5_SZ, .name = RC_MAP_STREAMZAP, } }; diff --git a/drivers/media/rc/keymaps/rc-tbs-nec.c b/drivers/media/rc/keymaps/rc-tbs-nec.c index 3309631..4ef4f81 100644 --- a/drivers/media/rc/keymaps/rc-tbs-nec.c +++ b/drivers/media/rc/keymaps/rc-tbs-nec.c @@ -51,7 +51,7 @@ static struct rc_keymap tbs_nec_map = { .map = { .scan = tbs_nec, .size = ARRAY_SIZE(tbs_nec), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_TBS_NEC, } }; diff --git a/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c b/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c index 5326a0b..4064a32 100644 --- a/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c +++ b/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c @@ -70,7 +70,7 @@ static struct rc_keymap terratec_cinergy_xs_map = { .map = { .scan = terratec_cinergy_xs, .size = ARRAY_SIZE(terratec_cinergy_xs), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_TERRATEC_CINERGY_XS, } }; diff --git a/drivers/media/rc/keymaps/rc-terratec-slim.c b/drivers/media/rc/keymaps/rc-terratec-slim.c index 10dee4c..c23caf7 100644 --- a/drivers/media/rc/keymaps/rc-terratec-slim.c +++ b/drivers/media/rc/keymaps/rc-terratec-slim.c @@ -57,7 +57,7 @@ static struct rc_keymap terratec_slim_map = { .map = { .scan = terratec_slim, .size = ARRAY_SIZE(terratec_slim), - .ir_type = IR_TYPE_NEC, + .rc_type = RC_TYPE_NEC, .name = RC_MAP_TERRATEC_SLIM, } }; diff --git a/drivers/media/rc/keymaps/rc-tevii-nec.c b/drivers/media/rc/keymaps/rc-tevii-nec.c index e30d411..eabfb70 100644 --- a/drivers/media/rc/keymaps/rc-tevii-nec.c +++ b/drivers/media/rc/keymaps/rc-tevii-nec.c @@ -66,7 +66,7 @@ static struct rc_keymap tevii_nec_map = { .map = { .scan = tevii_nec, .size = ARRAY_SIZE(tevii_nec), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_TEVII_NEC, } }; diff --git a/drivers/media/rc/keymaps/rc-total-media-in-hand.c b/drivers/media/rc/keymaps/rc-total-media-in-hand.c index fd19857..cd39b3d 100644 --- a/drivers/media/rc/keymaps/rc-total-media-in-hand.c +++ b/drivers/media/rc/keymaps/rc-total-media-in-hand.c @@ -63,7 +63,7 @@ static struct rc_keymap total_media_in_hand_map = { .map = { .scan = total_media_in_hand, .size = ARRAY_SIZE(total_media_in_hand), - .ir_type = IR_TYPE_NEC, + .rc_type = RC_TYPE_NEC, .name = RC_MAP_TOTAL_MEDIA_IN_HAND, } }; diff --git a/drivers/media/rc/keymaps/rc-trekstor.c b/drivers/media/rc/keymaps/rc-trekstor.c index 91092ca..31d6c6c 100644 --- a/drivers/media/rc/keymaps/rc-trekstor.c +++ b/drivers/media/rc/keymaps/rc-trekstor.c @@ -58,7 +58,7 @@ static struct rc_keymap trekstor_map = { .map = { .scan = trekstor, .size = ARRAY_SIZE(trekstor), - .ir_type = IR_TYPE_NEC, + .rc_type = RC_TYPE_NEC, .name = RC_MAP_TREKSTOR, } }; diff --git a/drivers/media/rc/keymaps/rc-tt-1500.c b/drivers/media/rc/keymaps/rc-tt-1500.c index bc88de0..45a0608 100644 --- a/drivers/media/rc/keymaps/rc-tt-1500.c +++ b/drivers/media/rc/keymaps/rc-tt-1500.c @@ -60,7 +60,7 @@ static struct rc_keymap tt_1500_map = { .map = { .scan = tt_1500, .size = ARRAY_SIZE(tt_1500), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_TT_1500, } }; diff --git a/drivers/media/rc/keymaps/rc-twinhan1027.c b/drivers/media/rc/keymaps/rc-twinhan1027.c index 0b5d356..b5def53 100644 --- a/drivers/media/rc/keymaps/rc-twinhan1027.c +++ b/drivers/media/rc/keymaps/rc-twinhan1027.c @@ -65,7 +65,7 @@ static struct rc_keymap twinhan_vp1027_map = { .map = { .scan = twinhan_vp1027, .size = ARRAY_SIZE(twinhan_vp1027), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_TWINHAN_VP1027_DVBS, } }; diff --git a/drivers/media/rc/keymaps/rc-videomate-s350.c b/drivers/media/rc/keymaps/rc-videomate-s350.c index 4df7fcd..7c422b4 100644 --- a/drivers/media/rc/keymaps/rc-videomate-s350.c +++ b/drivers/media/rc/keymaps/rc-videomate-s350.c @@ -63,7 +63,7 @@ static struct rc_keymap videomate_s350_map = { .map = { .scan = videomate_s350, .size = ARRAY_SIZE(videomate_s350), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_VIDEOMATE_S350, } }; diff --git a/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c b/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c index 776b0a6..4d31b47 100644 --- a/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c +++ b/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c @@ -65,7 +65,7 @@ static struct rc_keymap videomate_tv_pvr_map = { .map = { .scan = videomate_tv_pvr, .size = ARRAY_SIZE(videomate_tv_pvr), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_VIDEOMATE_TV_PVR, } }; diff --git a/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c b/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c index 9d2d550..ade3c14 100644 --- a/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c +++ b/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c @@ -60,7 +60,7 @@ static struct rc_keymap winfast_usbii_deluxe_map = { .map = { .scan = winfast_usbii_deluxe, .size = ARRAY_SIZE(winfast_usbii_deluxe), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_WINFAST_USBII_DELUXE, } }; diff --git a/drivers/media/rc/keymaps/rc-winfast.c b/drivers/media/rc/keymaps/rc-winfast.c index 0e90a3b..502b5f5 100644 --- a/drivers/media/rc/keymaps/rc-winfast.c +++ b/drivers/media/rc/keymaps/rc-winfast.c @@ -80,7 +80,7 @@ static struct rc_keymap winfast_map = { .map = { .scan = winfast, .size = ARRAY_SIZE(winfast), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_WINFAST, } }; diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index db7787a..c2cb58a 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -1060,7 +1060,7 @@ static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir) rc->dev.parent = dev; rc->priv = ir; rc->driver_type = RC_DRIVER_IR_RAW; - rc->allowed_protos = IR_TYPE_ALL; + rc->allowed_protos = RC_TYPE_ALL; rc->timeout = MS_TO_NS(1000); if (!ir->flags.no_tx) { rc->s_tx_mask = mceusb_set_tx_mask; diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index bf3f58f..7fca6d1 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -1060,7 +1060,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) /* Set up the rc device */ rdev->priv = nvt; rdev->driver_type = RC_DRIVER_IR_RAW; - rdev->allowed_protos = IR_TYPE_ALL; + rdev->allowed_protos = RC_TYPE_ALL; rdev->open = nvt_open; rdev->close = nvt_close; rdev->tx_ir = nvt_tx_ir; diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 11e2703..f3244eb 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -102,7 +102,7 @@ static struct rc_keymap empty_map = { .map = { .scan = empty, .size = ARRAY_SIZE(empty), - .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ .name = RC_MAP_EMPTY, } }; @@ -111,7 +111,7 @@ static struct rc_keymap empty_map = { * ir_create_table() - initializes a scancode table * @rc_tab: the ir_scancode_table to initialize * @name: name to assign to the table - * @ir_type: ir type to assign to the new table + * @rc_type: ir type to assign to the new table * @size: initial size of the table * @return: zero on success or a negative error code * @@ -119,10 +119,10 @@ static struct rc_keymap empty_map = { * memory to hold at least the specified number of elements. */ static int ir_create_table(struct ir_scancode_table *rc_tab, - const char *name, u64 ir_type, size_t size) + const char *name, u64 rc_type, size_t size) { rc_tab->name = name; - rc_tab->ir_type = ir_type; + rc_tab->rc_type = rc_type; rc_tab->alloc = roundup_pow_of_two(size * sizeof(struct ir_scancode)); rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode); rc_tab->scan = kmalloc(rc_tab->alloc, GFP_KERNEL); @@ -372,7 +372,7 @@ static int ir_setkeytable(struct rc_dev *dev, int rc; rc = ir_create_table(rc_tab, from->name, - from->ir_type, from->size); + from->rc_type, from->size); if (rc) return rc; @@ -719,14 +719,14 @@ static struct { u64 type; char *name; } proto_names[] = { - { IR_TYPE_UNKNOWN, "unknown" }, - { IR_TYPE_RC5, "rc-5" }, - { IR_TYPE_NEC, "nec" }, - { IR_TYPE_RC6, "rc-6" }, - { IR_TYPE_JVC, "jvc" }, - { IR_TYPE_SONY, "sony" }, - { IR_TYPE_RC5_SZ, "rc-5-sz" }, - { IR_TYPE_LIRC, "lirc" }, + { RC_TYPE_UNKNOWN, "unknown" }, + { RC_TYPE_RC5, "rc-5" }, + { RC_TYPE_NEC, "nec" }, + { RC_TYPE_RC6, "rc-6" }, + { RC_TYPE_JVC, "jvc" }, + { RC_TYPE_SONY, "sony" }, + { RC_TYPE_RC5_SZ, "rc-5-sz" }, + { RC_TYPE_LIRC, "lirc" }, }; #define PROTO_NONE "none" @@ -755,7 +755,7 @@ static ssize_t show_protocols(struct device *device, return -EINVAL; if (dev->driver_type == RC_DRIVER_SCANCODE) { - enabled = dev->rc_tab.ir_type; + enabled = dev->rc_tab.rc_type; allowed = dev->allowed_protos; } else { enabled = dev->raw->enabled_protocols; @@ -813,7 +813,7 @@ static ssize_t store_protocols(struct device *device, return -EINVAL; if (dev->driver_type == RC_DRIVER_SCANCODE) - type = dev->rc_tab.ir_type; + type = dev->rc_tab.rc_type; else if (dev->raw) type = dev->raw->enabled_protocols; else { @@ -881,7 +881,7 @@ static ssize_t store_protocols(struct device *device, if (dev->driver_type == RC_DRIVER_SCANCODE) { spin_lock_irqsave(&dev->rc_tab.lock, flags); - dev->rc_tab.ir_type = type; + dev->rc_tab.rc_type = type; spin_unlock_irqrestore(&dev->rc_tab.lock, flags); } else { dev->raw->enabled_protocols = type; @@ -1052,7 +1052,7 @@ int rc_register_device(struct rc_dev *dev) } if (dev->change_protocol) { - rc = dev->change_protocol(dev, rc_tab->ir_type); + rc = dev->change_protocol(dev, rc_tab->rc_type); if (rc < 0) goto out_raw; } diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c index ea2cb63..7814ec7 100644 --- a/drivers/media/rc/streamzap.c +++ b/drivers/media/rc/streamzap.c @@ -318,7 +318,7 @@ static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz) rdev->input_phys = sz->phys; rdev->priv = sz; rdev->driver_type = RC_DRIVER_IR_RAW; - rdev->allowed_protos = IR_TYPE_ALL; + rdev->allowed_protos = RC_TYPE_ALL; rdev->driver_name = DRIVER_NAME; rdev->map_name = RC_MAP_STREAMZAP; diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index e71a026..c330fb9 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c @@ -98,7 +98,7 @@ static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw, case CX18_HW_Z8F0811_IR_RX_HAUP: init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; - init_data->type = IR_TYPE_RC5; + init_data->type = RC_TYPE_RC5; init_data->name = cx->card_name; info.platform_data = init_data; break; diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c index 1d043ed..c236a4e 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/video/cx231xx/cx231xx-input.c @@ -84,7 +84,7 @@ int cx231xx_ir_init(struct cx231xx *dev) /* The i2c micro-controller only outputs the cmd part of NEC protocol */ dev->init_data.rc_dev->scanmask = 0xff; dev->init_data.rc_dev->driver_name = "cx231xx"; - dev->init_data.type = IR_TYPE_NEC; + dev->init_data.type = RC_TYPE_NEC; info.addr = 0x30; /* Load and bind ir-kbd-i2c */ diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index e824ba6..0b0d066 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c @@ -264,14 +264,14 @@ int cx23885_input_init(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1250: /* Integrated CX2388[58] IR controller */ driver_type = RC_DRIVER_IR_RAW; - allowed_protos = IR_TYPE_ALL; + allowed_protos = RC_TYPE_ALL; /* The grey Hauppauge RC-5 remote */ rc_map = RC_MAP_RC5_HAUPPAUGE_NEW; break; case CX23885_BOARD_TEVII_S470: /* Integrated CX23885 IR controller */ driver_type = RC_DRIVER_IR_RAW; - allowed_protos = IR_TYPE_ALL; + allowed_protos = RC_TYPE_ALL; /* A guess at the remote */ rc_map = RC_MAP_TEVII_NEC; break; diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index cfeba4c..4a3bf54 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -241,7 +241,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) struct cx88_IR *ir; struct rc_dev *dev; char *ir_codes = NULL; - u64 ir_type = IR_TYPE_OTHER; + u64 rc_type = RC_TYPE_OTHER; int err = -ENOMEM; u32 hardware_mask = 0; /* For devices with a hardware mask, when * used with a full-code IR table @@ -404,7 +404,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_TWINHAN_VP1027_DVBS: ir_codes = RC_MAP_TWINHAN_VP1027_DVBS; - ir_type = IR_TYPE_NEC; + rc_type = RC_TYPE_NEC; ir->sampling = 0xff00; /* address */ break; } @@ -457,7 +457,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) dev->timeout = 10 * 1000 * 1000; /* 10 ms */ } else { dev->driver_type = RC_DRIVER_SCANCODE; - dev->allowed_protos = ir_type; + dev->allowed_protos = rc_type; } ir->core = core; @@ -557,7 +557,7 @@ void cx88_i2c_init_ir(struct cx88_core *core) /* Hauppauge XVR */ core->init_data.name = "cx88 Hauppauge XVR remote"; core->init_data.ir_codes = RC_MAP_HAUPPAUGE_NEW; - core->init_data.type = IR_TYPE_RC5; + core->init_data.type = RC_TYPE_RC5; core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; info.platform_data = &core->init_data; diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index e32eb38..29cc744 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -343,7 +343,7 @@ static void em28xx_ir_stop(struct rc_dev *rc) cancel_delayed_work_sync(&ir->work); } -int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 ir_type) +int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type) { int rc = 0; struct em28xx_IR *ir = rc_dev->priv; @@ -352,14 +352,14 @@ int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 ir_type) /* Adjust xclk based o IR table for RC5/NEC tables */ - if (ir_type == IR_TYPE_RC5) { + if (rc_type == RC_TYPE_RC5) { dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; ir->full_code = 1; - } else if (ir_type == IR_TYPE_NEC) { + } else if (rc_type == RC_TYPE_NEC) { dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; ir_config = EM2874_IR_NEC; ir->full_code = 1; - } else if (ir_type != IR_TYPE_UNKNOWN) + } else if (rc_type != RC_TYPE_UNKNOWN) rc = -EINVAL; em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, @@ -408,14 +408,14 @@ int em28xx_ir_init(struct em28xx *dev) * em2874 supports more protocols. For now, let's just announce * the two protocols that were already tested */ - rc->allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; + rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC; rc->priv = ir; rc->change_protocol = em28xx_ir_change_protocol; rc->open = em28xx_ir_start; rc->close = em28xx_ir_stop; /* By default, keep protocol field untouched */ - err = em28xx_ir_change_protocol(rc, IR_TYPE_UNKNOWN); + err = em28xx_ir_change_protocol(rc, RC_TYPE_UNKNOWN); if (err) goto err_out_free; diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index c77ea53..dd54c3d 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -269,7 +269,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) { char *ir_codes = NULL; const char *name = NULL; - u64 ir_type = IR_TYPE_UNKNOWN; + u64 rc_type = RC_TYPE_UNKNOWN; struct IR_i2c *ir; struct rc_dev *rc = NULL; struct i2c_adapter *adap = client->adapter; @@ -288,7 +288,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) case 0x64: name = "Pixelview"; ir->get_key = get_key_pixelview; - ir_type = IR_TYPE_OTHER; + rc_type = RC_TYPE_OTHER; ir_codes = RC_MAP_EMPTY; break; case 0x18: @@ -296,7 +296,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) case 0x1a: name = "Hauppauge"; ir->get_key = get_key_haup; - ir_type = IR_TYPE_RC5; + rc_type = RC_TYPE_RC5; if (hauppauge == 1) { ir_codes = RC_MAP_HAUPPAUGE_NEW; } else { @@ -306,19 +306,19 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) case 0x30: name = "KNC One"; ir->get_key = get_key_knc1; - ir_type = IR_TYPE_OTHER; + rc_type = RC_TYPE_OTHER; ir_codes = RC_MAP_EMPTY; break; case 0x6b: name = "FusionHDTV"; ir->get_key = get_key_fusionhdtv; - ir_type = IR_TYPE_RC5; + rc_type = RC_TYPE_RC5; ir_codes = RC_MAP_FUSIONHDTV_MCE; break; case 0x40: name = "AVerMedia Cardbus remote"; ir->get_key = get_key_avermedia_cardbus; - ir_type = IR_TYPE_OTHER; + rc_type = RC_TYPE_OTHER; ir_codes = RC_MAP_AVERMEDIA_CARDBUS; break; } @@ -333,7 +333,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) name = init_data->name; if (init_data->type) - ir_type = init_data->type; + rc_type = init_data->type; if (init_data->polling_interval) ir->polling_interval = init_data->polling_interval; @@ -378,7 +378,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir->rc = rc; /* Make sure we are all setup before going on */ - if (!name || !ir->get_key || !ir_type || !ir_codes) { + if (!name || !ir->get_key || !rc_type || !ir_codes) { dprintk(1, ": Unsupported device at address 0x%02x\n", addr); err = -ENODEV; @@ -405,7 +405,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) * Initialize the other fields of rc_dev */ rc->map_name = ir->ir_codes; - rc->allowed_protos = ir_type; + rc->allowed_protos = rc_type; if (!rc->driver_name) rc->driver_name = MODULE_NAME; diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index 665191c..6817092 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -172,7 +172,7 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) init_data->ir_codes = RC_MAP_AVERMEDIA_CARDBUS; init_data->internal_get_key_func = IR_KBD_GET_KEY_AVERMEDIA_CARDBUS; - init_data->type = IR_TYPE_OTHER; + init_data->type = RC_TYPE_OTHER; init_data->name = "AVerMedia AVerTV card"; break; case IVTV_HW_I2C_IR_RX_HAUP_EXT: @@ -180,14 +180,14 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) /* Default to old black remote */ init_data->ir_codes = RC_MAP_RC5_TV; init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP; - init_data->type = IR_TYPE_RC5; + init_data->type = RC_TYPE_RC5; init_data->name = itv->card_name; break; case IVTV_HW_Z8F0811_IR_RX_HAUP: /* Default to grey remote */ init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; - init_data->type = IR_TYPE_RC5; + init_data->type = RC_TYPE_RC5; init_data->name = itv->card_name; break; } diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index cd39aea..f3f4aff 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -909,7 +909,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) dev->init_data.name = "BeholdTV"; dev->init_data.get_key = get_key_beholdm6xx; dev->init_data.ir_codes = RC_MAP_BEHOLD; - dev->init_data.type = IR_TYPE_NEC; + dev->init_data.type = RC_TYPE_NEC; info.addr = 0x2d; break; case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/staging/tm6000/tm6000-input.c index 02b9829..e02ea67 100644 --- a/drivers/staging/tm6000/tm6000-input.c +++ b/drivers/staging/tm6000/tm6000-input.c @@ -65,7 +65,7 @@ struct tm6000_IR { int (*get_key) (struct tm6000_IR *, struct tm6000_ir_poll_result *); /* IR device properties */ - u64 ir_type; + u64 rc_type; }; @@ -143,7 +143,7 @@ static int default_polling_getkey(struct tm6000_IR *ir, return 0; if (&dev->int_in) { - if (ir->ir_type == IR_TYPE_RC5) + if (ir->rc_type == RC_TYPE_RC5) poll_result->rc_data = ir->urb_data[0]; else poll_result->rc_data = ir->urb_data[0] | ir->urb_data[1] << 8; @@ -153,7 +153,7 @@ static int default_polling_getkey(struct tm6000_IR *ir, tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1); msleep(10); - if (ir->ir_type == IR_TYPE_RC5) { + if (ir->rc_type == RC_TYPE_RC5) { rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, REQ_02_GET_IR_CODE, 0, 0, buf, 1); @@ -230,7 +230,7 @@ static void tm6000_ir_stop(struct rc_dev *rc) cancel_delayed_work_sync(&ir->work); } -int tm6000_ir_change_protocol(struct rc_dev *rc, u64 ir_type) +int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type) { struct tm6000_IR *ir = rc->priv; @@ -268,7 +268,7 @@ int tm6000_ir_init(struct tm6000_core *dev) ir->rc = rc; /* input einrichten */ - rc->allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; + rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC; rc->priv = ir; rc->change_protocol = tm6000_ir_change_protocol; rc->open = tm6000_ir_start; @@ -283,7 +283,7 @@ int tm6000_ir_init(struct tm6000_core *dev) usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); strlcat(ir->phys, "/input0", sizeof(ir->phys)); - tm6000_ir_change_protocol(rc, IR_TYPE_UNKNOWN); + tm6000_ir_change_protocol(rc, RC_TYPE_UNKNOWN); rc->input_name = ir->name; rc->input_phys = ir->phys; diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h index f22b359..768aa77 100644 --- a/include/media/ir-kbd-i2c.h +++ b/include/media/ir-kbd-i2c.h @@ -37,7 +37,7 @@ enum ir_kbd_get_key_fn { struct IR_i2c_init_data { char *ir_codes; const char *name; - u64 type; /* IR_TYPE_RC5, etc */ + u64 type; /* RC_TYPE_RC5, etc */ u32 polling_interval; /* 0 means DEFAULT_POLLING_INTERVAL */ /* diff --git a/include/media/rc-core.h b/include/media/rc-core.h index 170581b4..4254325 100644 --- a/include/media/rc-core.h +++ b/include/media/rc-core.h @@ -45,7 +45,7 @@ enum rc_driver_type { * @input_dev: the input child device used to communicate events to userspace * @driver_type: specifies if protocol decoding is done in hardware or software * @idle: used to keep track of RX state - * @allowed_protos: bitmask with the supported IR_TYPE_* protocols + * @allowed_protos: bitmask with the supported RC_TYPE_* protocols * @scanmask: some hardware decoders are not capable of providing the full * scancode to the application. As this is a hardware limit, we can't do * anything with it. Yet, as the same keycode table can be used with other @@ -107,7 +107,7 @@ struct rc_dev { u32 max_timeout; u32 rx_resolution; u32 tx_resolution; - int (*change_protocol)(struct rc_dev *dev, u64 ir_type); + int (*change_protocol)(struct rc_dev *dev, u64 rc_type); int (*open)(struct rc_dev *dev); void (*close)(struct rc_dev *dev); int (*s_tx_mask)(struct rc_dev *dev, u32 mask); diff --git a/include/media/rc-map.h b/include/media/rc-map.h index e0f17ed..c53351e 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -11,19 +11,19 @@ #include -#define IR_TYPE_UNKNOWN 0 -#define IR_TYPE_RC5 (1 << 0) /* Philips RC5 protocol */ -#define IR_TYPE_NEC (1 << 1) -#define IR_TYPE_RC6 (1 << 2) /* Philips RC6 protocol */ -#define IR_TYPE_JVC (1 << 3) /* JVC protocol */ -#define IR_TYPE_SONY (1 << 4) /* Sony12/15/20 protocol */ -#define IR_TYPE_RC5_SZ (1 << 5) /* RC5 variant used by Streamzap */ -#define IR_TYPE_LIRC (1 << 30) /* Pass raw IR to lirc userspace */ -#define IR_TYPE_OTHER (1u << 31) +#define RC_TYPE_UNKNOWN 0 +#define RC_TYPE_RC5 (1 << 0) /* Philips RC5 protocol */ +#define RC_TYPE_NEC (1 << 1) +#define RC_TYPE_RC6 (1 << 2) /* Philips RC6 protocol */ +#define RC_TYPE_JVC (1 << 3) /* JVC protocol */ +#define RC_TYPE_SONY (1 << 4) /* Sony12/15/20 protocol */ +#define RC_TYPE_RC5_SZ (1 << 5) /* RC5 variant used by Streamzap */ +#define RC_TYPE_LIRC (1 << 30) /* Pass raw IR to lirc userspace */ +#define RC_TYPE_OTHER (1u << 31) -#define IR_TYPE_ALL (IR_TYPE_RC5 | IR_TYPE_NEC | IR_TYPE_RC6 | \ - IR_TYPE_JVC | IR_TYPE_SONY | IR_TYPE_LIRC | \ - IR_TYPE_RC5_SZ | IR_TYPE_OTHER) +#define RC_TYPE_ALL (RC_TYPE_RC5 | RC_TYPE_NEC | RC_TYPE_RC6 | \ + RC_TYPE_JVC | RC_TYPE_SONY | RC_TYPE_LIRC | \ + RC_TYPE_RC5_SZ | RC_TYPE_OTHER) struct ir_scancode { u32 scancode; @@ -35,7 +35,7 @@ struct ir_scancode_table { unsigned int size; /* Max number of entries */ unsigned int len; /* Used number of entries */ unsigned int alloc; /* Size of *scan in bytes */ - u64 ir_type; + u64 rc_type; const char *name; spinlock_t lock; }; -- cgit v0.10.2 From b088ba658b3438056dab4d744701364db3f08b9a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2010 14:28:27 -0300 Subject: [media] rc: Properly name the rc_map struct The struct that describes a rc mapping had an weird and long name. We should properly name it, to make easier for developers to work with it, and to avoid confusion. Basically, generated by this script: for i in `find drivers/staging -type f -name *.[ch]` `find include/media -type f -name *.[ch]` `find drivers/media -type f -name *.[ch]`; do sed s,ir_scancode_table,rc_map,g <$i >a && mv a $i; done for i in `find drivers/staging -type f -name *.[ch]` `find include/media -type f -name *.[ch]` `find drivers/media -type f -name *.[ch]`; do sed s,rc_tab,rc_map,g <$i >a && mv a $i; done (and manually fixed where needed) Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index f3244eb..caa8d70 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -47,7 +47,7 @@ static struct rc_keymap *seek_rc_map(const char *name) return NULL; } -struct ir_scancode_table *get_rc_map(const char *name) +struct rc_map *get_rc_map(const char *name) { struct rc_keymap *map; @@ -109,71 +109,71 @@ static struct rc_keymap empty_map = { /** * ir_create_table() - initializes a scancode table - * @rc_tab: the ir_scancode_table to initialize + * @rc_map: the rc_map to initialize * @name: name to assign to the table * @rc_type: ir type to assign to the new table * @size: initial size of the table * @return: zero on success or a negative error code * - * This routine will initialize the ir_scancode_table and will allocate + * This routine will initialize the rc_map and will allocate * memory to hold at least the specified number of elements. */ -static int ir_create_table(struct ir_scancode_table *rc_tab, +static int ir_create_table(struct rc_map *rc_map, const char *name, u64 rc_type, size_t size) { - rc_tab->name = name; - rc_tab->rc_type = rc_type; - rc_tab->alloc = roundup_pow_of_two(size * sizeof(struct ir_scancode)); - rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode); - rc_tab->scan = kmalloc(rc_tab->alloc, GFP_KERNEL); - if (!rc_tab->scan) + rc_map->name = name; + rc_map->rc_type = rc_type; + rc_map->alloc = roundup_pow_of_two(size * sizeof(struct ir_scancode)); + rc_map->size = rc_map->alloc / sizeof(struct ir_scancode); + rc_map->scan = kmalloc(rc_map->alloc, GFP_KERNEL); + if (!rc_map->scan) return -ENOMEM; IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", - rc_tab->size, rc_tab->alloc); + rc_map->size, rc_map->alloc); return 0; } /** * ir_free_table() - frees memory allocated by a scancode table - * @rc_tab: the table whose mappings need to be freed + * @rc_map: the table whose mappings need to be freed * * This routine will free memory alloctaed for key mappings used by given * scancode table. */ -static void ir_free_table(struct ir_scancode_table *rc_tab) +static void ir_free_table(struct rc_map *rc_map) { - rc_tab->size = 0; - kfree(rc_tab->scan); - rc_tab->scan = NULL; + rc_map->size = 0; + kfree(rc_map->scan); + rc_map->scan = NULL; } /** * ir_resize_table() - resizes a scancode table if necessary - * @rc_tab: the ir_scancode_table to resize + * @rc_map: the rc_map to resize * @gfp_flags: gfp flags to use when allocating memory * @return: zero on success or a negative error code * - * This routine will shrink the ir_scancode_table if it has lots of + * This routine will shrink the rc_map if it has lots of * unused entries and grow it if it is full. */ -static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags) +static int ir_resize_table(struct rc_map *rc_map, gfp_t gfp_flags) { - unsigned int oldalloc = rc_tab->alloc; + unsigned int oldalloc = rc_map->alloc; unsigned int newalloc = oldalloc; - struct ir_scancode *oldscan = rc_tab->scan; + struct ir_scancode *oldscan = rc_map->scan; struct ir_scancode *newscan; - if (rc_tab->size == rc_tab->len) { + if (rc_map->size == rc_map->len) { /* All entries in use -> grow keytable */ - if (rc_tab->alloc >= IR_TAB_MAX_SIZE) + if (rc_map->alloc >= IR_TAB_MAX_SIZE) return -ENOMEM; newalloc *= 2; IR_dprintk(1, "Growing table to %u bytes\n", newalloc); } - if ((rc_tab->len * 3 < rc_tab->size) && (oldalloc > IR_TAB_MIN_SIZE)) { + if ((rc_map->len * 3 < rc_map->size) && (oldalloc > IR_TAB_MIN_SIZE)) { /* Less than 1/3 of entries in use -> shrink keytable */ newalloc /= 2; IR_dprintk(1, "Shrinking table to %u bytes\n", newalloc); @@ -188,10 +188,10 @@ static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags) return -ENOMEM; } - memcpy(newscan, rc_tab->scan, rc_tab->len * sizeof(struct ir_scancode)); - rc_tab->scan = newscan; - rc_tab->alloc = newalloc; - rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode); + memcpy(newscan, rc_map->scan, rc_map->len * sizeof(struct ir_scancode)); + rc_map->scan = newscan; + rc_map->alloc = newalloc; + rc_map->size = rc_map->alloc / sizeof(struct ir_scancode); kfree(oldscan); return 0; } @@ -199,7 +199,7 @@ static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags) /** * ir_update_mapping() - set a keycode in the scancode->keycode table * @dev: the struct rc_dev device descriptor - * @rc_tab: scancode table to be adjusted + * @rc_map: scancode table to be adjusted * @index: index of the mapping that needs to be updated * @keycode: the desired keycode * @return: previous keycode assigned to the mapping @@ -208,26 +208,26 @@ static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags) * position. */ static unsigned int ir_update_mapping(struct rc_dev *dev, - struct ir_scancode_table *rc_tab, + struct rc_map *rc_map, unsigned int index, unsigned int new_keycode) { - int old_keycode = rc_tab->scan[index].keycode; + int old_keycode = rc_map->scan[index].keycode; int i; /* Did the user wish to remove the mapping? */ if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) { IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", - index, rc_tab->scan[index].scancode); - rc_tab->len--; - memmove(&rc_tab->scan[index], &rc_tab->scan[index+ 1], - (rc_tab->len - index) * sizeof(struct ir_scancode)); + index, rc_map->scan[index].scancode); + rc_map->len--; + memmove(&rc_map->scan[index], &rc_map->scan[index+ 1], + (rc_map->len - index) * sizeof(struct ir_scancode)); } else { IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n", index, old_keycode == KEY_RESERVED ? "New" : "Replacing", - rc_tab->scan[index].scancode, new_keycode); - rc_tab->scan[index].keycode = new_keycode; + rc_map->scan[index].scancode, new_keycode); + rc_map->scan[index].keycode = new_keycode; __set_bit(new_keycode, dev->input_dev->keybit); } @@ -235,15 +235,15 @@ static unsigned int ir_update_mapping(struct rc_dev *dev, /* A previous mapping was updated... */ __clear_bit(old_keycode, dev->input_dev->keybit); /* ... but another scancode might use the same keycode */ - for (i = 0; i < rc_tab->len; i++) { - if (rc_tab->scan[i].keycode == old_keycode) { + for (i = 0; i < rc_map->len; i++) { + if (rc_map->scan[i].keycode == old_keycode) { __set_bit(old_keycode, dev->input_dev->keybit); break; } } /* Possibly shrink the keytable, failure is not a problem */ - ir_resize_table(rc_tab, GFP_ATOMIC); + ir_resize_table(rc_map, GFP_ATOMIC); } return old_keycode; @@ -252,19 +252,19 @@ static unsigned int ir_update_mapping(struct rc_dev *dev, /** * ir_establish_scancode() - set a keycode in the scancode->keycode table * @dev: the struct rc_dev device descriptor - * @rc_tab: scancode table to be searched + * @rc_map: scancode table to be searched * @scancode: the desired scancode * @resize: controls whether we allowed to resize the table to * accomodate not yet present scancodes * @return: index of the mapping containing scancode in question * or -1U in case of failure. * - * This routine is used to locate given scancode in ir_scancode_table. + * This routine is used to locate given scancode in rc_map. * If scancode is not yet present the routine will allocate a new slot * for it. */ static unsigned int ir_establish_scancode(struct rc_dev *dev, - struct ir_scancode_table *rc_tab, + struct rc_map *rc_map, unsigned int scancode, bool resize) { @@ -282,28 +282,28 @@ static unsigned int ir_establish_scancode(struct rc_dev *dev, scancode &= dev->scanmask; /* First check if we already have a mapping for this ir command */ - for (i = 0; i < rc_tab->len; i++) { - if (rc_tab->scan[i].scancode == scancode) + for (i = 0; i < rc_map->len; i++) { + if (rc_map->scan[i].scancode == scancode) return i; /* Keytable is sorted from lowest to highest scancode */ - if (rc_tab->scan[i].scancode >= scancode) + if (rc_map->scan[i].scancode >= scancode) break; } /* No previous mapping found, we might need to grow the table */ - if (rc_tab->size == rc_tab->len) { - if (!resize || ir_resize_table(rc_tab, GFP_ATOMIC)) + if (rc_map->size == rc_map->len) { + if (!resize || ir_resize_table(rc_map, GFP_ATOMIC)) return -1U; } /* i is the proper index to insert our new keycode */ - if (i < rc_tab->len) - memmove(&rc_tab->scan[i + 1], &rc_tab->scan[i], - (rc_tab->len - i) * sizeof(struct ir_scancode)); - rc_tab->scan[i].scancode = scancode; - rc_tab->scan[i].keycode = KEY_RESERVED; - rc_tab->len++; + if (i < rc_map->len) + memmove(&rc_map->scan[i + 1], &rc_map->scan[i], + (rc_map->len - i) * sizeof(struct ir_scancode)); + rc_map->scan[i].scancode = scancode; + rc_map->scan[i].keycode = KEY_RESERVED; + rc_map->len++; return i; } @@ -322,17 +322,17 @@ static int ir_setkeycode(struct input_dev *idev, unsigned int *old_keycode) { struct rc_dev *rdev = input_get_drvdata(idev); - struct ir_scancode_table *rc_tab = &rdev->rc_tab; + struct rc_map *rc_map = &rdev->rc_map; unsigned int index; unsigned int scancode; int retval; unsigned long flags; - spin_lock_irqsave(&rc_tab->lock, flags); + spin_lock_irqsave(&rc_map->lock, flags); if (ke->flags & INPUT_KEYMAP_BY_INDEX) { index = ke->index; - if (index >= rc_tab->len) { + if (index >= rc_map->len) { retval = -EINVAL; goto out; } @@ -341,83 +341,83 @@ static int ir_setkeycode(struct input_dev *idev, if (retval) goto out; - index = ir_establish_scancode(rdev, rc_tab, scancode, true); - if (index >= rc_tab->len) { + index = ir_establish_scancode(rdev, rc_map, scancode, true); + if (index >= rc_map->len) { retval = -ENOMEM; goto out; } } - *old_keycode = ir_update_mapping(rdev, rc_tab, index, ke->keycode); + *old_keycode = ir_update_mapping(rdev, rc_map, index, ke->keycode); out: - spin_unlock_irqrestore(&rc_tab->lock, flags); + spin_unlock_irqrestore(&rc_map->lock, flags); return retval; } /** * ir_setkeytable() - sets several entries in the scancode->keycode table * @dev: the struct rc_dev device descriptor - * @to: the struct ir_scancode_table to copy entries to - * @from: the struct ir_scancode_table to copy entries from + * @to: the struct rc_map to copy entries to + * @from: the struct rc_map to copy entries from * @return: -ENOMEM if all keycodes could not be inserted, otherwise zero. * * This routine is used to handle table initialization. */ static int ir_setkeytable(struct rc_dev *dev, - const struct ir_scancode_table *from) + const struct rc_map *from) { - struct ir_scancode_table *rc_tab = &dev->rc_tab; + struct rc_map *rc_map = &dev->rc_map; unsigned int i, index; int rc; - rc = ir_create_table(rc_tab, from->name, + rc = ir_create_table(rc_map, from->name, from->rc_type, from->size); if (rc) return rc; IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", - rc_tab->size, rc_tab->alloc); + rc_map->size, rc_map->alloc); for (i = 0; i < from->size; i++) { - index = ir_establish_scancode(dev, rc_tab, + index = ir_establish_scancode(dev, rc_map, from->scan[i].scancode, false); - if (index >= rc_tab->len) { + if (index >= rc_map->len) { rc = -ENOMEM; break; } - ir_update_mapping(dev, rc_tab, index, + ir_update_mapping(dev, rc_map, index, from->scan[i].keycode); } if (rc) - ir_free_table(rc_tab); + ir_free_table(rc_map); return rc; } /** * ir_lookup_by_scancode() - locate mapping by scancode - * @rc_tab: the struct ir_scancode_table to search + * @rc_map: the struct rc_map to search * @scancode: scancode to look for in the table * @return: index in the table, -1U if not found * * This routine performs binary search in RC keykeymap table for * given scancode. */ -static unsigned int ir_lookup_by_scancode(const struct ir_scancode_table *rc_tab, +static unsigned int ir_lookup_by_scancode(const struct rc_map *rc_map, unsigned int scancode) { int start = 0; - int end = rc_tab->len - 1; + int end = rc_map->len - 1; int mid; while (start <= end) { mid = (start + end) / 2; - if (rc_tab->scan[mid].scancode < scancode) + if (rc_map->scan[mid].scancode < scancode) start = mid + 1; - else if (rc_tab->scan[mid].scancode > scancode) + else if (rc_map->scan[mid].scancode > scancode) end = mid - 1; else return mid; @@ -439,14 +439,14 @@ static int ir_getkeycode(struct input_dev *idev, struct input_keymap_entry *ke) { struct rc_dev *rdev = input_get_drvdata(idev); - struct ir_scancode_table *rc_tab = &rdev->rc_tab; + struct rc_map *rc_map = &rdev->rc_map; struct ir_scancode *entry; unsigned long flags; unsigned int index; unsigned int scancode; int retval; - spin_lock_irqsave(&rc_tab->lock, flags); + spin_lock_irqsave(&rc_map->lock, flags); if (ke->flags & INPUT_KEYMAP_BY_INDEX) { index = ke->index; @@ -455,10 +455,10 @@ static int ir_getkeycode(struct input_dev *idev, if (retval) goto out; - index = ir_lookup_by_scancode(rc_tab, scancode); + index = ir_lookup_by_scancode(rc_map, scancode); } - if (index >= rc_tab->len) { + if (index >= rc_map->len) { if (!(ke->flags & INPUT_KEYMAP_BY_INDEX)) IR_dprintk(1, "unknown key for scancode 0x%04x\n", scancode); @@ -466,7 +466,7 @@ static int ir_getkeycode(struct input_dev *idev, goto out; } - entry = &rc_tab->scan[index]; + entry = &rc_map->scan[index]; ke->index = index; ke->keycode = entry->keycode; @@ -476,7 +476,7 @@ static int ir_getkeycode(struct input_dev *idev, retval = 0; out: - spin_unlock_irqrestore(&rc_tab->lock, flags); + spin_unlock_irqrestore(&rc_map->lock, flags); return retval; } @@ -492,18 +492,18 @@ out: */ u32 rc_g_keycode_from_table(struct rc_dev *dev, u32 scancode) { - struct ir_scancode_table *rc_tab = &dev->rc_tab; + struct rc_map *rc_map = &dev->rc_map; unsigned int keycode; unsigned int index; unsigned long flags; - spin_lock_irqsave(&rc_tab->lock, flags); + spin_lock_irqsave(&rc_map->lock, flags); - index = ir_lookup_by_scancode(rc_tab, scancode); - keycode = index < rc_tab->len ? - rc_tab->scan[index].keycode : KEY_RESERVED; + index = ir_lookup_by_scancode(rc_map, scancode); + keycode = index < rc_map->len ? + rc_map->scan[index].keycode : KEY_RESERVED; - spin_unlock_irqrestore(&rc_tab->lock, flags); + spin_unlock_irqrestore(&rc_map->lock, flags); if (keycode != KEY_RESERVED) IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", @@ -755,7 +755,7 @@ static ssize_t show_protocols(struct device *device, return -EINVAL; if (dev->driver_type == RC_DRIVER_SCANCODE) { - enabled = dev->rc_tab.rc_type; + enabled = dev->rc_map.rc_type; allowed = dev->allowed_protos; } else { enabled = dev->raw->enabled_protocols; @@ -813,7 +813,7 @@ static ssize_t store_protocols(struct device *device, return -EINVAL; if (dev->driver_type == RC_DRIVER_SCANCODE) - type = dev->rc_tab.rc_type; + type = dev->rc_map.rc_type; else if (dev->raw) type = dev->raw->enabled_protocols; else { @@ -880,9 +880,9 @@ static ssize_t store_protocols(struct device *device, } if (dev->driver_type == RC_DRIVER_SCANCODE) { - spin_lock_irqsave(&dev->rc_tab.lock, flags); - dev->rc_tab.rc_type = type; - spin_unlock_irqrestore(&dev->rc_tab.lock, flags); + spin_lock_irqsave(&dev->rc_map.lock, flags); + dev->rc_map.rc_type = type; + spin_unlock_irqrestore(&dev->rc_map.lock, flags); } else { dev->raw->enabled_protocols = type; } @@ -912,8 +912,8 @@ static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) { struct rc_dev *dev = to_rc_dev(device); - if (dev->rc_tab.name) - ADD_HOTPLUG_VAR("NAME=%s", dev->rc_tab.name); + if (dev->rc_map.name) + ADD_HOTPLUG_VAR("NAME=%s", dev->rc_map.name); if (dev->driver_name) ADD_HOTPLUG_VAR("DRV_NAME=%s", dev->driver_name); @@ -964,7 +964,7 @@ struct rc_dev *rc_allocate_device(void) dev->input_dev->setkeycode_new = ir_setkeycode; input_set_drvdata(dev->input_dev, dev); - spin_lock_init(&dev->rc_tab.lock); + spin_lock_init(&dev->rc_map.lock); spin_lock_init(&dev->keylock); setup_timer(&dev->timer_keyup, ir_timer_keyup, (unsigned long)dev); @@ -989,17 +989,17 @@ EXPORT_SYMBOL_GPL(rc_free_device); int rc_register_device(struct rc_dev *dev) { static atomic_t devno = ATOMIC_INIT(0); - struct ir_scancode_table *rc_tab; + struct rc_map *rc_map; const char *path; int rc; if (!dev || !dev->map_name) return -EINVAL; - rc_tab = get_rc_map(dev->map_name); - if (!rc_tab) - rc_tab = get_rc_map(RC_MAP_EMPTY); - if (!rc_tab || !rc_tab->scan || rc_tab->size == 0) + rc_map = get_rc_map(dev->map_name); + if (!rc_map) + rc_map = get_rc_map(RC_MAP_EMPTY); + if (!rc_map || !rc_map->scan || rc_map->size == 0) return -EINVAL; set_bit(EV_KEY, dev->input_dev->evbit); @@ -1018,7 +1018,7 @@ int rc_register_device(struct rc_dev *dev) if (rc) return rc; - rc = ir_setkeytable(dev, rc_tab); + rc = ir_setkeytable(dev, rc_map); if (rc) goto out_dev; @@ -1052,7 +1052,7 @@ int rc_register_device(struct rc_dev *dev) } if (dev->change_protocol) { - rc = dev->change_protocol(dev, rc_tab->rc_type); + rc = dev->change_protocol(dev, rc_map->rc_type); if (rc < 0) goto out_raw; } @@ -1060,7 +1060,7 @@ int rc_register_device(struct rc_dev *dev) IR_dprintk(1, "Registered rc%ld (driver: %s, remote: %s, mode %s)\n", dev->devno, dev->driver_name ? dev->driver_name : "unknown", - rc_tab->name ? rc_tab->name : "unknown", + rc_map->name ? rc_map->name : "unknown", dev->driver_type == RC_DRIVER_IR_RAW ? "raw" : "cooked"); return 0; @@ -1072,7 +1072,7 @@ out_input: input_unregister_device(dev->input_dev); dev->input_dev = NULL; out_table: - ir_free_table(&dev->rc_tab); + ir_free_table(&dev->rc_map); out_dev: device_del(&dev->dev); return rc; @@ -1092,7 +1092,7 @@ void rc_unregister_device(struct rc_dev *dev) input_unregister_device(dev->input_dev); dev->input_dev = NULL; - ir_free_table(&dev->rc_tab); + ir_free_table(&dev->rc_map); IR_dprintk(1, "Freed keycode table\n"); device_unregister(&dev->dev); diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h index 709cb87..72bbea2 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/video/cx231xx/cx231xx.h @@ -362,7 +362,7 @@ struct cx231xx_board { struct cx231xx_input input[MAX_CX231XX_INPUT]; struct cx231xx_input radio; - struct ir_scancode_table *ir_codes; + struct rc_map *ir_codes; }; /* device states */ diff --git a/include/media/rc-core.h b/include/media/rc-core.h index 4254325..affb93f 100644 --- a/include/media/rc-core.h +++ b/include/media/rc-core.h @@ -39,7 +39,7 @@ enum rc_driver_type { * @input_id: id of the input child device (struct input_id) * @driver_name: name of the hardware driver which registered this device * @map_name: name of the default keymap - * @rc_tab: current scan/key table + * @rc_map: current scan/key table * @devno: unique remote control device number * @raw: additional data for raw pulse/space devices * @input_dev: the input child device used to communicate events to userspace @@ -86,7 +86,7 @@ struct rc_dev { struct input_id input_id; char *driver_name; const char *map_name; - struct ir_scancode_table rc_tab; + struct rc_map rc_map; unsigned long devno; struct ir_raw_event_ctrl *raw; struct input_dev *input_dev; diff --git a/include/media/rc-map.h b/include/media/rc-map.h index c53351e..a6b2738f 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -30,7 +30,7 @@ struct ir_scancode { u32 keycode; }; -struct ir_scancode_table { +struct rc_map { struct ir_scancode *scan; unsigned int size; /* Max number of entries */ unsigned int len; /* Used number of entries */ @@ -42,14 +42,14 @@ struct ir_scancode_table { struct rc_keymap { struct list_head list; - struct ir_scancode_table map; + struct rc_map map; }; /* Routines from rc-map.c */ int ir_register_map(struct rc_keymap *map); void ir_unregister_map(struct rc_keymap *map); -struct ir_scancode_table *get_rc_map(const char *name); +struct rc_map *get_rc_map(const char *name); void rc_map_init(void); /* Names of the several keytables defined in-kernel */ -- cgit v0.10.2 From 2f4f58d689dd71dea67407b74405a3c43e797cb1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2010 15:46:09 -0300 Subject: [media] rc: Name RC keymap tables as rc_map_table Remote keytables had different names all over the place. Part of the fault is due to a bad naming when rc subsystem was created, but there were lots of old names that were still here. Use a common standard for everything. Patch generated by this script: for i in `find drivers/staging -type f -name *.[ch]` `find include/media -type f -name *.[ch]` `find drivers/media -type f -name *.[ch]`; do sed s,ir_scancode,rc_map_table,g <$i >a && mv a $i; done for i in `find drivers/staging -type f -name *.[ch]` `find include/media -type f -name *.[ch]` `find drivers/media -type f -name *.[ch]`; do sed s,ir_codes_,rc_map_,g <$i >a && mv a $i; done for i in `find drivers/staging -type f -name *.[ch]` `find include/media -type f -name *.[ch]` `find drivers/media -type f -name *.[ch]`; do sed s,rc_key_map,rc_map_table,g <$i >a && mv a $i; done for i in `find drivers/staging -type f -name *.[ch]` `find include/media -type f -name *.[ch]` `find drivers/media -type f -name *.[ch]`; do sed s,rc_map_table_size,rc_map_size,g <$i >a && mv a $i; done Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c index a5c3637..53b93a4 100644 --- a/drivers/media/dvb/dvb-usb/a800.c +++ b/drivers/media/dvb/dvb-usb/a800.c @@ -37,7 +37,7 @@ static int a800_identify_state(struct usb_device *udev, struct dvb_usb_device_pr return 0; } -static struct ir_scancode ir_codes_a800_table[] = { +static struct rc_map_table rc_map_a800_table[] = { { 0x0201, KEY_PROG1 }, /* SOURCE */ { 0x0200, KEY_POWER }, /* POWER */ { 0x0205, KEY_1 }, /* 1 */ @@ -148,8 +148,8 @@ static struct dvb_usb_device_properties a800_properties = { .rc.legacy = { .rc_interval = DEFAULT_RC_INTERVAL, - .rc_key_map = ir_codes_a800_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_a800_table), + .rc_map_table = rc_map_a800_table, + .rc_map_size = ARRAY_SIZE(rc_map_a800_table), .rc_query = a800_rc_query, }, diff --git a/drivers/media/dvb/dvb-usb/af9005-remote.c b/drivers/media/dvb/dvb-usb/af9005-remote.c index 696207f..c3bc64e 100644 --- a/drivers/media/dvb/dvb-usb/af9005-remote.c +++ b/drivers/media/dvb/dvb-usb/af9005-remote.c @@ -33,7 +33,7 @@ MODULE_PARM_DESC(debug, #define deb_decode(args...) dprintk(dvb_usb_af9005_remote_debug,0x01,args) -struct ir_scancode ir_codes_af9005_table[] = { +struct rc_map_table rc_map_af9005_table[] = { {0x01b7, KEY_POWER}, {0x01a7, KEY_VOLUMEUP}, @@ -74,7 +74,7 @@ struct ir_scancode ir_codes_af9005_table[] = { {0x00d5, KEY_GOTO}, /* marked jump on the remote */ }; -int ir_codes_af9005_table_size = ARRAY_SIZE(ir_codes_af9005_table); +int rc_map_af9005_table_size = ARRAY_SIZE(rc_map_af9005_table); static int repeatable_keys[] = { KEY_VOLUMEUP, @@ -130,10 +130,10 @@ int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, u32 * event, deb_decode("code != inverted code\n"); return 0; } - for (i = 0; i < ir_codes_af9005_table_size; i++) { - if (rc5_custom(&ir_codes_af9005_table[i]) == cust - && rc5_data(&ir_codes_af9005_table[i]) == dat) { - *event = ir_codes_af9005_table[i].keycode; + for (i = 0; i < rc_map_af9005_table_size; i++) { + if (rc5_custom(&rc_map_af9005_table[i]) == cust + && rc5_data(&rc_map_af9005_table[i]) == dat) { + *event = rc_map_af9005_table[i].keycode; *state = REMOTE_KEY_PRESSED; deb_decode ("key pressed, event %x\n", *event); @@ -146,8 +146,8 @@ int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, u32 * event, return 0; } -EXPORT_SYMBOL(ir_codes_af9005_table); -EXPORT_SYMBOL(ir_codes_af9005_table_size); +EXPORT_SYMBOL(rc_map_af9005_table); +EXPORT_SYMBOL(rc_map_af9005_table_size); EXPORT_SYMBOL(af9005_rc_decode); MODULE_AUTHOR("Luca Olivetti "); diff --git a/drivers/media/dvb/dvb-usb/af9005.c b/drivers/media/dvb/dvb-usb/af9005.c index 8ecba88..51f6439 100644 --- a/drivers/media/dvb/dvb-usb/af9005.c +++ b/drivers/media/dvb/dvb-usb/af9005.c @@ -1027,8 +1027,8 @@ static struct dvb_usb_device_properties af9005_properties = { .rc.legacy = { .rc_interval = 200, - .rc_key_map = NULL, - .rc_key_map_size = 0, + .rc_map_table = NULL, + .rc_map_size = 0, .rc_query = af9005_rc_query, }, @@ -1070,14 +1070,14 @@ static int __init af9005_usb_module_init(void) return result; } rc_decode = symbol_request(af9005_rc_decode); - rc_keys = symbol_request(ir_codes_af9005_table); - rc_keys_size = symbol_request(ir_codes_af9005_table_size); + rc_keys = symbol_request(rc_map_af9005_table); + rc_keys_size = symbol_request(rc_map_af9005_table_size); if (rc_decode == NULL || rc_keys == NULL || rc_keys_size == NULL) { err("af9005_rc_decode function not found, disabling remote"); af9005_properties.rc.legacy.rc_query = NULL; } else { - af9005_properties.rc.legacy.rc_key_map = rc_keys; - af9005_properties.rc.legacy.rc_key_map_size = *rc_keys_size; + af9005_properties.rc.legacy.rc_map_table = rc_keys; + af9005_properties.rc.legacy.rc_map_size = *rc_keys_size; } return 0; @@ -1089,9 +1089,9 @@ static void __exit af9005_usb_module_exit(void) if (rc_decode != NULL) symbol_put(af9005_rc_decode); if (rc_keys != NULL) - symbol_put(ir_codes_af9005_table); + symbol_put(rc_map_af9005_table); if (rc_keys_size != NULL) - symbol_put(ir_codes_af9005_table_size); + symbol_put(rc_map_af9005_table_size); /* deregister this driver from the USB subsystem */ usb_deregister(&af9005_usb_driver); } diff --git a/drivers/media/dvb/dvb-usb/af9005.h b/drivers/media/dvb/dvb-usb/af9005.h index 3c1fbd1..c71c77b 100644 --- a/drivers/media/dvb/dvb-usb/af9005.h +++ b/drivers/media/dvb/dvb-usb/af9005.h @@ -3490,7 +3490,7 @@ extern u8 regmask[8]; /* remote control decoder */ extern int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, u32 * event, int *state); -extern struct ir_scancode ir_codes_af9005_table[]; -extern int ir_codes_af9005_table_size; +extern struct rc_map_table rc_map_af9005_table[]; +extern int rc_map_af9005_table_size; #endif diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c index 62c5828..9a7837f 100644 --- a/drivers/media/dvb/dvb-usb/az6027.c +++ b/drivers/media/dvb/dvb-usb/az6027.c @@ -386,7 +386,7 @@ static int az6027_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) } /* keys for the enclosed remote control */ -static struct ir_scancode ir_codes_az6027_table[] = { +static struct rc_map_table rc_map_az6027_table[] = { { 0x01, KEY_1 }, { 0x02, KEY_2 }, }; @@ -1126,8 +1126,8 @@ static struct dvb_usb_device_properties az6027_properties = { .read_mac_address = az6027_read_mac_addr, */ .rc.legacy = { - .rc_key_map = ir_codes_az6027_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_az6027_table), + .rc_map_table = rc_map_az6027_table, + .rc_map_size = ARRAY_SIZE(rc_map_az6027_table), .rc_interval = 400, .rc_query = az6027_rc_query, }, diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-core.c b/drivers/media/dvb/dvb-usb/cinergyT2-core.c index 4f5aa83f..16f2ce2 100644 --- a/drivers/media/dvb/dvb-usb/cinergyT2-core.c +++ b/drivers/media/dvb/dvb-usb/cinergyT2-core.c @@ -84,7 +84,7 @@ static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap) return 0; } -static struct ir_scancode ir_codes_cinergyt2_table[] = { +static struct rc_map_table rc_map_cinergyt2_table[] = { { 0x0401, KEY_POWER }, { 0x0402, KEY_1 }, { 0x0403, KEY_2 }, @@ -219,8 +219,8 @@ static struct dvb_usb_device_properties cinergyt2_properties = { .rc.legacy = { .rc_interval = 50, - .rc_key_map = ir_codes_cinergyt2_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_cinergyt2_table), + .rc_map_table = rc_map_cinergyt2_table, + .rc_map_size = ARRAY_SIZE(rc_map_cinergyt2_table), .rc_query = cinergyt2_rc_query, }, diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index cd9f362..acb5fb2 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -385,7 +385,7 @@ static int cxusb_d680_dmb_streaming_ctrl( static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { - struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map; + struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; u8 ircode[4]; int i; @@ -394,7 +394,7 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) *event = 0; *state = REMOTE_NO_KEY_PRESSED; - for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) { + for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) { if (rc5_custom(&keymap[i]) == ircode[2] && rc5_data(&keymap[i]) == ircode[3]) { *event = keymap[i].keycode; @@ -410,7 +410,7 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { - struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map; + struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; u8 ircode[4]; int i; struct i2c_msg msg = { .addr = 0x6b, .flags = I2C_M_RD, @@ -422,7 +422,7 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event, if (cxusb_i2c_xfer(&d->i2c_adap, &msg, 1) != 1) return 0; - for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) { + for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) { if (rc5_custom(&keymap[i]) == ircode[1] && rc5_data(&keymap[i]) == ircode[2]) { *event = keymap[i].keycode; @@ -438,7 +438,7 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event, static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { - struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map; + struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; u8 ircode[2]; int i; @@ -448,7 +448,7 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event, if (cxusb_ctrl_msg(d, 0x10, NULL, 0, ircode, 2) < 0) return 0; - for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) { + for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) { if (rc5_custom(&keymap[i]) == ircode[0] && rc5_data(&keymap[i]) == ircode[1]) { *event = keymap[i].keycode; @@ -461,7 +461,7 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event, return 0; } -static struct ir_scancode ir_codes_dvico_mce_table[] = { +static struct rc_map_table rc_map_dvico_mce_table[] = { { 0xfe02, KEY_TV }, { 0xfe0e, KEY_MP3 }, { 0xfe1a, KEY_DVD }, @@ -509,7 +509,7 @@ static struct ir_scancode ir_codes_dvico_mce_table[] = { { 0xfe4e, KEY_POWER }, }; -static struct ir_scancode ir_codes_dvico_portable_table[] = { +static struct rc_map_table rc_map_dvico_portable_table[] = { { 0xfc02, KEY_SETUP }, /* Profile */ { 0xfc43, KEY_POWER2 }, { 0xfc06, KEY_EPG }, @@ -548,7 +548,7 @@ static struct ir_scancode ir_codes_dvico_portable_table[] = { { 0xfc00, KEY_UNKNOWN }, /* HD */ }; -static struct ir_scancode ir_codes_d680_dmb_table[] = { +static struct rc_map_table rc_map_d680_dmb_table[] = { { 0x0038, KEY_UNKNOWN }, /* TV/AV */ { 0x080c, KEY_ZOOM }, { 0x0800, KEY_0 }, @@ -923,7 +923,7 @@ static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap) return -EIO; /* try to determine if there is no IR decoder on the I2C bus */ - for (i = 0; adap->dev->props.rc.legacy.rc_key_map != NULL && i < 5; i++) { + for (i = 0; adap->dev->props.rc.legacy.rc_map_table != NULL && i < 5; i++) { msleep(20); if (cxusb_i2c_xfer(&adap->dev->i2c_adap, &msg, 1) != 1) goto no_IR; @@ -931,7 +931,7 @@ static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap) continue; if (ircode[2] + ircode[3] != 0xff) { no_IR: - adap->dev->props.rc.legacy.rc_key_map = NULL; + adap->dev->props.rc.legacy.rc_map_table = NULL; info("No IR receiver detected on this device."); break; } @@ -1453,8 +1453,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = { .rc.legacy = { .rc_interval = 100, - .rc_key_map = ir_codes_dvico_portable_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table), + .rc_map_table = rc_map_dvico_portable_table, + .rc_map_size = ARRAY_SIZE(rc_map_dvico_portable_table), .rc_query = cxusb_rc_query, }, @@ -1506,8 +1506,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = { .rc.legacy = { .rc_interval = 150, - .rc_key_map = ir_codes_dvico_mce_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table), + .rc_map_table = rc_map_dvico_mce_table, + .rc_map_size = ARRAY_SIZE(rc_map_dvico_mce_table), .rc_query = cxusb_rc_query, }, @@ -1567,8 +1567,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = { .rc.legacy = { .rc_interval = 100, - .rc_key_map = ir_codes_dvico_portable_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table), + .rc_map_table = rc_map_dvico_portable_table, + .rc_map_size = ARRAY_SIZE(rc_map_dvico_portable_table), .rc_query = cxusb_rc_query, }, @@ -1619,8 +1619,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = { .rc.legacy = { .rc_interval = 100, - .rc_key_map = ir_codes_dvico_portable_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table), + .rc_map_table = rc_map_dvico_portable_table, + .rc_map_size = ARRAY_SIZE(rc_map_dvico_portable_table), .rc_query = cxusb_rc_query, }, @@ -1670,8 +1670,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = { .rc.legacy = { .rc_interval = 100, - .rc_key_map = ir_codes_dvico_mce_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table), + .rc_map_table = rc_map_dvico_mce_table, + .rc_map_size = ARRAY_SIZE(rc_map_dvico_mce_table), .rc_query = cxusb_bluebird2_rc_query, }, @@ -1720,8 +1720,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = { .rc.legacy = { .rc_interval = 100, - .rc_key_map = ir_codes_dvico_portable_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table), + .rc_map_table = rc_map_dvico_portable_table, + .rc_map_size = ARRAY_SIZE(rc_map_dvico_portable_table), .rc_query = cxusb_bluebird2_rc_query, }, @@ -1772,8 +1772,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope .rc.legacy = { .rc_interval = 100, - .rc_key_map = ir_codes_dvico_portable_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table), + .rc_map_table = rc_map_dvico_portable_table, + .rc_map_size = ARRAY_SIZE(rc_map_dvico_portable_table), .rc_query = cxusb_rc_query, }, @@ -1865,8 +1865,8 @@ struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = { .rc.legacy = { .rc_interval = 100, - .rc_key_map = ir_codes_dvico_mce_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table), + .rc_map_table = rc_map_dvico_mce_table, + .rc_map_size = ARRAY_SIZE(rc_map_dvico_mce_table), .rc_query = cxusb_rc_query, }, @@ -1915,8 +1915,8 @@ static struct dvb_usb_device_properties cxusb_d680_dmb_properties = { .rc.legacy = { .rc_interval = 100, - .rc_key_map = ir_codes_d680_dmb_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_d680_dmb_table), + .rc_map_table = rc_map_d680_dmb_table, + .rc_map_size = ARRAY_SIZE(rc_map_d680_dmb_table), .rc_query = cxusb_d680_dmb_rc_query, }, @@ -1966,8 +1966,8 @@ static struct dvb_usb_device_properties cxusb_mygica_d689_properties = { .rc.legacy = { .rc_interval = 100, - .rc_key_map = ir_codes_d680_dmb_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_d680_dmb_table), + .rc_map_table = rc_map_d680_dmb_table, + .rc_map_size = ARRAY_SIZE(rc_map_d680_dmb_table), .rc_query = cxusb_d680_dmb_rc_query, }, diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c index ba991aa..956f7ae 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/drivers/media/dvb/dvb-usb/dibusb-common.c @@ -327,7 +327,7 @@ EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach); /* * common remote control stuff */ -struct ir_scancode ir_codes_dibusb_table[] = { +struct rc_map_table rc_map_dibusb_table[] = { /* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */ { 0x0016, KEY_POWER }, { 0x0010, KEY_MUTE }, @@ -456,7 +456,7 @@ struct ir_scancode ir_codes_dibusb_table[] = { { 0x804e, KEY_ENTER }, { 0x804f, KEY_VOLUMEDOWN }, }; -EXPORT_SYMBOL(ir_codes_dibusb_table); +EXPORT_SYMBOL(rc_map_dibusb_table); int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c index 8e3c0d2..04d91bd 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mb.c +++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c @@ -213,8 +213,8 @@ static struct dvb_usb_device_properties dibusb1_1_properties = { .rc.legacy = { .rc_interval = DEFAULT_RC_INTERVAL, - .rc_key_map = ir_codes_dibusb_table, - .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ + .rc_map_table = rc_map_dibusb_table, + .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ .rc_query = dibusb_rc_query, }, @@ -299,8 +299,8 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = { .rc.legacy = { .rc_interval = DEFAULT_RC_INTERVAL, - .rc_key_map = ir_codes_dibusb_table, - .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ + .rc_map_table = rc_map_dibusb_table, + .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ .rc_query = dibusb_rc_query, }, @@ -365,8 +365,8 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = { .rc.legacy = { .rc_interval = DEFAULT_RC_INTERVAL, - .rc_key_map = ir_codes_dibusb_table, - .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ + .rc_map_table = rc_map_dibusb_table, + .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ .rc_query = dibusb_rc_query, }, @@ -424,8 +424,8 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = { .rc.legacy = { .rc_interval = DEFAULT_RC_INTERVAL, - .rc_key_map = ir_codes_dibusb_table, - .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ + .rc_map_table = rc_map_dibusb_table, + .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ .rc_query = dibusb_rc_query, }, diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c index 1cbc41c..c1d9094 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mc.c +++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c @@ -83,8 +83,8 @@ static struct dvb_usb_device_properties dibusb_mc_properties = { .rc.legacy = { .rc_interval = DEFAULT_RC_INTERVAL, - .rc_key_map = ir_codes_dibusb_table, - .rc_key_map_size = 111, /* FIXME */ + .rc_map_table = rc_map_dibusb_table, + .rc_map_size = 111, /* FIXME */ .rc_query = dibusb_rc_query, }, diff --git a/drivers/media/dvb/dvb-usb/dibusb.h b/drivers/media/dvb/dvb-usb/dibusb.h index 61a6bf3..e47c321 100644 --- a/drivers/media/dvb/dvb-usb/dibusb.h +++ b/drivers/media/dvb/dvb-usb/dibusb.h @@ -124,7 +124,7 @@ extern int dibusb2_0_power_ctrl(struct dvb_usb_device *, int); #define DEFAULT_RC_INTERVAL 150 //#define DEFAULT_RC_INTERVAL 100000 -extern struct ir_scancode ir_codes_dibusb_table[]; +extern struct rc_map_table rc_map_dibusb_table[]; extern int dibusb_rc_query(struct dvb_usb_device *, u32 *, int *); extern int dibusb_read_eeprom_byte(struct dvb_usb_device *, u8, u8 *); diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c index 13d006b..f2dbce7 100644 --- a/drivers/media/dvb/dvb-usb/digitv.c +++ b/drivers/media/dvb/dvb-usb/digitv.c @@ -161,7 +161,7 @@ static int digitv_tuner_attach(struct dvb_usb_adapter *adap) return 0; } -static struct ir_scancode ir_codes_digitv_table[] = { +static struct rc_map_table rc_map_digitv_table[] = { { 0x5f55, KEY_0 }, { 0x6f55, KEY_1 }, { 0x9f55, KEY_2 }, @@ -237,10 +237,10 @@ static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state) /* if something is inside the buffer, simulate key press */ if (key[1] != 0) { - for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) { - if (rc5_custom(&d->props.rc.legacy.rc_key_map[i]) == key[1] && - rc5_data(&d->props.rc.legacy.rc_key_map[i]) == key[2]) { - *event = d->props.rc.legacy.rc_key_map[i].keycode; + for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) { + if (rc5_custom(&d->props.rc.legacy.rc_map_table[i]) == key[1] && + rc5_data(&d->props.rc.legacy.rc_map_table[i]) == key[2]) { + *event = d->props.rc.legacy.rc_map_table[i].keycode; *state = REMOTE_KEY_PRESSED; return 0; } @@ -312,8 +312,8 @@ static struct dvb_usb_device_properties digitv_properties = { .rc.legacy = { .rc_interval = 1000, - .rc_key_map = ir_codes_digitv_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_digitv_table), + .rc_map_table = rc_map_digitv_table, + .rc_map_size = ARRAY_SIZE(rc_map_digitv_table), .rc_query = digitv_rc_query, }, diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c index ca495e0..ecd86ec 100644 --- a/drivers/media/dvb/dvb-usb/dtt200u.c +++ b/drivers/media/dvb/dvb-usb/dtt200u.c @@ -57,7 +57,7 @@ static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, /* remote control */ /* key list for the tiny remote control (Yakumo, don't know about the others) */ -static struct ir_scancode ir_codes_dtt200u_table[] = { +static struct rc_map_table rc_map_dtt200u_table[] = { { 0x8001, KEY_MUTE }, { 0x8002, KEY_CHANNELDOWN }, { 0x8003, KEY_VOLUMEDOWN }, @@ -163,8 +163,8 @@ static struct dvb_usb_device_properties dtt200u_properties = { .rc.legacy = { .rc_interval = 300, - .rc_key_map = ir_codes_dtt200u_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table), + .rc_map_table = rc_map_dtt200u_table, + .rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table), .rc_query = dtt200u_rc_query, }, @@ -210,8 +210,8 @@ static struct dvb_usb_device_properties wt220u_properties = { .rc.legacy = { .rc_interval = 300, - .rc_key_map = ir_codes_dtt200u_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table), + .rc_map_table = rc_map_dtt200u_table, + .rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table), .rc_query = dtt200u_rc_query, }, @@ -257,8 +257,8 @@ static struct dvb_usb_device_properties wt220u_fc_properties = { .rc.legacy = { .rc_interval = 300, - .rc_key_map = ir_codes_dtt200u_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table), + .rc_map_table = rc_map_dtt200u_table, + .rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table), .rc_query = dtt200u_rc_query, }, @@ -304,8 +304,8 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = { .rc.legacy = { .rc_interval = 300, - .rc_key_map = ir_codes_dtt200u_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table), + .rc_map_table = rc_map_dtt200u_table, + .rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table), .rc_query = dtt200u_rc_query, }, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index bbba149..c6498f5 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -13,11 +13,11 @@ static int legacy_dvb_usb_getkeycode(struct input_dev *dev, { struct dvb_usb_device *d = input_get_drvdata(dev); - struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map; + struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; int i; /* See if we can match the raw key code. */ - for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) + for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) if (keymap[i].scancode == scancode) { *keycode = keymap[i].keycode; return 0; @@ -28,7 +28,7 @@ static int legacy_dvb_usb_getkeycode(struct input_dev *dev, * otherwise, input core won't let legacy_dvb_usb_setkeycode * to work */ - for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) + for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) if (keymap[i].keycode == KEY_RESERVED || keymap[i].keycode == KEY_UNKNOWN) { *keycode = KEY_RESERVED; @@ -43,18 +43,18 @@ static int legacy_dvb_usb_setkeycode(struct input_dev *dev, { struct dvb_usb_device *d = input_get_drvdata(dev); - struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map; + struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; int i; /* Search if it is replacing an existing keycode */ - for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) + for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) if (keymap[i].scancode == scancode) { keymap[i].keycode = keycode; return 0; } /* Search if is there a clean entry. If so, use it */ - for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) + for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) if (keymap[i].keycode == KEY_RESERVED || keymap[i].keycode == KEY_UNKNOWN) { keymap[i].scancode = scancode; @@ -175,11 +175,11 @@ static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d) input_dev->setkeycode = legacy_dvb_usb_setkeycode; /* set the bits for the keys */ - deb_rc("key map size: %d\n", d->props.rc.legacy.rc_key_map_size); - for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) { + deb_rc("key map size: %d\n", d->props.rc.legacy.rc_map_size); + for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) { deb_rc("setting bit for event %d item %d\n", - d->props.rc.legacy.rc_key_map[i].keycode, i); - set_bit(d->props.rc.legacy.rc_key_map[i].keycode, input_dev->keybit); + d->props.rc.legacy.rc_map_table[i].keycode, i); + set_bit(d->props.rc.legacy.rc_map_table[i].keycode, input_dev->keybit); } /* setting these two values to non-zero, we have to manage key repeats */ @@ -284,7 +284,7 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) if (dvb_usb_disable_rc_polling) return 0; - if (d->props.rc.legacy.rc_key_map && d->props.rc.legacy.rc_query) + if (d->props.rc.legacy.rc_map_table && d->props.rc.legacy.rc_query) d->props.rc.mode = DVB_RC_LEGACY; else if (d->props.rc.core.rc_codes) d->props.rc.mode = DVB_RC_CORE; @@ -331,7 +331,7 @@ int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d, u8 keybuf[5], u32 *event, int *state) { int i; - struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map; + struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; *event = 0; *state = REMOTE_NO_KEY_PRESSED; switch (keybuf[0]) { @@ -344,7 +344,7 @@ int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d, break; } /* See if we can match the raw key code. */ - for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) + for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) if (rc5_custom(&keymap[i]) == keybuf[1] && rc5_data(&keymap[i]) == keybuf[3]) { *event = keymap[i].keycode; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index 95b1603..65fa926 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -75,17 +75,17 @@ struct dvb_usb_device_description { struct usb_device_id *warm_ids[DVB_USB_ID_MAX_NUM]; }; -static inline u8 rc5_custom(struct ir_scancode *key) +static inline u8 rc5_custom(struct rc_map_table *key) { return (key->scancode >> 8) & 0xff; } -static inline u8 rc5_data(struct ir_scancode *key) +static inline u8 rc5_data(struct rc_map_table *key) { return key->scancode & 0xff; } -static inline u8 rc5_scan(struct ir_scancode *key) +static inline u8 rc5_scan(struct rc_map_table *key) { return key->scancode & 0xffff; } @@ -159,9 +159,9 @@ struct dvb_usb_adapter_properties { /** * struct dvb_rc_legacy - old properties of remote controller - * @rc_key_map: a hard-wired array of struct ir_scancode (NULL to disable + * @rc_map_table: a hard-wired array of struct rc_map_table (NULL to disable * remote control handling). - * @rc_key_map_size: number of items in @rc_key_map. + * @rc_map_size: number of items in @rc_map_table. * @rc_query: called to query an event event. * @rc_interval: time in ms between two queries. */ @@ -170,8 +170,8 @@ struct dvb_rc_legacy { #define REMOTE_NO_KEY_PRESSED 0x00 #define REMOTE_KEY_PRESSED 0x01 #define REMOTE_KEY_REPEAT 0x02 - struct ir_scancode *rc_key_map; - int rc_key_map_size; + struct rc_map_table *rc_map_table; + int rc_map_size; int (*rc_query) (struct dvb_usb_device *, u32 *, int *); int rc_interval; }; diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c index 774df88..2c307ba 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.c +++ b/drivers/media/dvb/dvb-usb/dw2102.c @@ -73,8 +73,8 @@ "Please see linux/Documentation/dvb/ for more details " \ "on firmware-problems." -struct ir_codes_dvb_usb_table_table { - struct ir_scancode *rc_keys; +struct rc_map_dvb_usb_table_table { + struct rc_map_table *rc_keys; int rc_keys_size; }; @@ -948,7 +948,7 @@ static int dw3101_tuner_attach(struct dvb_usb_adapter *adap) return 0; } -static struct ir_scancode ir_codes_dw210x_table[] = { +static struct rc_map_table rc_map_dw210x_table[] = { { 0xf80a, KEY_Q }, /*power*/ { 0xf80c, KEY_M }, /*mute*/ { 0xf811, KEY_1 }, @@ -982,7 +982,7 @@ static struct ir_scancode ir_codes_dw210x_table[] = { { 0xf81b, KEY_B }, /*recall*/ }; -static struct ir_scancode ir_codes_tevii_table[] = { +static struct rc_map_table rc_map_tevii_table[] = { { 0xf80a, KEY_POWER }, { 0xf80c, KEY_MUTE }, { 0xf811, KEY_1 }, @@ -1032,7 +1032,7 @@ static struct ir_scancode ir_codes_tevii_table[] = { { 0xf858, KEY_SWITCHVIDEOMODE }, }; -static struct ir_scancode ir_codes_tbs_table[] = { +static struct rc_map_table rc_map_tbs_table[] = { { 0xf884, KEY_POWER }, { 0xf894, KEY_MUTE }, { 0xf887, KEY_1 }, @@ -1067,16 +1067,16 @@ static struct ir_scancode ir_codes_tbs_table[] = { { 0xf89b, KEY_MODE } }; -static struct ir_codes_dvb_usb_table_table keys_tables[] = { - { ir_codes_dw210x_table, ARRAY_SIZE(ir_codes_dw210x_table) }, - { ir_codes_tevii_table, ARRAY_SIZE(ir_codes_tevii_table) }, - { ir_codes_tbs_table, ARRAY_SIZE(ir_codes_tbs_table) }, +static struct rc_map_dvb_usb_table_table keys_tables[] = { + { rc_map_dw210x_table, ARRAY_SIZE(rc_map_dw210x_table) }, + { rc_map_tevii_table, ARRAY_SIZE(rc_map_tevii_table) }, + { rc_map_tbs_table, ARRAY_SIZE(rc_map_tbs_table) }, }; static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { - struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map; - int keymap_size = d->props.rc.legacy.rc_key_map_size; + struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; + int keymap_size = d->props.rc.legacy.rc_map_size; u8 key[2]; struct i2c_msg msg = { .addr = DW2102_RC_QUERY, @@ -1185,14 +1185,14 @@ static int dw2102_load_firmware(struct usb_device *dev, /* init registers */ switch (dev->descriptor.idProduct) { case USB_PID_PROF_1100: - s6x0_properties.rc.legacy.rc_key_map = ir_codes_tbs_table; - s6x0_properties.rc.legacy.rc_key_map_size = - ARRAY_SIZE(ir_codes_tbs_table); + s6x0_properties.rc.legacy.rc_map_table = rc_map_tbs_table; + s6x0_properties.rc.legacy.rc_map_size = + ARRAY_SIZE(rc_map_tbs_table); break; case USB_PID_TEVII_S650: - dw2104_properties.rc.legacy.rc_key_map = ir_codes_tevii_table; - dw2104_properties.rc.legacy.rc_key_map_size = - ARRAY_SIZE(ir_codes_tevii_table); + dw2104_properties.rc.legacy.rc_map_table = rc_map_tevii_table; + dw2104_properties.rc.legacy.rc_map_size = + ARRAY_SIZE(rc_map_tevii_table); case USB_PID_DW2104: reset = 1; dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, @@ -1257,8 +1257,8 @@ static struct dvb_usb_device_properties dw2102_properties = { .i2c_algo = &dw2102_serit_i2c_algo, .rc.legacy = { - .rc_key_map = ir_codes_dw210x_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table), + .rc_map_table = rc_map_dw210x_table, + .rc_map_size = ARRAY_SIZE(rc_map_dw210x_table), .rc_interval = 150, .rc_query = dw2102_rc_query, }, @@ -1310,8 +1310,8 @@ static struct dvb_usb_device_properties dw2104_properties = { .i2c_algo = &dw2104_i2c_algo, .rc.legacy = { - .rc_key_map = ir_codes_dw210x_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table), + .rc_map_table = rc_map_dw210x_table, + .rc_map_size = ARRAY_SIZE(rc_map_dw210x_table), .rc_interval = 150, .rc_query = dw2102_rc_query, }, @@ -1359,8 +1359,8 @@ static struct dvb_usb_device_properties dw3101_properties = { .i2c_algo = &dw3101_i2c_algo, .rc.legacy = { - .rc_key_map = ir_codes_dw210x_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table), + .rc_map_table = rc_map_dw210x_table, + .rc_map_size = ARRAY_SIZE(rc_map_dw210x_table), .rc_interval = 150, .rc_query = dw2102_rc_query, }, @@ -1404,8 +1404,8 @@ static struct dvb_usb_device_properties s6x0_properties = { .i2c_algo = &s6x0_i2c_algo, .rc.legacy = { - .rc_key_map = ir_codes_tevii_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_tevii_table), + .rc_map_table = rc_map_tevii_table, + .rc_map_size = ARRAY_SIZE(rc_map_tevii_table), .rc_interval = 150, .rc_query = dw2102_rc_query, }, @@ -1468,8 +1468,8 @@ static int dw2102_probe(struct usb_interface *intf, /* fill only different fields */ p7500->firmware = "dvb-usb-p7500.fw"; p7500->devices[0] = d7500; - p7500->rc.legacy.rc_key_map = ir_codes_tbs_table; - p7500->rc.legacy.rc_key_map_size = ARRAY_SIZE(ir_codes_tbs_table); + p7500->rc.legacy.rc_map_table = rc_map_tbs_table; + p7500->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table); p7500->adapter->frontend_attach = prof_7500_frontend_attach; if (0 == dvb_usb_device_init(intf, &dw2102_properties, diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c index bdef1a1..da9dc91 100644 --- a/drivers/media/dvb/dvb-usb/m920x.c +++ b/drivers/media/dvb/dvb-usb/m920x.c @@ -142,9 +142,9 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0) goto unlock; - for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) - if (rc5_data(&d->props.rc.legacy.rc_key_map[i]) == rc_state[1]) { - *event = d->props.rc.legacy.rc_key_map[i].keycode; + for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) + if (rc5_data(&d->props.rc.legacy.rc_map_table[i]) == rc_state[1]) { + *event = d->props.rc.legacy.rc_map_table[i].keycode; switch(rc_state[0]) { case 0x80: @@ -589,7 +589,7 @@ static struct m920x_inits pinnacle310e_init[] = { }; /* ir keymaps */ -static struct ir_scancode ir_codes_megasky_table[] = { +static struct rc_map_table rc_map_megasky_table[] = { { 0x0012, KEY_POWER }, { 0x001e, KEY_CYCLEWINDOWS }, /* min/max */ { 0x0002, KEY_CHANNELUP }, @@ -608,7 +608,7 @@ static struct ir_scancode ir_codes_megasky_table[] = { { 0x000e, KEY_COFFEE }, /* "MTS" */ }; -static struct ir_scancode ir_codes_tvwalkertwin_table[] = { +static struct rc_map_table rc_map_tvwalkertwin_table[] = { { 0x0001, KEY_ZOOM }, /* Full Screen */ { 0x0002, KEY_CAMERA }, /* snapshot */ { 0x0003, KEY_MUTE }, @@ -628,7 +628,7 @@ static struct ir_scancode ir_codes_tvwalkertwin_table[] = { { 0x001e, KEY_VOLUMEUP }, }; -static struct ir_scancode ir_codes_pinnacle310e_table[] = { +static struct rc_map_table rc_map_pinnacle310e_table[] = { { 0x16, KEY_POWER }, { 0x17, KEY_FAVORITES }, { 0x0f, KEY_TEXT }, @@ -786,8 +786,8 @@ static struct dvb_usb_device_properties megasky_properties = { .rc.legacy = { .rc_interval = 100, - .rc_key_map = ir_codes_megasky_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_megasky_table), + .rc_map_table = rc_map_megasky_table, + .rc_map_size = ARRAY_SIZE(rc_map_megasky_table), .rc_query = m920x_rc_query, }, @@ -889,8 +889,8 @@ static struct dvb_usb_device_properties tvwalkertwin_properties = { .rc.legacy = { .rc_interval = 100, - .rc_key_map = ir_codes_tvwalkertwin_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_tvwalkertwin_table), + .rc_map_table = rc_map_tvwalkertwin_table, + .rc_map_size = ARRAY_SIZE(rc_map_tvwalkertwin_table), .rc_query = m920x_rc_query, }, @@ -998,8 +998,8 @@ static struct dvb_usb_device_properties pinnacle_pctv310e_properties = { .rc.legacy = { .rc_interval = 100, - .rc_key_map = ir_codes_pinnacle310e_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_pinnacle310e_table), + .rc_map_table = rc_map_pinnacle310e_table, + .rc_map_size = ARRAY_SIZE(rc_map_pinnacle310e_table), .rc_query = m920x_rc_query, }, diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c index 181f36a..9d3cd2d 100644 --- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c +++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c @@ -21,7 +21,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); #define deb_ee(args...) dprintk(debug,0x02,args) /* Hauppauge NOVA-T USB2 keys */ -static struct ir_scancode ir_codes_haupp_table[] = { +static struct rc_map_table rc_map_haupp_table[] = { { 0x1e00, KEY_0 }, { 0x1e01, KEY_1 }, { 0x1e02, KEY_2 }, @@ -91,14 +91,14 @@ static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state) deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",key[1],key[2],key[3],custom,data,toggle); - for (i = 0; i < ARRAY_SIZE(ir_codes_haupp_table); i++) { - if (rc5_data(&ir_codes_haupp_table[i]) == data && - rc5_custom(&ir_codes_haupp_table[i]) == custom) { + for (i = 0; i < ARRAY_SIZE(rc_map_haupp_table); i++) { + if (rc5_data(&rc_map_haupp_table[i]) == data && + rc5_custom(&rc_map_haupp_table[i]) == custom) { - deb_rc("c: %x, d: %x\n", rc5_data(&ir_codes_haupp_table[i]), - rc5_custom(&ir_codes_haupp_table[i])); + deb_rc("c: %x, d: %x\n", rc5_data(&rc_map_haupp_table[i]), + rc5_custom(&rc_map_haupp_table[i])); - *event = ir_codes_haupp_table[i].keycode; + *event = rc_map_haupp_table[i].keycode; *state = REMOTE_KEY_PRESSED; if (st->old_toggle == toggle) { if (st->last_repeat_count++ < 2) @@ -197,8 +197,8 @@ static struct dvb_usb_device_properties nova_t_properties = { .rc.legacy = { .rc_interval = 100, - .rc_key_map = ir_codes_haupp_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_haupp_table), + .rc_map_table = rc_map_haupp_table, + .rc_map_size = ARRAY_SIZE(rc_map_haupp_table), .rc_query = nova_t_rc_query, }, diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c index f896337..1f1b7d6 100644 --- a/drivers/media/dvb/dvb-usb/opera1.c +++ b/drivers/media/dvb/dvb-usb/opera1.c @@ -35,7 +35,7 @@ struct opera1_state { u32 last_key_pressed; }; -struct ir_codes_opera_table { +struct rc_map_opera_table { u32 keycode; u32 event; }; @@ -331,7 +331,7 @@ static int opera1_pid_filter_control(struct dvb_usb_adapter *adap, int onoff) return 0; } -static struct ir_scancode ir_codes_opera1_table[] = { +static struct rc_map_table rc_map_opera1_table[] = { {0x5fa0, KEY_1}, {0x51af, KEY_2}, {0x5da2, KEY_3}, @@ -404,12 +404,12 @@ static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state) send_key = (send_key & 0xffff) | 0x0100; - for (i = 0; i < ARRAY_SIZE(ir_codes_opera1_table); i++) { - if (rc5_scan(&ir_codes_opera1_table[i]) == (send_key & 0xffff)) { + for (i = 0; i < ARRAY_SIZE(rc_map_opera1_table); i++) { + if (rc5_scan(&rc_map_opera1_table[i]) == (send_key & 0xffff)) { *state = REMOTE_KEY_PRESSED; - *event = ir_codes_opera1_table[i].keycode; + *event = rc_map_opera1_table[i].keycode; opst->last_key_pressed = - ir_codes_opera1_table[i].keycode; + rc_map_opera1_table[i].keycode; break; } opst->last_key_pressed = 0; @@ -497,8 +497,8 @@ static struct dvb_usb_device_properties opera1_properties = { .i2c_algo = &opera1_i2c_algo, .rc.legacy = { - .rc_key_map = ir_codes_opera1_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_opera1_table), + .rc_map_table = rc_map_opera1_table, + .rc_map_size = ARRAY_SIZE(rc_map_opera1_table), .rc_interval = 200, .rc_query = opera1_rc_query, }, diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c index 5c9f327..7890e75 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.c +++ b/drivers/media/dvb/dvb-usb/vp702x.c @@ -174,7 +174,7 @@ static int vp702x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) } /* keys for the enclosed remote control */ -static struct ir_scancode ir_codes_vp702x_table[] = { +static struct rc_map_table rc_map_vp702x_table[] = { { 0x0001, KEY_1 }, { 0x0002, KEY_2 }, }; @@ -197,10 +197,10 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) return 0; } - for (i = 0; i < ARRAY_SIZE(ir_codes_vp702x_table); i++) - if (rc5_custom(&ir_codes_vp702x_table[i]) == key[1]) { + for (i = 0; i < ARRAY_SIZE(rc_map_vp702x_table); i++) + if (rc5_custom(&rc_map_vp702x_table[i]) == key[1]) { *state = REMOTE_KEY_PRESSED; - *event = ir_codes_vp702x_table[i].keycode; + *event = rc_map_vp702x_table[i].keycode; break; } return 0; @@ -284,8 +284,8 @@ static struct dvb_usb_device_properties vp702x_properties = { .read_mac_address = vp702x_read_mac_addr, .rc.legacy = { - .rc_key_map = ir_codes_vp702x_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_vp702x_table), + .rc_map_table = rc_map_vp702x_table, + .rc_map_size = ARRAY_SIZE(rc_map_vp702x_table), .rc_interval = 400, .rc_query = vp702x_rc_query, }, diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c index f13791c..ab0ab3c 100644 --- a/drivers/media/dvb/dvb-usb/vp7045.c +++ b/drivers/media/dvb/dvb-usb/vp7045.c @@ -99,7 +99,7 @@ static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff) /* The keymapping struct. Somehow this should be loaded to the driver, but * currently it is hardcoded. */ -static struct ir_scancode ir_codes_vp7045_table[] = { +static struct rc_map_table rc_map_vp7045_table[] = { { 0x0016, KEY_POWER }, { 0x0010, KEY_MUTE }, { 0x0003, KEY_1 }, @@ -165,10 +165,10 @@ static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state) return 0; } - for (i = 0; i < ARRAY_SIZE(ir_codes_vp7045_table); i++) - if (rc5_data(&ir_codes_vp7045_table[i]) == key) { + for (i = 0; i < ARRAY_SIZE(rc_map_vp7045_table); i++) + if (rc5_data(&rc_map_vp7045_table[i]) == key) { *state = REMOTE_KEY_PRESSED; - *event = ir_codes_vp7045_table[i].keycode; + *event = rc_map_vp7045_table[i].keycode; break; } return 0; @@ -261,8 +261,8 @@ static struct dvb_usb_device_properties vp7045_properties = { .rc.legacy = { .rc_interval = 400, - .rc_key_map = ir_codes_vp7045_table, - .rc_key_map_size = ARRAY_SIZE(ir_codes_vp7045_table), + .rc_map_table = rc_map_vp7045_table, + .rc_map_size = ARRAY_SIZE(rc_map_vp7045_table), .rc_query = vp7045_rc_query, }, diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c index cf5f8ca..572929a 100644 --- a/drivers/media/dvb/mantis/mantis_input.c +++ b/drivers/media/dvb/mantis/mantis_input.c @@ -34,7 +34,7 @@ #define MODULE_NAME "mantis_core" #define RC_MAP_MANTIS "rc-mantis" -static struct ir_scancode mantis_ir_table[] = { +static struct rc_map_table mantis_ir_table[] = { { 0x29, KEY_POWER }, { 0x28, KEY_FAVORITES }, { 0x30, KEY_TEXT }, diff --git a/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c b/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c index 0ea0aee..da6556d 100644 --- a/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c +++ b/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c @@ -14,7 +14,7 @@ /* ADS Tech Instant TV DVB-T PCI Remote */ -static struct ir_scancode adstech_dvb_t_pci[] = { +static struct rc_map_table adstech_dvb_t_pci[] = { /* Keys 0 to 9 */ { 0x4d, KEY_0 }, { 0x57, KEY_1 }, diff --git a/drivers/media/rc/keymaps/rc-alink-dtu-m.c b/drivers/media/rc/keymaps/rc-alink-dtu-m.c index b0ec1c8..36e1eb1 100644 --- a/drivers/media/rc/keymaps/rc-alink-dtu-m.c +++ b/drivers/media/rc/keymaps/rc-alink-dtu-m.c @@ -21,7 +21,7 @@ #include /* A-Link DTU(m) slim remote, 6 rows, 3 columns. */ -static struct ir_scancode alink_dtu_m[] = { +static struct rc_map_table alink_dtu_m[] = { { 0x0800, KEY_VOLUMEUP }, { 0x0801, KEY_1 }, { 0x0802, KEY_3 }, diff --git a/drivers/media/rc/keymaps/rc-anysee.c b/drivers/media/rc/keymaps/rc-anysee.c index 9bfe60e..6ca91e0 100644 --- a/drivers/media/rc/keymaps/rc-anysee.c +++ b/drivers/media/rc/keymaps/rc-anysee.c @@ -20,7 +20,7 @@ #include -static struct ir_scancode anysee[] = { +static struct rc_map_table anysee[] = { { 0x0800, KEY_0 }, { 0x0801, KEY_1 }, { 0x0802, KEY_2 }, diff --git a/drivers/media/rc/keymaps/rc-apac-viewcomp.c b/drivers/media/rc/keymaps/rc-apac-viewcomp.c index a32840d..a40a1b6 100644 --- a/drivers/media/rc/keymaps/rc-apac-viewcomp.c +++ b/drivers/media/rc/keymaps/rc-apac-viewcomp.c @@ -14,7 +14,7 @@ /* Attila Kondoros */ -static struct ir_scancode apac_viewcomp[] = { +static struct rc_map_table apac_viewcomp[] = { { 0x01, KEY_1 }, { 0x02, KEY_2 }, diff --git a/drivers/media/rc/keymaps/rc-asus-pc39.c b/drivers/media/rc/keymaps/rc-asus-pc39.c index f86bfb7..2a58ffe 100644 --- a/drivers/media/rc/keymaps/rc-asus-pc39.c +++ b/drivers/media/rc/keymaps/rc-asus-pc39.c @@ -18,7 +18,7 @@ * which has a label saying is "Model PC-39" */ -static struct ir_scancode asus_pc39[] = { +static struct rc_map_table asus_pc39[] = { /* Keys 0 to 9 */ { 0x082a, KEY_0 }, { 0x0816, KEY_1 }, diff --git a/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c b/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c index 0cefe1c..ac0a7d9 100644 --- a/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c +++ b/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c @@ -16,7 +16,7 @@ Devin Heitmueller */ -static struct ir_scancode ati_tv_wonder_hd_600[] = { +static struct rc_map_table ati_tv_wonder_hd_600[] = { { 0x00, KEY_RECORD}, /* Row 1 */ { 0x01, KEY_PLAYPAUSE}, { 0x02, KEY_STOP}, diff --git a/drivers/media/rc/keymaps/rc-avermedia-a16d.c b/drivers/media/rc/keymaps/rc-avermedia-a16d.c index 43525c8..df3360f 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-a16d.c +++ b/drivers/media/rc/keymaps/rc-avermedia-a16d.c @@ -12,7 +12,7 @@ #include -static struct ir_scancode avermedia_a16d[] = { +static struct rc_map_table avermedia_a16d[] = { { 0x20, KEY_LIST}, { 0x00, KEY_POWER}, { 0x28, KEY_1}, diff --git a/drivers/media/rc/keymaps/rc-avermedia-cardbus.c b/drivers/media/rc/keymaps/rc-avermedia-cardbus.c index 2d528ca..40f2f2d 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-cardbus.c +++ b/drivers/media/rc/keymaps/rc-avermedia-cardbus.c @@ -14,7 +14,7 @@ /* Oldrich Jedlicka */ -static struct ir_scancode avermedia_cardbus[] = { +static struct rc_map_table avermedia_cardbus[] = { { 0x00, KEY_POWER }, { 0x01, KEY_TUNER }, /* TV/FM */ { 0x03, KEY_TEXT }, /* Teletext */ diff --git a/drivers/media/rc/keymaps/rc-avermedia-dvbt.c b/drivers/media/rc/keymaps/rc-avermedia-dvbt.c index e45b67f..b4a1aa1 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-dvbt.c +++ b/drivers/media/rc/keymaps/rc-avermedia-dvbt.c @@ -14,7 +14,7 @@ /* Matt Jesson */ -static struct ir_scancode avermedia_m135a[] = { +static struct rc_map_table avermedia_m135a[] = { /* RM-JX */ { 0x0200, KEY_POWER2 }, { 0x022e, KEY_DOT }, /* '.' */ diff --git a/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c b/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c index b0e10be..74f3a20 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c +++ b/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c @@ -16,7 +16,7 @@ * Herton Ronaldo Krzesinski */ -static struct ir_scancode avermedia_m733a_rm_k6[] = { +static struct rc_map_table avermedia_m733a_rm_k6[] = { { 0x0401, KEY_POWER2 }, { 0x0406, KEY_MUTE }, { 0x0408, KEY_MODE }, /* TV/FM */ diff --git a/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c b/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c index 3348466..dc6a321 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c +++ b/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c @@ -23,7 +23,7 @@ /* Initial keytable is from Jose Alberto Reguero and Felipe Morales Moreno */ /* FIXME: mappings are not 100% correct? */ -static struct ir_scancode avermedia_rm_ks[] = { +static struct rc_map_table avermedia_rm_ks[] = { { 0x0501, KEY_POWER2 }, { 0x0502, KEY_CHANNELUP }, { 0x0503, KEY_CHANNELDOWN }, diff --git a/drivers/media/rc/keymaps/rc-avermedia.c b/drivers/media/rc/keymaps/rc-avermedia.c index cfde54e..a5ef695 100644 --- a/drivers/media/rc/keymaps/rc-avermedia.c +++ b/drivers/media/rc/keymaps/rc-avermedia.c @@ -14,7 +14,7 @@ /* Alex Hermann */ -static struct ir_scancode avermedia[] = { +static struct rc_map_table avermedia[] = { { 0x28, KEY_1 }, { 0x18, KEY_2 }, { 0x38, KEY_3 }, diff --git a/drivers/media/rc/keymaps/rc-avertv-303.c b/drivers/media/rc/keymaps/rc-avertv-303.c index ae58663..386ba59 100644 --- a/drivers/media/rc/keymaps/rc-avertv-303.c +++ b/drivers/media/rc/keymaps/rc-avertv-303.c @@ -14,7 +14,7 @@ /* AVERTV STUDIO 303 Remote */ -static struct ir_scancode avertv_303[] = { +static struct rc_map_table avertv_303[] = { { 0x2a, KEY_1 }, { 0x32, KEY_2 }, { 0x3a, KEY_3 }, diff --git a/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c b/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c index 579fafe..fbaaba5 100644 --- a/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c +++ b/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c @@ -20,7 +20,7 @@ #include -static struct ir_scancode azurewave_ad_tu700[] = { +static struct rc_map_table azurewave_ad_tu700[] = { { 0x0000, KEY_TAB }, /* Tab */ { 0x0001, KEY_2 }, { 0x0002, KEY_CHANNELDOWN }, diff --git a/drivers/media/rc/keymaps/rc-behold-columbus.c b/drivers/media/rc/keymaps/rc-behold-columbus.c index 6abb712..33accf5 100644 --- a/drivers/media/rc/keymaps/rc-behold-columbus.c +++ b/drivers/media/rc/keymaps/rc-behold-columbus.c @@ -21,7 +21,7 @@ * helps to descide which keycodes to assign to the buttons. */ -static struct ir_scancode behold_columbus[] = { +static struct rc_map_table behold_columbus[] = { /* 0x13 0x11 0x1C 0x12 * * Mute Source TV/FM Power * diff --git a/drivers/media/rc/keymaps/rc-behold.c b/drivers/media/rc/keymaps/rc-behold.c index 5694185..4402414 100644 --- a/drivers/media/rc/keymaps/rc-behold.c +++ b/drivers/media/rc/keymaps/rc-behold.c @@ -24,7 +24,7 @@ * helps to descide which keycodes to assign to the buttons. */ -static struct ir_scancode behold[] = { +static struct rc_map_table behold[] = { /* 0x1c 0x12 * * TV/FM POWER * diff --git a/drivers/media/rc/keymaps/rc-budget-ci-old.c b/drivers/media/rc/keymaps/rc-budget-ci-old.c index 99f7323..e4827a6 100644 --- a/drivers/media/rc/keymaps/rc-budget-ci-old.c +++ b/drivers/media/rc/keymaps/rc-budget-ci-old.c @@ -18,7 +18,7 @@ * This is a "middle of the road" approach, differences are noted */ -static struct ir_scancode budget_ci_old[] = { +static struct rc_map_table budget_ci_old[] = { { 0x00, KEY_0 }, { 0x01, KEY_1 }, { 0x02, KEY_2 }, diff --git a/drivers/media/rc/keymaps/rc-cinergy-1400.c b/drivers/media/rc/keymaps/rc-cinergy-1400.c index b504ddd..6a69866 100644 --- a/drivers/media/rc/keymaps/rc-cinergy-1400.c +++ b/drivers/media/rc/keymaps/rc-cinergy-1400.c @@ -14,7 +14,7 @@ /* Cinergy 1400 DVB-T */ -static struct ir_scancode cinergy_1400[] = { +static struct rc_map_table cinergy_1400[] = { { 0x01, KEY_POWER }, { 0x02, KEY_1 }, { 0x03, KEY_2 }, diff --git a/drivers/media/rc/keymaps/rc-cinergy.c b/drivers/media/rc/keymaps/rc-cinergy.c index 8bf02f1..ba36d14 100644 --- a/drivers/media/rc/keymaps/rc-cinergy.c +++ b/drivers/media/rc/keymaps/rc-cinergy.c @@ -12,7 +12,7 @@ #include -static struct ir_scancode cinergy[] = { +static struct rc_map_table cinergy[] = { { 0x00, KEY_0 }, { 0x01, KEY_1 }, { 0x02, KEY_2 }, diff --git a/drivers/media/rc/keymaps/rc-dib0700-nec.c b/drivers/media/rc/keymaps/rc-dib0700-nec.c index 47d5476..921230d 100644 --- a/drivers/media/rc/keymaps/rc-dib0700-nec.c +++ b/drivers/media/rc/keymaps/rc-dib0700-nec.c @@ -17,7 +17,7 @@ #include -static struct ir_scancode dib0700_nec_table[] = { +static struct rc_map_table dib0700_nec_table[] = { /* Key codes for the Pixelview SBTVD remote */ { 0x8613, KEY_MUTE }, { 0x8612, KEY_POWER }, diff --git a/drivers/media/rc/keymaps/rc-dib0700-rc5.c b/drivers/media/rc/keymaps/rc-dib0700-rc5.c index 1d09921..9febb72 100644 --- a/drivers/media/rc/keymaps/rc-dib0700-rc5.c +++ b/drivers/media/rc/keymaps/rc-dib0700-rc5.c @@ -17,7 +17,7 @@ #include -static struct ir_scancode dib0700_rc5_table[] = { +static struct rc_map_table dib0700_rc5_table[] = { /* Key codes for the tiny Pinnacle remote*/ { 0x0700, KEY_MUTE }, { 0x0701, KEY_MENU }, /* Pinnacle logo */ diff --git a/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c b/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c index 8ae726b..da50d7d 100644 --- a/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c +++ b/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c @@ -20,7 +20,7 @@ #include -static struct ir_scancode digitalnow_tinytwin[] = { +static struct rc_map_table digitalnow_tinytwin[] = { { 0x0000, KEY_MUTE }, /* [symbol speaker] */ { 0x0001, KEY_VOLUMEUP }, { 0x0002, KEY_POWER2 }, /* TV [power button] */ diff --git a/drivers/media/rc/keymaps/rc-digittrade.c b/drivers/media/rc/keymaps/rc-digittrade.c index 206469f..706f95dd 100644 --- a/drivers/media/rc/keymaps/rc-digittrade.c +++ b/drivers/media/rc/keymaps/rc-digittrade.c @@ -25,7 +25,7 @@ Initial keytable was from Alain Kalker */ /* Digittrade DVB-T USB Stick */ -static struct ir_scancode digittrade[] = { +static struct rc_map_table digittrade[] = { { 0x0000, KEY_9 }, { 0x0001, KEY_EPG }, /* EPG */ { 0x0002, KEY_VOLUMEDOWN }, /* Vol Dn */ diff --git a/drivers/media/rc/keymaps/rc-dm1105-nec.c b/drivers/media/rc/keymaps/rc-dm1105-nec.c index ba6fb0b..9023dc9 100644 --- a/drivers/media/rc/keymaps/rc-dm1105-nec.c +++ b/drivers/media/rc/keymaps/rc-dm1105-nec.c @@ -16,7 +16,7 @@ Igor M. Liplianin */ -static struct ir_scancode dm1105_nec[] = { +static struct rc_map_table dm1105_nec[] = { { 0x0a, KEY_POWER2}, /* power */ { 0x0c, KEY_MUTE}, /* mute */ { 0x11, KEY_1}, diff --git a/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c b/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c index b703937..7fbeaed 100644 --- a/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c +++ b/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c @@ -14,7 +14,7 @@ /* DigitalNow DNTV Live DVB-T Remote */ -static struct ir_scancode dntv_live_dvb_t[] = { +static struct rc_map_table dntv_live_dvb_t[] = { { 0x00, KEY_ESC }, /* 'go up a level?' */ /* Keys 0 to 9 */ { 0x0a, KEY_0 }, diff --git a/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c b/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c index b0126b2..660f2e7 100644 --- a/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c +++ b/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c @@ -14,7 +14,7 @@ /* DigitalNow DNTV Live! DVB-T Pro Remote */ -static struct ir_scancode dntv_live_dvbt_pro[] = { +static struct rc_map_table dntv_live_dvbt_pro[] = { { 0x16, KEY_POWER }, { 0x5b, KEY_HOME }, diff --git a/drivers/media/rc/keymaps/rc-em-terratec.c b/drivers/media/rc/keymaps/rc-em-terratec.c index 57bcd55..4d0ad8c 100644 --- a/drivers/media/rc/keymaps/rc-em-terratec.c +++ b/drivers/media/rc/keymaps/rc-em-terratec.c @@ -12,7 +12,7 @@ #include -static struct ir_scancode em_terratec[] = { +static struct rc_map_table em_terratec[] = { { 0x01, KEY_CHANNEL }, { 0x02, KEY_SELECT }, { 0x03, KEY_MUTE }, diff --git a/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c b/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c index 97e01f4..3005d4b 100644 --- a/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c +++ b/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c @@ -16,7 +16,7 @@ Mauro Carvalho Chehab */ -static struct ir_scancode encore_enltv_fm53[] = { +static struct rc_map_table encore_enltv_fm53[] = { { 0x10, KEY_POWER2}, { 0x06, KEY_MUTE}, diff --git a/drivers/media/rc/keymaps/rc-encore-enltv.c b/drivers/media/rc/keymaps/rc-encore-enltv.c index d3030cf..d16db50 100644 --- a/drivers/media/rc/keymaps/rc-encore-enltv.c +++ b/drivers/media/rc/keymaps/rc-encore-enltv.c @@ -15,7 +15,7 @@ /* Encore ENLTV-FM - black plastic, white front cover with white glowing buttons Juan Pablo Sormani */ -static struct ir_scancode encore_enltv[] = { +static struct rc_map_table encore_enltv[] = { /* Power button does nothing, neither in Windows app, although it sends data (used for BIOS wakeup?) */ diff --git a/drivers/media/rc/keymaps/rc-encore-enltv2.c b/drivers/media/rc/keymaps/rc-encore-enltv2.c index 1871b32..a5e07c7 100644 --- a/drivers/media/rc/keymaps/rc-encore-enltv2.c +++ b/drivers/media/rc/keymaps/rc-encore-enltv2.c @@ -15,7 +15,7 @@ /* Encore ENLTV2-FM - silver plastic - "Wand Media" written at the botton Mauro Carvalho Chehab */ -static struct ir_scancode encore_enltv2[] = { +static struct rc_map_table encore_enltv2[] = { { 0x4c, KEY_POWER2 }, { 0x4a, KEY_TUNER }, { 0x40, KEY_1 }, diff --git a/drivers/media/rc/keymaps/rc-evga-indtube.c b/drivers/media/rc/keymaps/rc-evga-indtube.c index 192d7f8..e2d0590 100644 --- a/drivers/media/rc/keymaps/rc-evga-indtube.c +++ b/drivers/media/rc/keymaps/rc-evga-indtube.c @@ -16,7 +16,7 @@ Devin Heitmueller */ -static struct ir_scancode evga_indtube[] = { +static struct rc_map_table evga_indtube[] = { { 0x12, KEY_POWER}, { 0x02, KEY_MODE}, /* TV */ { 0x14, KEY_MUTE}, diff --git a/drivers/media/rc/keymaps/rc-eztv.c b/drivers/media/rc/keymaps/rc-eztv.c index fe3ab5e..ee134c5 100644 --- a/drivers/media/rc/keymaps/rc-eztv.c +++ b/drivers/media/rc/keymaps/rc-eztv.c @@ -15,7 +15,7 @@ /* Alfons Geser * updates from Job D. R. Borges */ -static struct ir_scancode eztv[] = { +static struct rc_map_table eztv[] = { { 0x12, KEY_POWER }, { 0x01, KEY_TV }, /* DVR */ { 0x15, KEY_DVD }, /* DVD */ diff --git a/drivers/media/rc/keymaps/rc-flydvb.c b/drivers/media/rc/keymaps/rc-flydvb.c index f48249e..ef90a05 100644 --- a/drivers/media/rc/keymaps/rc-flydvb.c +++ b/drivers/media/rc/keymaps/rc-flydvb.c @@ -12,7 +12,7 @@ #include -static struct ir_scancode flydvb[] = { +static struct rc_map_table flydvb[] = { { 0x01, KEY_ZOOM }, /* Full Screen */ { 0x00, KEY_POWER }, /* Power */ diff --git a/drivers/media/rc/keymaps/rc-flyvideo.c b/drivers/media/rc/keymaps/rc-flyvideo.c index 59713fb4..20a1333 100644 --- a/drivers/media/rc/keymaps/rc-flyvideo.c +++ b/drivers/media/rc/keymaps/rc-flyvideo.c @@ -12,7 +12,7 @@ #include -static struct ir_scancode flyvideo[] = { +static struct rc_map_table flyvideo[] = { { 0x0f, KEY_0 }, { 0x03, KEY_1 }, { 0x04, KEY_2 }, diff --git a/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c b/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c index e69458d..2687af7 100644 --- a/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c +++ b/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c @@ -14,7 +14,7 @@ /* DViCO FUSION HDTV MCE remote */ -static struct ir_scancode fusionhdtv_mce[] = { +static struct rc_map_table fusionhdtv_mce[] = { { 0x0b, KEY_1 }, { 0x17, KEY_2 }, diff --git a/drivers/media/rc/keymaps/rc-gadmei-rm008z.c b/drivers/media/rc/keymaps/rc-gadmei-rm008z.c index 13587b8..fb247ba 100644 --- a/drivers/media/rc/keymaps/rc-gadmei-rm008z.c +++ b/drivers/media/rc/keymaps/rc-gadmei-rm008z.c @@ -16,7 +16,7 @@ Shine Liu */ -static struct ir_scancode gadmei_rm008z[] = { +static struct rc_map_table gadmei_rm008z[] = { { 0x14, KEY_POWER2}, /* POWER OFF */ { 0x0c, KEY_MUTE}, /* MUTE */ diff --git a/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c b/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c index 2304bf6..7e6834a 100644 --- a/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c +++ b/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c @@ -17,7 +17,7 @@ * Adrian Pardini */ -static struct ir_scancode genius_tvgo_a11mce[] = { +static struct rc_map_table genius_tvgo_a11mce[] = { /* Keys 0 to 9 */ { 0x48, KEY_0 }, { 0x09, KEY_1 }, diff --git a/drivers/media/rc/keymaps/rc-gotview7135.c b/drivers/media/rc/keymaps/rc-gotview7135.c index b5be7bf..54222ca 100644 --- a/drivers/media/rc/keymaps/rc-gotview7135.c +++ b/drivers/media/rc/keymaps/rc-gotview7135.c @@ -14,7 +14,7 @@ /* Mike Baikov */ -static struct ir_scancode gotview7135[] = { +static struct rc_map_table gotview7135[] = { { 0x11, KEY_POWER }, { 0x35, KEY_TV }, diff --git a/drivers/media/rc/keymaps/rc-hauppauge-new.c b/drivers/media/rc/keymaps/rc-hauppauge-new.c index c60f845..2396257 100644 --- a/drivers/media/rc/keymaps/rc-hauppauge-new.c +++ b/drivers/media/rc/keymaps/rc-hauppauge-new.c @@ -16,7 +16,7 @@ * slightly different versions), shipped with cx88+ivtv cards. * almost rc5 coding, but some non-standard keys */ -static struct ir_scancode hauppauge_new[] = { +static struct rc_map_table hauppauge_new[] = { /* Keys 0 to 9 */ { 0x00, KEY_0 }, { 0x01, KEY_1 }, diff --git a/drivers/media/rc/keymaps/rc-imon-mce.c b/drivers/media/rc/keymaps/rc-imon-mce.c index 4ce902f..291e5d8 100644 --- a/drivers/media/rc/keymaps/rc-imon-mce.c +++ b/drivers/media/rc/keymaps/rc-imon-mce.c @@ -12,7 +12,7 @@ #include /* mce-mode imon mce remote key table */ -static struct ir_scancode imon_mce[] = { +static struct rc_map_table imon_mce[] = { /* keys sorted mostly by frequency of use to optimize lookups */ { 0x800ff415, KEY_REWIND }, { 0x800ff414, KEY_FASTFORWARD }, diff --git a/drivers/media/rc/keymaps/rc-imon-pad.c b/drivers/media/rc/keymaps/rc-imon-pad.c index 6d4633af..33f28d4 100644 --- a/drivers/media/rc/keymaps/rc-imon-pad.c +++ b/drivers/media/rc/keymaps/rc-imon-pad.c @@ -17,7 +17,7 @@ * same remote to different hex codes, and the silkscreened names * vary a bit between the SoundGraph and Antec remotes... ugh. */ -static struct ir_scancode imon_pad[] = { +static struct rc_map_table imon_pad[] = { /* keys sorted mostly by frequency of use to optimize lookups */ { 0x2a8195b7, KEY_REWIND }, { 0x298315b7, KEY_REWIND }, diff --git a/drivers/media/rc/keymaps/rc-iodata-bctv7e.c b/drivers/media/rc/keymaps/rc-iodata-bctv7e.c index c5208f1..5e5263f 100644 --- a/drivers/media/rc/keymaps/rc-iodata-bctv7e.c +++ b/drivers/media/rc/keymaps/rc-iodata-bctv7e.c @@ -14,7 +14,7 @@ /* IO-DATA BCTV7E Remote */ -static struct ir_scancode iodata_bctv7e[] = { +static struct rc_map_table iodata_bctv7e[] = { { 0x40, KEY_TV }, { 0x20, KEY_RADIO }, /* FM */ { 0x60, KEY_EPG }, diff --git a/drivers/media/rc/keymaps/rc-kaiomy.c b/drivers/media/rc/keymaps/rc-kaiomy.c index 1b6da7f..527ab1b 100644 --- a/drivers/media/rc/keymaps/rc-kaiomy.c +++ b/drivers/media/rc/keymaps/rc-kaiomy.c @@ -16,7 +16,7 @@ Mauro Carvalho Chehab */ -static struct ir_scancode kaiomy[] = { +static struct rc_map_table kaiomy[] = { { 0x43, KEY_POWER2}, { 0x01, KEY_LIST}, { 0x0b, KEY_ZOOM}, diff --git a/drivers/media/rc/keymaps/rc-kworld-315u.c b/drivers/media/rc/keymaps/rc-kworld-315u.c index 3418e07..f58703e 100644 --- a/drivers/media/rc/keymaps/rc-kworld-315u.c +++ b/drivers/media/rc/keymaps/rc-kworld-315u.c @@ -15,7 +15,7 @@ /* Kworld 315U */ -static struct ir_scancode kworld_315u[] = { +static struct rc_map_table kworld_315u[] = { { 0x6143, KEY_POWER }, { 0x6101, KEY_TUNER }, /* source */ { 0x610b, KEY_ZOOM }, diff --git a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c index 4d681eb..f6235bb 100644 --- a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c +++ b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c @@ -16,7 +16,7 @@ Mauro Carvalho Chehab */ -static struct ir_scancode kworld_plus_tv_analog[] = { +static struct rc_map_table kworld_plus_tv_analog[] = { { 0x0c, KEY_PROG1 }, /* Kworld key */ { 0x16, KEY_CLOSECD }, /* -> ) */ { 0x1d, KEY_POWER2 }, diff --git a/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c b/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c index ebdd122..e1b8726 100644 --- a/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c +++ b/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c @@ -20,7 +20,7 @@ #include -static struct ir_scancode leadtek_y04g0051[] = { +static struct rc_map_table leadtek_y04g0051[] = { { 0x0300, KEY_POWER2 }, { 0x0303, KEY_SCREEN }, { 0x0304, KEY_RIGHT }, diff --git a/drivers/media/rc/keymaps/rc-lirc.c b/drivers/media/rc/keymaps/rc-lirc.c index 6d8a641..d4dfee7 100644 --- a/drivers/media/rc/keymaps/rc-lirc.c +++ b/drivers/media/rc/keymaps/rc-lirc.c @@ -11,7 +11,7 @@ #include -static struct ir_scancode lirc[] = { +static struct rc_map_table lirc[] = { { }, }; diff --git a/drivers/media/rc/keymaps/rc-lme2510.c b/drivers/media/rc/keymaps/rc-lme2510.c index ca7e2ac..eb2d396 100644 --- a/drivers/media/rc/keymaps/rc-lme2510.c +++ b/drivers/media/rc/keymaps/rc-lme2510.c @@ -12,7 +12,7 @@ #include -static struct ir_scancode lme2510_rc[] = { +static struct rc_map_table lme2510_rc[] = { { 0xba45, KEY_0 }, { 0xa05f, KEY_1 }, { 0xaf50, KEY_2 }, diff --git a/drivers/media/rc/keymaps/rc-manli.c b/drivers/media/rc/keymaps/rc-manli.c index 056cf52..b24b082 100644 --- a/drivers/media/rc/keymaps/rc-manli.c +++ b/drivers/media/rc/keymaps/rc-manli.c @@ -21,7 +21,7 @@ helps to descide which keycodes to assign to the buttons. */ -static struct ir_scancode manli[] = { +static struct rc_map_table manli[] = { /* 0x1c 0x12 * * FUNCTION POWER * diff --git a/drivers/media/rc/keymaps/rc-msi-digivox-ii.c b/drivers/media/rc/keymaps/rc-msi-digivox-ii.c index 3a14d31..4ad89b7 100644 --- a/drivers/media/rc/keymaps/rc-msi-digivox-ii.c +++ b/drivers/media/rc/keymaps/rc-msi-digivox-ii.c @@ -20,7 +20,7 @@ #include -static struct ir_scancode msi_digivox_ii[] = { +static struct rc_map_table msi_digivox_ii[] = { { 0x0002, KEY_2 }, { 0x0003, KEY_UP }, /* up */ { 0x0004, KEY_3 }, diff --git a/drivers/media/rc/keymaps/rc-msi-digivox-iii.c b/drivers/media/rc/keymaps/rc-msi-digivox-iii.c index 16c5b0a..d3304e7 100644 --- a/drivers/media/rc/keymaps/rc-msi-digivox-iii.c +++ b/drivers/media/rc/keymaps/rc-msi-digivox-iii.c @@ -24,7 +24,7 @@ /* Uses NEC extended 0x61d6. */ /* This remote seems to be same as rc-kworld-315u.c. Anyhow, add new remote since rc-kworld-315u.c lacks NEC extended address byte. */ -static struct ir_scancode msi_digivox_iii[] = { +static struct rc_map_table msi_digivox_iii[] = { { 0x61d601, KEY_VIDEO }, /* Source */ { 0x61d602, KEY_3 }, { 0x61d603, KEY_POWER }, /* ShutDown */ diff --git a/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c b/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c index d4c9102..51999c4 100644 --- a/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c +++ b/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c @@ -26,7 +26,7 @@ Some changes to formatting and keycodes by Mark Schultz */ -static struct ir_scancode msi_tvanywhere_plus[] = { +static struct rc_map_table msi_tvanywhere_plus[] = { /* ---- Remote Button Layout ---- diff --git a/drivers/media/rc/keymaps/rc-msi-tvanywhere.c b/drivers/media/rc/keymaps/rc-msi-tvanywhere.c index aec064c..619df9d 100644 --- a/drivers/media/rc/keymaps/rc-msi-tvanywhere.c +++ b/drivers/media/rc/keymaps/rc-msi-tvanywhere.c @@ -14,7 +14,7 @@ /* MSI TV@nywhere MASTER remote */ -static struct ir_scancode msi_tvanywhere[] = { +static struct rc_map_table msi_tvanywhere[] = { /* Keys 0 to 9 */ { 0x00, KEY_0 }, { 0x01, KEY_1 }, diff --git a/drivers/media/rc/keymaps/rc-nebula.c b/drivers/media/rc/keymaps/rc-nebula.c index 2c44b90..8672859 100644 --- a/drivers/media/rc/keymaps/rc-nebula.c +++ b/drivers/media/rc/keymaps/rc-nebula.c @@ -12,7 +12,7 @@ #include -static struct ir_scancode nebula[] = { +static struct rc_map_table nebula[] = { { 0x00, KEY_0 }, { 0x01, KEY_1 }, { 0x02, KEY_2 }, diff --git a/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c b/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c index 929084b..2f560dc 100644 --- a/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c +++ b/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c @@ -16,7 +16,7 @@ Mauro Carvalho Chehab */ -static struct ir_scancode nec_terratec_cinergy_xs[] = { +static struct rc_map_table nec_terratec_cinergy_xs[] = { { 0x1441, KEY_HOME}, { 0x1401, KEY_POWER2}, diff --git a/drivers/media/rc/keymaps/rc-norwood.c b/drivers/media/rc/keymaps/rc-norwood.c index 7fe7746..f4a8503 100644 --- a/drivers/media/rc/keymaps/rc-norwood.c +++ b/drivers/media/rc/keymaps/rc-norwood.c @@ -16,7 +16,7 @@ By Peter Naulls Key comments are the functions given in the manual */ -static struct ir_scancode norwood[] = { +static struct rc_map_table norwood[] = { /* Keys 0 to 9 */ { 0x20, KEY_0 }, { 0x21, KEY_1 }, diff --git a/drivers/media/rc/keymaps/rc-npgtech.c b/drivers/media/rc/keymaps/rc-npgtech.c index a9cbcde..fdfa549 100644 --- a/drivers/media/rc/keymaps/rc-npgtech.c +++ b/drivers/media/rc/keymaps/rc-npgtech.c @@ -12,7 +12,7 @@ #include -static struct ir_scancode npgtech[] = { +static struct rc_map_table npgtech[] = { { 0x1d, KEY_SWITCHVIDEOMODE }, /* switch inputs */ { 0x2a, KEY_FRONT }, diff --git a/drivers/media/rc/keymaps/rc-pctv-sedna.c b/drivers/media/rc/keymaps/rc-pctv-sedna.c index 68b33b3..86c1101 100644 --- a/drivers/media/rc/keymaps/rc-pctv-sedna.c +++ b/drivers/media/rc/keymaps/rc-pctv-sedna.c @@ -17,7 +17,7 @@ Pavel Mihaylov Also for the remote bundled with Kozumi KTV-01C card */ -static struct ir_scancode pctv_sedna[] = { +static struct rc_map_table pctv_sedna[] = { { 0x00, KEY_0 }, { 0x01, KEY_1 }, { 0x02, KEY_2 }, diff --git a/drivers/media/rc/keymaps/rc-pinnacle-color.c b/drivers/media/rc/keymaps/rc-pinnacle-color.c index 364ccde..d3f4cd4 100644 --- a/drivers/media/rc/keymaps/rc-pinnacle-color.c +++ b/drivers/media/rc/keymaps/rc-pinnacle-color.c @@ -12,7 +12,7 @@ #include -static struct ir_scancode pinnacle_color[] = { +static struct rc_map_table pinnacle_color[] = { { 0x59, KEY_MUTE }, { 0x4a, KEY_POWER }, diff --git a/drivers/media/rc/keymaps/rc-pinnacle-grey.c b/drivers/media/rc/keymaps/rc-pinnacle-grey.c index 993eff7..1f48b43 100644 --- a/drivers/media/rc/keymaps/rc-pinnacle-grey.c +++ b/drivers/media/rc/keymaps/rc-pinnacle-grey.c @@ -12,7 +12,7 @@ #include -static struct ir_scancode pinnacle_grey[] = { +static struct rc_map_table pinnacle_grey[] = { { 0x3a, KEY_0 }, { 0x31, KEY_1 }, { 0x32, KEY_2 }, diff --git a/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c index 56e6a7e..dc7267c 100644 --- a/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c +++ b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c @@ -14,7 +14,7 @@ /* Pinnacle PCTV HD 800i mini remote */ -static struct ir_scancode pinnacle_pctv_hd[] = { +static struct rc_map_table pinnacle_pctv_hd[] = { { 0x0f, KEY_1 }, { 0x15, KEY_2 }, diff --git a/drivers/media/rc/keymaps/rc-pixelview-mk12.c b/drivers/media/rc/keymaps/rc-pixelview-mk12.c index 84f89eb..93f7248 100644 --- a/drivers/media/rc/keymaps/rc-pixelview-mk12.c +++ b/drivers/media/rc/keymaps/rc-pixelview-mk12.c @@ -16,7 +16,7 @@ * Keytable for MK-F12 IR remote provided together with Pixelview * Ultra Pro Remote Controller. Uses NEC extended format. */ -static struct ir_scancode pixelview_mk12[] = { +static struct rc_map_table pixelview_mk12[] = { { 0x866b03, KEY_TUNER }, /* Timeshift */ { 0x866b1e, KEY_POWER2 }, /* power */ diff --git a/drivers/media/rc/keymaps/rc-pixelview-new.c b/drivers/media/rc/keymaps/rc-pixelview-new.c index 703f86b..e6d60d2 100644 --- a/drivers/media/rc/keymaps/rc-pixelview-new.c +++ b/drivers/media/rc/keymaps/rc-pixelview-new.c @@ -17,7 +17,7 @@ present on PV MPEG 8000GT */ -static struct ir_scancode pixelview_new[] = { +static struct rc_map_table pixelview_new[] = { { 0x3c, KEY_TIME }, /* Timeshift */ { 0x12, KEY_POWER }, diff --git a/drivers/media/rc/keymaps/rc-pixelview.c b/drivers/media/rc/keymaps/rc-pixelview.c index 5a50aa7..2a76710 100644 --- a/drivers/media/rc/keymaps/rc-pixelview.c +++ b/drivers/media/rc/keymaps/rc-pixelview.c @@ -12,7 +12,7 @@ #include -static struct ir_scancode pixelview[] = { +static struct rc_map_table pixelview[] = { { 0x1e, KEY_POWER }, /* power */ { 0x07, KEY_MEDIA }, /* source */ diff --git a/drivers/media/rc/keymaps/rc-powercolor-real-angel.c b/drivers/media/rc/keymaps/rc-powercolor-real-angel.c index 4eec437..7cc0d57 100644 --- a/drivers/media/rc/keymaps/rc-powercolor-real-angel.c +++ b/drivers/media/rc/keymaps/rc-powercolor-real-angel.c @@ -17,7 +17,7 @@ * Daniel Fraga */ -static struct ir_scancode powercolor_real_angel[] = { +static struct rc_map_table powercolor_real_angel[] = { { 0x38, KEY_SWITCHVIDEOMODE }, /* switch inputs */ { 0x0c, KEY_MEDIA }, /* Turn ON/OFF App */ { 0x00, KEY_0 }, diff --git a/drivers/media/rc/keymaps/rc-proteus-2309.c b/drivers/media/rc/keymaps/rc-proteus-2309.c index 802c58a..d5e62a5 100644 --- a/drivers/media/rc/keymaps/rc-proteus-2309.c +++ b/drivers/media/rc/keymaps/rc-proteus-2309.c @@ -14,7 +14,7 @@ /* Michal Majchrowicz */ -static struct ir_scancode proteus_2309[] = { +static struct rc_map_table proteus_2309[] = { /* numeric */ { 0x00, KEY_0 }, { 0x01, KEY_1 }, diff --git a/drivers/media/rc/keymaps/rc-purpletv.c b/drivers/media/rc/keymaps/rc-purpletv.c index f3e9709..5dbfd91 100644 --- a/drivers/media/rc/keymaps/rc-purpletv.c +++ b/drivers/media/rc/keymaps/rc-purpletv.c @@ -12,7 +12,7 @@ #include -static struct ir_scancode purpletv[] = { +static struct rc_map_table purpletv[] = { { 0x03, KEY_POWER }, { 0x6f, KEY_MUTE }, { 0x10, KEY_BACKSPACE }, /* Recall */ diff --git a/drivers/media/rc/keymaps/rc-pv951.c b/drivers/media/rc/keymaps/rc-pv951.c index e301ff0..d9c7e2f 100644 --- a/drivers/media/rc/keymaps/rc-pv951.c +++ b/drivers/media/rc/keymaps/rc-pv951.c @@ -14,7 +14,7 @@ /* Mark Phalan */ -static struct ir_scancode pv951[] = { +static struct rc_map_table pv951[] = { { 0x00, KEY_0 }, { 0x01, KEY_1 }, { 0x02, KEY_2 }, diff --git a/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c b/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c index 91bcab8..eef2e87 100644 --- a/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c +++ b/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c @@ -19,7 +19,7 @@ * This table contains the complete RC5 code, instead of just the data part */ -static struct ir_scancode rc5_hauppauge_new[] = { +static struct rc_map_table rc5_hauppauge_new[] = { /* Keys 0 to 9 */ { 0x1e00, KEY_0 }, { 0x1e01, KEY_1 }, diff --git a/drivers/media/rc/keymaps/rc-rc5-tv.c b/drivers/media/rc/keymaps/rc-rc5-tv.c index cda2a2f..efa1488 100644 --- a/drivers/media/rc/keymaps/rc-rc5-tv.c +++ b/drivers/media/rc/keymaps/rc-rc5-tv.c @@ -16,7 +16,7 @@ /* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ /* used by old (black) Hauppauge remotes */ -static struct ir_scancode rc5_tv[] = { +static struct rc_map_table rc5_tv[] = { /* Keys 0 to 9 */ { 0x00, KEY_0 }, { 0x01, KEY_1 }, diff --git a/drivers/media/rc/keymaps/rc-rc6-mce.c b/drivers/media/rc/keymaps/rc-rc6-mce.c index f926477..81f4172 100644 --- a/drivers/media/rc/keymaps/rc-rc6-mce.c +++ b/drivers/media/rc/keymaps/rc-rc6-mce.c @@ -11,7 +11,7 @@ #include -static struct ir_scancode rc6_mce[] = { +static struct rc_map_table rc6_mce[] = { { 0x800f0400, KEY_NUMERIC_0 }, { 0x800f0401, KEY_NUMERIC_1 }, diff --git a/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c b/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c index 6781426..884416c 100644 --- a/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c +++ b/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c @@ -14,7 +14,7 @@ /* Zogis Real Audio 220 - 32 keys IR */ -static struct ir_scancode real_audio_220_32_keys[] = { +static struct rc_map_table real_audio_220_32_keys[] = { { 0x1c, KEY_RADIO}, { 0x12, KEY_POWER2}, diff --git a/drivers/media/rc/keymaps/rc-streamzap.c b/drivers/media/rc/keymaps/rc-streamzap.c index bafe5b8..5a86a71 100644 --- a/drivers/media/rc/keymaps/rc-streamzap.c +++ b/drivers/media/rc/keymaps/rc-streamzap.c @@ -11,7 +11,7 @@ #include -static struct ir_scancode streamzap[] = { +static struct rc_map_table streamzap[] = { /* * The Streamzap remote is almost, but not quite, RC-5, as it has an extra * bit in it, which throws the in-kernel RC-5 decoder for a loop. Currently, diff --git a/drivers/media/rc/keymaps/rc-tbs-nec.c b/drivers/media/rc/keymaps/rc-tbs-nec.c index 4ef4f81..6e2f5b5 100644 --- a/drivers/media/rc/keymaps/rc-tbs-nec.c +++ b/drivers/media/rc/keymaps/rc-tbs-nec.c @@ -12,7 +12,7 @@ #include -static struct ir_scancode tbs_nec[] = { +static struct rc_map_table tbs_nec[] = { { 0x04, KEY_POWER2}, /*power*/ { 0x14, KEY_MUTE}, /*mute*/ { 0x07, KEY_1}, diff --git a/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c b/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c index 4064a32..540020a 100644 --- a/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c +++ b/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c @@ -16,7 +16,7 @@ Devin Heitmueller */ -static struct ir_scancode terratec_cinergy_xs[] = { +static struct rc_map_table terratec_cinergy_xs[] = { { 0x41, KEY_HOME}, { 0x01, KEY_POWER}, { 0x42, KEY_MENU}, diff --git a/drivers/media/rc/keymaps/rc-terratec-slim.c b/drivers/media/rc/keymaps/rc-terratec-slim.c index c23caf7..a1513f0 100644 --- a/drivers/media/rc/keymaps/rc-terratec-slim.c +++ b/drivers/media/rc/keymaps/rc-terratec-slim.c @@ -22,7 +22,7 @@ /* TerraTec slim remote, 7 rows, 4 columns. */ /* Uses NEC extended 0x02bd. */ -static struct ir_scancode terratec_slim[] = { +static struct rc_map_table terratec_slim[] = { { 0x02bd00, KEY_1 }, { 0x02bd01, KEY_2 }, { 0x02bd02, KEY_3 }, diff --git a/drivers/media/rc/keymaps/rc-tevii-nec.c b/drivers/media/rc/keymaps/rc-tevii-nec.c index eabfb70..6b2fc43 100644 --- a/drivers/media/rc/keymaps/rc-tevii-nec.c +++ b/drivers/media/rc/keymaps/rc-tevii-nec.c @@ -12,7 +12,7 @@ #include -static struct ir_scancode tevii_nec[] = { +static struct rc_map_table tevii_nec[] = { { 0x0a, KEY_POWER2}, { 0x0c, KEY_MUTE}, { 0x11, KEY_1}, diff --git a/drivers/media/rc/keymaps/rc-total-media-in-hand.c b/drivers/media/rc/keymaps/rc-total-media-in-hand.c index cd39b3d..61a4234 100644 --- a/drivers/media/rc/keymaps/rc-total-media-in-hand.c +++ b/drivers/media/rc/keymaps/rc-total-media-in-hand.c @@ -21,7 +21,7 @@ #include /* Uses NEC extended 0x02bd */ -static struct ir_scancode total_media_in_hand[] = { +static struct rc_map_table total_media_in_hand[] = { { 0x02bd00, KEY_1 }, { 0x02bd01, KEY_2 }, { 0x02bd02, KEY_3 }, diff --git a/drivers/media/rc/keymaps/rc-trekstor.c b/drivers/media/rc/keymaps/rc-trekstor.c index 31d6c6c..2d7bbf8 100644 --- a/drivers/media/rc/keymaps/rc-trekstor.c +++ b/drivers/media/rc/keymaps/rc-trekstor.c @@ -23,7 +23,7 @@ /* TrekStor DVB-T USB Stick remote controller. */ /* Imported from af9015.h. Initial keytable was from Marc Schneider */ -static struct ir_scancode trekstor[] = { +static struct rc_map_table trekstor[] = { { 0x0084, KEY_0 }, { 0x0085, KEY_MUTE }, /* Mute */ { 0x0086, KEY_HOMEPAGE }, /* Home */ diff --git a/drivers/media/rc/keymaps/rc-tt-1500.c b/drivers/media/rc/keymaps/rc-tt-1500.c index 45a0608..f3fe9f3 100644 --- a/drivers/media/rc/keymaps/rc-tt-1500.c +++ b/drivers/media/rc/keymaps/rc-tt-1500.c @@ -14,7 +14,7 @@ /* for the Technotrend 1500 bundled remotes (grey and black): */ -static struct ir_scancode tt_1500[] = { +static struct rc_map_table tt_1500[] = { { 0x01, KEY_POWER }, { 0x02, KEY_SHUFFLE }, /* ? double-arrow key */ { 0x03, KEY_1 }, diff --git a/drivers/media/rc/keymaps/rc-twinhan1027.c b/drivers/media/rc/keymaps/rc-twinhan1027.c index b5def53..67cc6e0 100644 --- a/drivers/media/rc/keymaps/rc-twinhan1027.c +++ b/drivers/media/rc/keymaps/rc-twinhan1027.c @@ -1,6 +1,6 @@ #include -static struct ir_scancode twinhan_vp1027[] = { +static struct rc_map_table twinhan_vp1027[] = { { 0x16, KEY_POWER2 }, { 0x17, KEY_FAVORITES }, { 0x0f, KEY_TEXT }, diff --git a/drivers/media/rc/keymaps/rc-videomate-s350.c b/drivers/media/rc/keymaps/rc-videomate-s350.c index 7c422b4..f8a0d10 100644 --- a/drivers/media/rc/keymaps/rc-videomate-s350.c +++ b/drivers/media/rc/keymaps/rc-videomate-s350.c @@ -12,7 +12,7 @@ #include -static struct ir_scancode videomate_s350[] = { +static struct rc_map_table videomate_s350[] = { { 0x00, KEY_TV}, { 0x01, KEY_DVD}, { 0x04, KEY_RECORD}, diff --git a/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c b/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c index 4d31b47..04d1024 100644 --- a/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c +++ b/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c @@ -12,7 +12,7 @@ #include -static struct ir_scancode videomate_tv_pvr[] = { +static struct rc_map_table videomate_tv_pvr[] = { { 0x14, KEY_MUTE }, { 0x24, KEY_ZOOM }, diff --git a/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c b/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c index ade3c14..78fc7da 100644 --- a/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c +++ b/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c @@ -16,7 +16,7 @@ Magnus Alm */ -static struct ir_scancode winfast_usbii_deluxe[] = { +static struct rc_map_table winfast_usbii_deluxe[] = { { 0x62, KEY_0}, { 0x75, KEY_1}, { 0x76, KEY_2}, diff --git a/drivers/media/rc/keymaps/rc-winfast.c b/drivers/media/rc/keymaps/rc-winfast.c index 502b5f5..a8fbd766 100644 --- a/drivers/media/rc/keymaps/rc-winfast.c +++ b/drivers/media/rc/keymaps/rc-winfast.c @@ -14,7 +14,7 @@ /* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ -static struct ir_scancode winfast[] = { +static struct rc_map_table winfast[] = { /* Keys 0 to 9 */ { 0x12, KEY_0 }, { 0x05, KEY_1 }, diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index caa8d70..b989f5d 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -94,7 +94,7 @@ void ir_unregister_map(struct rc_keymap *map) EXPORT_SYMBOL_GPL(ir_unregister_map); -static struct ir_scancode empty[] = { +static struct rc_map_table empty[] = { { 0x2a, KEY_COFFEE }, }; @@ -123,8 +123,8 @@ static int ir_create_table(struct rc_map *rc_map, { rc_map->name = name; rc_map->rc_type = rc_type; - rc_map->alloc = roundup_pow_of_two(size * sizeof(struct ir_scancode)); - rc_map->size = rc_map->alloc / sizeof(struct ir_scancode); + rc_map->alloc = roundup_pow_of_two(size * sizeof(struct rc_map_table)); + rc_map->size = rc_map->alloc / sizeof(struct rc_map_table); rc_map->scan = kmalloc(rc_map->alloc, GFP_KERNEL); if (!rc_map->scan) return -ENOMEM; @@ -161,8 +161,8 @@ static int ir_resize_table(struct rc_map *rc_map, gfp_t gfp_flags) { unsigned int oldalloc = rc_map->alloc; unsigned int newalloc = oldalloc; - struct ir_scancode *oldscan = rc_map->scan; - struct ir_scancode *newscan; + struct rc_map_table *oldscan = rc_map->scan; + struct rc_map_table *newscan; if (rc_map->size == rc_map->len) { /* All entries in use -> grow keytable */ @@ -188,10 +188,10 @@ static int ir_resize_table(struct rc_map *rc_map, gfp_t gfp_flags) return -ENOMEM; } - memcpy(newscan, rc_map->scan, rc_map->len * sizeof(struct ir_scancode)); + memcpy(newscan, rc_map->scan, rc_map->len * sizeof(struct rc_map_table)); rc_map->scan = newscan; rc_map->alloc = newalloc; - rc_map->size = rc_map->alloc / sizeof(struct ir_scancode); + rc_map->size = rc_map->alloc / sizeof(struct rc_map_table); kfree(oldscan); return 0; } @@ -221,7 +221,7 @@ static unsigned int ir_update_mapping(struct rc_dev *dev, index, rc_map->scan[index].scancode); rc_map->len--; memmove(&rc_map->scan[index], &rc_map->scan[index+ 1], - (rc_map->len - index) * sizeof(struct ir_scancode)); + (rc_map->len - index) * sizeof(struct rc_map_table)); } else { IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n", index, @@ -300,7 +300,7 @@ static unsigned int ir_establish_scancode(struct rc_dev *dev, /* i is the proper index to insert our new keycode */ if (i < rc_map->len) memmove(&rc_map->scan[i + 1], &rc_map->scan[i], - (rc_map->len - i) * sizeof(struct ir_scancode)); + (rc_map->len - i) * sizeof(struct rc_map_table)); rc_map->scan[i].scancode = scancode; rc_map->scan[i].keycode = KEY_RESERVED; rc_map->len++; @@ -440,7 +440,7 @@ static int ir_getkeycode(struct input_dev *idev, { struct rc_dev *rdev = input_get_drvdata(idev); struct rc_map *rc_map = &rdev->rc_map; - struct ir_scancode *entry; + struct rc_map_table *entry; unsigned long flags; unsigned int index; unsigned int scancode; diff --git a/include/media/rc-map.h b/include/media/rc-map.h index a6b2738f..5e9c06a 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -25,13 +25,13 @@ RC_TYPE_JVC | RC_TYPE_SONY | RC_TYPE_LIRC | \ RC_TYPE_RC5_SZ | RC_TYPE_OTHER) -struct ir_scancode { +struct rc_map_table { u32 scancode; u32 keycode; }; struct rc_map { - struct ir_scancode *scan; + struct rc_map_table *scan; unsigned int size; /* Max number of entries */ unsigned int len; /* Used number of entries */ unsigned int alloc; /* Size of *scan in bytes */ -- cgit v0.10.2 From d100e659b61a735c3343b3d82c1c009b04072cdd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2010 15:56:53 -0300 Subject: [media] rc: use rc_map_ prefix for all rc map tables Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c index 572929a..db6d54d 100644 --- a/drivers/media/dvb/mantis/mantis_input.c +++ b/drivers/media/dvb/mantis/mantis_input.c @@ -95,7 +95,7 @@ static struct rc_map_table mantis_ir_table[] = { { 0x00, KEY_BLUE }, }; -static struct rc_keymap ir_mantis_map = { +static struct rc_map_list ir_mantis_map = { .map = { .scan = mantis_ir_table, .size = ARRAY_SIZE(mantis_ir_table), @@ -109,7 +109,7 @@ int mantis_input_init(struct mantis_pci *mantis) struct rc_dev *dev; int err; - err = ir_register_map(&ir_mantis_map); + err = rc_map_register(&ir_mantis_map); if (err) goto out; @@ -145,7 +145,7 @@ int mantis_input_init(struct mantis_pci *mantis) out_dev: rc_free_device(dev); out_map: - ir_unregister_map(&ir_mantis_map); + rc_map_unregister(&ir_mantis_map); out: return err; } @@ -153,7 +153,7 @@ out: int mantis_exit(struct mantis_pci *mantis) { rc_unregister_device(mantis->rc); - ir_unregister_map(&ir_mantis_map); + rc_map_unregister(&ir_mantis_map); return 0; } diff --git a/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c b/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c index da6556d..136d395 100644 --- a/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c +++ b/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c @@ -63,7 +63,7 @@ static struct rc_map_table adstech_dvb_t_pci[] = { { 0x1c, KEY_VOLUMEDOWN }, }; -static struct rc_keymap adstech_dvb_t_pci_map = { +static struct rc_map_list adstech_dvb_t_pci_map = { .map = { .scan = adstech_dvb_t_pci, .size = ARRAY_SIZE(adstech_dvb_t_pci), @@ -74,12 +74,12 @@ static struct rc_keymap adstech_dvb_t_pci_map = { static int __init init_rc_map_adstech_dvb_t_pci(void) { - return ir_register_map(&adstech_dvb_t_pci_map); + return rc_map_register(&adstech_dvb_t_pci_map); } static void __exit exit_rc_map_adstech_dvb_t_pci(void) { - ir_unregister_map(&adstech_dvb_t_pci_map); + rc_map_unregister(&adstech_dvb_t_pci_map); } module_init(init_rc_map_adstech_dvb_t_pci) diff --git a/drivers/media/rc/keymaps/rc-alink-dtu-m.c b/drivers/media/rc/keymaps/rc-alink-dtu-m.c index 36e1eb1..fe652e9 100644 --- a/drivers/media/rc/keymaps/rc-alink-dtu-m.c +++ b/drivers/media/rc/keymaps/rc-alink-dtu-m.c @@ -42,7 +42,7 @@ static struct rc_map_table alink_dtu_m[] = { { 0x081d, KEY_CHANNELDOWN }, }; -static struct rc_keymap alink_dtu_m_map = { +static struct rc_map_list alink_dtu_m_map = { .map = { .scan = alink_dtu_m, .size = ARRAY_SIZE(alink_dtu_m), @@ -53,12 +53,12 @@ static struct rc_keymap alink_dtu_m_map = { static int __init init_rc_map_alink_dtu_m(void) { - return ir_register_map(&alink_dtu_m_map); + return rc_map_register(&alink_dtu_m_map); } static void __exit exit_rc_map_alink_dtu_m(void) { - ir_unregister_map(&alink_dtu_m_map); + rc_map_unregister(&alink_dtu_m_map); } module_init(init_rc_map_alink_dtu_m) diff --git a/drivers/media/rc/keymaps/rc-anysee.c b/drivers/media/rc/keymaps/rc-anysee.c index 6ca91e0..884f1b5 100644 --- a/drivers/media/rc/keymaps/rc-anysee.c +++ b/drivers/media/rc/keymaps/rc-anysee.c @@ -67,7 +67,7 @@ static struct rc_map_table anysee[] = { { 0x0851, KEY_PAUSE }, }; -static struct rc_keymap anysee_map = { +static struct rc_map_list anysee_map = { .map = { .scan = anysee, .size = ARRAY_SIZE(anysee), @@ -78,12 +78,12 @@ static struct rc_keymap anysee_map = { static int __init init_rc_map_anysee(void) { - return ir_register_map(&anysee_map); + return rc_map_register(&anysee_map); } static void __exit exit_rc_map_anysee(void) { - ir_unregister_map(&anysee_map); + rc_map_unregister(&anysee_map); } module_init(init_rc_map_anysee) diff --git a/drivers/media/rc/keymaps/rc-apac-viewcomp.c b/drivers/media/rc/keymaps/rc-apac-viewcomp.c index a40a1b6..7af1882 100644 --- a/drivers/media/rc/keymaps/rc-apac-viewcomp.c +++ b/drivers/media/rc/keymaps/rc-apac-viewcomp.c @@ -54,7 +54,7 @@ static struct rc_map_table apac_viewcomp[] = { { 0x18, KEY_KPMINUS }, /* fine tune <<<< */ }; -static struct rc_keymap apac_viewcomp_map = { +static struct rc_map_list apac_viewcomp_map = { .map = { .scan = apac_viewcomp, .size = ARRAY_SIZE(apac_viewcomp), @@ -65,12 +65,12 @@ static struct rc_keymap apac_viewcomp_map = { static int __init init_rc_map_apac_viewcomp(void) { - return ir_register_map(&apac_viewcomp_map); + return rc_map_register(&apac_viewcomp_map); } static void __exit exit_rc_map_apac_viewcomp(void) { - ir_unregister_map(&apac_viewcomp_map); + rc_map_unregister(&apac_viewcomp_map); } module_init(init_rc_map_apac_viewcomp) diff --git a/drivers/media/rc/keymaps/rc-asus-pc39.c b/drivers/media/rc/keymaps/rc-asus-pc39.c index 2a58ffe..b248115 100644 --- a/drivers/media/rc/keymaps/rc-asus-pc39.c +++ b/drivers/media/rc/keymaps/rc-asus-pc39.c @@ -65,7 +65,7 @@ static struct rc_map_table asus_pc39[] = { { 0x083e, KEY_DVD }, /* dvd */ }; -static struct rc_keymap asus_pc39_map = { +static struct rc_map_list asus_pc39_map = { .map = { .scan = asus_pc39, .size = ARRAY_SIZE(asus_pc39), @@ -76,12 +76,12 @@ static struct rc_keymap asus_pc39_map = { static int __init init_rc_map_asus_pc39(void) { - return ir_register_map(&asus_pc39_map); + return rc_map_register(&asus_pc39_map); } static void __exit exit_rc_map_asus_pc39(void) { - ir_unregister_map(&asus_pc39_map); + rc_map_unregister(&asus_pc39_map); } module_init(init_rc_map_asus_pc39) diff --git a/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c b/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c index ac0a7d9..f766b24 100644 --- a/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c +++ b/drivers/media/rc/keymaps/rc-ati-tv-wonder-hd-600.c @@ -43,7 +43,7 @@ static struct rc_map_table ati_tv_wonder_hd_600[] = { { 0x17, KEY_VOLUMEDOWN}, }; -static struct rc_keymap ati_tv_wonder_hd_600_map = { +static struct rc_map_list ati_tv_wonder_hd_600_map = { .map = { .scan = ati_tv_wonder_hd_600, .size = ARRAY_SIZE(ati_tv_wonder_hd_600), @@ -54,12 +54,12 @@ static struct rc_keymap ati_tv_wonder_hd_600_map = { static int __init init_rc_map_ati_tv_wonder_hd_600(void) { - return ir_register_map(&ati_tv_wonder_hd_600_map); + return rc_map_register(&ati_tv_wonder_hd_600_map); } static void __exit exit_rc_map_ati_tv_wonder_hd_600(void) { - ir_unregister_map(&ati_tv_wonder_hd_600_map); + rc_map_unregister(&ati_tv_wonder_hd_600_map); } module_init(init_rc_map_ati_tv_wonder_hd_600) diff --git a/drivers/media/rc/keymaps/rc-avermedia-a16d.c b/drivers/media/rc/keymaps/rc-avermedia-a16d.c index df3360f..ec9beee 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-a16d.c +++ b/drivers/media/rc/keymaps/rc-avermedia-a16d.c @@ -49,7 +49,7 @@ static struct rc_map_table avermedia_a16d[] = { { 0x2a, KEY_MENU}, }; -static struct rc_keymap avermedia_a16d_map = { +static struct rc_map_list avermedia_a16d_map = { .map = { .scan = avermedia_a16d, .size = ARRAY_SIZE(avermedia_a16d), @@ -60,12 +60,12 @@ static struct rc_keymap avermedia_a16d_map = { static int __init init_rc_map_avermedia_a16d(void) { - return ir_register_map(&avermedia_a16d_map); + return rc_map_register(&avermedia_a16d_map); } static void __exit exit_rc_map_avermedia_a16d(void) { - ir_unregister_map(&avermedia_a16d_map); + rc_map_unregister(&avermedia_a16d_map); } module_init(init_rc_map_avermedia_a16d) diff --git a/drivers/media/rc/keymaps/rc-avermedia-cardbus.c b/drivers/media/rc/keymaps/rc-avermedia-cardbus.c index 40f2f2d..bdf97b7 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-cardbus.c +++ b/drivers/media/rc/keymaps/rc-avermedia-cardbus.c @@ -71,7 +71,7 @@ static struct rc_map_table avermedia_cardbus[] = { { 0x43, KEY_CHANNELUP }, /* Channel up */ }; -static struct rc_keymap avermedia_cardbus_map = { +static struct rc_map_list avermedia_cardbus_map = { .map = { .scan = avermedia_cardbus, .size = ARRAY_SIZE(avermedia_cardbus), @@ -82,12 +82,12 @@ static struct rc_keymap avermedia_cardbus_map = { static int __init init_rc_map_avermedia_cardbus(void) { - return ir_register_map(&avermedia_cardbus_map); + return rc_map_register(&avermedia_cardbus_map); } static void __exit exit_rc_map_avermedia_cardbus(void) { - ir_unregister_map(&avermedia_cardbus_map); + rc_map_unregister(&avermedia_cardbus_map); } module_init(init_rc_map_avermedia_cardbus) diff --git a/drivers/media/rc/keymaps/rc-avermedia-dvbt.c b/drivers/media/rc/keymaps/rc-avermedia-dvbt.c index b4a1aa1..3ddb41b 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-dvbt.c +++ b/drivers/media/rc/keymaps/rc-avermedia-dvbt.c @@ -52,7 +52,7 @@ static struct rc_map_table avermedia_dvbt[] = { { 0x3e, KEY_VOLUMEUP }, /* 'volume +' */ }; -static struct rc_keymap avermedia_dvbt_map = { +static struct rc_map_list avermedia_dvbt_map = { .map = { .scan = avermedia_dvbt, .size = ARRAY_SIZE(avermedia_dvbt), @@ -63,12 +63,12 @@ static struct rc_keymap avermedia_dvbt_map = { static int __init init_rc_map_avermedia_dvbt(void) { - return ir_register_map(&avermedia_dvbt_map); + return rc_map_register(&avermedia_dvbt_map); } static void __exit exit_rc_map_avermedia_dvbt(void) { - ir_unregister_map(&avermedia_dvbt_map); + rc_map_unregister(&avermedia_dvbt_map); } module_init(init_rc_map_avermedia_dvbt) diff --git a/drivers/media/rc/keymaps/rc-avermedia-m135a.c b/drivers/media/rc/keymaps/rc-avermedia-m135a.c index 971c6f9..357fea58 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-m135a.c +++ b/drivers/media/rc/keymaps/rc-avermedia-m135a.c @@ -121,7 +121,7 @@ static struct rc_map_table avermedia_m135a[] = { { 0x041e, KEY_NEXT }, }; -static struct rc_keymap avermedia_m135a_map = { +static struct rc_map_list avermedia_m135a_map = { .map = { .scan = avermedia_m135a, .size = ARRAY_SIZE(avermedia_m135a), @@ -132,12 +132,12 @@ static struct rc_keymap avermedia_m135a_map = { static int __init init_rc_map_avermedia_m135a(void) { - return ir_register_map(&avermedia_m135a_map); + return rc_map_register(&avermedia_m135a_map); } static void __exit exit_rc_map_avermedia_m135a(void) { - ir_unregister_map(&avermedia_m135a_map); + rc_map_unregister(&avermedia_m135a_map); } module_init(init_rc_map_avermedia_m135a) diff --git a/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c b/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c index 74f3a20..e694e6e 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c +++ b/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c @@ -69,7 +69,7 @@ static struct rc_map_table avermedia_m733a_rm_k6[] = { { 0x041e, KEY_NEXT }, }; -static struct rc_keymap avermedia_m733a_rm_k6_map = { +static struct rc_map_list avermedia_m733a_rm_k6_map = { .map = { .scan = avermedia_m733a_rm_k6, .size = ARRAY_SIZE(avermedia_m733a_rm_k6), @@ -80,12 +80,12 @@ static struct rc_keymap avermedia_m733a_rm_k6_map = { static int __init init_rc_map_avermedia_m733a_rm_k6(void) { - return ir_register_map(&avermedia_m733a_rm_k6_map); + return rc_map_register(&avermedia_m733a_rm_k6_map); } static void __exit exit_rc_map_avermedia_m733a_rm_k6(void) { - ir_unregister_map(&avermedia_m733a_rm_k6_map); + rc_map_unregister(&avermedia_m733a_rm_k6_map); } module_init(init_rc_map_avermedia_m733a_rm_k6) diff --git a/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c b/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c index dc6a321..f4ca1ff 100644 --- a/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c +++ b/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c @@ -53,7 +53,7 @@ static struct rc_map_table avermedia_rm_ks[] = { { 0x0556, KEY_ZOOM }, }; -static struct rc_keymap avermedia_rm_ks_map = { +static struct rc_map_list avermedia_rm_ks_map = { .map = { .scan = avermedia_rm_ks, .size = ARRAY_SIZE(avermedia_rm_ks), @@ -64,12 +64,12 @@ static struct rc_keymap avermedia_rm_ks_map = { static int __init init_rc_map_avermedia_rm_ks(void) { - return ir_register_map(&avermedia_rm_ks_map); + return rc_map_register(&avermedia_rm_ks_map); } static void __exit exit_rc_map_avermedia_rm_ks(void) { - ir_unregister_map(&avermedia_rm_ks_map); + rc_map_unregister(&avermedia_rm_ks_map); } module_init(init_rc_map_avermedia_rm_ks) diff --git a/drivers/media/rc/keymaps/rc-avermedia.c b/drivers/media/rc/keymaps/rc-avermedia.c index a5ef695..edfa715 100644 --- a/drivers/media/rc/keymaps/rc-avermedia.c +++ b/drivers/media/rc/keymaps/rc-avermedia.c @@ -60,7 +60,7 @@ static struct rc_map_table avermedia[] = { { 0x31, KEY_CHANNELUP } /* CHANNEL/PAGE+ */ }; -static struct rc_keymap avermedia_map = { +static struct rc_map_list avermedia_map = { .map = { .scan = avermedia, .size = ARRAY_SIZE(avermedia), @@ -71,12 +71,12 @@ static struct rc_keymap avermedia_map = { static int __init init_rc_map_avermedia(void) { - return ir_register_map(&avermedia_map); + return rc_map_register(&avermedia_map); } static void __exit exit_rc_map_avermedia(void) { - ir_unregister_map(&avermedia_map); + rc_map_unregister(&avermedia_map); } module_init(init_rc_map_avermedia) diff --git a/drivers/media/rc/keymaps/rc-avertv-303.c b/drivers/media/rc/keymaps/rc-avertv-303.c index 386ba59..32e9498 100644 --- a/drivers/media/rc/keymaps/rc-avertv-303.c +++ b/drivers/media/rc/keymaps/rc-avertv-303.c @@ -59,7 +59,7 @@ static struct rc_map_table avertv_303[] = { { 0x1b, KEY_UP }, }; -static struct rc_keymap avertv_303_map = { +static struct rc_map_list avertv_303_map = { .map = { .scan = avertv_303, .size = ARRAY_SIZE(avertv_303), @@ -70,12 +70,12 @@ static struct rc_keymap avertv_303_map = { static int __init init_rc_map_avertv_303(void) { - return ir_register_map(&avertv_303_map); + return rc_map_register(&avertv_303_map); } static void __exit exit_rc_map_avertv_303(void) { - ir_unregister_map(&avertv_303_map); + rc_map_unregister(&avertv_303_map); } module_init(init_rc_map_avertv_303) diff --git a/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c b/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c index fbaaba5..c3f6d62 100644 --- a/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c +++ b/drivers/media/rc/keymaps/rc-azurewave-ad-tu700.c @@ -76,7 +76,7 @@ static struct rc_map_table azurewave_ad_tu700[] = { { 0x005f, KEY_BLUE }, }; -static struct rc_keymap azurewave_ad_tu700_map = { +static struct rc_map_list azurewave_ad_tu700_map = { .map = { .scan = azurewave_ad_tu700, .size = ARRAY_SIZE(azurewave_ad_tu700), @@ -87,12 +87,12 @@ static struct rc_keymap azurewave_ad_tu700_map = { static int __init init_rc_map_azurewave_ad_tu700(void) { - return ir_register_map(&azurewave_ad_tu700_map); + return rc_map_register(&azurewave_ad_tu700_map); } static void __exit exit_rc_map_azurewave_ad_tu700(void) { - ir_unregister_map(&azurewave_ad_tu700_map); + rc_map_unregister(&azurewave_ad_tu700_map); } module_init(init_rc_map_azurewave_ad_tu700) diff --git a/drivers/media/rc/keymaps/rc-behold-columbus.c b/drivers/media/rc/keymaps/rc-behold-columbus.c index 33accf5..4b787fa 100644 --- a/drivers/media/rc/keymaps/rc-behold-columbus.c +++ b/drivers/media/rc/keymaps/rc-behold-columbus.c @@ -82,7 +82,7 @@ static struct rc_map_table behold_columbus[] = { }; -static struct rc_keymap behold_columbus_map = { +static struct rc_map_list behold_columbus_map = { .map = { .scan = behold_columbus, .size = ARRAY_SIZE(behold_columbus), @@ -93,12 +93,12 @@ static struct rc_keymap behold_columbus_map = { static int __init init_rc_map_behold_columbus(void) { - return ir_register_map(&behold_columbus_map); + return rc_map_register(&behold_columbus_map); } static void __exit exit_rc_map_behold_columbus(void) { - ir_unregister_map(&behold_columbus_map); + rc_map_unregister(&behold_columbus_map); } module_init(init_rc_map_behold_columbus) diff --git a/drivers/media/rc/keymaps/rc-behold.c b/drivers/media/rc/keymaps/rc-behold.c index 4402414..ae4d235 100644 --- a/drivers/media/rc/keymaps/rc-behold.c +++ b/drivers/media/rc/keymaps/rc-behold.c @@ -115,7 +115,7 @@ static struct rc_map_table behold[] = { }; -static struct rc_keymap behold_map = { +static struct rc_map_list behold_map = { .map = { .scan = behold, .size = ARRAY_SIZE(behold), @@ -126,12 +126,12 @@ static struct rc_keymap behold_map = { static int __init init_rc_map_behold(void) { - return ir_register_map(&behold_map); + return rc_map_register(&behold_map); } static void __exit exit_rc_map_behold(void) { - ir_unregister_map(&behold_map); + rc_map_unregister(&behold_map); } module_init(init_rc_map_behold) diff --git a/drivers/media/rc/keymaps/rc-budget-ci-old.c b/drivers/media/rc/keymaps/rc-budget-ci-old.c index e4827a6..97fc386 100644 --- a/drivers/media/rc/keymaps/rc-budget-ci-old.c +++ b/drivers/media/rc/keymaps/rc-budget-ci-old.c @@ -66,7 +66,7 @@ static struct rc_map_table budget_ci_old[] = { { 0x3e, KEY_TUNER }, }; -static struct rc_keymap budget_ci_old_map = { +static struct rc_map_list budget_ci_old_map = { .map = { .scan = budget_ci_old, .size = ARRAY_SIZE(budget_ci_old), @@ -77,12 +77,12 @@ static struct rc_keymap budget_ci_old_map = { static int __init init_rc_map_budget_ci_old(void) { - return ir_register_map(&budget_ci_old_map); + return rc_map_register(&budget_ci_old_map); } static void __exit exit_rc_map_budget_ci_old(void) { - ir_unregister_map(&budget_ci_old_map); + rc_map_unregister(&budget_ci_old_map); } module_init(init_rc_map_budget_ci_old) diff --git a/drivers/media/rc/keymaps/rc-cinergy-1400.c b/drivers/media/rc/keymaps/rc-cinergy-1400.c index 6a69866..284534b 100644 --- a/drivers/media/rc/keymaps/rc-cinergy-1400.c +++ b/drivers/media/rc/keymaps/rc-cinergy-1400.c @@ -58,7 +58,7 @@ static struct rc_map_table cinergy_1400[] = { { 0x5c, KEY_NEXT }, }; -static struct rc_keymap cinergy_1400_map = { +static struct rc_map_list cinergy_1400_map = { .map = { .scan = cinergy_1400, .size = ARRAY_SIZE(cinergy_1400), @@ -69,12 +69,12 @@ static struct rc_keymap cinergy_1400_map = { static int __init init_rc_map_cinergy_1400(void) { - return ir_register_map(&cinergy_1400_map); + return rc_map_register(&cinergy_1400_map); } static void __exit exit_rc_map_cinergy_1400(void) { - ir_unregister_map(&cinergy_1400_map); + rc_map_unregister(&cinergy_1400_map); } module_init(init_rc_map_cinergy_1400) diff --git a/drivers/media/rc/keymaps/rc-cinergy.c b/drivers/media/rc/keymaps/rc-cinergy.c index ba36d14..99520ff 100644 --- a/drivers/media/rc/keymaps/rc-cinergy.c +++ b/drivers/media/rc/keymaps/rc-cinergy.c @@ -52,7 +52,7 @@ static struct rc_map_table cinergy[] = { { 0x23, KEY_STOP }, }; -static struct rc_keymap cinergy_map = { +static struct rc_map_list cinergy_map = { .map = { .scan = cinergy, .size = ARRAY_SIZE(cinergy), @@ -63,12 +63,12 @@ static struct rc_keymap cinergy_map = { static int __init init_rc_map_cinergy(void) { - return ir_register_map(&cinergy_map); + return rc_map_register(&cinergy_map); } static void __exit exit_rc_map_cinergy(void) { - ir_unregister_map(&cinergy_map); + rc_map_unregister(&cinergy_map); } module_init(init_rc_map_cinergy) diff --git a/drivers/media/rc/keymaps/rc-dib0700-nec.c b/drivers/media/rc/keymaps/rc-dib0700-nec.c index 921230d..c59851b 100644 --- a/drivers/media/rc/keymaps/rc-dib0700-nec.c +++ b/drivers/media/rc/keymaps/rc-dib0700-nec.c @@ -98,7 +98,7 @@ static struct rc_map_table dib0700_nec_table[] = { { 0x4542, KEY_SELECT }, /* Select video input, 'Select' for Teletext */ }; -static struct rc_keymap dib0700_nec_map = { +static struct rc_map_list dib0700_nec_map = { .map = { .scan = dib0700_nec_table, .size = ARRAY_SIZE(dib0700_nec_table), @@ -109,12 +109,12 @@ static struct rc_keymap dib0700_nec_map = { static int __init init_rc_map(void) { - return ir_register_map(&dib0700_nec_map); + return rc_map_register(&dib0700_nec_map); } static void __exit exit_rc_map(void) { - ir_unregister_map(&dib0700_nec_map); + rc_map_unregister(&dib0700_nec_map); } module_init(init_rc_map) diff --git a/drivers/media/rc/keymaps/rc-dib0700-rc5.c b/drivers/media/rc/keymaps/rc-dib0700-rc5.c index 9febb72..4af12e4 100644 --- a/drivers/media/rc/keymaps/rc-dib0700-rc5.c +++ b/drivers/media/rc/keymaps/rc-dib0700-rc5.c @@ -209,7 +209,7 @@ static struct rc_map_table dib0700_rc5_table[] = { { 0x1d3d, KEY_POWER }, }; -static struct rc_keymap dib0700_rc5_map = { +static struct rc_map_list dib0700_rc5_map = { .map = { .scan = dib0700_rc5_table, .size = ARRAY_SIZE(dib0700_rc5_table), @@ -220,12 +220,12 @@ static struct rc_keymap dib0700_rc5_map = { static int __init init_rc_map(void) { - return ir_register_map(&dib0700_rc5_map); + return rc_map_register(&dib0700_rc5_map); } static void __exit exit_rc_map(void) { - ir_unregister_map(&dib0700_rc5_map); + rc_map_unregister(&dib0700_rc5_map); } module_init(init_rc_map) diff --git a/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c b/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c index da50d7d..f68b450 100644 --- a/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c +++ b/drivers/media/rc/keymaps/rc-digitalnow-tinytwin.c @@ -72,7 +72,7 @@ static struct rc_map_table digitalnow_tinytwin[] = { { 0x005a, KEY_PREVIOUS }, /* REPLAY */ }; -static struct rc_keymap digitalnow_tinytwin_map = { +static struct rc_map_list digitalnow_tinytwin_map = { .map = { .scan = digitalnow_tinytwin, .size = ARRAY_SIZE(digitalnow_tinytwin), @@ -83,12 +83,12 @@ static struct rc_keymap digitalnow_tinytwin_map = { static int __init init_rc_map_digitalnow_tinytwin(void) { - return ir_register_map(&digitalnow_tinytwin_map); + return rc_map_register(&digitalnow_tinytwin_map); } static void __exit exit_rc_map_digitalnow_tinytwin(void) { - ir_unregister_map(&digitalnow_tinytwin_map); + rc_map_unregister(&digitalnow_tinytwin_map); } module_init(init_rc_map_digitalnow_tinytwin) diff --git a/drivers/media/rc/keymaps/rc-digittrade.c b/drivers/media/rc/keymaps/rc-digittrade.c index 706f95dd..21d4987 100644 --- a/drivers/media/rc/keymaps/rc-digittrade.c +++ b/drivers/media/rc/keymaps/rc-digittrade.c @@ -56,7 +56,7 @@ static struct rc_map_table digittrade[] = { { 0x0054, KEY_0 }, }; -static struct rc_keymap digittrade_map = { +static struct rc_map_list digittrade_map = { .map = { .scan = digittrade, .size = ARRAY_SIZE(digittrade), @@ -67,12 +67,12 @@ static struct rc_keymap digittrade_map = { static int __init init_rc_map_digittrade(void) { - return ir_register_map(&digittrade_map); + return rc_map_register(&digittrade_map); } static void __exit exit_rc_map_digittrade(void) { - ir_unregister_map(&digittrade_map); + rc_map_unregister(&digittrade_map); } module_init(init_rc_map_digittrade) diff --git a/drivers/media/rc/keymaps/rc-dm1105-nec.c b/drivers/media/rc/keymaps/rc-dm1105-nec.c index 9023dc9..d024fbf 100644 --- a/drivers/media/rc/keymaps/rc-dm1105-nec.c +++ b/drivers/media/rc/keymaps/rc-dm1105-nec.c @@ -50,7 +50,7 @@ static struct rc_map_table dm1105_nec[] = { { 0x1b, KEY_B}, /* recall */ }; -static struct rc_keymap dm1105_nec_map = { +static struct rc_map_list dm1105_nec_map = { .map = { .scan = dm1105_nec, .size = ARRAY_SIZE(dm1105_nec), @@ -61,12 +61,12 @@ static struct rc_keymap dm1105_nec_map = { static int __init init_rc_map_dm1105_nec(void) { - return ir_register_map(&dm1105_nec_map); + return rc_map_register(&dm1105_nec_map); } static void __exit exit_rc_map_dm1105_nec(void) { - ir_unregister_map(&dm1105_nec_map); + rc_map_unregister(&dm1105_nec_map); } module_init(init_rc_map_dm1105_nec) diff --git a/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c b/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c index 7fbeaed..43912bd 100644 --- a/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c +++ b/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c @@ -52,7 +52,7 @@ static struct rc_map_table dntv_live_dvb_t[] = { { 0x1f, KEY_VOLUMEDOWN }, }; -static struct rc_keymap dntv_live_dvb_t_map = { +static struct rc_map_list dntv_live_dvb_t_map = { .map = { .scan = dntv_live_dvb_t, .size = ARRAY_SIZE(dntv_live_dvb_t), @@ -63,12 +63,12 @@ static struct rc_keymap dntv_live_dvb_t_map = { static int __init init_rc_map_dntv_live_dvb_t(void) { - return ir_register_map(&dntv_live_dvb_t_map); + return rc_map_register(&dntv_live_dvb_t_map); } static void __exit exit_rc_map_dntv_live_dvb_t(void) { - ir_unregister_map(&dntv_live_dvb_t_map); + rc_map_unregister(&dntv_live_dvb_t_map); } module_init(init_rc_map_dntv_live_dvb_t) diff --git a/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c b/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c index 660f2e7..015e99d 100644 --- a/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c +++ b/drivers/media/rc/keymaps/rc-dntv-live-dvbt-pro.c @@ -71,7 +71,7 @@ static struct rc_map_table dntv_live_dvbt_pro[] = { { 0x5d, KEY_BLUE }, }; -static struct rc_keymap dntv_live_dvbt_pro_map = { +static struct rc_map_list dntv_live_dvbt_pro_map = { .map = { .scan = dntv_live_dvbt_pro, .size = ARRAY_SIZE(dntv_live_dvbt_pro), @@ -82,12 +82,12 @@ static struct rc_keymap dntv_live_dvbt_pro_map = { static int __init init_rc_map_dntv_live_dvbt_pro(void) { - return ir_register_map(&dntv_live_dvbt_pro_map); + return rc_map_register(&dntv_live_dvbt_pro_map); } static void __exit exit_rc_map_dntv_live_dvbt_pro(void) { - ir_unregister_map(&dntv_live_dvbt_pro_map); + rc_map_unregister(&dntv_live_dvbt_pro_map); } module_init(init_rc_map_dntv_live_dvbt_pro) diff --git a/drivers/media/rc/keymaps/rc-em-terratec.c b/drivers/media/rc/keymaps/rc-em-terratec.c index 4d0ad8c..269d429 100644 --- a/drivers/media/rc/keymaps/rc-em-terratec.c +++ b/drivers/media/rc/keymaps/rc-em-terratec.c @@ -43,7 +43,7 @@ static struct rc_map_table em_terratec[] = { { 0x40, KEY_ZOOM }, }; -static struct rc_keymap em_terratec_map = { +static struct rc_map_list em_terratec_map = { .map = { .scan = em_terratec, .size = ARRAY_SIZE(em_terratec), @@ -54,12 +54,12 @@ static struct rc_keymap em_terratec_map = { static int __init init_rc_map_em_terratec(void) { - return ir_register_map(&em_terratec_map); + return rc_map_register(&em_terratec_map); } static void __exit exit_rc_map_em_terratec(void) { - ir_unregister_map(&em_terratec_map); + rc_map_unregister(&em_terratec_map); } module_init(init_rc_map_em_terratec) diff --git a/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c b/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c index 3005d4b..e388698 100644 --- a/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c +++ b/drivers/media/rc/keymaps/rc-encore-enltv-fm53.c @@ -55,7 +55,7 @@ static struct rc_map_table encore_enltv_fm53[] = { { 0x47, KEY_SLEEP}, /* shutdown */ }; -static struct rc_keymap encore_enltv_fm53_map = { +static struct rc_map_list encore_enltv_fm53_map = { .map = { .scan = encore_enltv_fm53, .size = ARRAY_SIZE(encore_enltv_fm53), @@ -66,12 +66,12 @@ static struct rc_keymap encore_enltv_fm53_map = { static int __init init_rc_map_encore_enltv_fm53(void) { - return ir_register_map(&encore_enltv_fm53_map); + return rc_map_register(&encore_enltv_fm53_map); } static void __exit exit_rc_map_encore_enltv_fm53(void) { - ir_unregister_map(&encore_enltv_fm53_map); + rc_map_unregister(&encore_enltv_fm53_map); } module_init(init_rc_map_encore_enltv_fm53) diff --git a/drivers/media/rc/keymaps/rc-encore-enltv.c b/drivers/media/rc/keymaps/rc-encore-enltv.c index d16db50..afa4e92 100644 --- a/drivers/media/rc/keymaps/rc-encore-enltv.c +++ b/drivers/media/rc/keymaps/rc-encore-enltv.c @@ -86,7 +86,7 @@ static struct rc_map_table encore_enltv[] = { { 0x57, KEY_BLUE }, /* AP4 */ }; -static struct rc_keymap encore_enltv_map = { +static struct rc_map_list encore_enltv_map = { .map = { .scan = encore_enltv, .size = ARRAY_SIZE(encore_enltv), @@ -97,12 +97,12 @@ static struct rc_keymap encore_enltv_map = { static int __init init_rc_map_encore_enltv(void) { - return ir_register_map(&encore_enltv_map); + return rc_map_register(&encore_enltv_map); } static void __exit exit_rc_map_encore_enltv(void) { - ir_unregister_map(&encore_enltv_map); + rc_map_unregister(&encore_enltv_map); } module_init(init_rc_map_encore_enltv) diff --git a/drivers/media/rc/keymaps/rc-encore-enltv2.c b/drivers/media/rc/keymaps/rc-encore-enltv2.c index a5e07c7..7d5b00e 100644 --- a/drivers/media/rc/keymaps/rc-encore-enltv2.c +++ b/drivers/media/rc/keymaps/rc-encore-enltv2.c @@ -64,7 +64,7 @@ static struct rc_map_table encore_enltv2[] = { { 0x79, KEY_STOP }, }; -static struct rc_keymap encore_enltv2_map = { +static struct rc_map_list encore_enltv2_map = { .map = { .scan = encore_enltv2, .size = ARRAY_SIZE(encore_enltv2), @@ -75,12 +75,12 @@ static struct rc_keymap encore_enltv2_map = { static int __init init_rc_map_encore_enltv2(void) { - return ir_register_map(&encore_enltv2_map); + return rc_map_register(&encore_enltv2_map); } static void __exit exit_rc_map_encore_enltv2(void) { - ir_unregister_map(&encore_enltv2_map); + rc_map_unregister(&encore_enltv2_map); } module_init(init_rc_map_encore_enltv2) diff --git a/drivers/media/rc/keymaps/rc-evga-indtube.c b/drivers/media/rc/keymaps/rc-evga-indtube.c index e2d0590..a2bf24f 100644 --- a/drivers/media/rc/keymaps/rc-evga-indtube.c +++ b/drivers/media/rc/keymaps/rc-evga-indtube.c @@ -35,7 +35,7 @@ static struct rc_map_table evga_indtube[] = { { 0x13, KEY_CAMERA}, }; -static struct rc_keymap evga_indtube_map = { +static struct rc_map_list evga_indtube_map = { .map = { .scan = evga_indtube, .size = ARRAY_SIZE(evga_indtube), @@ -46,12 +46,12 @@ static struct rc_keymap evga_indtube_map = { static int __init init_rc_map_evga_indtube(void) { - return ir_register_map(&evga_indtube_map); + return rc_map_register(&evga_indtube_map); } static void __exit exit_rc_map_evga_indtube(void) { - ir_unregister_map(&evga_indtube_map); + rc_map_unregister(&evga_indtube_map); } module_init(init_rc_map_evga_indtube) diff --git a/drivers/media/rc/keymaps/rc-eztv.c b/drivers/media/rc/keymaps/rc-eztv.c index ee134c5..1e8e5b2 100644 --- a/drivers/media/rc/keymaps/rc-eztv.c +++ b/drivers/media/rc/keymaps/rc-eztv.c @@ -70,7 +70,7 @@ static struct rc_map_table eztv[] = { { 0x21, KEY_DOT }, /* . (decimal dot) */ }; -static struct rc_keymap eztv_map = { +static struct rc_map_list eztv_map = { .map = { .scan = eztv, .size = ARRAY_SIZE(eztv), @@ -81,12 +81,12 @@ static struct rc_keymap eztv_map = { static int __init init_rc_map_eztv(void) { - return ir_register_map(&eztv_map); + return rc_map_register(&eztv_map); } static void __exit exit_rc_map_eztv(void) { - ir_unregister_map(&eztv_map); + rc_map_unregister(&eztv_map); } module_init(init_rc_map_eztv) diff --git a/drivers/media/rc/keymaps/rc-flydvb.c b/drivers/media/rc/keymaps/rc-flydvb.c index ef90a05..aea2f4a 100644 --- a/drivers/media/rc/keymaps/rc-flydvb.c +++ b/drivers/media/rc/keymaps/rc-flydvb.c @@ -51,7 +51,7 @@ static struct rc_map_table flydvb[] = { { 0x0e, KEY_NEXT }, /* End >>| */ }; -static struct rc_keymap flydvb_map = { +static struct rc_map_list flydvb_map = { .map = { .scan = flydvb, .size = ARRAY_SIZE(flydvb), @@ -62,12 +62,12 @@ static struct rc_keymap flydvb_map = { static int __init init_rc_map_flydvb(void) { - return ir_register_map(&flydvb_map); + return rc_map_register(&flydvb_map); } static void __exit exit_rc_map_flydvb(void) { - ir_unregister_map(&flydvb_map); + rc_map_unregister(&flydvb_map); } module_init(init_rc_map_flydvb) diff --git a/drivers/media/rc/keymaps/rc-flyvideo.c b/drivers/media/rc/keymaps/rc-flyvideo.c index 20a1333..5bbe683 100644 --- a/drivers/media/rc/keymaps/rc-flyvideo.c +++ b/drivers/media/rc/keymaps/rc-flyvideo.c @@ -44,7 +44,7 @@ static struct rc_map_table flyvideo[] = { { 0x0a, KEY_ANGLE }, /* no label, may be used as the PAUSE button */ }; -static struct rc_keymap flyvideo_map = { +static struct rc_map_list flyvideo_map = { .map = { .scan = flyvideo, .size = ARRAY_SIZE(flyvideo), @@ -55,12 +55,12 @@ static struct rc_keymap flyvideo_map = { static int __init init_rc_map_flyvideo(void) { - return ir_register_map(&flyvideo_map); + return rc_map_register(&flyvideo_map); } static void __exit exit_rc_map_flyvideo(void) { - ir_unregister_map(&flyvideo_map); + rc_map_unregister(&flyvideo_map); } module_init(init_rc_map_flyvideo) diff --git a/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c b/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c index 2687af7..c80b25c 100644 --- a/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c +++ b/drivers/media/rc/keymaps/rc-fusionhdtv-mce.c @@ -72,7 +72,7 @@ static struct rc_map_table fusionhdtv_mce[] = { { 0x4e, KEY_POWER }, }; -static struct rc_keymap fusionhdtv_mce_map = { +static struct rc_map_list fusionhdtv_mce_map = { .map = { .scan = fusionhdtv_mce, .size = ARRAY_SIZE(fusionhdtv_mce), @@ -83,12 +83,12 @@ static struct rc_keymap fusionhdtv_mce_map = { static int __init init_rc_map_fusionhdtv_mce(void) { - return ir_register_map(&fusionhdtv_mce_map); + return rc_map_register(&fusionhdtv_mce_map); } static void __exit exit_rc_map_fusionhdtv_mce(void) { - ir_unregister_map(&fusionhdtv_mce_map); + rc_map_unregister(&fusionhdtv_mce_map); } module_init(init_rc_map_fusionhdtv_mce) diff --git a/drivers/media/rc/keymaps/rc-gadmei-rm008z.c b/drivers/media/rc/keymaps/rc-gadmei-rm008z.c index fb247ba..068c9ea 100644 --- a/drivers/media/rc/keymaps/rc-gadmei-rm008z.c +++ b/drivers/media/rc/keymaps/rc-gadmei-rm008z.c @@ -55,7 +55,7 @@ static struct rc_map_table gadmei_rm008z[] = { { 0x15, KEY_ENTER}, /* OK */ }; -static struct rc_keymap gadmei_rm008z_map = { +static struct rc_map_list gadmei_rm008z_map = { .map = { .scan = gadmei_rm008z, .size = ARRAY_SIZE(gadmei_rm008z), @@ -66,12 +66,12 @@ static struct rc_keymap gadmei_rm008z_map = { static int __init init_rc_map_gadmei_rm008z(void) { - return ir_register_map(&gadmei_rm008z_map); + return rc_map_register(&gadmei_rm008z_map); } static void __exit exit_rc_map_gadmei_rm008z(void) { - ir_unregister_map(&gadmei_rm008z_map); + rc_map_unregister(&gadmei_rm008z_map); } module_init(init_rc_map_gadmei_rm008z) diff --git a/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c b/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c index 7e6834a..cdbbed4 100644 --- a/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c +++ b/drivers/media/rc/keymaps/rc-genius-tvgo-a11mce.c @@ -58,7 +58,7 @@ static struct rc_map_table genius_tvgo_a11mce[] = { { 0x50, KEY_BLUE }, }; -static struct rc_keymap genius_tvgo_a11mce_map = { +static struct rc_map_list genius_tvgo_a11mce_map = { .map = { .scan = genius_tvgo_a11mce, .size = ARRAY_SIZE(genius_tvgo_a11mce), @@ -69,12 +69,12 @@ static struct rc_keymap genius_tvgo_a11mce_map = { static int __init init_rc_map_genius_tvgo_a11mce(void) { - return ir_register_map(&genius_tvgo_a11mce_map); + return rc_map_register(&genius_tvgo_a11mce_map); } static void __exit exit_rc_map_genius_tvgo_a11mce(void) { - ir_unregister_map(&genius_tvgo_a11mce_map); + rc_map_unregister(&genius_tvgo_a11mce_map); } module_init(init_rc_map_genius_tvgo_a11mce) diff --git a/drivers/media/rc/keymaps/rc-gotview7135.c b/drivers/media/rc/keymaps/rc-gotview7135.c index 54222ca..a38bdde 100644 --- a/drivers/media/rc/keymaps/rc-gotview7135.c +++ b/drivers/media/rc/keymaps/rc-gotview7135.c @@ -53,7 +53,7 @@ static struct rc_map_table gotview7135[] = { { 0x38, KEY_F24 }, /* NORMAL TIMESHIFT */ }; -static struct rc_keymap gotview7135_map = { +static struct rc_map_list gotview7135_map = { .map = { .scan = gotview7135, .size = ARRAY_SIZE(gotview7135), @@ -64,12 +64,12 @@ static struct rc_keymap gotview7135_map = { static int __init init_rc_map_gotview7135(void) { - return ir_register_map(&gotview7135_map); + return rc_map_register(&gotview7135_map); } static void __exit exit_rc_map_gotview7135(void) { - ir_unregister_map(&gotview7135_map); + rc_map_unregister(&gotview7135_map); } module_init(init_rc_map_gotview7135) diff --git a/drivers/media/rc/keymaps/rc-hauppauge-new.c b/drivers/media/rc/keymaps/rc-hauppauge-new.c index 2396257..bd11da4 100644 --- a/drivers/media/rc/keymaps/rc-hauppauge-new.c +++ b/drivers/media/rc/keymaps/rc-hauppauge-new.c @@ -74,7 +74,7 @@ static struct rc_map_table hauppauge_new[] = { { 0x3d, KEY_POWER }, /* system power (green button) */ }; -static struct rc_keymap hauppauge_new_map = { +static struct rc_map_list hauppauge_new_map = { .map = { .scan = hauppauge_new, .size = ARRAY_SIZE(hauppauge_new), @@ -85,12 +85,12 @@ static struct rc_keymap hauppauge_new_map = { static int __init init_rc_map_hauppauge_new(void) { - return ir_register_map(&hauppauge_new_map); + return rc_map_register(&hauppauge_new_map); } static void __exit exit_rc_map_hauppauge_new(void) { - ir_unregister_map(&hauppauge_new_map); + rc_map_unregister(&hauppauge_new_map); } module_init(init_rc_map_hauppauge_new) diff --git a/drivers/media/rc/keymaps/rc-imon-mce.c b/drivers/media/rc/keymaps/rc-imon-mce.c index 291e5d8..cb67184 100644 --- a/drivers/media/rc/keymaps/rc-imon-mce.c +++ b/drivers/media/rc/keymaps/rc-imon-mce.c @@ -115,7 +115,7 @@ static struct rc_map_table imon_mce[] = { }; -static struct rc_keymap imon_mce_map = { +static struct rc_map_list imon_mce_map = { .map = { .scan = imon_mce, .size = ARRAY_SIZE(imon_mce), @@ -127,12 +127,12 @@ static struct rc_keymap imon_mce_map = { static int __init init_rc_map_imon_mce(void) { - return ir_register_map(&imon_mce_map); + return rc_map_register(&imon_mce_map); } static void __exit exit_rc_map_imon_mce(void) { - ir_unregister_map(&imon_mce_map); + rc_map_unregister(&imon_mce_map); } module_init(init_rc_map_imon_mce) diff --git a/drivers/media/rc/keymaps/rc-imon-pad.c b/drivers/media/rc/keymaps/rc-imon-pad.c index 33f28d4..eef46b7 100644 --- a/drivers/media/rc/keymaps/rc-imon-pad.c +++ b/drivers/media/rc/keymaps/rc-imon-pad.c @@ -129,7 +129,7 @@ static struct rc_map_table imon_pad[] = { { 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */ }; -static struct rc_keymap imon_pad_map = { +static struct rc_map_list imon_pad_map = { .map = { .scan = imon_pad, .size = ARRAY_SIZE(imon_pad), @@ -141,12 +141,12 @@ static struct rc_keymap imon_pad_map = { static int __init init_rc_map_imon_pad(void) { - return ir_register_map(&imon_pad_map); + return rc_map_register(&imon_pad_map); } static void __exit exit_rc_map_imon_pad(void) { - ir_unregister_map(&imon_pad_map); + rc_map_unregister(&imon_pad_map); } module_init(init_rc_map_imon_pad) diff --git a/drivers/media/rc/keymaps/rc-iodata-bctv7e.c b/drivers/media/rc/keymaps/rc-iodata-bctv7e.c index 5e5263f..1f59e16 100644 --- a/drivers/media/rc/keymaps/rc-iodata-bctv7e.c +++ b/drivers/media/rc/keymaps/rc-iodata-bctv7e.c @@ -62,7 +62,7 @@ static struct rc_map_table iodata_bctv7e[] = { { 0x01, KEY_NEXT }, /* skip >| */ }; -static struct rc_keymap iodata_bctv7e_map = { +static struct rc_map_list iodata_bctv7e_map = { .map = { .scan = iodata_bctv7e, .size = ARRAY_SIZE(iodata_bctv7e), @@ -73,12 +73,12 @@ static struct rc_keymap iodata_bctv7e_map = { static int __init init_rc_map_iodata_bctv7e(void) { - return ir_register_map(&iodata_bctv7e_map); + return rc_map_register(&iodata_bctv7e_map); } static void __exit exit_rc_map_iodata_bctv7e(void) { - ir_unregister_map(&iodata_bctv7e_map); + rc_map_unregister(&iodata_bctv7e_map); } module_init(init_rc_map_iodata_bctv7e) diff --git a/drivers/media/rc/keymaps/rc-kaiomy.c b/drivers/media/rc/keymaps/rc-kaiomy.c index 527ab1b..f31dc5c 100644 --- a/drivers/media/rc/keymaps/rc-kaiomy.c +++ b/drivers/media/rc/keymaps/rc-kaiomy.c @@ -61,7 +61,7 @@ static struct rc_map_table kaiomy[] = { { 0x1f, KEY_BLUE}, }; -static struct rc_keymap kaiomy_map = { +static struct rc_map_list kaiomy_map = { .map = { .scan = kaiomy, .size = ARRAY_SIZE(kaiomy), @@ -72,12 +72,12 @@ static struct rc_keymap kaiomy_map = { static int __init init_rc_map_kaiomy(void) { - return ir_register_map(&kaiomy_map); + return rc_map_register(&kaiomy_map); } static void __exit exit_rc_map_kaiomy(void) { - ir_unregister_map(&kaiomy_map); + rc_map_unregister(&kaiomy_map); } module_init(init_rc_map_kaiomy) diff --git a/drivers/media/rc/keymaps/rc-kworld-315u.c b/drivers/media/rc/keymaps/rc-kworld-315u.c index f58703e..3ce6ef7 100644 --- a/drivers/media/rc/keymaps/rc-kworld-315u.c +++ b/drivers/media/rc/keymaps/rc-kworld-315u.c @@ -57,7 +57,7 @@ static struct rc_map_table kworld_315u[] = { { 0x611f, KEY_BLUE }, }; -static struct rc_keymap kworld_315u_map = { +static struct rc_map_list kworld_315u_map = { .map = { .scan = kworld_315u, .size = ARRAY_SIZE(kworld_315u), @@ -68,12 +68,12 @@ static struct rc_keymap kworld_315u_map = { static int __init init_rc_map_kworld_315u(void) { - return ir_register_map(&kworld_315u_map); + return rc_map_register(&kworld_315u_map); } static void __exit exit_rc_map_kworld_315u(void) { - ir_unregister_map(&kworld_315u_map); + rc_map_unregister(&kworld_315u_map); } module_init(init_rc_map_kworld_315u) diff --git a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c index f6235bb..e45f0b8 100644 --- a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c +++ b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c @@ -73,7 +73,7 @@ static struct rc_map_table kworld_plus_tv_analog[] = { { 0x23, KEY_GREEN}, /* C */ }; -static struct rc_keymap kworld_plus_tv_analog_map = { +static struct rc_map_list kworld_plus_tv_analog_map = { .map = { .scan = kworld_plus_tv_analog, .size = ARRAY_SIZE(kworld_plus_tv_analog), @@ -84,12 +84,12 @@ static struct rc_keymap kworld_plus_tv_analog_map = { static int __init init_rc_map_kworld_plus_tv_analog(void) { - return ir_register_map(&kworld_plus_tv_analog_map); + return rc_map_register(&kworld_plus_tv_analog_map); } static void __exit exit_rc_map_kworld_plus_tv_analog(void) { - ir_unregister_map(&kworld_plus_tv_analog_map); + rc_map_unregister(&kworld_plus_tv_analog_map); } module_init(init_rc_map_kworld_plus_tv_analog) diff --git a/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c b/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c index e1b8726..8faa54f 100644 --- a/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c +++ b/drivers/media/rc/keymaps/rc-leadtek-y04g0051.c @@ -73,7 +73,7 @@ static struct rc_map_table leadtek_y04g0051[] = { { 0x035f, KEY_CHANNELDOWN }, }; -static struct rc_keymap leadtek_y04g0051_map = { +static struct rc_map_list leadtek_y04g0051_map = { .map = { .scan = leadtek_y04g0051, .size = ARRAY_SIZE(leadtek_y04g0051), @@ -84,12 +84,12 @@ static struct rc_keymap leadtek_y04g0051_map = { static int __init init_rc_map_leadtek_y04g0051(void) { - return ir_register_map(&leadtek_y04g0051_map); + return rc_map_register(&leadtek_y04g0051_map); } static void __exit exit_rc_map_leadtek_y04g0051(void) { - ir_unregister_map(&leadtek_y04g0051_map); + rc_map_unregister(&leadtek_y04g0051_map); } module_init(init_rc_map_leadtek_y04g0051) diff --git a/drivers/media/rc/keymaps/rc-lirc.c b/drivers/media/rc/keymaps/rc-lirc.c index d4dfee7..e8e23e2 100644 --- a/drivers/media/rc/keymaps/rc-lirc.c +++ b/drivers/media/rc/keymaps/rc-lirc.c @@ -15,7 +15,7 @@ static struct rc_map_table lirc[] = { { }, }; -static struct rc_keymap lirc_map = { +static struct rc_map_list lirc_map = { .map = { .scan = lirc, .size = ARRAY_SIZE(lirc), @@ -26,12 +26,12 @@ static struct rc_keymap lirc_map = { static int __init init_rc_map_lirc(void) { - return ir_register_map(&lirc_map); + return rc_map_register(&lirc_map); } static void __exit exit_rc_map_lirc(void) { - ir_unregister_map(&lirc_map); + rc_map_unregister(&lirc_map); } module_init(init_rc_map_lirc) diff --git a/drivers/media/rc/keymaps/rc-lme2510.c b/drivers/media/rc/keymaps/rc-lme2510.c index eb2d396..875cd81 100644 --- a/drivers/media/rc/keymaps/rc-lme2510.c +++ b/drivers/media/rc/keymaps/rc-lme2510.c @@ -42,7 +42,7 @@ static struct rc_map_table lme2510_rc[] = { }; -static struct rc_keymap lme2510_map = { +static struct rc_map_list lme2510_map = { .map = { .scan = lme2510_rc, .size = ARRAY_SIZE(lme2510_rc), @@ -53,12 +53,12 @@ static struct rc_keymap lme2510_map = { static int __init init_rc_lme2510_map(void) { - return ir_register_map(&lme2510_map); + return rc_map_register(&lme2510_map); } static void __exit exit_rc_lme2510_map(void) { - ir_unregister_map(&lme2510_map); + rc_map_unregister(&lme2510_map); } module_init(init_rc_lme2510_map) diff --git a/drivers/media/rc/keymaps/rc-manli.c b/drivers/media/rc/keymaps/rc-manli.c index b24b082..23b2d04 100644 --- a/drivers/media/rc/keymaps/rc-manli.c +++ b/drivers/media/rc/keymaps/rc-manli.c @@ -108,7 +108,7 @@ static struct rc_map_table manli[] = { /* 0x1d unused ? */ }; -static struct rc_keymap manli_map = { +static struct rc_map_list manli_map = { .map = { .scan = manli, .size = ARRAY_SIZE(manli), @@ -119,12 +119,12 @@ static struct rc_keymap manli_map = { static int __init init_rc_map_manli(void) { - return ir_register_map(&manli_map); + return rc_map_register(&manli_map); } static void __exit exit_rc_map_manli(void) { - ir_unregister_map(&manli_map); + rc_map_unregister(&manli_map); } module_init(init_rc_map_manli) diff --git a/drivers/media/rc/keymaps/rc-msi-digivox-ii.c b/drivers/media/rc/keymaps/rc-msi-digivox-ii.c index 4ad89b7..7b9a01b 100644 --- a/drivers/media/rc/keymaps/rc-msi-digivox-ii.c +++ b/drivers/media/rc/keymaps/rc-msi-digivox-ii.c @@ -41,7 +41,7 @@ static struct rc_map_table msi_digivox_ii[] = { { 0x001f, KEY_VOLUMEDOWN }, }; -static struct rc_keymap msi_digivox_ii_map = { +static struct rc_map_list msi_digivox_ii_map = { .map = { .scan = msi_digivox_ii, .size = ARRAY_SIZE(msi_digivox_ii), @@ -52,12 +52,12 @@ static struct rc_keymap msi_digivox_ii_map = { static int __init init_rc_map_msi_digivox_ii(void) { - return ir_register_map(&msi_digivox_ii_map); + return rc_map_register(&msi_digivox_ii_map); } static void __exit exit_rc_map_msi_digivox_ii(void) { - ir_unregister_map(&msi_digivox_ii_map); + rc_map_unregister(&msi_digivox_ii_map); } module_init(init_rc_map_msi_digivox_ii) diff --git a/drivers/media/rc/keymaps/rc-msi-digivox-iii.c b/drivers/media/rc/keymaps/rc-msi-digivox-iii.c index d3304e7..ae9d06b 100644 --- a/drivers/media/rc/keymaps/rc-msi-digivox-iii.c +++ b/drivers/media/rc/keymaps/rc-msi-digivox-iii.c @@ -59,7 +59,7 @@ static struct rc_map_table msi_digivox_iii[] = { { 0x61d643, KEY_POWER2 }, /* [red power button] */ }; -static struct rc_keymap msi_digivox_iii_map = { +static struct rc_map_list msi_digivox_iii_map = { .map = { .scan = msi_digivox_iii, .size = ARRAY_SIZE(msi_digivox_iii), @@ -70,12 +70,12 @@ static struct rc_keymap msi_digivox_iii_map = { static int __init init_rc_map_msi_digivox_iii(void) { - return ir_register_map(&msi_digivox_iii_map); + return rc_map_register(&msi_digivox_iii_map); } static void __exit exit_rc_map_msi_digivox_iii(void) { - ir_unregister_map(&msi_digivox_iii_map); + rc_map_unregister(&msi_digivox_iii_map); } module_init(init_rc_map_msi_digivox_iii) diff --git a/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c b/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c index 51999c4..fa8fd0a 100644 --- a/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c +++ b/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c @@ -97,7 +97,7 @@ static struct rc_map_table msi_tvanywhere_plus[] = { { 0x1d, KEY_RESTART }, /* Reset */ }; -static struct rc_keymap msi_tvanywhere_plus_map = { +static struct rc_map_list msi_tvanywhere_plus_map = { .map = { .scan = msi_tvanywhere_plus, .size = ARRAY_SIZE(msi_tvanywhere_plus), @@ -108,12 +108,12 @@ static struct rc_keymap msi_tvanywhere_plus_map = { static int __init init_rc_map_msi_tvanywhere_plus(void) { - return ir_register_map(&msi_tvanywhere_plus_map); + return rc_map_register(&msi_tvanywhere_plus_map); } static void __exit exit_rc_map_msi_tvanywhere_plus(void) { - ir_unregister_map(&msi_tvanywhere_plus_map); + rc_map_unregister(&msi_tvanywhere_plus_map); } module_init(init_rc_map_msi_tvanywhere_plus) diff --git a/drivers/media/rc/keymaps/rc-msi-tvanywhere.c b/drivers/media/rc/keymaps/rc-msi-tvanywhere.c index 619df9d..18b37fa 100644 --- a/drivers/media/rc/keymaps/rc-msi-tvanywhere.c +++ b/drivers/media/rc/keymaps/rc-msi-tvanywhere.c @@ -43,7 +43,7 @@ static struct rc_map_table msi_tvanywhere[] = { { 0x1f, KEY_VOLUMEDOWN }, }; -static struct rc_keymap msi_tvanywhere_map = { +static struct rc_map_list msi_tvanywhere_map = { .map = { .scan = msi_tvanywhere, .size = ARRAY_SIZE(msi_tvanywhere), @@ -54,12 +54,12 @@ static struct rc_keymap msi_tvanywhere_map = { static int __init init_rc_map_msi_tvanywhere(void) { - return ir_register_map(&msi_tvanywhere_map); + return rc_map_register(&msi_tvanywhere_map); } static void __exit exit_rc_map_msi_tvanywhere(void) { - ir_unregister_map(&msi_tvanywhere_map); + rc_map_unregister(&msi_tvanywhere_map); } module_init(init_rc_map_msi_tvanywhere) diff --git a/drivers/media/rc/keymaps/rc-nebula.c b/drivers/media/rc/keymaps/rc-nebula.c index 8672859..3e6f077 100644 --- a/drivers/media/rc/keymaps/rc-nebula.c +++ b/drivers/media/rc/keymaps/rc-nebula.c @@ -70,7 +70,7 @@ static struct rc_map_table nebula[] = { { 0x36, KEY_PC }, }; -static struct rc_keymap nebula_map = { +static struct rc_map_list nebula_map = { .map = { .scan = nebula, .size = ARRAY_SIZE(nebula), @@ -81,12 +81,12 @@ static struct rc_keymap nebula_map = { static int __init init_rc_map_nebula(void) { - return ir_register_map(&nebula_map); + return rc_map_register(&nebula_map); } static void __exit exit_rc_map_nebula(void) { - ir_unregister_map(&nebula_map); + rc_map_unregister(&nebula_map); } module_init(init_rc_map_nebula) diff --git a/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c b/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c index 2f560dc..26f114c 100644 --- a/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c +++ b/drivers/media/rc/keymaps/rc-nec-terratec-cinergy-xs.c @@ -79,7 +79,7 @@ static struct rc_map_table nec_terratec_cinergy_xs[] = { { 0x145c, KEY_NEXT}, }; -static struct rc_keymap nec_terratec_cinergy_xs_map = { +static struct rc_map_list nec_terratec_cinergy_xs_map = { .map = { .scan = nec_terratec_cinergy_xs, .size = ARRAY_SIZE(nec_terratec_cinergy_xs), @@ -90,12 +90,12 @@ static struct rc_keymap nec_terratec_cinergy_xs_map = { static int __init init_rc_map_nec_terratec_cinergy_xs(void) { - return ir_register_map(&nec_terratec_cinergy_xs_map); + return rc_map_register(&nec_terratec_cinergy_xs_map); } static void __exit exit_rc_map_nec_terratec_cinergy_xs(void) { - ir_unregister_map(&nec_terratec_cinergy_xs_map); + rc_map_unregister(&nec_terratec_cinergy_xs_map); } module_init(init_rc_map_nec_terratec_cinergy_xs) diff --git a/drivers/media/rc/keymaps/rc-norwood.c b/drivers/media/rc/keymaps/rc-norwood.c index f4a8503..629ee9d 100644 --- a/drivers/media/rc/keymaps/rc-norwood.c +++ b/drivers/media/rc/keymaps/rc-norwood.c @@ -59,7 +59,7 @@ static struct rc_map_table norwood[] = { { 0x65, KEY_POWER }, /* Computer power */ }; -static struct rc_keymap norwood_map = { +static struct rc_map_list norwood_map = { .map = { .scan = norwood, .size = ARRAY_SIZE(norwood), @@ -70,12 +70,12 @@ static struct rc_keymap norwood_map = { static int __init init_rc_map_norwood(void) { - return ir_register_map(&norwood_map); + return rc_map_register(&norwood_map); } static void __exit exit_rc_map_norwood(void) { - ir_unregister_map(&norwood_map); + rc_map_unregister(&norwood_map); } module_init(init_rc_map_norwood) diff --git a/drivers/media/rc/keymaps/rc-npgtech.c b/drivers/media/rc/keymaps/rc-npgtech.c index fdfa549..4aa588b 100644 --- a/drivers/media/rc/keymaps/rc-npgtech.c +++ b/drivers/media/rc/keymaps/rc-npgtech.c @@ -54,7 +54,7 @@ static struct rc_map_table npgtech[] = { }; -static struct rc_keymap npgtech_map = { +static struct rc_map_list npgtech_map = { .map = { .scan = npgtech, .size = ARRAY_SIZE(npgtech), @@ -65,12 +65,12 @@ static struct rc_keymap npgtech_map = { static int __init init_rc_map_npgtech(void) { - return ir_register_map(&npgtech_map); + return rc_map_register(&npgtech_map); } static void __exit exit_rc_map_npgtech(void) { - ir_unregister_map(&npgtech_map); + rc_map_unregister(&npgtech_map); } module_init(init_rc_map_npgtech) diff --git a/drivers/media/rc/keymaps/rc-pctv-sedna.c b/drivers/media/rc/keymaps/rc-pctv-sedna.c index 86c1101..fa5ae59 100644 --- a/drivers/media/rc/keymaps/rc-pctv-sedna.c +++ b/drivers/media/rc/keymaps/rc-pctv-sedna.c @@ -54,7 +54,7 @@ static struct rc_map_table pctv_sedna[] = { { 0x1f, KEY_PLAY }, /* Play */ }; -static struct rc_keymap pctv_sedna_map = { +static struct rc_map_list pctv_sedna_map = { .map = { .scan = pctv_sedna, .size = ARRAY_SIZE(pctv_sedna), @@ -65,12 +65,12 @@ static struct rc_keymap pctv_sedna_map = { static int __init init_rc_map_pctv_sedna(void) { - return ir_register_map(&pctv_sedna_map); + return rc_map_register(&pctv_sedna_map); } static void __exit exit_rc_map_pctv_sedna(void) { - ir_unregister_map(&pctv_sedna_map); + rc_map_unregister(&pctv_sedna_map); } module_init(init_rc_map_pctv_sedna) diff --git a/drivers/media/rc/keymaps/rc-pinnacle-color.c b/drivers/media/rc/keymaps/rc-pinnacle-color.c index d3f4cd4..23b8c50 100644 --- a/drivers/media/rc/keymaps/rc-pinnacle-color.c +++ b/drivers/media/rc/keymaps/rc-pinnacle-color.c @@ -68,7 +68,7 @@ static struct rc_map_table pinnacle_color[] = { { 0x0a, KEY_BACKSPACE }, }; -static struct rc_keymap pinnacle_color_map = { +static struct rc_map_list pinnacle_color_map = { .map = { .scan = pinnacle_color, .size = ARRAY_SIZE(pinnacle_color), @@ -79,12 +79,12 @@ static struct rc_keymap pinnacle_color_map = { static int __init init_rc_map_pinnacle_color(void) { - return ir_register_map(&pinnacle_color_map); + return rc_map_register(&pinnacle_color_map); } static void __exit exit_rc_map_pinnacle_color(void) { - ir_unregister_map(&pinnacle_color_map); + rc_map_unregister(&pinnacle_color_map); } module_init(init_rc_map_pinnacle_color) diff --git a/drivers/media/rc/keymaps/rc-pinnacle-grey.c b/drivers/media/rc/keymaps/rc-pinnacle-grey.c index 1f48b43..6ba8c36 100644 --- a/drivers/media/rc/keymaps/rc-pinnacle-grey.c +++ b/drivers/media/rc/keymaps/rc-pinnacle-grey.c @@ -63,7 +63,7 @@ static struct rc_map_table pinnacle_grey[] = { { 0x18, KEY_EPG }, }; -static struct rc_keymap pinnacle_grey_map = { +static struct rc_map_list pinnacle_grey_map = { .map = { .scan = pinnacle_grey, .size = ARRAY_SIZE(pinnacle_grey), @@ -74,12 +74,12 @@ static struct rc_keymap pinnacle_grey_map = { static int __init init_rc_map_pinnacle_grey(void) { - return ir_register_map(&pinnacle_grey_map); + return rc_map_register(&pinnacle_grey_map); } static void __exit exit_rc_map_pinnacle_grey(void) { - ir_unregister_map(&pinnacle_grey_map); + rc_map_unregister(&pinnacle_grey_map); } module_init(init_rc_map_pinnacle_grey) diff --git a/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c index dc7267c..bb10ffe 100644 --- a/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c +++ b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c @@ -47,7 +47,7 @@ static struct rc_map_table pinnacle_pctv_hd[] = { { 0x3f, KEY_EPG }, /* Labeled "?" */ }; -static struct rc_keymap pinnacle_pctv_hd_map = { +static struct rc_map_list pinnacle_pctv_hd_map = { .map = { .scan = pinnacle_pctv_hd, .size = ARRAY_SIZE(pinnacle_pctv_hd), @@ -58,12 +58,12 @@ static struct rc_keymap pinnacle_pctv_hd_map = { static int __init init_rc_map_pinnacle_pctv_hd(void) { - return ir_register_map(&pinnacle_pctv_hd_map); + return rc_map_register(&pinnacle_pctv_hd_map); } static void __exit exit_rc_map_pinnacle_pctv_hd(void) { - ir_unregister_map(&pinnacle_pctv_hd_map); + rc_map_unregister(&pinnacle_pctv_hd_map); } module_init(init_rc_map_pinnacle_pctv_hd) diff --git a/drivers/media/rc/keymaps/rc-pixelview-mk12.c b/drivers/media/rc/keymaps/rc-pixelview-mk12.c index 93f7248..8d9f664 100644 --- a/drivers/media/rc/keymaps/rc-pixelview-mk12.c +++ b/drivers/media/rc/keymaps/rc-pixelview-mk12.c @@ -57,7 +57,7 @@ static struct rc_map_table pixelview_mk12[] = { { 0x866b07, KEY_RADIO }, /* FM */ }; -static struct rc_keymap pixelview_map = { +static struct rc_map_list pixelview_map = { .map = { .scan = pixelview_mk12, .size = ARRAY_SIZE(pixelview_mk12), @@ -68,12 +68,12 @@ static struct rc_keymap pixelview_map = { static int __init init_rc_map_pixelview(void) { - return ir_register_map(&pixelview_map); + return rc_map_register(&pixelview_map); } static void __exit exit_rc_map_pixelview(void) { - ir_unregister_map(&pixelview_map); + rc_map_unregister(&pixelview_map); } module_init(init_rc_map_pixelview) diff --git a/drivers/media/rc/keymaps/rc-pixelview-new.c b/drivers/media/rc/keymaps/rc-pixelview-new.c index e6d60d2..777a700 100644 --- a/drivers/media/rc/keymaps/rc-pixelview-new.c +++ b/drivers/media/rc/keymaps/rc-pixelview-new.c @@ -57,7 +57,7 @@ static struct rc_map_table pixelview_new[] = { { 0x34, KEY_RADIO }, }; -static struct rc_keymap pixelview_new_map = { +static struct rc_map_list pixelview_new_map = { .map = { .scan = pixelview_new, .size = ARRAY_SIZE(pixelview_new), @@ -68,12 +68,12 @@ static struct rc_keymap pixelview_new_map = { static int __init init_rc_map_pixelview_new(void) { - return ir_register_map(&pixelview_new_map); + return rc_map_register(&pixelview_new_map); } static void __exit exit_rc_map_pixelview_new(void) { - ir_unregister_map(&pixelview_new_map); + rc_map_unregister(&pixelview_new_map); } module_init(init_rc_map_pixelview_new) diff --git a/drivers/media/rc/keymaps/rc-pixelview.c b/drivers/media/rc/keymaps/rc-pixelview.c index 2a76710..0ec5988 100644 --- a/drivers/media/rc/keymaps/rc-pixelview.c +++ b/drivers/media/rc/keymaps/rc-pixelview.c @@ -56,7 +56,7 @@ static struct rc_map_table pixelview[] = { { 0x18, KEY_MUTE }, /* mute/unmute */ }; -static struct rc_keymap pixelview_map = { +static struct rc_map_list pixelview_map = { .map = { .scan = pixelview, .size = ARRAY_SIZE(pixelview), @@ -67,12 +67,12 @@ static struct rc_keymap pixelview_map = { static int __init init_rc_map_pixelview(void) { - return ir_register_map(&pixelview_map); + return rc_map_register(&pixelview_map); } static void __exit exit_rc_map_pixelview(void) { - ir_unregister_map(&pixelview_map); + rc_map_unregister(&pixelview_map); } module_init(init_rc_map_pixelview) diff --git a/drivers/media/rc/keymaps/rc-powercolor-real-angel.c b/drivers/media/rc/keymaps/rc-powercolor-real-angel.c index 7cc0d57..5f9d546 100644 --- a/drivers/media/rc/keymaps/rc-powercolor-real-angel.c +++ b/drivers/media/rc/keymaps/rc-powercolor-real-angel.c @@ -55,7 +55,7 @@ static struct rc_map_table powercolor_real_angel[] = { { 0x25, KEY_POWER }, /* power */ }; -static struct rc_keymap powercolor_real_angel_map = { +static struct rc_map_list powercolor_real_angel_map = { .map = { .scan = powercolor_real_angel, .size = ARRAY_SIZE(powercolor_real_angel), @@ -66,12 +66,12 @@ static struct rc_keymap powercolor_real_angel_map = { static int __init init_rc_map_powercolor_real_angel(void) { - return ir_register_map(&powercolor_real_angel_map); + return rc_map_register(&powercolor_real_angel_map); } static void __exit exit_rc_map_powercolor_real_angel(void) { - ir_unregister_map(&powercolor_real_angel_map); + rc_map_unregister(&powercolor_real_angel_map); } module_init(init_rc_map_powercolor_real_angel) diff --git a/drivers/media/rc/keymaps/rc-proteus-2309.c b/drivers/media/rc/keymaps/rc-proteus-2309.c index d5e62a5..8a3a643 100644 --- a/drivers/media/rc/keymaps/rc-proteus-2309.c +++ b/drivers/media/rc/keymaps/rc-proteus-2309.c @@ -43,7 +43,7 @@ static struct rc_map_table proteus_2309[] = { { 0x14, KEY_F1 }, }; -static struct rc_keymap proteus_2309_map = { +static struct rc_map_list proteus_2309_map = { .map = { .scan = proteus_2309, .size = ARRAY_SIZE(proteus_2309), @@ -54,12 +54,12 @@ static struct rc_keymap proteus_2309_map = { static int __init init_rc_map_proteus_2309(void) { - return ir_register_map(&proteus_2309_map); + return rc_map_register(&proteus_2309_map); } static void __exit exit_rc_map_proteus_2309(void) { - ir_unregister_map(&proteus_2309_map); + rc_map_unregister(&proteus_2309_map); } module_init(init_rc_map_proteus_2309) diff --git a/drivers/media/rc/keymaps/rc-purpletv.c b/drivers/media/rc/keymaps/rc-purpletv.c index 5dbfd91..ef90296 100644 --- a/drivers/media/rc/keymaps/rc-purpletv.c +++ b/drivers/media/rc/keymaps/rc-purpletv.c @@ -55,7 +55,7 @@ static struct rc_map_table purpletv[] = { }; -static struct rc_keymap purpletv_map = { +static struct rc_map_list purpletv_map = { .map = { .scan = purpletv, .size = ARRAY_SIZE(purpletv), @@ -66,12 +66,12 @@ static struct rc_keymap purpletv_map = { static int __init init_rc_map_purpletv(void) { - return ir_register_map(&purpletv_map); + return rc_map_register(&purpletv_map); } static void __exit exit_rc_map_purpletv(void) { - ir_unregister_map(&purpletv_map); + rc_map_unregister(&purpletv_map); } module_init(init_rc_map_purpletv) diff --git a/drivers/media/rc/keymaps/rc-pv951.c b/drivers/media/rc/keymaps/rc-pv951.c index d9c7e2f..83a418d 100644 --- a/drivers/media/rc/keymaps/rc-pv951.c +++ b/drivers/media/rc/keymaps/rc-pv951.c @@ -52,7 +52,7 @@ static struct rc_map_table pv951[] = { { 0x1c, KEY_MEDIA }, /* PC/TV */ }; -static struct rc_keymap pv951_map = { +static struct rc_map_list pv951_map = { .map = { .scan = pv951, .size = ARRAY_SIZE(pv951), @@ -63,12 +63,12 @@ static struct rc_keymap pv951_map = { static int __init init_rc_map_pv951(void) { - return ir_register_map(&pv951_map); + return rc_map_register(&pv951_map); } static void __exit exit_rc_map_pv951(void) { - ir_unregister_map(&pv951_map); + rc_map_unregister(&pv951_map); } module_init(init_rc_map_pv951) diff --git a/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c b/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c index eef2e87..df534b0 100644 --- a/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c +++ b/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c @@ -77,7 +77,7 @@ static struct rc_map_table rc5_hauppauge_new[] = { { 0x1e3d, KEY_POWER }, /* system power (green button) */ }; -static struct rc_keymap rc5_hauppauge_new_map = { +static struct rc_map_list rc5_hauppauge_new_map = { .map = { .scan = rc5_hauppauge_new, .size = ARRAY_SIZE(rc5_hauppauge_new), @@ -88,12 +88,12 @@ static struct rc_keymap rc5_hauppauge_new_map = { static int __init init_rc_map_rc5_hauppauge_new(void) { - return ir_register_map(&rc5_hauppauge_new_map); + return rc_map_register(&rc5_hauppauge_new_map); } static void __exit exit_rc_map_rc5_hauppauge_new(void) { - ir_unregister_map(&rc5_hauppauge_new_map); + rc_map_unregister(&rc5_hauppauge_new_map); } module_init(init_rc_map_rc5_hauppauge_new) diff --git a/drivers/media/rc/keymaps/rc-rc5-tv.c b/drivers/media/rc/keymaps/rc-rc5-tv.c index efa1488..4fcef9f 100644 --- a/drivers/media/rc/keymaps/rc-rc5-tv.c +++ b/drivers/media/rc/keymaps/rc-rc5-tv.c @@ -55,7 +55,7 @@ static struct rc_map_table rc5_tv[] = { }; -static struct rc_keymap rc5_tv_map = { +static struct rc_map_list rc5_tv_map = { .map = { .scan = rc5_tv, .size = ARRAY_SIZE(rc5_tv), @@ -66,12 +66,12 @@ static struct rc_keymap rc5_tv_map = { static int __init init_rc_map_rc5_tv(void) { - return ir_register_map(&rc5_tv_map); + return rc_map_register(&rc5_tv_map); } static void __exit exit_rc_map_rc5_tv(void) { - ir_unregister_map(&rc5_tv_map); + rc_map_unregister(&rc5_tv_map); } module_init(init_rc_map_rc5_tv) diff --git a/drivers/media/rc/keymaps/rc-rc6-mce.c b/drivers/media/rc/keymaps/rc-rc6-mce.c index 81f4172..3bf3337 100644 --- a/drivers/media/rc/keymaps/rc-rc6-mce.c +++ b/drivers/media/rc/keymaps/rc-rc6-mce.c @@ -87,7 +87,7 @@ static struct rc_map_table rc6_mce[] = { { 0x800f0481, KEY_PLAYPAUSE }, }; -static struct rc_keymap rc6_mce_map = { +static struct rc_map_list rc6_mce_map = { .map = { .scan = rc6_mce, .size = ARRAY_SIZE(rc6_mce), @@ -98,12 +98,12 @@ static struct rc_keymap rc6_mce_map = { static int __init init_rc_map_rc6_mce(void) { - return ir_register_map(&rc6_mce_map); + return rc_map_register(&rc6_mce_map); } static void __exit exit_rc_map_rc6_mce(void) { - ir_unregister_map(&rc6_mce_map); + rc_map_unregister(&rc6_mce_map); } module_init(init_rc_map_rc6_mce) diff --git a/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c b/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c index 884416c..2d14598 100644 --- a/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c +++ b/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c @@ -52,7 +52,7 @@ static struct rc_map_table real_audio_220_32_keys[] = { }; -static struct rc_keymap real_audio_220_32_keys_map = { +static struct rc_map_list real_audio_220_32_keys_map = { .map = { .scan = real_audio_220_32_keys, .size = ARRAY_SIZE(real_audio_220_32_keys), @@ -63,12 +63,12 @@ static struct rc_keymap real_audio_220_32_keys_map = { static int __init init_rc_map_real_audio_220_32_keys(void) { - return ir_register_map(&real_audio_220_32_keys_map); + return rc_map_register(&real_audio_220_32_keys_map); } static void __exit exit_rc_map_real_audio_220_32_keys(void) { - ir_unregister_map(&real_audio_220_32_keys_map); + rc_map_unregister(&real_audio_220_32_keys_map); } module_init(init_rc_map_real_audio_220_32_keys) diff --git a/drivers/media/rc/keymaps/rc-streamzap.c b/drivers/media/rc/keymaps/rc-streamzap.c index 5a86a71..92cc10d 100644 --- a/drivers/media/rc/keymaps/rc-streamzap.c +++ b/drivers/media/rc/keymaps/rc-streamzap.c @@ -56,7 +56,7 @@ static struct rc_map_table streamzap[] = { }; -static struct rc_keymap streamzap_map = { +static struct rc_map_list streamzap_map = { .map = { .scan = streamzap, .size = ARRAY_SIZE(streamzap), @@ -67,12 +67,12 @@ static struct rc_keymap streamzap_map = { static int __init init_rc_map_streamzap(void) { - return ir_register_map(&streamzap_map); + return rc_map_register(&streamzap_map); } static void __exit exit_rc_map_streamzap(void) { - ir_unregister_map(&streamzap_map); + rc_map_unregister(&streamzap_map); } module_init(init_rc_map_streamzap) diff --git a/drivers/media/rc/keymaps/rc-tbs-nec.c b/drivers/media/rc/keymaps/rc-tbs-nec.c index 6e2f5b5..15b9a9b 100644 --- a/drivers/media/rc/keymaps/rc-tbs-nec.c +++ b/drivers/media/rc/keymaps/rc-tbs-nec.c @@ -47,7 +47,7 @@ static struct rc_map_table tbs_nec[] = { { 0x1b, KEY_MODE}, }; -static struct rc_keymap tbs_nec_map = { +static struct rc_map_list tbs_nec_map = { .map = { .scan = tbs_nec, .size = ARRAY_SIZE(tbs_nec), @@ -58,12 +58,12 @@ static struct rc_keymap tbs_nec_map = { static int __init init_rc_map_tbs_nec(void) { - return ir_register_map(&tbs_nec_map); + return rc_map_register(&tbs_nec_map); } static void __exit exit_rc_map_tbs_nec(void) { - ir_unregister_map(&tbs_nec_map); + rc_map_unregister(&tbs_nec_map); } module_init(init_rc_map_tbs_nec) diff --git a/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c b/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c index 540020a..bc38e34 100644 --- a/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c +++ b/drivers/media/rc/keymaps/rc-terratec-cinergy-xs.c @@ -66,7 +66,7 @@ static struct rc_map_table terratec_cinergy_xs[] = { { 0x5c, KEY_NEXT}, }; -static struct rc_keymap terratec_cinergy_xs_map = { +static struct rc_map_list terratec_cinergy_xs_map = { .map = { .scan = terratec_cinergy_xs, .size = ARRAY_SIZE(terratec_cinergy_xs), @@ -77,12 +77,12 @@ static struct rc_keymap terratec_cinergy_xs_map = { static int __init init_rc_map_terratec_cinergy_xs(void) { - return ir_register_map(&terratec_cinergy_xs_map); + return rc_map_register(&terratec_cinergy_xs_map); } static void __exit exit_rc_map_terratec_cinergy_xs(void) { - ir_unregister_map(&terratec_cinergy_xs_map); + rc_map_unregister(&terratec_cinergy_xs_map); } module_init(init_rc_map_terratec_cinergy_xs) diff --git a/drivers/media/rc/keymaps/rc-terratec-slim.c b/drivers/media/rc/keymaps/rc-terratec-slim.c index a1513f0..1abafa5 100644 --- a/drivers/media/rc/keymaps/rc-terratec-slim.c +++ b/drivers/media/rc/keymaps/rc-terratec-slim.c @@ -53,7 +53,7 @@ static struct rc_map_table terratec_slim[] = { { 0x02bd45, KEY_POWER2 }, /* [red power button] */ }; -static struct rc_keymap terratec_slim_map = { +static struct rc_map_list terratec_slim_map = { .map = { .scan = terratec_slim, .size = ARRAY_SIZE(terratec_slim), @@ -64,12 +64,12 @@ static struct rc_keymap terratec_slim_map = { static int __init init_rc_map_terratec_slim(void) { - return ir_register_map(&terratec_slim_map); + return rc_map_register(&terratec_slim_map); } static void __exit exit_rc_map_terratec_slim(void) { - ir_unregister_map(&terratec_slim_map); + rc_map_unregister(&terratec_slim_map); } module_init(init_rc_map_terratec_slim) diff --git a/drivers/media/rc/keymaps/rc-tevii-nec.c b/drivers/media/rc/keymaps/rc-tevii-nec.c index 6b2fc43..ef5ba3f 100644 --- a/drivers/media/rc/keymaps/rc-tevii-nec.c +++ b/drivers/media/rc/keymaps/rc-tevii-nec.c @@ -62,7 +62,7 @@ static struct rc_map_table tevii_nec[] = { { 0x58, KEY_SWITCHVIDEOMODE}, }; -static struct rc_keymap tevii_nec_map = { +static struct rc_map_list tevii_nec_map = { .map = { .scan = tevii_nec, .size = ARRAY_SIZE(tevii_nec), @@ -73,12 +73,12 @@ static struct rc_keymap tevii_nec_map = { static int __init init_rc_map_tevii_nec(void) { - return ir_register_map(&tevii_nec_map); + return rc_map_register(&tevii_nec_map); } static void __exit exit_rc_map_tevii_nec(void) { - ir_unregister_map(&tevii_nec_map); + rc_map_unregister(&tevii_nec_map); } module_init(init_rc_map_tevii_nec) diff --git a/drivers/media/rc/keymaps/rc-total-media-in-hand.c b/drivers/media/rc/keymaps/rc-total-media-in-hand.c index 61a4234..20ac4e1 100644 --- a/drivers/media/rc/keymaps/rc-total-media-in-hand.c +++ b/drivers/media/rc/keymaps/rc-total-media-in-hand.c @@ -59,7 +59,7 @@ static struct rc_map_table total_media_in_hand[] = { { 0x02bd45, KEY_INFO }, /* [red (I)] */ }; -static struct rc_keymap total_media_in_hand_map = { +static struct rc_map_list total_media_in_hand_map = { .map = { .scan = total_media_in_hand, .size = ARRAY_SIZE(total_media_in_hand), @@ -70,12 +70,12 @@ static struct rc_keymap total_media_in_hand_map = { static int __init init_rc_map_total_media_in_hand(void) { - return ir_register_map(&total_media_in_hand_map); + return rc_map_register(&total_media_in_hand_map); } static void __exit exit_rc_map_total_media_in_hand(void) { - ir_unregister_map(&total_media_in_hand_map); + rc_map_unregister(&total_media_in_hand_map); } module_init(init_rc_map_total_media_in_hand) diff --git a/drivers/media/rc/keymaps/rc-trekstor.c b/drivers/media/rc/keymaps/rc-trekstor.c index 2d7bbf8..f8190ea 100644 --- a/drivers/media/rc/keymaps/rc-trekstor.c +++ b/drivers/media/rc/keymaps/rc-trekstor.c @@ -54,7 +54,7 @@ static struct rc_map_table trekstor[] = { { 0x009f, KEY_LEFT }, /* Left */ }; -static struct rc_keymap trekstor_map = { +static struct rc_map_list trekstor_map = { .map = { .scan = trekstor, .size = ARRAY_SIZE(trekstor), @@ -65,12 +65,12 @@ static struct rc_keymap trekstor_map = { static int __init init_rc_map_trekstor(void) { - return ir_register_map(&trekstor_map); + return rc_map_register(&trekstor_map); } static void __exit exit_rc_map_trekstor(void) { - ir_unregister_map(&trekstor_map); + rc_map_unregister(&trekstor_map); } module_init(init_rc_map_trekstor) diff --git a/drivers/media/rc/keymaps/rc-tt-1500.c b/drivers/media/rc/keymaps/rc-tt-1500.c index f3fe9f3..bb19487 100644 --- a/drivers/media/rc/keymaps/rc-tt-1500.c +++ b/drivers/media/rc/keymaps/rc-tt-1500.c @@ -56,7 +56,7 @@ static struct rc_map_table tt_1500[] = { { 0x3f, KEY_FORWARD }, }; -static struct rc_keymap tt_1500_map = { +static struct rc_map_list tt_1500_map = { .map = { .scan = tt_1500, .size = ARRAY_SIZE(tt_1500), @@ -67,12 +67,12 @@ static struct rc_keymap tt_1500_map = { static int __init init_rc_map_tt_1500(void) { - return ir_register_map(&tt_1500_map); + return rc_map_register(&tt_1500_map); } static void __exit exit_rc_map_tt_1500(void) { - ir_unregister_map(&tt_1500_map); + rc_map_unregister(&tt_1500_map); } module_init(init_rc_map_tt_1500) diff --git a/drivers/media/rc/keymaps/rc-twinhan1027.c b/drivers/media/rc/keymaps/rc-twinhan1027.c index 67cc6e0..8bf8df6 100644 --- a/drivers/media/rc/keymaps/rc-twinhan1027.c +++ b/drivers/media/rc/keymaps/rc-twinhan1027.c @@ -61,7 +61,7 @@ static struct rc_map_table twinhan_vp1027[] = { { 0x5f, KEY_BLUE }, }; -static struct rc_keymap twinhan_vp1027_map = { +static struct rc_map_list twinhan_vp1027_map = { .map = { .scan = twinhan_vp1027, .size = ARRAY_SIZE(twinhan_vp1027), @@ -72,12 +72,12 @@ static struct rc_keymap twinhan_vp1027_map = { static int __init init_rc_map_twinhan_vp1027(void) { - return ir_register_map(&twinhan_vp1027_map); + return rc_map_register(&twinhan_vp1027_map); } static void __exit exit_rc_map_twinhan_vp1027(void) { - ir_unregister_map(&twinhan_vp1027_map); + rc_map_unregister(&twinhan_vp1027_map); } module_init(init_rc_map_twinhan_vp1027) diff --git a/drivers/media/rc/keymaps/rc-videomate-s350.c b/drivers/media/rc/keymaps/rc-videomate-s350.c index f8a0d10..9e474a6 100644 --- a/drivers/media/rc/keymaps/rc-videomate-s350.c +++ b/drivers/media/rc/keymaps/rc-videomate-s350.c @@ -59,7 +59,7 @@ static struct rc_map_table videomate_s350[] = { { 0x20, KEY_TEXT}, }; -static struct rc_keymap videomate_s350_map = { +static struct rc_map_list videomate_s350_map = { .map = { .scan = videomate_s350, .size = ARRAY_SIZE(videomate_s350), @@ -70,12 +70,12 @@ static struct rc_keymap videomate_s350_map = { static int __init init_rc_map_videomate_s350(void) { - return ir_register_map(&videomate_s350_map); + return rc_map_register(&videomate_s350_map); } static void __exit exit_rc_map_videomate_s350(void) { - ir_unregister_map(&videomate_s350_map); + rc_map_unregister(&videomate_s350_map); } module_init(init_rc_map_videomate_s350) diff --git a/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c b/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c index 04d1024..5f2a46e 100644 --- a/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c +++ b/drivers/media/rc/keymaps/rc-videomate-tv-pvr.c @@ -61,7 +61,7 @@ static struct rc_map_table videomate_tv_pvr[] = { { 0x21, KEY_SLEEP }, }; -static struct rc_keymap videomate_tv_pvr_map = { +static struct rc_map_list videomate_tv_pvr_map = { .map = { .scan = videomate_tv_pvr, .size = ARRAY_SIZE(videomate_tv_pvr), @@ -72,12 +72,12 @@ static struct rc_keymap videomate_tv_pvr_map = { static int __init init_rc_map_videomate_tv_pvr(void) { - return ir_register_map(&videomate_tv_pvr_map); + return rc_map_register(&videomate_tv_pvr_map); } static void __exit exit_rc_map_videomate_tv_pvr(void) { - ir_unregister_map(&videomate_tv_pvr_map); + rc_map_unregister(&videomate_tv_pvr_map); } module_init(init_rc_map_videomate_tv_pvr) diff --git a/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c b/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c index 78fc7da..bd8d021 100644 --- a/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c +++ b/drivers/media/rc/keymaps/rc-winfast-usbii-deluxe.c @@ -56,7 +56,7 @@ static struct rc_map_table winfast_usbii_deluxe[] = { }; -static struct rc_keymap winfast_usbii_deluxe_map = { +static struct rc_map_list winfast_usbii_deluxe_map = { .map = { .scan = winfast_usbii_deluxe, .size = ARRAY_SIZE(winfast_usbii_deluxe), @@ -67,12 +67,12 @@ static struct rc_keymap winfast_usbii_deluxe_map = { static int __init init_rc_map_winfast_usbii_deluxe(void) { - return ir_register_map(&winfast_usbii_deluxe_map); + return rc_map_register(&winfast_usbii_deluxe_map); } static void __exit exit_rc_map_winfast_usbii_deluxe(void) { - ir_unregister_map(&winfast_usbii_deluxe_map); + rc_map_unregister(&winfast_usbii_deluxe_map); } module_init(init_rc_map_winfast_usbii_deluxe) diff --git a/drivers/media/rc/keymaps/rc-winfast.c b/drivers/media/rc/keymaps/rc-winfast.c index a8fbd766..2747db4 100644 --- a/drivers/media/rc/keymaps/rc-winfast.c +++ b/drivers/media/rc/keymaps/rc-winfast.c @@ -76,7 +76,7 @@ static struct rc_map_table winfast[] = { { 0x3f, KEY_F24 } /* MCE -CH, on Y04G0033 */ }; -static struct rc_keymap winfast_map = { +static struct rc_map_list winfast_map = { .map = { .scan = winfast, .size = ARRAY_SIZE(winfast), @@ -87,12 +87,12 @@ static struct rc_keymap winfast_map = { static int __init init_rc_map_winfast(void) { - return ir_register_map(&winfast_map); + return rc_map_register(&winfast_map); } static void __exit exit_rc_map_winfast(void) { - ir_unregister_map(&winfast_map); + rc_map_unregister(&winfast_map); } module_init(init_rc_map_winfast) diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index b989f5d..0b0524c 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -31,9 +31,9 @@ static LIST_HEAD(rc_map_list); static DEFINE_SPINLOCK(rc_map_lock); -static struct rc_keymap *seek_rc_map(const char *name) +static struct rc_map_list *seek_rc_map(const char *name) { - struct rc_keymap *map = NULL; + struct rc_map_list *map = NULL; spin_lock(&rc_map_lock); list_for_each_entry(map, &rc_map_list, list) { @@ -47,10 +47,10 @@ static struct rc_keymap *seek_rc_map(const char *name) return NULL; } -struct rc_map *get_rc_map(const char *name) +struct rc_map *rc_map_get(const char *name) { - struct rc_keymap *map; + struct rc_map_list *map; map = seek_rc_map(name); #ifdef MODULE @@ -74,31 +74,31 @@ struct rc_map *get_rc_map(const char *name) return &map->map; } -EXPORT_SYMBOL_GPL(get_rc_map); +EXPORT_SYMBOL_GPL(rc_map_get); -int ir_register_map(struct rc_keymap *map) +int rc_map_register(struct rc_map_list *map) { spin_lock(&rc_map_lock); list_add_tail(&map->list, &rc_map_list); spin_unlock(&rc_map_lock); return 0; } -EXPORT_SYMBOL_GPL(ir_register_map); +EXPORT_SYMBOL_GPL(rc_map_register); -void ir_unregister_map(struct rc_keymap *map) +void rc_map_unregister(struct rc_map_list *map) { spin_lock(&rc_map_lock); list_del(&map->list); spin_unlock(&rc_map_lock); } -EXPORT_SYMBOL_GPL(ir_unregister_map); +EXPORT_SYMBOL_GPL(rc_map_unregister); static struct rc_map_table empty[] = { { 0x2a, KEY_COFFEE }, }; -static struct rc_keymap empty_map = { +static struct rc_map_list empty_map = { .map = { .scan = empty, .size = ARRAY_SIZE(empty), @@ -996,9 +996,9 @@ int rc_register_device(struct rc_dev *dev) if (!dev || !dev->map_name) return -EINVAL; - rc_map = get_rc_map(dev->map_name); + rc_map = rc_map_get(dev->map_name); if (!rc_map) - rc_map = get_rc_map(RC_MAP_EMPTY); + rc_map = rc_map_get(RC_MAP_EMPTY); if (!rc_map || !rc_map->scan || rc_map->size == 0) return -EINVAL; @@ -1113,7 +1113,7 @@ static int __init rc_core_init(void) /* Initialize/load the decoders/keymap code that will be used */ ir_raw_init(); - ir_register_map(&empty_map); + rc_map_register(&empty_map); return 0; } @@ -1121,7 +1121,7 @@ static int __init rc_core_init(void) static void __exit rc_core_exit(void) { class_unregister(&ir_input_class); - ir_unregister_map(&empty_map); + rc_map_unregister(&empty_map); } module_init(rc_core_init); diff --git a/include/media/rc-map.h b/include/media/rc-map.h index 5e9c06a..1a3d51d 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -40,16 +40,16 @@ struct rc_map { spinlock_t lock; }; -struct rc_keymap { +struct rc_map_list { struct list_head list; struct rc_map map; }; /* Routines from rc-map.c */ -int ir_register_map(struct rc_keymap *map); -void ir_unregister_map(struct rc_keymap *map); -struct rc_map *get_rc_map(const char *name); +int rc_map_register(struct rc_map_list *map); +void rc_map_unregister(struct rc_map_list *map); +struct rc_map *rc_map_get(const char *name); void rc_map_init(void); /* Names of the several keytables defined in-kernel */ -- cgit v0.10.2 From 03c9a806e30c3904e5b5702874eebc1a4f2082bd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Nov 2010 16:05:05 -0300 Subject: [media] rc: Rename IR raw interface to ir-raw.c Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 21251ba..78ac8c5 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -1,4 +1,4 @@ -rc-core-objs := rc-main.o rc-raw.o +rc-core-objs := rc-main.o ir-raw.o obj-y += keymaps/ diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c new file mode 100644 index 0000000..165412f --- /dev/null +++ b/drivers/media/rc/ir-raw.c @@ -0,0 +1,371 @@ +/* ir-raw-event.c - handle IR Pulse/Space event + * + * Copyright (C) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include "rc-core-priv.h" + +/* Define the max number of pulse/space transitions to buffer */ +#define MAX_IR_EVENT_SIZE 512 + +/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */ +static LIST_HEAD(ir_raw_client_list); + +/* Used to handle IR raw handler extensions */ +static DEFINE_MUTEX(ir_raw_handler_lock); +static LIST_HEAD(ir_raw_handler_list); +static u64 available_protocols; + +#ifdef MODULE +/* Used to load the decoders */ +static struct work_struct wq_load; +#endif + +static int ir_raw_event_thread(void *data) +{ + struct ir_raw_event ev; + struct ir_raw_handler *handler; + struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data; + int retval; + + while (!kthread_should_stop()) { + + spin_lock_irq(&raw->lock); + retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev)); + + if (!retval) { + set_current_state(TASK_INTERRUPTIBLE); + + if (kthread_should_stop()) + set_current_state(TASK_RUNNING); + + spin_unlock_irq(&raw->lock); + schedule(); + continue; + } + + spin_unlock_irq(&raw->lock); + + + BUG_ON(retval != sizeof(ev)); + + mutex_lock(&ir_raw_handler_lock); + list_for_each_entry(handler, &ir_raw_handler_list, list) + handler->decode(raw->dev, ev); + raw->prev_ev = ev; + mutex_unlock(&ir_raw_handler_lock); + } + + return 0; +} + +/** + * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders + * @dev: the struct rc_dev device descriptor + * @ev: the struct ir_raw_event descriptor of the pulse/space + * + * This routine (which may be called from an interrupt context) stores a + * pulse/space duration for the raw ir decoding state machines. Pulses are + * signalled as positive values and spaces as negative values. A zero value + * will reset the decoding state machines. + */ +int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev) +{ + if (!dev->raw) + return -EINVAL; + + IR_dprintk(2, "sample: (%05dus %s)\n", + TO_US(ev->duration), TO_STR(ev->pulse)); + + if (kfifo_in(&dev->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) + return -ENOMEM; + + return 0; +} +EXPORT_SYMBOL_GPL(ir_raw_event_store); + +/** + * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space + * @dev: the struct rc_dev device descriptor + * @type: the type of the event that has occurred + * + * This routine (which may be called from an interrupt context) is used to + * store the beginning of an ir pulse or space (or the start/end of ir + * reception) for the raw ir decoding state machines. This is used by + * hardware which does not provide durations directly but only interrupts + * (or similar events) on state change. + */ +int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type) +{ + ktime_t now; + s64 delta; /* ns */ + struct ir_raw_event ev; + int rc = 0; + + if (!dev->raw) + return -EINVAL; + + now = ktime_get(); + delta = ktime_to_ns(ktime_sub(now, dev->raw->last_event)); + + /* Check for a long duration since last event or if we're + * being called for the first time, note that delta can't + * possibly be negative. + */ + ev.duration = 0; + if (delta > IR_MAX_DURATION || !dev->raw->last_type) + type |= IR_START_EVENT; + else + ev.duration = delta; + + if (type & IR_START_EVENT) + ir_raw_event_reset(dev); + else if (dev->raw->last_type & IR_SPACE) { + ev.pulse = false; + rc = ir_raw_event_store(dev, &ev); + } else if (dev->raw->last_type & IR_PULSE) { + ev.pulse = true; + rc = ir_raw_event_store(dev, &ev); + } else + return 0; + + dev->raw->last_event = now; + dev->raw->last_type = type; + return rc; +} +EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); + +/** + * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing + * @dev: the struct rc_dev device descriptor + * @type: the type of the event that has occurred + * + * This routine (which may be called from an interrupt context) works + * in similiar manner to ir_raw_event_store_edge. + * This routine is intended for devices with limited internal buffer + * It automerges samples of same type, and handles timeouts + */ +int ir_raw_event_store_with_filter(struct rc_dev *dev, struct ir_raw_event *ev) +{ + if (!dev->raw) + return -EINVAL; + + /* Ignore spaces in idle mode */ + if (dev->idle && !ev->pulse) + return 0; + else if (dev->idle) + ir_raw_event_set_idle(dev, false); + + if (!dev->raw->this_ev.duration) + dev->raw->this_ev = *ev; + else if (ev->pulse == dev->raw->this_ev.pulse) + dev->raw->this_ev.duration += ev->duration; + else { + ir_raw_event_store(dev, &dev->raw->this_ev); + dev->raw->this_ev = *ev; + } + + /* Enter idle mode if nessesary */ + if (!ev->pulse && dev->timeout && + dev->raw->this_ev.duration >= dev->timeout) + ir_raw_event_set_idle(dev, true); + + return 0; +} +EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter); + +/** + * ir_raw_event_set_idle() - provide hint to rc-core when the device is idle or not + * @dev: the struct rc_dev device descriptor + * @idle: whether the device is idle or not + */ +void ir_raw_event_set_idle(struct rc_dev *dev, bool idle) +{ + if (!dev->raw) + return; + + IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave"); + + if (idle) { + dev->raw->this_ev.timeout = true; + ir_raw_event_store(dev, &dev->raw->this_ev); + init_ir_raw_event(&dev->raw->this_ev); + } + + if (dev->s_idle) + dev->s_idle(dev, idle); + + dev->idle = idle; +} +EXPORT_SYMBOL_GPL(ir_raw_event_set_idle); + +/** + * ir_raw_event_handle() - schedules the decoding of stored ir data + * @dev: the struct rc_dev device descriptor + * + * This routine will tell rc-core to start decoding stored ir data. + */ +void ir_raw_event_handle(struct rc_dev *dev) +{ + unsigned long flags; + + if (!dev->raw) + return; + + spin_lock_irqsave(&dev->raw->lock, flags); + wake_up_process(dev->raw->thread); + spin_unlock_irqrestore(&dev->raw->lock, flags); +} +EXPORT_SYMBOL_GPL(ir_raw_event_handle); + +/* used internally by the sysfs interface */ +u64 +ir_raw_get_allowed_protocols() +{ + u64 protocols; + mutex_lock(&ir_raw_handler_lock); + protocols = available_protocols; + mutex_unlock(&ir_raw_handler_lock); + return protocols; +} + +/* + * Used to (un)register raw event clients + */ +int ir_raw_event_register(struct rc_dev *dev) +{ + int rc; + struct ir_raw_handler *handler; + + if (!dev) + return -EINVAL; + + dev->raw = kzalloc(sizeof(*dev->raw), GFP_KERNEL); + if (!dev->raw) + return -ENOMEM; + + dev->raw->dev = dev; + dev->raw->enabled_protocols = ~0; + rc = kfifo_alloc(&dev->raw->kfifo, + sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE, + GFP_KERNEL); + if (rc < 0) + goto out; + + spin_lock_init(&dev->raw->lock); + dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw, + "rc%ld", dev->devno); + + if (IS_ERR(dev->raw->thread)) { + rc = PTR_ERR(dev->raw->thread); + goto out; + } + + mutex_lock(&ir_raw_handler_lock); + list_add_tail(&dev->raw->list, &ir_raw_client_list); + list_for_each_entry(handler, &ir_raw_handler_list, list) + if (handler->raw_register) + handler->raw_register(dev); + mutex_unlock(&ir_raw_handler_lock); + + return 0; + +out: + kfree(dev->raw); + dev->raw = NULL; + return rc; +} + +void ir_raw_event_unregister(struct rc_dev *dev) +{ + struct ir_raw_handler *handler; + + if (!dev || !dev->raw) + return; + + kthread_stop(dev->raw->thread); + + mutex_lock(&ir_raw_handler_lock); + list_del(&dev->raw->list); + list_for_each_entry(handler, &ir_raw_handler_list, list) + if (handler->raw_unregister) + handler->raw_unregister(dev); + mutex_unlock(&ir_raw_handler_lock); + + kfifo_free(&dev->raw->kfifo); + kfree(dev->raw); + dev->raw = NULL; +} + +/* + * Extension interface - used to register the IR decoders + */ + +int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) +{ + struct ir_raw_event_ctrl *raw; + + mutex_lock(&ir_raw_handler_lock); + list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); + if (ir_raw_handler->raw_register) + list_for_each_entry(raw, &ir_raw_client_list, list) + ir_raw_handler->raw_register(raw->dev); + available_protocols |= ir_raw_handler->protocols; + mutex_unlock(&ir_raw_handler_lock); + + return 0; +} +EXPORT_SYMBOL(ir_raw_handler_register); + +void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) +{ + struct ir_raw_event_ctrl *raw; + + mutex_lock(&ir_raw_handler_lock); + list_del(&ir_raw_handler->list); + if (ir_raw_handler->raw_unregister) + list_for_each_entry(raw, &ir_raw_client_list, list) + ir_raw_handler->raw_unregister(raw->dev); + available_protocols &= ~ir_raw_handler->protocols; + mutex_unlock(&ir_raw_handler_lock); +} +EXPORT_SYMBOL(ir_raw_handler_unregister); + +#ifdef MODULE +static void init_decoders(struct work_struct *work) +{ + /* Load the decoder modules */ + + load_nec_decode(); + load_rc5_decode(); + load_rc6_decode(); + load_jvc_decode(); + load_sony_decode(); + load_lirc_codec(); + + /* If needed, we may later add some init code. In this case, + it is needed to change the CONFIG_MODULE test at rc-core.h + */ +} +#endif + +void ir_raw_init(void) +{ +#ifdef MODULE + INIT_WORK(&wq_load, init_decoders); + schedule_work(&wq_load); +#endif +} diff --git a/drivers/media/rc/rc-raw.c b/drivers/media/rc/rc-raw.c deleted file mode 100644 index 165412f..0000000 --- a/drivers/media/rc/rc-raw.c +++ /dev/null @@ -1,371 +0,0 @@ -/* ir-raw-event.c - handle IR Pulse/Space event - * - * Copyright (C) 2010 by Mauro Carvalho Chehab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include "rc-core-priv.h" - -/* Define the max number of pulse/space transitions to buffer */ -#define MAX_IR_EVENT_SIZE 512 - -/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */ -static LIST_HEAD(ir_raw_client_list); - -/* Used to handle IR raw handler extensions */ -static DEFINE_MUTEX(ir_raw_handler_lock); -static LIST_HEAD(ir_raw_handler_list); -static u64 available_protocols; - -#ifdef MODULE -/* Used to load the decoders */ -static struct work_struct wq_load; -#endif - -static int ir_raw_event_thread(void *data) -{ - struct ir_raw_event ev; - struct ir_raw_handler *handler; - struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data; - int retval; - - while (!kthread_should_stop()) { - - spin_lock_irq(&raw->lock); - retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev)); - - if (!retval) { - set_current_state(TASK_INTERRUPTIBLE); - - if (kthread_should_stop()) - set_current_state(TASK_RUNNING); - - spin_unlock_irq(&raw->lock); - schedule(); - continue; - } - - spin_unlock_irq(&raw->lock); - - - BUG_ON(retval != sizeof(ev)); - - mutex_lock(&ir_raw_handler_lock); - list_for_each_entry(handler, &ir_raw_handler_list, list) - handler->decode(raw->dev, ev); - raw->prev_ev = ev; - mutex_unlock(&ir_raw_handler_lock); - } - - return 0; -} - -/** - * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders - * @dev: the struct rc_dev device descriptor - * @ev: the struct ir_raw_event descriptor of the pulse/space - * - * This routine (which may be called from an interrupt context) stores a - * pulse/space duration for the raw ir decoding state machines. Pulses are - * signalled as positive values and spaces as negative values. A zero value - * will reset the decoding state machines. - */ -int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev) -{ - if (!dev->raw) - return -EINVAL; - - IR_dprintk(2, "sample: (%05dus %s)\n", - TO_US(ev->duration), TO_STR(ev->pulse)); - - if (kfifo_in(&dev->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) - return -ENOMEM; - - return 0; -} -EXPORT_SYMBOL_GPL(ir_raw_event_store); - -/** - * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space - * @dev: the struct rc_dev device descriptor - * @type: the type of the event that has occurred - * - * This routine (which may be called from an interrupt context) is used to - * store the beginning of an ir pulse or space (or the start/end of ir - * reception) for the raw ir decoding state machines. This is used by - * hardware which does not provide durations directly but only interrupts - * (or similar events) on state change. - */ -int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type) -{ - ktime_t now; - s64 delta; /* ns */ - struct ir_raw_event ev; - int rc = 0; - - if (!dev->raw) - return -EINVAL; - - now = ktime_get(); - delta = ktime_to_ns(ktime_sub(now, dev->raw->last_event)); - - /* Check for a long duration since last event or if we're - * being called for the first time, note that delta can't - * possibly be negative. - */ - ev.duration = 0; - if (delta > IR_MAX_DURATION || !dev->raw->last_type) - type |= IR_START_EVENT; - else - ev.duration = delta; - - if (type & IR_START_EVENT) - ir_raw_event_reset(dev); - else if (dev->raw->last_type & IR_SPACE) { - ev.pulse = false; - rc = ir_raw_event_store(dev, &ev); - } else if (dev->raw->last_type & IR_PULSE) { - ev.pulse = true; - rc = ir_raw_event_store(dev, &ev); - } else - return 0; - - dev->raw->last_event = now; - dev->raw->last_type = type; - return rc; -} -EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); - -/** - * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing - * @dev: the struct rc_dev device descriptor - * @type: the type of the event that has occurred - * - * This routine (which may be called from an interrupt context) works - * in similiar manner to ir_raw_event_store_edge. - * This routine is intended for devices with limited internal buffer - * It automerges samples of same type, and handles timeouts - */ -int ir_raw_event_store_with_filter(struct rc_dev *dev, struct ir_raw_event *ev) -{ - if (!dev->raw) - return -EINVAL; - - /* Ignore spaces in idle mode */ - if (dev->idle && !ev->pulse) - return 0; - else if (dev->idle) - ir_raw_event_set_idle(dev, false); - - if (!dev->raw->this_ev.duration) - dev->raw->this_ev = *ev; - else if (ev->pulse == dev->raw->this_ev.pulse) - dev->raw->this_ev.duration += ev->duration; - else { - ir_raw_event_store(dev, &dev->raw->this_ev); - dev->raw->this_ev = *ev; - } - - /* Enter idle mode if nessesary */ - if (!ev->pulse && dev->timeout && - dev->raw->this_ev.duration >= dev->timeout) - ir_raw_event_set_idle(dev, true); - - return 0; -} -EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter); - -/** - * ir_raw_event_set_idle() - provide hint to rc-core when the device is idle or not - * @dev: the struct rc_dev device descriptor - * @idle: whether the device is idle or not - */ -void ir_raw_event_set_idle(struct rc_dev *dev, bool idle) -{ - if (!dev->raw) - return; - - IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave"); - - if (idle) { - dev->raw->this_ev.timeout = true; - ir_raw_event_store(dev, &dev->raw->this_ev); - init_ir_raw_event(&dev->raw->this_ev); - } - - if (dev->s_idle) - dev->s_idle(dev, idle); - - dev->idle = idle; -} -EXPORT_SYMBOL_GPL(ir_raw_event_set_idle); - -/** - * ir_raw_event_handle() - schedules the decoding of stored ir data - * @dev: the struct rc_dev device descriptor - * - * This routine will tell rc-core to start decoding stored ir data. - */ -void ir_raw_event_handle(struct rc_dev *dev) -{ - unsigned long flags; - - if (!dev->raw) - return; - - spin_lock_irqsave(&dev->raw->lock, flags); - wake_up_process(dev->raw->thread); - spin_unlock_irqrestore(&dev->raw->lock, flags); -} -EXPORT_SYMBOL_GPL(ir_raw_event_handle); - -/* used internally by the sysfs interface */ -u64 -ir_raw_get_allowed_protocols() -{ - u64 protocols; - mutex_lock(&ir_raw_handler_lock); - protocols = available_protocols; - mutex_unlock(&ir_raw_handler_lock); - return protocols; -} - -/* - * Used to (un)register raw event clients - */ -int ir_raw_event_register(struct rc_dev *dev) -{ - int rc; - struct ir_raw_handler *handler; - - if (!dev) - return -EINVAL; - - dev->raw = kzalloc(sizeof(*dev->raw), GFP_KERNEL); - if (!dev->raw) - return -ENOMEM; - - dev->raw->dev = dev; - dev->raw->enabled_protocols = ~0; - rc = kfifo_alloc(&dev->raw->kfifo, - sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE, - GFP_KERNEL); - if (rc < 0) - goto out; - - spin_lock_init(&dev->raw->lock); - dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw, - "rc%ld", dev->devno); - - if (IS_ERR(dev->raw->thread)) { - rc = PTR_ERR(dev->raw->thread); - goto out; - } - - mutex_lock(&ir_raw_handler_lock); - list_add_tail(&dev->raw->list, &ir_raw_client_list); - list_for_each_entry(handler, &ir_raw_handler_list, list) - if (handler->raw_register) - handler->raw_register(dev); - mutex_unlock(&ir_raw_handler_lock); - - return 0; - -out: - kfree(dev->raw); - dev->raw = NULL; - return rc; -} - -void ir_raw_event_unregister(struct rc_dev *dev) -{ - struct ir_raw_handler *handler; - - if (!dev || !dev->raw) - return; - - kthread_stop(dev->raw->thread); - - mutex_lock(&ir_raw_handler_lock); - list_del(&dev->raw->list); - list_for_each_entry(handler, &ir_raw_handler_list, list) - if (handler->raw_unregister) - handler->raw_unregister(dev); - mutex_unlock(&ir_raw_handler_lock); - - kfifo_free(&dev->raw->kfifo); - kfree(dev->raw); - dev->raw = NULL; -} - -/* - * Extension interface - used to register the IR decoders - */ - -int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) -{ - struct ir_raw_event_ctrl *raw; - - mutex_lock(&ir_raw_handler_lock); - list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); - if (ir_raw_handler->raw_register) - list_for_each_entry(raw, &ir_raw_client_list, list) - ir_raw_handler->raw_register(raw->dev); - available_protocols |= ir_raw_handler->protocols; - mutex_unlock(&ir_raw_handler_lock); - - return 0; -} -EXPORT_SYMBOL(ir_raw_handler_register); - -void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) -{ - struct ir_raw_event_ctrl *raw; - - mutex_lock(&ir_raw_handler_lock); - list_del(&ir_raw_handler->list); - if (ir_raw_handler->raw_unregister) - list_for_each_entry(raw, &ir_raw_client_list, list) - ir_raw_handler->raw_unregister(raw->dev); - available_protocols &= ~ir_raw_handler->protocols; - mutex_unlock(&ir_raw_handler_lock); -} -EXPORT_SYMBOL(ir_raw_handler_unregister); - -#ifdef MODULE -static void init_decoders(struct work_struct *work) -{ - /* Load the decoder modules */ - - load_nec_decode(); - load_rc5_decode(); - load_rc6_decode(); - load_jvc_decode(); - load_sony_decode(); - load_lirc_codec(); - - /* If needed, we may later add some init code. In this case, - it is needed to change the CONFIG_MODULE test at rc-core.h - */ -} -#endif - -void ir_raw_init(void) -{ -#ifdef MODULE - INIT_WORK(&wq_load, init_decoders); - schedule_work(&wq_load); -#endif -} -- cgit v0.10.2 From a931910d3be6f63464befb2dde94ec58a6eaf5c1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2010 13:22:37 -0300 Subject: [media] stb6100: warning cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/dvb/frontends/stb6100.c:120: warning: ‘stb6100_normalise_regs’ defined but not used Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/stb6100.c b/drivers/media/dvb/frontends/stb6100.c index db66248..64673b8 100644 --- a/drivers/media/dvb/frontends/stb6100.c +++ b/drivers/media/dvb/frontends/stb6100.c @@ -117,7 +117,10 @@ static const struct stb6100_regmask stb6100_template[] = { [STB6100_TEST3] = { 0x00, 0xde }, }; -static void stb6100_normalise_regs(u8 regs[]) +/* + * Currently unused. Some boards might need it in the future + */ +static inline void stb6100_normalise_regs(u8 regs[]) { int i; -- cgit v0.10.2 From 3751e288bcf3d77652ef979edc0b3ea8b21d8b97 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 16 Nov 2010 11:39:25 -0300 Subject: [media] pwc: do not start isoc stream on /dev/video open pwc was starting streaming on /dev/video# open rather then on STREAM_ON. Now that the v4l1 compat code is removed from the pwc driver there is no reason left to do this. So this patch changes the pwc driver to delay starting the isoc stream (and thus using valuable usb bandwidth) until the application does a STREAM_ON Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c index 6b8fbdd..1593f8d 100644 --- a/drivers/media/video/pwc/pwc-ctrl.c +++ b/drivers/media/video/pwc/pwc-ctrl.c @@ -1386,11 +1386,16 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) { ARG_DEF(int, qual) + if (pdev->iso_init) { + ret = -EBUSY; + break; + } + ARG_IN(qual) if (ARGR(qual) < 0 || ARGR(qual) > 3) ret = -EINVAL; else - ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot); + ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot); if (ret >= 0) pdev->vcompression = ARGR(qual); break; diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index b821065..6f8b682 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -966,36 +966,6 @@ void pwc_isoc_cleanup(struct pwc_device *pdev) PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n"); } -int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot) -{ - int ret, start; - - /* Stop isoc stuff */ - pwc_isoc_cleanup(pdev); - /* Reset parameters */ - pwc_reset_buffers(pdev); - /* Try to set video mode... */ - start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot); - if (ret) { - PWC_DEBUG_FLOW("pwc_set_video_mode attempt 1 failed.\n"); - /* That failed... restore old mode (we know that worked) */ - start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); - if (start) { - PWC_DEBUG_FLOW("pwc_set_video_mode attempt 2 failed.\n"); - } - } - if (start == 0) - { - if (pwc_isoc_init(pdev) < 0) - { - PWC_WARNING("Failed to restart ISOC transfers in pwc_try_video_mode.\n"); - ret = -EAGAIN; /* let's try again, who knows if it works a second time */ - } - } - pdev->drop_frames++; /* try to avoid garbage during switch */ - return ret; /* Return original error code */ -} - /********* * sysfs *********/ @@ -1175,7 +1145,7 @@ static int pwc_video_open(struct file *file) /* Set some defaults */ pdev->vsnapshot = 0; - /* Start iso pipe for video; first try the last used video size + /* Set video size, first try the last used video size (or the default one); if that fails try QCIF/10 or QSIF/10; it that fails too, give up. */ @@ -1202,15 +1172,6 @@ static int pwc_video_open(struct file *file) return i; } - i = pwc_isoc_init(pdev); - if (i) { - PWC_DEBUG_OPEN("Failed to init ISOC stuff = %d.\n", i); - pwc_isoc_cleanup(pdev); - pwc_free_buffers(pdev); - mutex_unlock(&pdev->modlock); - return i; - } - /* Initialize the webcam to sane value */ pwc_set_brightness(pdev, 0x7fff); pwc_set_agc(pdev, 1, 0); @@ -1325,6 +1286,11 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf, goto err_out; } + /* Start the stream (if not already started) */ + rv = pwc_isoc_init(pdev); + if (rv) + goto err_out; + /* In case we're doing partial reads, we don't have to wait for a frame */ if (pdev->image_read_pos == 0) { /* Do wait queueing according to the (doc)book */ @@ -1394,6 +1360,7 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait) { struct video_device *vdev = file->private_data; struct pwc_device *pdev; + int ret; if (vdev == NULL) return -EFAULT; @@ -1401,6 +1368,13 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait) if (pdev == NULL) return -EFAULT; + /* Start the stream (if not already started) */ + mutex_lock(&pdev->modlock); + ret = pwc_isoc_init(pdev); + mutex_unlock(&pdev->modlock); + if (ret) + return ret; + poll_wait(file, &pdev->frameq, wait); if (pdev->error_status) return POLLERR; diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c index 7061a03..2ef1668 100644 --- a/drivers/media/video/pwc/pwc-v4l.c +++ b/drivers/media/video/pwc/pwc-v4l.c @@ -309,7 +309,10 @@ static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f) pixelformat != V4L2_PIX_FMT_PWC2) return -EINVAL; - PWC_DEBUG_IOCTL("Try to change format to: width=%d height=%d fps=%d " + if (pdev->iso_init) + return -EBUSY; + + PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d " "compression=%d snapshot=%d format=%c%c%c%c\n", f->fmt.pix.width, f->fmt.pix.height, fps, compression, snapshot, @@ -318,14 +321,14 @@ static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f) (pixelformat>>16)&255, (pixelformat>>24)&255); - ret = pwc_try_video_mode(pdev, + ret = pwc_set_video_mode(pdev, f->fmt.pix.width, f->fmt.pix.height, fps, compression, snapshot); - PWC_DEBUG_IOCTL("pwc_try_video_mode(), return=%d\n", ret); + PWC_DEBUG_IOCTL("pwc_set_video_mode(), return=%d\n", ret); if (ret) return ret; @@ -882,9 +885,7 @@ long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_STREAMON: { - /* WARNING: pwc_try_video_mode() called pwc_isoc_init */ - pwc_isoc_init(pdev); - return 0; + return pwc_isoc_init(pdev); } case VIDIOC_STREAMOFF: diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h index 36a9c83..16bbc6d 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/video/pwc/pwc.h @@ -275,7 +275,6 @@ extern int pwc_trace; extern int pwc_mbufs; /** functions in pwc-if.c */ -int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot); int pwc_handle_frame(struct pwc_device *pdev); void pwc_next_image(struct pwc_device *pdev); int pwc_isoc_init(struct pwc_device *pdev); -- cgit v0.10.2 From c7d18867c82657a97f0bdb90ba1151b251b6a29b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 16 Nov 2010 12:26:00 -0300 Subject: [media] pwc: Also set alt setting to alt0 when no error occured isoc_cleanup contains a check to not set the altsetting to alt0 when the device was unplugged, but the check currently is buggy, and causes the alt setting to only be set to 0 if an error occured while streaming. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 6f8b682..97319ef 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -957,7 +957,7 @@ void pwc_isoc_cleanup(struct pwc_device *pdev) /* Stop camera, but only if we are sure the camera is still there (unplug is signalled by EPIPE) */ - if (pdev->error_status && pdev->error_status != EPIPE) { + if (pdev->error_status != EPIPE) { PWC_DEBUG_OPEN("Setting alternate interface 0.\n"); usb_set_interface(pdev->udev, 0, 0); } -- cgit v0.10.2 From 622d9f5d302e99dc7a06cb442e9d9ff2bb0f59b5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 16 Nov 2010 12:32:09 -0300 Subject: [media] pwc: failure to submit an urb is a fatal error Failure to submit an urb is a fatal error, make isoc_init return an error when this happens rather then only log it. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 97319ef..bd1519a 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -898,10 +898,13 @@ int pwc_isoc_init(struct pwc_device *pdev) /* link */ for (i = 0; i < MAX_ISO_BUFS; i++) { ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL); - if (ret) + if (ret) { PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret); - else - PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->sbuf[i].urb); + pdev->iso_init = 1; + pwc_isoc_cleanup(pdev); + return ret; + } + PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->sbuf[i].urb); } /* All is done... */ -- cgit v0.10.2 From a29df8579ab2779605b181a38ac7fb99796666df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=83=C2=A4rdeman?= Date: Fri, 19 Nov 2010 20:42:41 -0300 Subject: [media] saa7134: remove unused module parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ir_rc5_remote_gap is a leftover from ir-common, remove it. Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index f3f4aff..4fdc165 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -41,9 +41,6 @@ static int pinnacle_remote; module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */ MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)"); -static int ir_rc5_remote_gap = 885; -module_param(ir_rc5_remote_gap, int, 0644); - static unsigned int disable_other_ir; module_param(disable_other_ir, int, 0644); MODULE_PARM_DESC(disable_other_ir, "disable full codes of " -- cgit v0.10.2 From b0ddb0f364f926785f50a8cea8a399ba63e3c227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=83=C2=A4rdeman?= Date: Fri, 19 Nov 2010 20:42:46 -0300 Subject: [media] saa7134: use full keycode for BeholdTV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the full keycode for BeholdTV hardware makes another module parameter unnecessary. Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/keymaps/rc-behold.c b/drivers/media/rc/keymaps/rc-behold.c index ae4d235..0ee1f14 100644 --- a/drivers/media/rc/keymaps/rc-behold.c +++ b/drivers/media/rc/keymaps/rc-behold.c @@ -29,8 +29,8 @@ static struct rc_map_table behold[] = { /* 0x1c 0x12 * * TV/FM POWER * * */ - { 0x1c, KEY_TUNER }, /* XXX KEY_TV / KEY_RADIO */ - { 0x12, KEY_POWER }, + { 0x6b861c, KEY_TUNER }, /* XXX KEY_TV / KEY_RADIO */ + { 0x6b8612, KEY_POWER }, /* 0x01 0x02 0x03 * * 1 2 3 * @@ -41,28 +41,28 @@ static struct rc_map_table behold[] = { * 0x07 0x08 0x09 * * 7 8 9 * * */ - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, + { 0x6b8601, KEY_1 }, + { 0x6b8602, KEY_2 }, + { 0x6b8603, KEY_3 }, + { 0x6b8604, KEY_4 }, + { 0x6b8605, KEY_5 }, + { 0x6b8606, KEY_6 }, + { 0x6b8607, KEY_7 }, + { 0x6b8608, KEY_8 }, + { 0x6b8609, KEY_9 }, /* 0x0a 0x00 0x17 * * RECALL 0 MODE * * */ - { 0x0a, KEY_AGAIN }, - { 0x00, KEY_0 }, - { 0x17, KEY_MODE }, + { 0x6b860a, KEY_AGAIN }, + { 0x6b8600, KEY_0 }, + { 0x6b8617, KEY_MODE }, /* 0x14 0x10 * * ASPECT FULLSCREEN * * */ - { 0x14, KEY_SCREEN }, - { 0x10, KEY_ZOOM }, + { 0x6b8614, KEY_SCREEN }, + { 0x6b8610, KEY_ZOOM }, /* 0x0b * * Up * @@ -73,17 +73,17 @@ static struct rc_map_table behold[] = { * 0x015 * * Down * * */ - { 0x0b, KEY_CHANNELUP }, - { 0x18, KEY_VOLUMEDOWN }, - { 0x16, KEY_OK }, /* XXX KEY_ENTER */ - { 0x0c, KEY_VOLUMEUP }, - { 0x15, KEY_CHANNELDOWN }, + { 0x6b860b, KEY_CHANNELUP }, + { 0x6b8618, KEY_VOLUMEDOWN }, + { 0x6b8616, KEY_OK }, /* XXX KEY_ENTER */ + { 0x6b860c, KEY_VOLUMEUP }, + { 0x6b8615, KEY_CHANNELDOWN }, /* 0x11 0x0d * * MUTE INFO * * */ - { 0x11, KEY_MUTE }, - { 0x0d, KEY_INFO }, + { 0x6b8611, KEY_MUTE }, + { 0x6b860d, KEY_INFO }, /* 0x0f 0x1b 0x1a * * RECORD PLAY/PAUSE STOP * @@ -92,26 +92,26 @@ static struct rc_map_table behold[] = { *TELETEXT AUDIO SOURCE * * RED YELLOW * * */ - { 0x0f, KEY_RECORD }, - { 0x1b, KEY_PLAYPAUSE }, - { 0x1a, KEY_STOP }, - { 0x0e, KEY_TEXT }, - { 0x1f, KEY_RED }, /*XXX KEY_AUDIO */ - { 0x1e, KEY_YELLOW }, /*XXX KEY_SOURCE */ + { 0x6b860f, KEY_RECORD }, + { 0x6b861b, KEY_PLAYPAUSE }, + { 0x6b861a, KEY_STOP }, + { 0x6b860e, KEY_TEXT }, + { 0x6b861f, KEY_RED }, /*XXX KEY_AUDIO */ + { 0x6b861e, KEY_YELLOW }, /*XXX KEY_SOURCE */ /* 0x1d 0x13 0x19 * * SLEEP PREVIEW DVB * * GREEN BLUE * * */ - { 0x1d, KEY_SLEEP }, - { 0x13, KEY_GREEN }, - { 0x19, KEY_BLUE }, /* XXX KEY_SAT */ + { 0x6b861d, KEY_SLEEP }, + { 0x6b8613, KEY_GREEN }, + { 0x6b8619, KEY_BLUE }, /* XXX KEY_SAT */ /* 0x58 0x5c * * FREEZE SNAPSHOT * * */ - { 0x58, KEY_SLOW }, - { 0x5c, KEY_CAMERA }, + { 0x6b8658, KEY_SLOW }, + { 0x6b865c, KEY_CAMERA }, }; @@ -119,7 +119,7 @@ static struct rc_map_list behold_map = { .map = { .scan = behold, .size = ARRAY_SIZE(behold), - .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_NEC, .name = RC_MAP_BEHOLD, } }; diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 4fdc165..10dc9ad 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -41,11 +41,6 @@ static int pinnacle_remote; module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */ MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)"); -static unsigned int disable_other_ir; -module_param(disable_other_ir, int, 0644); -MODULE_PARM_DESC(disable_other_ir, "disable full codes of " - "alternative remotes from other manufacturers"); - #define dprintk(fmt, arg...) if (ir_debug) \ printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg) #define i2cdprintk(fmt, arg...) if (ir_debug) \ @@ -282,22 +277,12 @@ static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) i2cdprintk("read error\n"); return -EIO; } - /* IR of this card normally decode signals NEC-standard from - * - Sven IHOO MT 5.1R remote. xxyye718 - * - Sven DVD HD-10xx remote. xxyyf708 - * - BBK ... - * - mayby others - * So, skip not our, if disable full codes mode. - */ - if (data[10] != 0x6b && data[11] != 0x86 && disable_other_ir) - return 0; - /* Wrong data decode fix */ if (data[9] != (unsigned char)(~data[8])) return 0; - *ir_key = data[9]; - *ir_raw = data[9]; + *ir_raw = ((data[10] << 16) | (data[11] << 8) | (data[9] << 0)); + *ir_key = *ir_raw; return 1; } -- cgit v0.10.2 From 651c7a5f7f2f7277f8fc4fb38e89c79845ec9bf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=83=C2=A4rdeman?= Date: Fri, 19 Nov 2010 20:42:51 -0300 Subject: [media] saa7134: some minor cleanups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mostly using appropriate data types and constants (e.g. int -> bool). Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 10dc9ad..d75c307 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -407,17 +407,16 @@ static int __saa7134_ir_start(void *priv) struct saa7134_dev *dev = priv; struct saa7134_card_ir *ir; - if (!dev) + if (!dev || !dev->remote) return -EINVAL; ir = dev->remote; - if (!ir) - return -EINVAL; - if (ir->running) return 0; ir->running = true; + ir->active = false; + if (ir->polling) { setup_timer(&ir->timer, saa7134_input_timer, (unsigned long)dev); @@ -425,10 +424,8 @@ static int __saa7134_ir_start(void *priv) add_timer(&ir->timer); } else if (ir->raw_decode) { /* set timer_end for code completion */ - init_timer(&ir->timer_end); - ir->timer_end.function = ir_raw_decode_timer_end; - ir->timer_end.data = (unsigned long)dev; - ir->active = false; + setup_timer(&ir->timer_end, ir_raw_decode_timer_end, + (unsigned long)dev); } return 0; @@ -439,22 +436,19 @@ static void __saa7134_ir_stop(void *priv) struct saa7134_dev *dev = priv; struct saa7134_card_ir *ir; - if (!dev) + if (!dev || !dev->remote) return; ir = dev->remote; - if (!ir) - return; - if (!ir->running) return; - if (dev->remote->polling) - del_timer_sync(&dev->remote->timer); - else if (ir->raw_decode) { + + if (ir->polling) + del_timer_sync(&ir->timer); + else if (ir->raw_decode) del_timer_sync(&ir->timer_end); - ir->active = false; - } + ir->active = false; ir->running = false; return; @@ -499,8 +493,8 @@ int saa7134_input_init1(struct saa7134_dev *dev) u32 mask_keycode = 0; u32 mask_keydown = 0; u32 mask_keyup = 0; - int polling = 0; - int raw_decode = 0; + unsigned polling = 0; + bool raw_decode = false; int err; if (dev->has_remote != SAA7134_REMOTE_GPIO) @@ -565,14 +559,14 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ mask_keyup = 0x0040000; mask_keycode = 0xffff; - raw_decode = 1; + raw_decode = true; break; case SAA7134_BOARD_AVERMEDIA_M733A: ir_codes = RC_MAP_AVERMEDIA_M733A_RM_K6; mask_keydown = 0x0040000; mask_keyup = 0x0040000; mask_keycode = 0xffff; - raw_decode = 1; + raw_decode = true; break; case SAA7134_BOARD_AVERMEDIA_777: case SAA7134_BOARD_AVERMEDIA_A16AR: @@ -679,7 +673,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ mask_keyup = 0x0040000; mask_keycode = 0xffff; - raw_decode = 1; + raw_decode = true; break; case SAA7134_BOARD_ENCORE_ENLTV: case SAA7134_BOARD_ENCORE_ENLTV_FM: @@ -693,7 +687,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ mask_keyup = 0x0040000; mask_keycode = 0xffff; - raw_decode = 1; + raw_decode = true; break; case SAA7134_BOARD_10MOONSTVMASTER3: ir_codes = RC_MAP_ENCORE_ENLTV; @@ -746,8 +740,6 @@ int saa7134_input_init1(struct saa7134_dev *dev) ir->dev = rc; dev->remote = ir; - ir->running = false; - /* init hardware-specific stuff */ ir->mask_keycode = mask_keycode; ir->mask_keydown = mask_keydown; @@ -809,14 +801,12 @@ void saa7134_input_fini(struct saa7134_dev *dev) void saa7134_probe_i2c_ir(struct saa7134_dev *dev) { struct i2c_board_info info; - struct i2c_msg msg_msi = { .addr = 0x50, .flags = I2C_M_RD, .len = 0, .buf = NULL, }; - int rc; if (disable_ir) { @@ -916,8 +906,8 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) static int saa7134_raw_decode_irq(struct saa7134_dev *dev) { - struct saa7134_card_ir *ir = dev->remote; - unsigned long timeout; + struct saa7134_card_ir *ir = dev->remote; + unsigned long timeout; int space; /* Generate initial event */ @@ -926,7 +916,6 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev) space = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; ir_raw_event_store_edge(dev->remote->dev, space ? IR_SPACE : IR_PULSE); - /* * Wait 15 ms from the start of the first IR event before processing * the event. This time is enough for NEC protocol. May need adjustments diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 1923f3c..f93951a 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -124,7 +124,7 @@ struct saa7134_card_ir { char name[32]; char phys[32]; - int users; + unsigned users; u32 polling; u32 last_gpio; @@ -551,7 +551,7 @@ struct saa7134_dev { /* infrared remote */ int has_remote; - struct saa7134_card_ir *remote; + struct saa7134_card_ir *remote; /* pci i/o */ char name[32]; -- cgit v0.10.2 From 7c8352d18ddbe37cff8ad71175a11739662ef899 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=83=C2=A4rdeman?= Date: Fri, 19 Nov 2010 20:42:57 -0300 Subject: [media] saa7134: merge saa7134_card_ir->timer and saa7134_card_ir->timer_end MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both timers are used for a similar purpose. Merging them allows for some minor simplifications. Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index d75c307..98678d9 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -420,11 +420,11 @@ static int __saa7134_ir_start(void *priv) if (ir->polling) { setup_timer(&ir->timer, saa7134_input_timer, (unsigned long)dev); - ir->timer.expires = jiffies + HZ; + ir->timer.expires = jiffies + HZ; add_timer(&ir->timer); } else if (ir->raw_decode) { /* set timer_end for code completion */ - setup_timer(&ir->timer_end, ir_raw_decode_timer_end, + setup_timer(&ir->timer, ir_raw_decode_timer_end, (unsigned long)dev); } @@ -443,10 +443,8 @@ static void __saa7134_ir_stop(void *priv) if (!ir->running) return; - if (ir->polling) + if (ir->polling || ir->raw_decode) del_timer_sync(&ir->timer); - else if (ir->raw_decode) - del_timer_sync(&ir->timer_end); ir->active = false; ir->running = false; @@ -923,7 +921,7 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev) */ if (!ir->active) { timeout = jiffies + jiffies_to_msecs(15); - mod_timer(&ir->timer_end, timeout); + mod_timer(&ir->timer, timeout); ir->active = true; } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index f93951a..babfbe7 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -134,7 +134,6 @@ struct saa7134_card_ir { bool active; struct timer_list timer; - struct timer_list timer_end; /* timer_end for code completion */ /* IR core raw decoding */ u32 raw_decode; -- cgit v0.10.2 From edb4c25ca3a7997660500692eca3510eac9726e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=83=C2=A4rdeman?= Date: Fri, 19 Nov 2010 20:43:12 -0300 Subject: [media] bttv: rename struct card_ir to bttv_ir MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bttv_ir is more consistent with all other structs used in the same driver. Also, clean up the struct to remove commented out members and the work_struct which is unused. [mchehab@redhat.com: fix a warning at bttv_rc5_timer_end] Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 773ee6a..c344b62 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -49,7 +49,7 @@ module_param(ir_rc5_remote_gap, int, 0644); static void ir_handle_key(struct bttv *btv) { - struct card_ir *ir = btv->remote; + struct bttv_ir *ir = btv->remote; u32 gpio,data; /* read gpio value */ @@ -83,7 +83,7 @@ static void ir_handle_key(struct bttv *btv) static void ir_enltv_handle_key(struct bttv *btv) { - struct card_ir *ir = btv->remote; + struct bttv_ir *ir = btv->remote; u32 gpio, data, keyup; /* read gpio value */ @@ -122,7 +122,7 @@ static void ir_enltv_handle_key(struct bttv *btv) void bttv_input_irq(struct bttv *btv) { - struct card_ir *ir = btv->remote; + struct bttv_ir *ir = btv->remote; if (!ir->polling) ir_handle_key(btv); @@ -131,7 +131,7 @@ void bttv_input_irq(struct bttv *btv) static void bttv_input_timer(unsigned long data) { struct bttv *btv = (struct bttv*)data; - struct card_ir *ir = btv->remote; + struct bttv_ir *ir = btv->remote; if (btv->c.type == BTTV_BOARD_ENLTV_FM_2) ir_enltv_handle_key(btv); @@ -185,9 +185,9 @@ static u32 bttv_rc5_decode(unsigned int code) return rc5; } -void bttv_rc5_timer_end(unsigned long data) +static void bttv_rc5_timer_end(unsigned long data) { - struct card_ir *ir = (struct card_ir *)data; + struct bttv_ir *ir = (struct bttv_ir *)data; struct timeval tv; unsigned long current_jiffies; u32 gap; @@ -206,7 +206,7 @@ void bttv_rc5_timer_end(unsigned long data) } /* signal we're ready to start a new code */ - ir->active = 0; + ir->active = false; /* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */ if (gap < 28000) { @@ -242,7 +242,7 @@ void bttv_rc5_timer_end(unsigned long data) static int bttv_rc5_irq(struct bttv *btv) { - struct card_ir *ir = btv->remote; + struct bttv_ir *ir = btv->remote; struct timeval tv; u32 gpio; u32 gap; @@ -278,7 +278,7 @@ static int bttv_rc5_irq(struct bttv *btv) } /* starting new code */ } else { - ir->active = 1; + ir->active = true; ir->code = 0; ir->base_time = tv; ir->last_bit = 0; @@ -295,7 +295,7 @@ static int bttv_rc5_irq(struct bttv *btv) /* ---------------------------------------------------------------------- */ -static void bttv_ir_start(struct bttv *btv, struct card_ir *ir) +static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir) { if (ir->polling) { setup_timer(&ir->timer, bttv_input_timer, (unsigned long)btv); @@ -303,9 +303,8 @@ static void bttv_ir_start(struct bttv *btv, struct card_ir *ir) add_timer(&ir->timer); } else if (ir->rc5_gpio) { /* set timer_end for code completion */ - init_timer(&ir->timer_end); - ir->timer_end.function = bttv_rc5_timer_end; - ir->timer_end.data = (unsigned long)ir; + setup_timer(&ir->timer_end, bttv_rc5_timer_end, + (unsigned long)ir); ir->shift_by = 1; ir->start = 3; ir->addr = 0x0; @@ -409,7 +408,7 @@ int __devexit fini_bttv_i2c(struct bttv *btv) int bttv_input_init(struct bttv *btv) { - struct card_ir *ir; + struct bttv_ir *ir; char *ir_codes = NULL; struct rc_dev *rc; int err = -ENOMEM; diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index b71d04d..3d5b2bc 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -120,15 +120,12 @@ struct bttv_format { int hshift,vshift; /* for planar modes */ }; -struct card_ir { +struct bttv_ir { struct rc_dev *dev; char name[32]; char phys[32]; -#if 0 - int users; - u32 running:1; -#endif + /* Usual gpio signalling */ u32 mask_keycode; u32 mask_keydown; @@ -139,25 +136,15 @@ struct card_ir { int start; // What should RC5_START() be int addr; // What RC5_ADDR() should be. int rc5_remote_gap; - struct work_struct work; struct timer_list timer; /* RC5 gpio */ - u32 rc5_gpio; - struct timer_list timer_end; /* timer_end for code completion */ - u32 last_bit; /* last raw bit seen */ - u32 code; /* raw code under construction */ - struct timeval base_time; /* time of last seen code */ - int active; /* building raw code */ - -#if 0 - /* NEC decoding */ - u32 nec_gpio; - struct tasklet_struct tlet; - - /* IR core raw decoding */ - u32 raw_decode; -#endif + u32 rc5_gpio; + struct timer_list timer_end; /* timer_end for code completion */ + u32 last_bit; /* last raw bit seen */ + u32 code; /* raw code under construction */ + struct timeval base_time; /* time of last seen code */ + bool active; /* building raw code */ }; @@ -408,7 +395,7 @@ struct bttv { /* infrared remote */ int has_remote; - struct card_ir *remote; + struct bttv_ir *remote; /* I2C remote data */ struct IR_i2c_init_data init_data; -- cgit v0.10.2 From 3938e0cfeb812e7b66f4e1cb6e34eb2e6864c6a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=83=C2=A4rdeman?= Date: Fri, 19 Nov 2010 20:43:17 -0300 Subject: [media] bttv: merge ir decoding timers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similarly to saa7134, bttv_ir has two timers, only one of which is used at a time and which serve the same purpose. Merge them. Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index c344b62..989c048 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -283,8 +283,7 @@ static int bttv_rc5_irq(struct bttv *btv) ir->base_time = tv; ir->last_bit = 0; - mod_timer(&ir->timer_end, - current_jiffies + msecs_to_jiffies(30)); + mod_timer(&ir->timer, current_jiffies + msecs_to_jiffies(30)); } /* toggle GPIO pin 4 to reset the irq */ @@ -303,8 +302,7 @@ static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir) add_timer(&ir->timer); } else if (ir->rc5_gpio) { /* set timer_end for code completion */ - setup_timer(&ir->timer_end, bttv_rc5_timer_end, - (unsigned long)ir); + setup_timer(&ir->timer, bttv_rc5_timer_end, (unsigned long)ir); ir->shift_by = 1; ir->start = 3; ir->addr = 0x0; @@ -322,7 +320,7 @@ static void bttv_ir_stop(struct bttv *btv) if (btv->remote->rc5_gpio) { u32 gpio; - del_timer_sync(&btv->remote->timer_end); + del_timer_sync(&btv->remote->timer); flush_scheduled_work(); gpio = bttv_gpio_read(&btv->c); diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index 3d5b2bc..0712320 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -122,6 +122,7 @@ struct bttv_format { struct bttv_ir { struct rc_dev *dev; + struct timer_list timer; char name[32]; char phys[32]; @@ -136,11 +137,9 @@ struct bttv_ir { int start; // What should RC5_START() be int addr; // What RC5_ADDR() should be. int rc5_remote_gap; - struct timer_list timer; /* RC5 gpio */ u32 rc5_gpio; - struct timer_list timer_end; /* timer_end for code completion */ u32 last_bit; /* last raw bit seen */ u32 code; /* raw code under construction */ struct timeval base_time; /* time of last seen code */ -- cgit v0.10.2 From 829ba9fe34246f1f5e813b6bf84171d36e776734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=83=C2=A4rdeman?= Date: Fri, 19 Nov 2010 20:43:27 -0300 Subject: [media] rc-core: fix some leftovers from the renaming patches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix some minor comments etc which are leftover from the old naming scheme. Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c index 165412f..185badd 100644 --- a/drivers/media/rc/ir-raw.c +++ b/drivers/media/rc/ir-raw.c @@ -1,4 +1,4 @@ -/* ir-raw-event.c - handle IR Pulse/Space event +/* ir-raw.c - handle IR pulse/space events * * Copyright (C) 2010 by Mauro Carvalho Chehab * diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index 48065b7..873b387 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h @@ -13,8 +13,8 @@ * GNU General Public License for more details. */ -#ifndef _IR_RAW_EVENT -#define _IR_RAW_EVENT +#ifndef _RC_CORE_PRIV +#define _RC_CORE_PRIV #include #include @@ -190,4 +190,4 @@ void ir_raw_init(void); #endif -#endif /* _IR_RAW_EVENT */ +#endif /* _RC_CORE_PRIV */ diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 0b0524c..6bdd0d3 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -1,4 +1,4 @@ -/* rc-core.c - handle IR scancode->keycode tables +/* rc-main.c - Remote Controller core module * * Copyright (C) 2009-2010 by Mauro Carvalho Chehab * diff --git a/include/media/rc-core.h b/include/media/rc-core.h index affb93f..a23c1fc 100644 --- a/include/media/rc-core.h +++ b/include/media/rc-core.h @@ -206,12 +206,12 @@ static inline u32 ir_extract_bits(u32 data, u32 mask) u32 vbit = 1, value = 0; do { - if (mask & 1) { - if (data & 1) - value |= vbit; - vbit <<= 1; - } - data >>= 1; + if (mask & 1) { + if (data & 1) + value |= vbit; + vbit <<= 1; + } + data >>= 1; } while (mask >>= 1); return value; -- cgit v0.10.2 From 0e835087dfe7db19f1f072046f5e116d4ec6662b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 17 Nov 2010 02:13:39 -0300 Subject: [media] lirc_dev: add some __user annotations Sparse complains because there are no __user annotations. drivers/media/rc/lirc_dev.c:156:27: warning: incorrect type in initializer (incompatible argument 2 (different address spaces)) drivers/media/rc/lirc_dev.c:156:27: expected int ( *read )( ... ) drivers/media/rc/lirc_dev.c:156:27: got int ( extern [toplevel] * )( ... ) Signed-off-by: Dan Carpenter Acked-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 756656e..6b9fc74 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -627,7 +627,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) EXPORT_SYMBOL(lirc_dev_fop_ioctl); ssize_t lirc_dev_fop_read(struct file *file, - char *buffer, + char __user *buffer, size_t length, loff_t *ppos) { @@ -747,7 +747,7 @@ void *lirc_get_pdata(struct file *file) EXPORT_SYMBOL(lirc_get_pdata); -ssize_t lirc_dev_fop_write(struct file *file, const char *buffer, +ssize_t lirc_dev_fop_write(struct file *file, const char __user *buffer, size_t length, loff_t *ppos) { struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h index 54780a5..630e702 100644 --- a/include/media/lirc_dev.h +++ b/include/media/lirc_dev.h @@ -217,9 +217,9 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file); int lirc_dev_fop_close(struct inode *inode, struct file *file); unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait); long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -ssize_t lirc_dev_fop_read(struct file *file, char *buffer, size_t length, +ssize_t lirc_dev_fop_read(struct file *file, char __user *buffer, size_t length, loff_t *ppos); -ssize_t lirc_dev_fop_write(struct file *file, const char *buffer, size_t length, - loff_t *ppos); +ssize_t lirc_dev_fop_write(struct file *file, const char __user *buffer, + size_t length, loff_t *ppos); #endif -- cgit v0.10.2 From eac8ae087ac66b21de94fee3e920210b43d43076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Bia=C5=82o=C5=84czyk?= Date: Mon, 15 Nov 2010 15:50:13 -0300 Subject: [media] Fix rc-tbs-nec table after converting the cx88 driver to ir-core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The patch fixes the rc-tbs-nec table after converting drivers/media/video/cx88 to ir-core (commit ba7e90c9f878e0ac3c0614a5446fe5c62ccc33ec). It is also adds two missing buttons (10- and 10+) with its definition (KEY_10CHANNELSUP and KEY_10CHANNELSDOWN). [mchehab@redhat.com: move keycode numbers to 0x1b8/0x1b9 as requested by the input Maintainer] Signed-off-by: Mariusz BiaÅ‚oÅ„czyk Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/keymaps/rc-tbs-nec.c b/drivers/media/rc/keymaps/rc-tbs-nec.c index 15b9a9b..7242ee6 100644 --- a/drivers/media/rc/keymaps/rc-tbs-nec.c +++ b/drivers/media/rc/keymaps/rc-tbs-nec.c @@ -13,38 +13,40 @@ #include static struct rc_map_table tbs_nec[] = { - { 0x04, KEY_POWER2}, /*power*/ - { 0x14, KEY_MUTE}, /*mute*/ - { 0x07, KEY_1}, - { 0x06, KEY_2}, - { 0x05, KEY_3}, - { 0x0b, KEY_4}, - { 0x0a, KEY_5}, - { 0x09, KEY_6}, - { 0x0f, KEY_7}, - { 0x0e, KEY_8}, - { 0x0d, KEY_9}, - { 0x12, KEY_0}, - { 0x16, KEY_CHANNELUP}, /*ch+*/ - { 0x11, KEY_CHANNELDOWN},/*ch-*/ - { 0x13, KEY_VOLUMEUP}, /*vol+*/ - { 0x0c, KEY_VOLUMEDOWN},/*vol-*/ - { 0x03, KEY_RECORD}, /*rec*/ - { 0x18, KEY_PAUSE}, /*pause*/ - { 0x19, KEY_OK}, /*ok*/ - { 0x1a, KEY_CAMERA}, /* snapshot */ - { 0x01, KEY_UP}, - { 0x10, KEY_LEFT}, - { 0x02, KEY_RIGHT}, - { 0x08, KEY_DOWN}, - { 0x15, KEY_FAVORITES}, - { 0x17, KEY_SUBTITLE}, - { 0x1d, KEY_ZOOM}, - { 0x1f, KEY_EXIT}, - { 0x1e, KEY_MENU}, - { 0x1c, KEY_EPG}, - { 0x00, KEY_PREVIOUS}, - { 0x1b, KEY_MODE}, + { 0x84, KEY_POWER2}, /* power */ + { 0x94, KEY_MUTE}, /* mute */ + { 0x87, KEY_1}, + { 0x86, KEY_2}, + { 0x85, KEY_3}, + { 0x8b, KEY_4}, + { 0x8a, KEY_5}, + { 0x89, KEY_6}, + { 0x8f, KEY_7}, + { 0x8e, KEY_8}, + { 0x8d, KEY_9}, + { 0x92, KEY_0}, + { 0xc0, KEY_10CHANNELSUP}, /* 10+ */ + { 0xd0, KEY_10CHANNELSDOWN}, /* 10- */ + { 0x96, KEY_CHANNELUP}, /* ch+ */ + { 0x91, KEY_CHANNELDOWN}, /* ch- */ + { 0x93, KEY_VOLUMEUP}, /* vol+ */ + { 0x8c, KEY_VOLUMEDOWN}, /* vol- */ + { 0x83, KEY_RECORD}, /* rec */ + { 0x98, KEY_PAUSE}, /* pause, yellow */ + { 0x99, KEY_OK}, /* ok */ + { 0x9a, KEY_CAMERA}, /* snapshot */ + { 0x81, KEY_UP}, + { 0x90, KEY_LEFT}, + { 0x82, KEY_RIGHT}, + { 0x88, KEY_DOWN}, + { 0x95, KEY_FAVORITES}, /* blue */ + { 0x97, KEY_SUBTITLE}, /* green */ + { 0x9d, KEY_ZOOM}, + { 0x9f, KEY_EXIT}, + { 0x9e, KEY_MENU}, + { 0x9c, KEY_EPG}, + { 0x80, KEY_PREVIOUS}, /* red */ + { 0x9b, KEY_MODE}, }; static struct rc_map_list tbs_nec_map = { diff --git a/include/linux/input.h b/include/linux/input.h index 9777668..f7a6e19 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -590,6 +590,8 @@ struct input_keymap_entry { #define KEY_FRAMEFORWARD 0x1b5 #define KEY_CONTEXT_MENU 0x1b6 /* GenDesc - system context menu */ #define KEY_MEDIA_REPEAT 0x1b7 /* Consumer - transport control */ +#define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */ +#define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */ #define KEY_DEL_EOL 0x1c0 #define KEY_DEL_EOS 0x1c1 -- cgit v0.10.2 From 97108cf682566a79ad49f165435bddbb91844d9a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Nov 2010 15:50:51 -0300 Subject: [media] Fix parameter description for disable_ir It seems that a wrong cut-and-paste error were done here. Reported-by: Jeremy Kerr Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 9b9e169..7e0ee10 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -47,7 +47,7 @@ MODULE_PARM_DESC(latency,"pci latency timer"); static int disable_ir; module_param(disable_ir, int, 0444); -MODULE_PARM_DESC(latency, "Disable IR support"); +MODULE_PARM_DESC(disable_ir, "Disable IR support"); #define info_printk(core, fmt, arg...) \ printk(KERN_INFO "%s: " fmt, core->name , ## arg) -- cgit v0.10.2 From a363436396ad68509db4513c886055cc067a184c Mon Sep 17 00:00:00 2001 From: Alexey Chernov <4ernov@gmail.com> Date: Thu, 28 Oct 2010 18:12:02 -0300 Subject: [media] Patch for cx18 module with added support of GoTView PCI DVD3 Hybrid tuner I've got code which adds support of GoTView PCI DVD3 Hybrid tuner in cx18 module and Andy Walls in ivtv mailing-list gave me some advice on making a patch and sending it here. So here's the patch against staging/2.6.37-rc1 branch (the tutorial recommends to include it as plain text but if it's the case I can surely send as an attachment): Several comments on the patch: 1. Both users on the official Gotview forum and support said that PCI DVD3 is very similar to Yuan MPC718 card so the main part of code is taken from Yuan configuration. Some users reported it to work properly. 2. Everything is being initialized correctly including analog, dvb, radio and alsa parts. Analogue part and alsa virtual card is tested by myself using original Gotview card. [mchehab@redhat.com: Whitespace cleanups] Signed-off-by: Alexey Chernov <4ernov@gmail.com> Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index fe10909..52ba913 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -39,7 +39,7 @@ static struct cx18_card_tuner_i2c cx18_i2c_std = { .tv = { 0x61, 0x60, I2C_CLIENT_END }, }; -/* Please add new PCI IDs to: http://pci-ids.ucw.cz/ +/* Please add new PCI IDs to: http://pci-ids.ucw.cz/ This keeps the PCI ID database up to date. Note that the entries must be added under vendor 0x4444 (Conexant) as subsystem IDs. New vendor IDs should still be added to the vendor ID list. */ @@ -251,6 +251,66 @@ static const struct cx18_card cx18_card_mpc718 = { /* ------------------------------------------------------------------------- */ +/* GoTView PCI */ + +static const struct cx18_card_pci_info cx18_pci_gotview_dvd3[] = { + { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_GOTVIEW, 0x3343 }, + { 0, 0, 0 } +}; + +static const struct cx18_card cx18_card_gotview_dvd3 = { + .type = CX18_CARD_GOTVIEW_PCI_DVD3, + .name = "GoTView PCI DVD3 Hybrid", + .comment = "Experimenters needed for device to work well.\n" + "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", + .v4l2_capabilities = CX18_CAP_ENCODER, + .hw_audio_ctrl = CX18_HW_418_AV, + .hw_muxer = CX18_HW_GPIO_MUX, + .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER | + CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL, + .video_inputs = { + { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, + { CX18_CARD_INPUT_SVIDEO1, 1, + CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, + { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 }, + { CX18_CARD_INPUT_SVIDEO2, 2, + CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 }, + { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 }, + }, + .audio_inputs = { + { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, + { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 }, + { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL2, 1 }, + }, + .tuners = { + /* XC3028 tuner */ + { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, + }, + /* FIXME - the FM radio is just a guess and driver doesn't use SIF */ + .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 }, + .ddr = { + /* Hynix HY5DU283222B DDR RAM */ + .chip_config = 0x303, + .refresh = 0x3bd, + .timing1 = 0x36320966, + .timing2 = 0x1f, + .tune_lane = 0, + .initial_emrs = 2, + }, + .gpio_init.initial_value = 0x1, + .gpio_init.direction = 0x3, + + .gpio_audio_input = { .mask = 0x3, + .tuner = 0x1, + .linein = 0x2, + .radio = 0x1 }, + .xceive_pin = 0, + .pci_list = cx18_pci_gotview_dvd3, + .i2c = &cx18_i2c_std, +}; + +/* ------------------------------------------------------------------------- */ + /* Conexant Raptor PAL/SECAM: note that this card is analog only! */ static const struct cx18_card_pci_info cx18_pci_cnxt_raptor_pal[] = { @@ -463,6 +523,7 @@ static const struct cx18_card *cx18_card_list[] = { &cx18_card_toshiba_qosmio_dvbt, &cx18_card_leadtek_pvr2100, &cx18_card_leadtek_dvr3100h, + &cx18_card_gotview_dvd3 }; const struct cx18_card *cx18_get_card(u16 index) diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index df60f27..98ac2e9 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -156,6 +156,7 @@ MODULE_PARM_DESC(cardtype, "\t\t\t 6 = Toshiba Qosmio DVB-T/Analog\n" "\t\t\t 7 = Leadtek WinFast PVR2100\n" "\t\t\t 8 = Leadtek WinFast DVR3100 H\n" + "\t\t\t 9 = GoTView PCI DVD3 Hybrid\n" "\t\t\t 0 = Autodetect (default)\n" "\t\t\t-1 = Ignore this card\n\t\t"); MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60"); @@ -333,6 +334,7 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv) tveeprom_hauppauge_analog(&c, tv, eedata); break; case CX18_CARD_YUAN_MPC718: + case CX18_CARD_GOTVIEW_PCI_DVD3: tv->model = 0x718; cx18_eeprom_dump(cx, eedata, sizeof(eedata)); CX18_INFO("eeprom PCI ID: %02x%02x:%02x%02x\n", diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 77be58c..cf4f20e 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -84,7 +84,8 @@ #define CX18_CARD_TOSHIBA_QOSMIO_DVBT 5 /* Toshiba Qosmio Interal DVB-T/Analog*/ #define CX18_CARD_LEADTEK_PVR2100 6 /* Leadtek WinFast PVR2100 */ #define CX18_CARD_LEADTEK_DVR3100H 7 /* Leadtek WinFast DVR3100 H */ -#define CX18_CARD_LAST 7 +#define CX18_CARD_GOTVIEW_PCI_DVD3 8 /* GoTView PCI DVD3 Hybrid */ +#define CX18_CARD_LAST 8 #define CX18_ENC_STREAM_TYPE_MPG 0 #define CX18_ENC_STREAM_TYPE_TS 1 @@ -106,6 +107,7 @@ #define CX18_PCI_ID_CONEXANT 0x14f1 #define CX18_PCI_ID_TOSHIBA 0x1179 #define CX18_PCI_ID_LEADTEK 0x107D +#define CX18_PCI_ID_GOTVIEW 0x5854 /* ======================================================================== */ /* ========================== START USER SETTABLE DMA VARIABLES =========== */ diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 6d19f04..c7f0bad 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c @@ -203,6 +203,14 @@ static struct zl10353_config yuan_mpc718_zl10353_demod = { .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ }; +static struct zl10353_config gotview_dvd3_zl10353_demod = { + .demod_address = 0x1e >> 1, /* Datasheet suggested straps */ + .if2 = 45600, /* 4.560 MHz IF from the XC3028 */ + .parallel_ts = 1, /* Not a serial TS */ + .no_tuner = 1, /* XC3028 is not behind the gate */ + .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ +}; + static int dvb_register(struct cx18_stream *stream); /* Kernel DVB framework calls this when the feed needs to start. @@ -247,6 +255,7 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) case CX18_CARD_LEADTEK_DVR3100H: case CX18_CARD_YUAN_MPC718: + case CX18_CARD_GOTVIEW_PCI_DVD3: default: /* Assumption - Parallel transport - Signalling * undefined or default. @@ -495,6 +504,29 @@ static int dvb_register(struct cx18_stream *stream) fe->ops.tuner_ops.set_config(fe, &ctrl); } break; + case CX18_CARD_GOTVIEW_PCI_DVD3: + dvb->fe = dvb_attach(zl10353_attach, + &gotview_dvd3_zl10353_demod, + &cx->i2c_adap[1]); + if (dvb->fe != NULL) { + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &cx->i2c_adap[1], + .i2c_addr = 0xc2 >> 1, + .ctrl = NULL, + }; + static struct xc2028_ctrl ctrl = { + .fname = XC2028_DEFAULT_FIRMWARE, + .max_len = 64, + .demod = XC3028_FE_ZARLINK456, + .type = XC2028_AUTO, + }; + + fe = dvb_attach(xc2028_attach, dvb->fe, &cfg); + if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) + fe->ops.tuner_ops.set_config(fe, &ctrl); + } + break; default: /* No Digital Tv Support */ break; -- cgit v0.10.2 From b1dc614a81258eb7ff482892e7bc894f1089c144 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 15 Nov 2010 00:04:28 -0300 Subject: [media] drivers/media/video: Remove unnecessary semicolons Signed-off-by: Joe Perches Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index d7c9484..bca307e 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1064,7 +1064,7 @@ static int mpeg_open(struct file *file) err = drv->request_acquire(drv); if(err != 0) { dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err); - mutex_unlock(&dev->core->lock);; + mutex_unlock(&dev->core->lock); return err; } } diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 7333a9b..353eada 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -1276,7 +1276,7 @@ static int vpfe_videobuf_prepare(struct videobuf_queue *vq, vb->size = vpfe_dev->fmt.fmt.pix.sizeimage; vb->field = field; - ret = videobuf_iolock(vq, vb, NULL);; + ret = videobuf_iolock(vq, vb, NULL); if (ret < 0) return ret; diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 24caa851..ed25c55 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -2438,7 +2438,7 @@ void em28xx_register_i2c_ir(struct em28xx *dev) dev->init_data.get_key = em28xx_get_key_em_haup; dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: - dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE;; + dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE; dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe; dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)"; break; -- cgit v0.10.2 From ecfc95eb7410c04c23f59b02931e8f8b3aa4a5b3 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 15 Nov 2010 17:13:54 -0300 Subject: [media] ngene-core.c: Remove unnecessary casts of pci_get_drvdata Signed-off-by: Joe Perches Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index c7809f7..be71f91 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -1515,7 +1515,7 @@ static int init_channels(struct ngene *dev) void __devexit ngene_remove(struct pci_dev *pdev) { - struct ngene *dev = (struct ngene *)pci_get_drvdata(pdev); + struct ngene *dev = pci_get_drvdata(pdev); int i; tasklet_kill(&dev->event_tasklet); -- cgit v0.10.2 From 5df465df7bd9c352289ca63d4d9f78299be72c7d Mon Sep 17 00:00:00 2001 From: Nicolas Kaiser Date: Fri, 19 Nov 2010 17:42:40 -0300 Subject: [media] drivers/media: nuvoton: fix chip id probe v2 Make sure we have a matching chip id high and one or the other of the chip id low values. Print the values if the probe fails. Signed-off-by: Nicolas Kaiser Acked-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 7fca6d1..dd4caf8 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -248,9 +248,12 @@ static int nvt_hw_detect(struct nvt_dev *nvt) chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO); nvt_dbg("%s: chip id: 0x%02x 0x%02x", chip_id, chip_major, chip_minor); - if (chip_major != CHIP_ID_HIGH && - (chip_minor != CHIP_ID_LOW || chip_minor != CHIP_ID_LOW2)) + if (chip_major != CHIP_ID_HIGH || + (chip_minor != CHIP_ID_LOW && chip_minor != CHIP_ID_LOW2)) { + nvt_pr(KERN_ERR, "%s: unsupported chip, id: 0x%02x 0x%02x", + chip_id, chip_major, chip_minor); ret = -ENODEV; + } nvt_efm_disable(nvt); -- cgit v0.10.2 From 5ad1a55542dd69d2c6aa7db5ca79073d693bbfed Mon Sep 17 00:00:00 2001 From: Paul Bender Date: Wed, 17 Nov 2010 16:56:17 -0300 Subject: [media] rc: fix sysfs entry for mceusb and streamzap When trying to create persistent device names for mceusb and streamzap devices, I noticed that their respective drivers are not creating the rc device as a child of the USB device. Rather it creates it as virtual device. As a result, udev cannot use the USB device information to create persistent device names for event and lirc devices associated with the rc device. Not having persistent device names makes it more difficult to make use of the devices in userspace as their names can change. Forward-ported to media_tree staging/for_v2.6.38 and tested with both streamzap and mceusb devices: $ ll /dev/input/by-id/ ... lrwxrwxrwx. 1 root root 9 Nov 17 17:06 usb-Streamzap__Inc._Streamzap_Remote_Control-event-if00 -> ../event6 lrwxrwxrwx. 1 root root 9 Nov 17 17:05 usb-Topseed_Technology_Corp._eHome_Infrared_Transceiver_TS000BzY-event-if00 -> ../event5 Previously, nada. Signed-off-by: Paul Bender Tested-by: Jarod Wilson Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index c2cb58a..0fef6ef 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -1047,7 +1047,7 @@ static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir) snprintf(ir->name, sizeof(ir->name), "%s (%04x:%04x)", mceusb_model[ir->model].name ? - mceusb_model[ir->model].name : + mceusb_model[ir->model].name : "Media Center Ed. eHome Infrared Remote Transceiver", le16_to_cpu(ir->usbdev->descriptor.idVendor), le16_to_cpu(ir->usbdev->descriptor.idProduct)); diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c index 7814ec7..7f82f55 100644 --- a/drivers/media/rc/streamzap.c +++ b/drivers/media/rc/streamzap.c @@ -316,6 +316,8 @@ static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz) rdev->input_name = sz->name; rdev->input_phys = sz->phys; + usb_to_input_id(sz->usbdev, &rdev->input_id); + rdev->dev.parent = dev; rdev->priv = sz; rdev->driver_type = RC_DRIVER_IR_RAW; rdev->allowed_protos = RC_TYPE_ALL; -- cgit v0.10.2 From 5ae094cea1b4f3715ee6ea4f49d0b36d564f90e7 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 18 Nov 2010 00:56:37 -0300 Subject: [media] cx231xx: stray unlock on error path The lock isn't held here and doesn't need to be unlocked. The code has been like this since the driver was merged. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 2b61017..6175650 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c @@ -784,7 +784,7 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, retval = cx231xx_register_analog_devices(dev); if (retval < 0) { cx231xx_release_resources(dev); - goto fail_reg_devices; + return retval; } cx231xx_ir_init(dev); @@ -792,10 +792,6 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, cx231xx_init_extension(dev); return 0; - -fail_reg_devices: - mutex_unlock(&dev->lock); - return retval; } #if defined(CONFIG_MODULES) && defined(MODULE) -- cgit v0.10.2 From b7c7a4bed8d695933ae172031556de9de30ae598 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 28 Nov 2010 11:48:26 -0300 Subject: [media] bttv: remove custom_irq and gpioq from bttv struct The RC5 old decoder used custom_irq to indicate the need of handling the IRQ on a different way. Instead of doing it, let the core just call the bttv input IRQ handler, and add the code there to call the legacy decoder. While here, remove the gpioq waitqueue, as this is not used anywhere, and add a debug msg to help removing the legacy RC5 code. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 0902ec0..54fbab9 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -4041,9 +4041,6 @@ static irqreturn_t bttv_irq(int irq, void *dev_id) btv=(struct bttv *)dev_id; - if (btv->custom_irq) - handled = btv->custom_irq(btv); - count=0; while (1) { /* get/clear interrupt status bits */ @@ -4079,7 +4076,6 @@ static irqreturn_t bttv_irq(int irq, void *dev_id) btv->field_count++; if ((astat & BT848_INT_GPINT) && btv->remote) { - wake_up(&btv->gpioq); bttv_input_irq(btv); } @@ -4284,7 +4280,6 @@ static int __devinit bttv_probe(struct pci_dev *dev, mutex_init(&btv->lock); spin_lock_init(&btv->s_lock); spin_lock_init(&btv->gpio_lock); - init_waitqueue_head(&btv->gpioq); init_waitqueue_head(&btv->i2c_queue); INIT_LIST_HEAD(&btv->c.subs); INIT_LIST_HEAD(&btv->capture); @@ -4472,7 +4467,6 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev) /* tell gpio modules we are leaving ... */ btv->shutdown=1; - wake_up(&btv->gpioq); bttv_input_fini(btv); bttv_sub_del_devices(&btv->c); diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 989c048..7f48306 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -120,11 +120,15 @@ static void ir_enltv_handle_key(struct bttv *btv) ir->last_gpio = data | keyup; } +static int bttv_rc5_irq(struct bttv *btv); + void bttv_input_irq(struct bttv *btv) { struct bttv_ir *ir = btv->remote; - if (!ir->polling) + if (ir->rc5_gpio) + bttv_rc5_irq(btv); + else if (!ir->polling) ir_handle_key(btv); } @@ -251,10 +255,6 @@ static int bttv_rc5_irq(struct bttv *btv) /* read gpio port */ gpio = bttv_gpio_read(&btv->c); - /* remote IRQ? */ - if (!(gpio & 0x20)) - return 0; - /* get time of bit */ current_jiffies = jiffies; do_gettimeofday(&tv); @@ -267,6 +267,13 @@ static int bttv_rc5_irq(struct bttv *btv) tv.tv_usec - ir->base_time.tv_usec; } + dprintk(KERN_INFO DEVNAME ": RC5 IRQ: gap %d us for %s\n", + gap, (gpio & 0x20) ? "mark" : "space"); + + /* remote IRQ? */ + if (!(gpio & 0x20)) + return 0; + /* active code => add bit */ if (ir->active) { /* only if in the code (otherwise spurious IRQ or timer @@ -479,8 +486,7 @@ int bttv_input_init(struct bttv *btv) break; case BTTV_BOARD_NEBULA_DIGITV: ir_codes = RC_MAP_NEBULA; - btv->custom_irq = bttv_rc5_irq; - ir->rc5_gpio = 1; + ir->rc5_gpio = true; break; case BTTV_BOARD_MACHTV_MAGICTV: ir_codes = RC_MAP_APAC_VIEWCOMP; diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index 0712320..9b776fa 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -139,7 +139,7 @@ struct bttv_ir { int rc5_remote_gap; /* RC5 gpio */ - u32 rc5_gpio; + bool rc5_gpio; /* Is RC5 legacy GPIO enabled? */ u32 last_bit; /* last raw bit seen */ u32 code; /* raw code under construction */ struct timeval base_time; /* time of last seen code */ @@ -364,12 +364,10 @@ struct bttv { struct bttv_pll_info pll; int triton1; int gpioirq; - int (*custom_irq)(struct bttv *btv); int use_i2c_hw; /* old gpio interface */ - wait_queue_head_t gpioq; int shutdown; void (*volume_gpio)(struct bttv *btv, __u16 volume); -- cgit v0.10.2 From dea8a39fb569c23084c857ccdbf70a95ea3bf7dc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 29 Nov 2010 07:46:13 -0300 Subject: [media] rc-core: Initialize return value to zero At ir_setkeycode, if INPUT_KEYMAP_BY_INDEX is used, the routine may return an invalid value if not error. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 6bdd0d3..72be8a0 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -325,7 +325,7 @@ static int ir_setkeycode(struct input_dev *idev, struct rc_map *rc_map = &rdev->rc_map; unsigned int index; unsigned int scancode; - int retval; + int retval = 0; unsigned long flags; spin_lock_irqsave(&rc_map->lock, flags); -- cgit v0.10.2 From 801c73c04ad57689dc9b47baf62cbb23f954d987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Thu, 25 Nov 2010 18:36:27 -0300 Subject: [media] rc-core: add loopback driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds a loopback driver to rc-core which I've found useful for running scripted tests of different parts of rc-core without having to fiddle with real hardware. Basically it emulates hardware with a learning and a non-learning receiver and two transmitters (which correspond to the two receivers). TX data that is sent is fed back as input on the corresponding receiver, which allows for debugging of IR decoders, keymaps, etc. Signed-off-by: David Härdeman Acked-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 42b4feb..3785162 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -177,4 +177,17 @@ config IR_WINBOND_CIR To compile this driver as a module, choose M here: the module will be called winbond_cir. +config RC_LOOPBACK + tristate "Remote Control Loopback Driver" + depends on RC_CORE + ---help--- + Say Y here if you want support for the remote control loopback + driver which allows TX data to be sent back as RX data. + This is mostly useful for debugging purposes. + + If you're not sure, select N here. + + To compile this driver as a module, choose M here: the module will + be called rc_loopback. + endif #RC_CORE diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 78ac8c5..67b4f7f 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -19,3 +19,4 @@ obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o obj-$(CONFIG_IR_ENE) += ene_ir.o obj-$(CONFIG_IR_STREAMZAP) += streamzap.o obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o +obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c new file mode 100644 index 0000000..49cee61 --- /dev/null +++ b/drivers/media/rc/rc-loopback.c @@ -0,0 +1,260 @@ +/* + * Loopback driver for rc-core, + * + * Copyright (c) 2010 David Härdeman + * + * This driver receives TX data and passes it back as RX data, + * which is useful for (scripted) debugging of rc-core without + * having to use actual hardware. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include + +#define DRIVER_NAME "rc-loopback" +#define dprintk(x...) if (debug) printk(KERN_INFO DRIVER_NAME ": " x) +#define RXMASK_REGULAR 0x1 +#define RXMASK_LEARNING 0x2 + +static bool debug; + +struct loopback_dev { + struct rc_dev *dev; + u32 txmask; + u32 txcarrier; + u32 txduty; + bool idle; + bool learning; + bool carrierreport; + u32 rxcarriermin; + u32 rxcarriermax; +}; + +static struct loopback_dev loopdev; + +static int loop_set_tx_mask(struct rc_dev *dev, u32 mask) +{ + struct loopback_dev *lodev = dev->priv; + + if ((mask & (RXMASK_REGULAR | RXMASK_LEARNING)) != mask) { + dprintk("invalid tx mask: %u\n", mask); + return -EINVAL; + } + + dprintk("setting tx mask: %u\n", mask); + lodev->txmask = mask; + return 0; +} + +static int loop_set_tx_carrier(struct rc_dev *dev, u32 carrier) +{ + struct loopback_dev *lodev = dev->priv; + + dprintk("setting tx carrier: %u\n", carrier); + lodev->txcarrier = carrier; + return 0; +} + +static int loop_set_tx_duty_cycle(struct rc_dev *dev, u32 duty_cycle) +{ + struct loopback_dev *lodev = dev->priv; + + if (duty_cycle < 1 || duty_cycle > 99) { + dprintk("invalid duty cycle: %u\n", duty_cycle); + return -EINVAL; + } + + dprintk("setting duty cycle: %u\n", duty_cycle); + lodev->txduty = duty_cycle; + return 0; +} + +static int loop_set_rx_carrier_range(struct rc_dev *dev, u32 min, u32 max) +{ + struct loopback_dev *lodev = dev->priv; + + if (min < 1 || min > max) { + dprintk("invalid rx carrier range %u to %u\n", min, max); + return -EINVAL; + } + + dprintk("setting rx carrier range %u to %u\n", min, max); + lodev->rxcarriermin = min; + lodev->rxcarriermax = max; + return 0; +} + +static int loop_tx_ir(struct rc_dev *dev, int *txbuf, u32 n) +{ + struct loopback_dev *lodev = dev->priv; + u32 rxmask; + unsigned count; + unsigned total_duration = 0; + unsigned i; + DEFINE_IR_RAW_EVENT(rawir); + + if (n == 0 || n % sizeof(int)) { + dprintk("invalid tx buffer size\n"); + return -EINVAL; + } + + count = n / sizeof(int); + for (i = 0; i < count; i++) + total_duration += abs(txbuf[i]); + + if (total_duration == 0) { + dprintk("invalid tx data, total duration zero\n"); + return -EINVAL; + } + + if (lodev->txcarrier < lodev->rxcarriermin || + lodev->txcarrier > lodev->rxcarriermax) { + dprintk("ignoring tx, carrier out of range\n"); + goto out; + } + + if (lodev->learning) + rxmask = RXMASK_LEARNING; + else + rxmask = RXMASK_REGULAR; + + if (!(rxmask & lodev->txmask)) { + dprintk("ignoring tx, rx mask mismatch\n"); + goto out; + } + + for (i = 0; i < count; i++) { + rawir.pulse = i % 2 ? false : true; + rawir.duration = abs(txbuf[i]) * 1000; + if (rawir.duration) + ir_raw_event_store_with_filter(dev, &rawir); + } + ir_raw_event_handle(dev); + +out: + /* Lirc expects this function to take as long as the total duration */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(usecs_to_jiffies(total_duration)); + return n; +} + +static void loop_set_idle(struct rc_dev *dev, bool enable) +{ + struct loopback_dev *lodev = dev->priv; + + if (lodev->idle != enable) { + dprintk("%sing idle mode\n", enable ? "enter" : "exit"); + lodev->idle = enable; + } +} + +static int loop_set_learning_mode(struct rc_dev *dev, int enable) +{ + struct loopback_dev *lodev = dev->priv; + + if (lodev->learning != enable) { + dprintk("%sing learning mode\n", enable ? "enter" : "exit"); + lodev->learning = !!enable; + } + + return 0; +} + +static int loop_set_carrier_report(struct rc_dev *dev, int enable) +{ + struct loopback_dev *lodev = dev->priv; + + if (lodev->carrierreport != enable) { + dprintk("%sabling carrier reports\n", enable ? "en" : "dis"); + lodev->carrierreport = !!enable; + } + + return 0; +} + +static int __init loop_init(void) +{ + struct rc_dev *rc; + int ret; + + rc = rc_allocate_device(); + if (!rc) { + printk(KERN_ERR DRIVER_NAME ": rc_dev allocation failed\n"); + return -ENOMEM; + } + + rc->input_name = "rc-core loopback device"; + rc->input_phys = "rc-core/virtual"; + rc->input_id.bustype = BUS_VIRTUAL; + rc->input_id.version = 1; + rc->driver_name = DRIVER_NAME; + rc->map_name = RC_MAP_EMPTY; + rc->priv = &loopdev; + rc->driver_type = RC_DRIVER_IR_RAW; + rc->allowed_protos = RC_TYPE_ALL; + rc->timeout = 100 * 1000 * 1000; /* 100 ms */ + rc->min_timeout = 1; + rc->max_timeout = UINT_MAX; + rc->rx_resolution = 1000; + rc->tx_resolution = 1000; + rc->s_tx_mask = loop_set_tx_mask; + rc->s_tx_carrier = loop_set_tx_carrier; + rc->s_tx_duty_cycle = loop_set_tx_duty_cycle; + rc->s_rx_carrier_range = loop_set_rx_carrier_range; + rc->tx_ir = loop_tx_ir; + rc->s_idle = loop_set_idle; + rc->s_learning_mode = loop_set_learning_mode; + rc->s_carrier_report = loop_set_carrier_report; + rc->priv = &loopdev; + + loopdev.txmask = RXMASK_REGULAR; + loopdev.txcarrier = 36000; + loopdev.txduty = 50; + loopdev.rxcarriermin = 1; + loopdev.rxcarriermax = ~0; + loopdev.idle = true; + loopdev.learning = false; + loopdev.carrierreport = false; + + ret = rc_register_device(rc); + if (ret < 0) { + printk(KERN_ERR DRIVER_NAME ": rc_dev registration failed\n"); + rc_free_device(rc); + return ret; + } + + loopdev.dev = rc; + return 0; +} + +static void __exit loop_exit(void) +{ + rc_unregister_device(loopdev.dev); +} + +module_init(loop_init); +module_exit(loop_exit); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable debug messages"); + +MODULE_DESCRIPTION("Loopback device for rc-core debugging"); +MODULE_AUTHOR("David Härdeman "); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From b395cbac36e58a55729fe7e6262a3f0b1691bced Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Fri, 26 Nov 2010 14:06:41 -0300 Subject: [media] media: rc: lirc_dev: check kobject_set_name() result kobject_set_name() may fail with -ENOMEM, check for it. Signed-off-by: Vasiliy Kulikov Acked-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 6b9fc74..fd237ab 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -178,7 +178,9 @@ static int lirc_cdev_add(struct irctl *ir) cdev_init(cdev, &lirc_dev_fops); cdev->owner = THIS_MODULE; } - kobject_set_name(&cdev->kobj, "lirc%d", d->minor); + retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor); + if (retval) + return retval; retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1); if (retval) -- cgit v0.10.2 From 9124544320bd36d5aa21769d17a5781ba729aebf Mon Sep 17 00:00:00 2001 From: Philippe Bourdin Date: Sun, 31 Oct 2010 09:57:58 -0300 Subject: [media] Terratec Cinergy Hybrid T USB XS I found that the problems people have reported with the USB-TV-stick "Terratec Cinergy Hybrid T USB XS" (USB-ID: 0ccd:0042) are coming from a wrong header file in the v4l-sources. Attached is a diff, which fixes the problem (tested successfully here). Obviously the USB-ID has been associated with a wrong chip: EM2880 instead of EM2882, which would be correct. Reported-by: Philippe Bourdin Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index ed25c55..5d79d0e 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -1496,7 +1496,7 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2882_BOARD_TERRATEC_HYBRID_XS] = { - .name = "Terratec Hybrid XS (em2882)", + .name = "Terratec Cinnergy Hybrid T USB XS (em2882)", .tuner_type = TUNER_XC2028, .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, @@ -1820,7 +1820,7 @@ struct usb_device_id em28xx_id_table[] = { { USB_DEVICE(0x0ccd, 0x005e), .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS }, { USB_DEVICE(0x0ccd, 0x0042), - .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS }, + .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS }, { USB_DEVICE(0x0ccd, 0x0043), .driver_info = EM2870_BOARD_TERRATEC_XS }, { USB_DEVICE(0x0ccd, 0x0047), -- cgit v0.10.2 From 8350e1551c27ee784ded579fd224846972d4b0d3 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 30 Nov 2010 18:42:07 -0300 Subject: [media] media: Remove unnecessary casts of usb_get_intfdata Signed-off-by: Joe Perches Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c index 50d4338..0b8da57 100644 --- a/drivers/media/dvb/siano/smsusb.c +++ b/drivers/media/dvb/siano/smsusb.c @@ -288,8 +288,7 @@ static int smsusb1_setmode(void *context, int mode) static void smsusb_term_device(struct usb_interface *intf) { - struct smsusb_device_t *dev = - (struct smsusb_device_t *) usb_get_intfdata(intf); + struct smsusb_device_t *dev = usb_get_intfdata(intf); if (dev) { smsusb_stop_streaming(dev); @@ -445,8 +444,7 @@ static void smsusb_disconnect(struct usb_interface *intf) static int smsusb_suspend(struct usb_interface *intf, pm_message_t msg) { - struct smsusb_device_t *dev = - (struct smsusb_device_t *)usb_get_intfdata(intf); + struct smsusb_device_t *dev = usb_get_intfdata(intf); printk(KERN_INFO "%s: Entering status %d.\n", __func__, msg.event); smsusb_stop_streaming(dev); return 0; @@ -455,8 +453,7 @@ static int smsusb_suspend(struct usb_interface *intf, pm_message_t msg) static int smsusb_resume(struct usb_interface *intf) { int rc, i; - struct smsusb_device_t *dev = - (struct smsusb_device_t *)usb_get_intfdata(intf); + struct smsusb_device_t *dev = usb_get_intfdata(intf); struct usb_device *udev = interface_to_usbdev(intf); printk(KERN_INFO "%s: Entering.\n", __func__); diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index de9dc0e..6811512 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -2274,7 +2274,7 @@ static int __devinit imon_probe(struct usb_interface *interface, mutex_lock(&driver_lock); first_if = usb_ifnum_to_if(usbdev, 0); - first_if_ctx = (struct imon_context *)usb_get_intfdata(first_if); + first_if_ctx = usb_get_intfdata(first_if); if (ifnum == 0) { ictx = imon_init_intf0(interface); -- cgit v0.10.2 From dd89aec47325a251eeaf39ee4b84adb521270cba Mon Sep 17 00:00:00 2001 From: Richard Zidlicky Date: Wed, 1 Dec 2010 20:52:49 -0300 Subject: [media] keycodes for DSR-0112 remote bundled with Haupauge MiniStick Add kycodes for DSR-0112 remote that comes together with Haupauge MiniStick http://lirc.sourceforge.net/remotes/hauppauge/DSR-0112.jpg [mchehab@redhat.com: Fix KEY_PREVIOUS to match the definition for the other model] Signed-off-by: Richard Zidlicky Acked-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c b/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c index df534b0..dfc9b15 100644 --- a/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c +++ b/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c @@ -75,6 +75,44 @@ static struct rc_map_table rc5_hauppauge_new[] = { { 0x1e3b, KEY_SELECT }, /* top right button */ { 0x1e3c, KEY_ZOOM }, /* full */ { 0x1e3d, KEY_POWER }, /* system power (green button) */ + + /* Keycodes for DSR-0112 remote bundled with Haupauge MiniStick */ + { 0x1d00, KEY_0 }, + { 0x1d01, KEY_1 }, + { 0x1d02, KEY_2 }, + { 0x1d03, KEY_3 }, + { 0x1d04, KEY_4 }, + { 0x1d05, KEY_5 }, + { 0x1d06, KEY_6 }, + { 0x1d07, KEY_7 }, + { 0x1d08, KEY_8 }, + { 0x1d09, KEY_9 }, + { 0x1d0a, KEY_TEXT }, + { 0x1d0d, KEY_MENU }, + { 0x1d0f, KEY_MUTE }, + { 0x1d10, KEY_VOLUMEUP }, + { 0x1d11, KEY_VOLUMEDOWN }, + { 0x1d12, KEY_PREVIOUS }, /* Prev.Ch .. ??? */ + { 0x1d14, KEY_UP }, + { 0x1d15, KEY_DOWN }, + { 0x1d16, KEY_LEFT }, + { 0x1d17, KEY_RIGHT }, + { 0x1d1c, KEY_TV }, + { 0x1d1e, KEY_NEXT }, /* >| */ + { 0x1d1f, KEY_EXIT }, + { 0x1d20, KEY_CHANNELUP }, + { 0x1d21, KEY_CHANNELDOWN }, + { 0x1d24, KEY_LAST }, /* <| */ + { 0x1d25, KEY_OK }, + { 0x1d30, KEY_PAUSE }, + { 0x1d32, KEY_REWIND }, + { 0x1d34, KEY_FASTFORWARD }, + { 0x1d35, KEY_PLAY }, + { 0x1d36, KEY_STOP }, + { 0x1d37, KEY_RECORD }, + { 0x1d3b, KEY_GOTO }, + { 0x1d3d, KEY_POWER }, + { 0x1d3f, KEY_HOME }, }; static struct rc_map_list rc5_hauppauge_new_map = { -- cgit v0.10.2 From e78567d227ecd40543508342ba39a3dfba5af14f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 6 Dec 2010 06:53:05 -0300 Subject: [media] gspca/sn9c20x: Test if sensor is a OV sensor Instead of just assuming a ov9650 sensor based on USB ID, double-check it, by reading the sensor ID. Acked-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 6b155ae..1e0f219 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -1224,8 +1224,17 @@ static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) static int ov9650_init_sensor(struct gspca_dev *gspca_dev) { int i; + u16 id; struct sd *sd = (struct sd *) gspca_dev; + if (i2c_r2(gspca_dev, 0x1c, &id) < 0) + return -EINVAL; + + if (id != 0x7fa2) { + err("sensor id for ov9650 doesn't match (0x%04x)", id); + return -ENODEV; + } + for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) { if (i2c_w1(gspca_dev, ov9650_init[i].reg, ov9650_init[i].val) < 0) { -- cgit v0.10.2 From 86701c1d6a3ecae2f0e6771c730364d334d5a142 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 7 Dec 2010 14:47:10 -0300 Subject: [media] gspca/sn9c20x: Get rid of scale "magic" numbers Use macros for the supported scales, instead of using magic numbers from 0 to 3. Code become cleaner by using macros for it. Acked-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 1e0f219..e812598 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -33,6 +33,14 @@ MODULE_LICENSE("GPL"); #define MODULE_NAME "sn9c20x" +/* + * Pixel format private data + */ +#define SCALE_MASK 0x0f +#define SCALE_160x120 0 +#define SCALE_320x240 1 +#define SCALE_640x480 2 +#define SCALE_1280x1024 3 #define MODE_RAW 0x10 #define MODE_JPEG 0x20 #define MODE_SXGA 0x80 @@ -348,47 +356,47 @@ static const struct v4l2_pix_format vga_mode[] = { .bytesperline = 160, .sizeimage = 160 * 120 * 4 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0 | MODE_JPEG}, + .priv = SCALE_160x120 | MODE_JPEG}, {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 | MODE_RAW}, + .priv = SCALE_160x120 | MODE_RAW}, {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 240 * 120, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, + .priv = SCALE_160x120}, {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1 | MODE_JPEG}, + .priv = SCALE_320x240 | MODE_JPEG}, {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 , .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 | MODE_RAW}, + .priv = SCALE_320x240 | MODE_RAW}, {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 480 * 240 , .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, + .priv = SCALE_320x240}, {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2 | MODE_JPEG}, + .priv = SCALE_640x480 | MODE_JPEG}, {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2 | MODE_RAW}, + .priv = SCALE_640x480 | MODE_RAW}, {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 960 * 480, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2}, + .priv = SCALE_640x480}, }; static const struct v4l2_pix_format sxga_mode[] = { @@ -396,52 +404,52 @@ static const struct v4l2_pix_format sxga_mode[] = { .bytesperline = 160, .sizeimage = 160 * 120 * 4 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0 | MODE_JPEG}, + .priv = SCALE_160x120 | MODE_JPEG}, {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 | MODE_RAW}, + .priv = SCALE_160x120 | MODE_RAW}, {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 240 * 120, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, + .priv = SCALE_160x120}, {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1 | MODE_JPEG}, + .priv = SCALE_320x240 | MODE_JPEG}, {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 , .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 | MODE_RAW}, + .priv = SCALE_320x240 | MODE_RAW}, {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 480 * 240 , .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, + .priv = SCALE_320x240}, {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2 | MODE_JPEG}, + .priv = SCALE_640x480 | MODE_JPEG}, {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2 | MODE_RAW}, + .priv = SCALE_640x480 | MODE_RAW}, {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 960 * 480, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2}, + .priv = SCALE_640x480}, {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 1280, .sizeimage = 1280 * 1024, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 3 | MODE_RAW | MODE_SXGA}, + .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA}, }; static const s16 hsv_red_x[] = { @@ -2182,22 +2190,22 @@ static int sd_start(struct gspca_dev *gspca_dev) else if (mode & MODE_JPEG) fmt = 0x2c; else - fmt = 0x2f; + fmt = 0x2f; /* YUV 420 */ - switch (mode & 0x0f) { - case 3: + switch (mode & SCALE_MASK) { + case SCALE_1280x1024: scale = 0xc0; info("Set 1280x1024"); break; - case 2: + case SCALE_640x480: scale = 0x80; info("Set 640x480"); break; - case 1: + case SCALE_320x240: scale = 0x90; info("Set 320x240"); break; - case 0: + case SCALE_160x120: scale = 0xa0; info("Set 160x120"); break; -- cgit v0.10.2 From d4b416f26279bbbe07faaff1c9cd19d6b3709b2e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 7 Dec 2010 17:19:09 -0300 Subject: [media] gspca core: Fix regressions gspca breaking devices with audio Changeset 35680ba broke several devices: - Sony Playstation Eye (1415:2000); - Gigaware model 25-234 (0c45:628f); - Logitech Messenger Plus (046d:08f6). Probably more devices were broken by this change. What happens is that several devices don't need to save some bandwidth for audio. Also, as pointed by Hans de Goede , the logic that implements the bandwidth reservation for audio is broken, since it will reduce the alt number twice, on devices with audio. So, let's just revert the broken logic, and think on a better solution for usb 1.1 devices with audio that can't use the maximum packetsize. Acked-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 0a7af73..5a2274b 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -652,16 +652,12 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) : USB_ENDPOINT_XFER_ISOC; i = gspca_dev->alt; /* previous alt setting */ if (gspca_dev->cam.reverse_alts) { - if (gspca_dev->audio && i < gspca_dev->nbalt - 2) - i++; while (++i < gspca_dev->nbalt) { ep = alt_xfer(&intf->altsetting[i], xfer); if (ep) break; } } else { - if (gspca_dev->audio && i > 1) - i--; while (--i >= 0) { ep = alt_xfer(&intf->altsetting[i], xfer); if (ep) -- cgit v0.10.2 From d162e7aac24bfd8b96881582368f976e7e464c25 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 7 Dec 2010 19:39:33 -0300 Subject: [media] gspca/sn9c20x: Fix support for mt9m001 (mi1300) sensor Support for mt9m001 (mi1300) is broken: - Table is incomplete; - Only one resolution is currently supported by the driver; - Resolution is incomplete; - it complains about broken JPEG headers. Use the same init found on em28xx driver, and properly report the output format as 8-bits GRAY. Acked-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index e812598..cb08d00 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -452,6 +452,29 @@ static const struct v4l2_pix_format sxga_mode[] = { .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA}, }; +static const struct v4l2_pix_format mono_mode[] = { + {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, + .bytesperline = 160, + .sizeimage = 160 * 120, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = SCALE_160x120 | MODE_RAW}, + {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 , + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = SCALE_320x240 | MODE_RAW}, + {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = SCALE_640x480 | MODE_RAW}, + {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, + .bytesperline = 1280, + .sizeimage = 1280 * 1024, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA}, +}; + static const s16 hsv_red_x[] = { 41, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, @@ -1037,16 +1060,19 @@ static struct i2c_reg_u16 mt9v011_init[] = { }; static struct i2c_reg_u16 mt9m001_init[] = { - {0x0d, 0x0001}, {0x0d, 0x0000}, {0x01, 0x000e}, - {0x02, 0x0014}, {0x03, 0x03c1}, {0x04, 0x0501}, - {0x05, 0x0083}, {0x06, 0x0006}, {0x0d, 0x0002}, - {0x0a, 0x0000}, {0x0c, 0x0000}, {0x11, 0x0000}, - {0x1e, 0x8000}, {0x5f, 0x8904}, {0x60, 0x0000}, - {0x61, 0x0000}, {0x62, 0x0498}, {0x63, 0x0000}, - {0x64, 0x0000}, {0x20, 0x111d}, {0x06, 0x00f2}, - {0x05, 0x0013}, {0x09, 0x10f2}, {0x07, 0x0003}, - {0x2b, 0x002a}, {0x2d, 0x002a}, {0x2c, 0x002a}, - {0x2e, 0x0029}, {0x07, 0x0002}, + {0x0d, 0x0001}, + {0x0d, 0x0000}, + {0x04, 0x0500}, /* hres = 1280 */ + {0x03, 0x0400}, /* vres = 1024 */ + {0x20, 0x1100}, + {0x06, 0x0010}, + {0x2b, 0x0024}, + {0x2e, 0x0024}, + {0x35, 0x0024}, + {0x2d, 0x0020}, + {0x2c, 0x0020}, + {0x09, 0x0ad4}, + {0x35, 0x0057}, }; static struct i2c_reg_u16 mt9m111_init[] = { @@ -1442,6 +1468,25 @@ static int mt9m001_init_sensor(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i; + u16 id; + + if (i2c_r2(gspca_dev, 0x00, &id) < 0) + return -EINVAL; + + /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ + switch (id) { + case 0x8411: + case 0x8421: + info("MT9M001 color sensor detected"); + break; + case 0x8431: + info("MT9M001 mono sensor detected"); + break; + default: + err("No MT9M001 chip detected, ID = %x\n", id); + return -ENODEV; + } + for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) { if (i2c_w2(gspca_dev, mt9m001_init[i].reg, mt9m001_init[i].val) < 0) { @@ -1451,8 +1496,8 @@ static int mt9m001_init_sensor(struct gspca_dev *gspca_dev) } /* disable hflip and vflip */ gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); - sd->hstart = 2; - sd->vstart = 2; + sd->hstart = 1; + sd->vstart = 1; return 0; } @@ -1994,6 +2039,10 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = sxga_mode; cam->nmodes = ARRAY_SIZE(sxga_mode); break; + case SENSOR_MT9M001: + cam->cam_mode = mono_mode; + cam->nmodes = ARRAY_SIZE(mono_mode); + break; default: cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); @@ -2092,7 +2141,6 @@ static int sd_init(struct gspca_dev *gspca_dev) case SENSOR_MT9M001: if (mt9m001_init_sensor(gspca_dev) < 0) return -ENODEV; - info("MT9M001 sensor detected"); break; case SENSOR_HV7131R: if (hv7131r_init_sensor(gspca_dev) < 0) -- cgit v0.10.2 From 49aefd2bcda80d33497f0f26702c67e372cacef3 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 22 Nov 2010 23:35:17 -0300 Subject: [media] timblogiw: const and __devinitdata do not mix This fixes the following error in PowerPC builds: drivers/media/video/timblogiw.c: In function 'timblogiw_probe': drivers/media/video/timblogiw.c:749: error: timblogiw_ioctl_ops causes a section type conflict Signed-off-by: Stephen Rothwell Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/timblogiw.c b/drivers/media/video/timblogiw.c index bddcdb6..cf48aa9 100644 --- a/drivers/media/video/timblogiw.c +++ b/drivers/media/video/timblogiw.c @@ -746,7 +746,7 @@ static int timblogiw_mmap(struct file *file, struct vm_area_struct *vma) /* Platform device functions */ -static const __devinitdata struct v4l2_ioctl_ops timblogiw_ioctl_ops = { +static __devinitconst struct v4l2_ioctl_ops timblogiw_ioctl_ops = { .vidioc_querycap = timblogiw_querycap, .vidioc_enum_fmt_vid_cap = timblogiw_enum_fmt, .vidioc_g_fmt_vid_cap = timblogiw_g_fmt, @@ -768,7 +768,7 @@ static const __devinitdata struct v4l2_ioctl_ops timblogiw_ioctl_ops = { .vidioc_enum_framesizes = timblogiw_enum_framesizes, }; -static const __devinitdata struct v4l2_file_operations timblogiw_fops = { +static __devinitconst struct v4l2_file_operations timblogiw_fops = { .owner = THIS_MODULE, .open = timblogiw_open, .release = timblogiw_close, @@ -778,7 +778,7 @@ static const __devinitdata struct v4l2_file_operations timblogiw_fops = { .poll = timblogiw_poll, }; -static const __devinitdata struct video_device timblogiw_template = { +static __devinitconst struct video_device timblogiw_template = { .name = TIMBLOGIWIN_NAME, .fops = &timblogiw_fops, .ioctl_ops = &timblogiw_ioctl_ops, -- cgit v0.10.2 From e330289ed40f76819d6a13e682203c6fc9a86304 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 17 Dec 2010 14:22:09 -0300 Subject: [media] cx231xx: Fix inverted bits for RC on PV Hybrid At Pixelview SBTVD Hybrid, the bits sent by the IR are inverted. Due to that, the existing keytables produce wrong codes. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c index c236a4e..45e14ca 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/video/cx231xx/cx231xx-input.c @@ -27,7 +27,7 @@ static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { - u8 cmd; + u8 cmd, scancode; dev_dbg(&ir->rc->input_dev->dev, "%s\n", __func__); @@ -42,10 +42,21 @@ static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key, if (cmd == 0xff) return 0; - dev_dbg(&ir->rc->input_dev->dev, "scancode = %02x\n", cmd); - - *ir_key = cmd; - *ir_raw = cmd; + scancode = + ((cmd & 0x01) ? 0x80 : 0) | + ((cmd & 0x02) ? 0x40 : 0) | + ((cmd & 0x04) ? 0x20 : 0) | + ((cmd & 0x08) ? 0x10 : 0) | + ((cmd & 0x10) ? 0x08 : 0) | + ((cmd & 0x20) ? 0x04 : 0) | + ((cmd & 0x40) ? 0x02 : 0) | + ((cmd & 0x80) ? 0x01 : 0); + + dev_dbg(&ir->rc->input_dev->dev, "cmd %02x, scan = %02x\n", + cmd, scancode); + + *ir_key = scancode; + *ir_raw = scancode; return 1; } -- cgit v0.10.2 From 12007419b766b316998499bd07c6586928230729 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 17 Dec 2010 14:39:29 -0300 Subject: [media] Add a keymap for Pixelview 002-T remote Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index 3194d39..148900f 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -62,6 +62,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-pinnacle-pctv-hd.o \ rc-pixelview.o \ rc-pixelview-mk12.o \ + rc-pixelview-002t.o \ rc-pixelview-new.o \ rc-powercolor-real-angel.o \ rc-proteus-2309.o \ diff --git a/drivers/media/rc/keymaps/rc-pixelview-002t.c b/drivers/media/rc/keymaps/rc-pixelview-002t.c new file mode 100644 index 0000000..e5ab071 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-pixelview-002t.c @@ -0,0 +1,77 @@ +/* rc-pixelview-mk12.h - Keytable for pixelview Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * Keytable for 002-T IR remote provided together with Pixelview + * SBTVD Hybrid Remote Controller. Uses NEC extended format. + */ +static struct rc_map_table pixelview_002t[] = { + { 0x866b13, KEY_MUTE }, + { 0x866b12, KEY_POWER2 }, /* power */ + + { 0x866b01, KEY_1 }, + { 0x866b02, KEY_2 }, + { 0x866b03, KEY_3 }, + { 0x866b04, KEY_4 }, + { 0x866b05, KEY_5 }, + { 0x866b06, KEY_6 }, + { 0x866b07, KEY_7 }, + { 0x866b08, KEY_8 }, + { 0x866b09, KEY_9 }, + { 0x866b00, KEY_0 }, + + { 0x866b0d, KEY_CHANNELUP }, + { 0x866b19, KEY_CHANNELDOWN }, + { 0x866b10, KEY_VOLUMEUP }, /* vol + */ + { 0x866b0c, KEY_VOLUMEDOWN }, /* vol - */ + + { 0x866b0a, KEY_CAMERA }, /* snapshot */ + { 0x866b0b, KEY_ZOOM }, /* zoom */ + + { 0x866b1b, KEY_BACKSPACE }, + { 0x866b15, KEY_ENTER }, + + { 0x866b1d, KEY_UP }, + { 0x866b1e, KEY_DOWN }, + { 0x866b0e, KEY_LEFT }, + { 0x866b0f, KEY_RIGHT }, + + { 0x866b18, KEY_RECORD }, + { 0x866b1a, KEY_STOP }, +}; + +static struct rc_map_list pixelview_map = { + .map = { + .scan = pixelview_002t, + .size = ARRAY_SIZE(pixelview_002t), + .rc_type = RC_TYPE_NEC, + .name = RC_MAP_PIXELVIEW_002T, + } +}; + +static int __init init_rc_map_pixelview(void) +{ + return rc_map_register(&pixelview_map); +} + +static void __exit exit_rc_map_pixelview(void) +{ + rc_map_unregister(&pixelview_map); +} + +module_init(init_rc_map_pixelview) +module_exit(exit_rc_map_pixelview) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/include/media/rc-map.h b/include/media/rc-map.h index 1a3d51d..5d3a457 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -119,6 +119,7 @@ void rc_map_init(void); #define RC_MAP_PINNACLE_PCTV_HD "rc-pinnacle-pctv-hd" #define RC_MAP_PIXELVIEW_NEW "rc-pixelview-new" #define RC_MAP_PIXELVIEW "rc-pixelview" +#define RC_MAP_PIXELVIEW_002T "rc-pixelview-002t" #define RC_MAP_PIXELVIEW_MK12 "rc-pixelview-mk12" #define RC_MAP_POWERCOLOR_REAL_ANGEL "rc-powercolor-real-angel" #define RC_MAP_PROTEUS_2309 "rc-proteus-2309" -- cgit v0.10.2 From 788e5d4dc825ffc2eb863272d9a57fb93490dd92 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 17 Dec 2010 14:47:27 -0300 Subject: [media] cx231xx: Fix IR keymap for Pixelview SBTVD Hybrid Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 6175650..6905607 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c @@ -412,7 +412,7 @@ struct cx231xx_board cx231xx_boards[] = { .tuner_i2c_master = 2, .demod_i2c_master = 1, .ir_i2c_master = 2, - .rc_map_name = RC_MAP_PIXELVIEW_NEW, + .rc_map_name = RC_MAP_PIXELVIEW_002T, .has_dvb = 1, .demod_addr = 0x10, .norm = V4L2_STD_PAL_M, -- cgit v0.10.2 From d6746d55da0819edbe913a1447b1ab0e7b440241 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 10 Dec 2010 12:28:15 -0300 Subject: [media] gspca_sonixb: Make sonixb handle 0c45:6007 instead of sn9c102 I've a 0c45:6007 camera and it works fine with the gspca_sonixb driver, so make that handle it instead of the deprecated sn9c102 driver. Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 11b1972..bfbd8c1 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -1431,9 +1431,7 @@ static const struct sd_desc sd_desc = { static const struct usb_device_id device_table[] __devinitconst = { {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */ {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */ -#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */ -#endif {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)}, {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)}, {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)}, diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index ccfa59c..aba6d68 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -43,9 +43,7 @@ static const struct usb_device_id sn9c102_id_table[] = { #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), }, -#endif { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), }, -#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), }, /* { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */ -- cgit v0.10.2 From 2b3e284a89dfa53eb42b6470e4c03e5ddfdb24c5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 12 Dec 2010 08:55:04 -0300 Subject: [media] gspca_sonixb: Rewrite start of frame detection Our old start of frame detection code wrongly assumes that the sof marker always lives at the beginning of the frame. At least for the 0c45:602a camera this is not the case. This patch also improves the framerate from 28 fps to 30 fps with the 0c45:6005 and 0c45:6007 Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index bfbd8c1..f47a829 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -56,6 +56,8 @@ struct sd { int prev_avg_lum; int exp_too_low_cnt; int exp_too_high_cnt; + int header_read; + u8 header[12]; /* Header without sof marker */ unsigned short exposure; unsigned char gain; @@ -1177,13 +1179,10 @@ static void sd_stopN(struct gspca_dev *gspca_dev) sd_init(gspca_dev); } -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ +static u8* find_sof(struct gspca_dev *gspca_dev, u8 *data, int len) { - int i; struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam = &gspca_dev->cam; + int i, header_size = (sd->bridge == BRIDGE_103) ? 18 : 12; /* frames start with: * ff ff 00 c4 c4 96 synchro @@ -1194,58 +1193,84 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, * ll mm brightness sum outside auto exposure * (xx xx xx xx xx) audio values for snc103 */ - if (len > 6 && len < 24) { - for (i = 0; i < len - 6; i++) { - if (data[0 + i] == 0xff - && data[1 + i] == 0xff - && data[2 + i] == 0x00 - && data[3 + i] == 0xc4 - && data[4 + i] == 0xc4 - && data[5 + i] == 0x96) { /* start of frame */ - int lum = -1; - int pkt_type = LAST_PACKET; - int fr_h_sz = (sd->bridge == BRIDGE_103) ? - 18 : 12; - - if (len - i < fr_h_sz) { - PDEBUG(D_STREAM, "packet too short to" - " get avg brightness"); - } else if (sd->bridge == BRIDGE_103) { - lum = data[i + 9] + - (data[i + 10] << 8); - } else { - lum = data[i + 8] + (data[i + 9] << 8); - } - /* When exposure changes midway a frame we - get a lum of 0 in this case drop 2 frames - as the frames directly after an exposure - change have an unstable image. Sometimes lum - *really* is 0 (cam used in low light with - low exposure setting), so do not drop frames - if the previous lum was 0 too. */ - if (lum == 0 && sd->prev_avg_lum != 0) { - lum = -1; - sd->frames_to_drop = 2; - sd->prev_avg_lum = 0; - } else - sd->prev_avg_lum = lum; - atomic_set(&sd->avg_lum, lum); - - if (sd->frames_to_drop) { - sd->frames_to_drop--; - pkt_type = DISCARD_PACKET; - } - - gspca_frame_add(gspca_dev, pkt_type, - NULL, 0); - data += i + fr_h_sz; - len -= i + fr_h_sz; - gspca_frame_add(gspca_dev, FIRST_PACKET, - data, len); - return; + for (i = 0; i < len; i++) { + switch (sd->header_read) { + case 0: + if (data[i] == 0xff) + sd->header_read++; + break; + case 1: + if (data[i] == 0xff) + sd->header_read++; + else + sd->header_read = 0; + break; + case 2: + if (data[i] == 0x00) + sd->header_read++; + else if (data[i] != 0xff) + sd->header_read = 0; + break; + case 3: + if (data[i] == 0xc4) + sd->header_read++; + else if (data[i] == 0xff) + sd->header_read = 1; + else + sd->header_read = 0; + break; + case 4: + if (data[i] == 0xc4) + sd->header_read++; + else if (data[i] == 0xff) + sd->header_read = 1; + else + sd->header_read = 0; + break; + case 5: + if (data[i] == 0x96) + sd->header_read++; + else if (data[i] == 0xff) + sd->header_read = 1; + else + sd->header_read = 0; + break; + default: + sd->header[sd->header_read - 6] = data[i]; + sd->header_read++; + if (sd->header_read == header_size) { + sd->header_read = 0; + return data + i + 1; } } } + return NULL; +} + +static void sd_pkt_scan(struct gspca_dev *gspca_dev, + u8 *data, /* isoc packet */ + int len) /* iso packet length */ +{ + int fr_h_sz = 0, lum_offset = 0, len_after_sof = 0; + struct sd *sd = (struct sd *) gspca_dev; + struct cam *cam = &gspca_dev->cam; + u8 *sof; + + sof = find_sof(gspca_dev, data, len); + if (sof) { + if (sd->bridge == BRIDGE_103) { + fr_h_sz = 18; + lum_offset = 3; + } else { + fr_h_sz = 12; + lum_offset = 2; + } + + len_after_sof = len - (sof - data); + len = (sof - data) - fr_h_sz; + if (len < 0) + len = 0; + } if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) { /* In raw mode we sometimes get some garbage after the frame @@ -1259,6 +1284,33 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } gspca_frame_add(gspca_dev, INTER_PACKET, data, len); + + if (sof) { + int lum = sd->header[lum_offset] + + (sd->header[lum_offset + 1] << 8); + + /* When exposure changes midway a frame we + get a lum of 0 in this case drop 2 frames + as the frames directly after an exposure + change have an unstable image. Sometimes lum + *really* is 0 (cam used in low light with + low exposure setting), so do not drop frames + if the previous lum was 0 too. */ + if (lum == 0 && sd->prev_avg_lum != 0) { + lum = -1; + sd->frames_to_drop = 2; + sd->prev_avg_lum = 0; + } else + sd->prev_avg_lum = lum; + atomic_set(&sd->avg_lum, lum); + + if (sd->frames_to_drop) + sd->frames_to_drop--; + else + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); + + gspca_frame_add(gspca_dev, FIRST_PACKET, sof, len_after_sof); + } } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) -- cgit v0.10.2 From 00765f16f116b45aa67de306ac923ed4ba262bf9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 12 Dec 2010 15:55:03 -0300 Subject: [media] gspca_sonixb: Add support for 0c45:602a Add support for cameras with the HV7131D sensor, such as the 0c45:602a Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index f47a829..73504a3 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -73,14 +73,15 @@ struct sd { #define BRIDGE_103 1 __u8 sensor; /* Type of image sensor chip */ -#define SENSOR_HV7131R 0 -#define SENSOR_OV6650 1 -#define SENSOR_OV7630 2 -#define SENSOR_PAS106 3 -#define SENSOR_PAS202 4 -#define SENSOR_TAS5110C 5 -#define SENSOR_TAS5110D 6 -#define SENSOR_TAS5130CXX 7 +#define SENSOR_HV7131D 0 +#define SENSOR_HV7131R 1 +#define SENSOR_OV6650 2 +#define SENSOR_OV7630 3 +#define SENSOR_PAS106 4 +#define SENSOR_PAS202 5 +#define SENSOR_TAS5110C 6 +#define SENSOR_TAS5110D 7 +#define SENSOR_TAS5130CXX 8 __u8 reg11; }; @@ -305,14 +306,29 @@ static const struct v4l2_pix_format sif_mode[] = { .priv = 0}, }; -static const __u8 initHv7131[] = { +static const __u8 initHv7131d[] = { + 0x04, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, + 0x28, 0x1e, 0x60, 0x8e, 0x42, + 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c +}; +static const __u8 hv7131d_sensor_init[][8] = { + {0xa0, 0x11, 0x01, 0x04, 0x00, 0x00, 0x00, 0x17}, + {0xa0, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x17}, + {0xa0, 0x11, 0x28, 0x00, 0x00, 0x00, 0x00, 0x17}, + {0xa0, 0x11, 0x30, 0x30, 0x00, 0x00, 0x00, 0x17}, /* reset level */ + {0xa0, 0x11, 0x34, 0x02, 0x00, 0x00, 0x00, 0x17}, /* pixel bias volt */ +}; + +static const __u8 initHv7131r[] = { 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x28, 0x1e, 0x60, 0x8a, 0x20, 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c }; -static const __u8 hv7131_sensor_init[][8] = { +static const __u8 hv7131r_sensor_init[][8] = { {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10}, {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10}, {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10}, @@ -553,7 +569,8 @@ static const __u8 tas5130_sensor_init[][8] = { }; static struct sensor_data sensor_data[] = { -SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), +SENS(initHv7131d, NULL, hv7131d_sensor_init, NULL, NULL, F_GAIN, NO_BRIGHTNESS|NO_FREQ, 0), +SENS(initHv7131r, NULL, hv7131r_sensor_init, NULL, NULL, 0, NO_BRIGHTNESS|NO_EXPO|NO_FREQ, 0), SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, F_GAIN, 0, 0x21), @@ -703,7 +720,18 @@ static void setsensorgain(struct gspca_dev *gspca_dev) unsigned char gain = sd->gain; switch (sd->sensor) { + case SENSOR_HV7131D: { + __u8 i2c[] = + {0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17}; + + i2c[3] = 0x3f - (sd->gain / 4); + i2c[4] = 0x3f - (sd->gain / 4); + i2c[5] = 0x3f - (sd->gain / 4); + if (i2c_w(gspca_dev, i2c) < 0) + goto err; + break; + } case SENSOR_TAS5110C: case SENSOR_TAS5110D: { __u8 i2c[] = @@ -790,6 +818,23 @@ static void setexposure(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; switch (sd->sensor) { + case SENSOR_HV7131D: { + /* Note the datasheet wrongly says line mode exposure uses reg + 0x26 and 0x27, testing has shown 0x25 + 0x26 */ + __u8 i2c[] = {0xc0, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x17}; + /* The HV7131D's exposure goes from 0 - 65535, we scale our + exposure of 0-1023 to 0-6138. There are 2 reasons for this: + 1) This puts our exposure knee of 200 at approx the point + where the framerate starts dropping + 2) At 6138 the framerate has already dropped to 2 fps, + going any lower makes little sense */ + __u16 reg = sd->exposure * 6; + i2c[3] = reg >> 8; + i2c[4] = reg & 0xff; + if (i2c_w(gspca_dev, i2c) != 0) + goto err; + break; + } case SENSOR_TAS5110C: case SENSOR_TAS5110D: { /* register 19's high nibble contains the sn9c10x clock divider @@ -1494,9 +1539,12 @@ static const struct usb_device_id device_table[] __devinitconst = { #endif {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)}, {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, + {USB_DEVICE(0x0c45, 0x602a), SB(HV7131D, 102)}, + /* {USB_DEVICE(0x0c45, 0x602b), SB(MI0343, 102)}, */ {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)}, {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)}, + /* {USB_DEVICE(0x0c45, 0x602b), SB(MI03XX, 102)}, */ /* MI0343 MI0360 MI0330 */ {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)}, #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)}, diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index aba6d68..41064c7 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -54,8 +54,8 @@ static const struct usb_device_id sn9c102_id_table[] = { #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), }, -#endif { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), }, +#endif { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), }, -- cgit v0.10.2 From 383268a8e282fb549dabe3a33ccafc9434ab6006 Mon Sep 17 00:00:00 2001 From: Matti Aaltonen Date: Fri, 10 Dec 2010 11:41:33 -0300 Subject: [media] MFD: WL1273 FM Radio: MFD driver for the FM radio This is the core of the WL1273 FM radio driver, it connects the two child modules. The two child drivers are drivers/media/radio/radio-wl1273.c and sound/soc/codecs/wl1273.c. The radio-wl1273 driver implements the V4L2 interface and communicates with the device. The ALSA codec offers digital audio, without it only analog audio is available. Signed-off-by: Matti J. Aaltonen Acked-by: Samuel Ortiz Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 3a1493b..05ccab6 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -606,6 +606,16 @@ config MFD_VX855 VIA VX855/VX875 south bridge. You will need to enable the vx855_spi and/or vx855_gpio drivers for this to do anything useful. +config MFD_WL1273_CORE + tristate + depends on I2C + select MFD_CORE + default n + help + This is the core driver for the TI WL1273 FM radio. This MFD + driver connects the radio-wl1273 V4L2 module and the wl1273 + audio codec. + endif # MFD_SUPPORT menu "Multimedia Capabilities Port drivers" diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index f54b365..ae2f915 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -81,3 +81,4 @@ obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o obj-$(CONFIG_MFD_JZ4740_ADC) += jz4740-adc.o obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o obj-$(CONFIG_MFD_VX855) += vx855.o +obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c new file mode 100644 index 0000000..d2ecc24 --- /dev/null +++ b/drivers/mfd/wl1273-core.c @@ -0,0 +1,148 @@ +/* + * MFD driver for wl1273 FM radio and audio codec submodules. + * + * Copyright (C) 2010 Nokia Corporation + * Author: Matti Aaltonen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include + +#define DRIVER_DESC "WL1273 FM Radio Core" + +static struct i2c_device_id wl1273_driver_id_table[] = { + { WL1273_FM_DRIVER_NAME, 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, wl1273_driver_id_table); + +static int wl1273_core_remove(struct i2c_client *client) +{ + struct wl1273_core *core = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "%s\n", __func__); + + mfd_remove_devices(&client->dev); + i2c_set_clientdata(client, NULL); + kfree(core); + + return 0; +} + +static int __devinit wl1273_core_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct wl1273_fm_platform_data *pdata = client->dev.platform_data; + struct wl1273_core *core; + struct mfd_cell *cell; + int children = 0; + int r = 0; + + dev_dbg(&client->dev, "%s\n", __func__); + + if (!pdata) { + dev_err(&client->dev, "No platform data.\n"); + return -EINVAL; + } + + if (!(pdata->children & WL1273_RADIO_CHILD)) { + dev_err(&client->dev, "Cannot function without radio child.\n"); + return -EINVAL; + } + + core = kzalloc(sizeof(*core), GFP_KERNEL); + if (!core) + return -ENOMEM; + + core->pdata = pdata; + core->client = client; + mutex_init(&core->lock); + + i2c_set_clientdata(client, core); + + dev_dbg(&client->dev, "%s: Have V4L2.\n", __func__); + + cell = &core->cells[children]; + cell->name = "wl1273_fm_radio"; + cell->platform_data = &core; + cell->data_size = sizeof(core); + children++; + + if (pdata->children & WL1273_CODEC_CHILD) { + cell = &core->cells[children]; + + dev_dbg(&client->dev, "%s: Have codec.\n", __func__); + cell->name = "wl1273-codec"; + cell->platform_data = &core; + cell->data_size = sizeof(core); + children++; + } + + dev_dbg(&client->dev, "%s: number of children: %d.\n", + __func__, children); + + r = mfd_add_devices(&client->dev, -1, core->cells, + children, NULL, 0); + if (r) + goto err; + + return 0; + +err: + i2c_set_clientdata(client, NULL); + pdata->free_resources(); + kfree(core); + + dev_dbg(&client->dev, "%s\n", __func__); + + return r; +} + +static struct i2c_driver wl1273_core_driver = { + .driver = { + .name = WL1273_FM_DRIVER_NAME, + }, + .probe = wl1273_core_probe, + .id_table = wl1273_driver_id_table, + .remove = __devexit_p(wl1273_core_remove), +}; + +static int __init wl1273_core_init(void) +{ + int r; + + r = i2c_add_driver(&wl1273_core_driver); + if (r) { + pr_err(WL1273_FM_DRIVER_NAME + ": driver registration failed\n"); + return r; + } + + return r; +} + +static void __exit wl1273_core_exit(void) +{ + i2c_del_driver(&wl1273_core_driver); +} +late_initcall(wl1273_core_init); +module_exit(wl1273_core_exit); + +MODULE_AUTHOR("Matti Aaltonen "); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff --git a/include/linux/mfd/wl1273-core.h b/include/linux/mfd/wl1273-core.h new file mode 100644 index 0000000..9787293 --- /dev/null +++ b/include/linux/mfd/wl1273-core.h @@ -0,0 +1,288 @@ +/* + * include/linux/mfd/wl1273-core.h + * + * Some definitions for the wl1273 radio receiver/transmitter chip. + * + * Copyright (C) 2010 Nokia Corporation + * Author: Matti J. Aaltonen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef WL1273_CORE_H +#define WL1273_CORE_H + +#include +#include + +#define WL1273_FM_DRIVER_NAME "wl1273-fm" +#define RX71_FM_I2C_ADDR 0x22 + +#define WL1273_STEREO_GET 0 +#define WL1273_RSSI_LVL_GET 1 +#define WL1273_IF_COUNT_GET 2 +#define WL1273_FLAG_GET 3 +#define WL1273_RDS_SYNC_GET 4 +#define WL1273_RDS_DATA_GET 5 +#define WL1273_FREQ_SET 10 +#define WL1273_AF_FREQ_SET 11 +#define WL1273_MOST_MODE_SET 12 +#define WL1273_MOST_BLEND_SET 13 +#define WL1273_DEMPH_MODE_SET 14 +#define WL1273_SEARCH_LVL_SET 15 +#define WL1273_BAND_SET 16 +#define WL1273_MUTE_STATUS_SET 17 +#define WL1273_RDS_PAUSE_LVL_SET 18 +#define WL1273_RDS_PAUSE_DUR_SET 19 +#define WL1273_RDS_MEM_SET 20 +#define WL1273_RDS_BLK_B_SET 21 +#define WL1273_RDS_MSK_B_SET 22 +#define WL1273_RDS_PI_MASK_SET 23 +#define WL1273_RDS_PI_SET 24 +#define WL1273_RDS_SYSTEM_SET 25 +#define WL1273_INT_MASK_SET 26 +#define WL1273_SEARCH_DIR_SET 27 +#define WL1273_VOLUME_SET 28 +#define WL1273_AUDIO_ENABLE 29 +#define WL1273_PCM_MODE_SET 30 +#define WL1273_I2S_MODE_CONFIG_SET 31 +#define WL1273_POWER_SET 32 +#define WL1273_INTX_CONFIG_SET 33 +#define WL1273_PULL_EN_SET 34 +#define WL1273_HILO_SET 35 +#define WL1273_SWITCH2FREF 36 +#define WL1273_FREQ_DRIFT_REPORT 37 + +#define WL1273_PCE_GET 40 +#define WL1273_FIRM_VER_GET 41 +#define WL1273_ASIC_VER_GET 42 +#define WL1273_ASIC_ID_GET 43 +#define WL1273_MAN_ID_GET 44 +#define WL1273_TUNER_MODE_SET 45 +#define WL1273_STOP_SEARCH 46 +#define WL1273_RDS_CNTRL_SET 47 + +#define WL1273_WRITE_HARDWARE_REG 100 +#define WL1273_CODE_DOWNLOAD 101 +#define WL1273_RESET 102 + +#define WL1273_FM_POWER_MODE 254 +#define WL1273_FM_INTERRUPT 255 + +/* Transmitter API */ + +#define WL1273_CHANL_SET 55 +#define WL1273_SCAN_SPACING_SET 56 +#define WL1273_REF_SET 57 +#define WL1273_POWER_ENB_SET 90 +#define WL1273_POWER_ATT_SET 58 +#define WL1273_POWER_LEV_SET 59 +#define WL1273_AUDIO_DEV_SET 60 +#define WL1273_PILOT_DEV_SET 61 +#define WL1273_RDS_DEV_SET 62 +#define WL1273_PUPD_SET 91 +#define WL1273_AUDIO_IO_SET 63 +#define WL1273_PREMPH_SET 64 +#define WL1273_MONO_SET 66 +#define WL1273_MUTE 92 +#define WL1273_MPX_LMT_ENABLE 67 +#define WL1273_PI_SET 93 +#define WL1273_ECC_SET 69 +#define WL1273_PTY 70 +#define WL1273_AF 71 +#define WL1273_DISPLAY_MODE 74 +#define WL1273_RDS_REP_SET 77 +#define WL1273_RDS_CONFIG_DATA_SET 98 +#define WL1273_RDS_DATA_SET 99 +#define WL1273_RDS_DATA_ENB 94 +#define WL1273_TA_SET 78 +#define WL1273_TP_SET 79 +#define WL1273_DI_SET 80 +#define WL1273_MS_SET 81 +#define WL1273_PS_SCROLL_SPEED 82 +#define WL1273_TX_AUDIO_LEVEL_TEST 96 +#define WL1273_TX_AUDIO_LEVEL_TEST_THRESHOLD 73 +#define WL1273_TX_AUDIO_INPUT_LEVEL_RANGE_SET 54 +#define WL1273_RX_ANTENNA_SELECT 87 +#define WL1273_I2C_DEV_ADDR_SET 86 +#define WL1273_REF_ERR_CALIB_PARAM_SET 88 +#define WL1273_REF_ERR_CALIB_PERIODICITY_SET 89 +#define WL1273_SOC_INT_TRIGGER 52 +#define WL1273_SOC_AUDIO_PATH_SET 83 +#define WL1273_SOC_PCMI_OVERRIDE 84 +#define WL1273_SOC_I2S_OVERRIDE 85 +#define WL1273_RSSI_BLOCK_SCAN_FREQ_SET 95 +#define WL1273_RSSI_BLOCK_SCAN_START 97 +#define WL1273_RSSI_BLOCK_SCAN_DATA_GET 5 +#define WL1273_READ_FMANT_TUNE_VALUE 104 + +#define WL1273_RDS_OFF 0 +#define WL1273_RDS_ON 1 +#define WL1273_RDS_RESET 2 + +#define WL1273_AUDIO_DIGITAL 0 +#define WL1273_AUDIO_ANALOG 1 + +#define WL1273_MODE_RX BIT(0) +#define WL1273_MODE_TX BIT(1) +#define WL1273_MODE_OFF BIT(2) +#define WL1273_MODE_SUSPENDED BIT(3) + +#define WL1273_RADIO_CHILD BIT(0) +#define WL1273_CODEC_CHILD BIT(1) + +#define WL1273_RX_MONO 1 +#define WL1273_RX_STEREO 0 +#define WL1273_TX_MONO 0 +#define WL1273_TX_STEREO 1 + +#define WL1273_MAX_VOLUME 0xffff +#define WL1273_DEFAULT_VOLUME 0x78b8 + +/* I2S protocol, left channel first, data width 16 bits */ +#define WL1273_PCM_DEF_MODE 0x00 + +/* Rx */ +#define WL1273_AUDIO_ENABLE_I2S BIT(0) +#define WL1273_AUDIO_ENABLE_ANALOG BIT(1) + +/* Tx */ +#define WL1273_AUDIO_IO_SET_ANALOG 0 +#define WL1273_AUDIO_IO_SET_I2S 1 + +#define WL1273_PUPD_SET_OFF 0x00 +#define WL1273_PUPD_SET_ON 0x01 +#define WL1273_PUPD_SET_RETENTION 0x10 + +/* I2S mode */ +#define WL1273_IS2_WIDTH_32 0x0 +#define WL1273_IS2_WIDTH_40 0x1 +#define WL1273_IS2_WIDTH_22_23 0x2 +#define WL1273_IS2_WIDTH_23_22 0x3 +#define WL1273_IS2_WIDTH_48 0x4 +#define WL1273_IS2_WIDTH_50 0x5 +#define WL1273_IS2_WIDTH_60 0x6 +#define WL1273_IS2_WIDTH_64 0x7 +#define WL1273_IS2_WIDTH_80 0x8 +#define WL1273_IS2_WIDTH_96 0x9 +#define WL1273_IS2_WIDTH_128 0xa +#define WL1273_IS2_WIDTH 0xf + +#define WL1273_IS2_FORMAT_STD (0x0 << 4) +#define WL1273_IS2_FORMAT_LEFT (0x1 << 4) +#define WL1273_IS2_FORMAT_RIGHT (0x2 << 4) +#define WL1273_IS2_FORMAT_USER (0x3 << 4) + +#define WL1273_IS2_MASTER (0x0 << 6) +#define WL1273_IS2_SLAVEW (0x1 << 6) + +#define WL1273_IS2_TRI_AFTER_SENDING (0x0 << 7) +#define WL1273_IS2_TRI_ALWAYS_ACTIVE (0x1 << 7) + +#define WL1273_IS2_SDOWS_RR (0x0 << 8) +#define WL1273_IS2_SDOWS_RF (0x1 << 8) +#define WL1273_IS2_SDOWS_FR (0x2 << 8) +#define WL1273_IS2_SDOWS_FF (0x3 << 8) + +#define WL1273_IS2_TRI_OPT (0x0 << 10) +#define WL1273_IS2_TRI_ALWAYS (0x1 << 10) + +#define WL1273_IS2_RATE_48K (0x0 << 12) +#define WL1273_IS2_RATE_44_1K (0x1 << 12) +#define WL1273_IS2_RATE_32K (0x2 << 12) +#define WL1273_IS2_RATE_22_05K (0x4 << 12) +#define WL1273_IS2_RATE_16K (0x5 << 12) +#define WL1273_IS2_RATE_12K (0x8 << 12) +#define WL1273_IS2_RATE_11_025 (0x9 << 12) +#define WL1273_IS2_RATE_8K (0xa << 12) +#define WL1273_IS2_RATE (0xf << 12) + +#define WL1273_I2S_DEF_MODE (WL1273_IS2_WIDTH_32 | \ + WL1273_IS2_FORMAT_STD | \ + WL1273_IS2_MASTER | \ + WL1273_IS2_TRI_AFTER_SENDING | \ + WL1273_IS2_SDOWS_RR | \ + WL1273_IS2_TRI_OPT | \ + WL1273_IS2_RATE_48K) + +#define SCHAR_MIN (-128) +#define SCHAR_MAX 127 + +#define WL1273_FR_EVENT BIT(0) +#define WL1273_BL_EVENT BIT(1) +#define WL1273_RDS_EVENT BIT(2) +#define WL1273_BBLK_EVENT BIT(3) +#define WL1273_LSYNC_EVENT BIT(4) +#define WL1273_LEV_EVENT BIT(5) +#define WL1273_IFFR_EVENT BIT(6) +#define WL1273_PI_EVENT BIT(7) +#define WL1273_PD_EVENT BIT(8) +#define WL1273_STIC_EVENT BIT(9) +#define WL1273_MAL_EVENT BIT(10) +#define WL1273_POW_ENB_EVENT BIT(11) +#define WL1273_SCAN_OVER_EVENT BIT(12) +#define WL1273_ERROR_EVENT BIT(13) + +#define TUNER_MODE_STOP_SEARCH 0 +#define TUNER_MODE_PRESET 1 +#define TUNER_MODE_AUTO_SEEK 2 +#define TUNER_MODE_AF 3 +#define TUNER_MODE_AUTO_SEEK_PI 4 +#define TUNER_MODE_AUTO_SEEK_BULK 5 + +#define RDS_BLOCK_SIZE 3 + +struct wl1273_fm_platform_data { + int (*request_resources) (struct i2c_client *client); + void (*free_resources) (void); + void (*enable) (void); + void (*disable) (void); + + u8 forbidden_modes; + unsigned int children; +}; + +#define WL1273_FM_CORE_CELLS 2 + +#define WL1273_BAND_OTHER 0 +#define WL1273_BAND_JAPAN 1 + +#define WL1273_BAND_JAPAN_LOW 76000 +#define WL1273_BAND_JAPAN_HIGH 90000 +#define WL1273_BAND_OTHER_LOW 87500 +#define WL1273_BAND_OTHER_HIGH 108000 + +#define WL1273_BAND_TX_LOW 76000 +#define WL1273_BAND_TX_HIGH 108000 + +struct wl1273_core { + struct mfd_cell cells[WL1273_FM_CORE_CELLS]; + struct wl1273_fm_platform_data *pdata; + + unsigned int mode; + unsigned int i2s_mode; + unsigned int volume; + unsigned int audio_mode; + unsigned int channel_number; + struct mutex lock; /* for serializing fm radio operations */ + + struct i2c_client *client; + + int (*write)(struct wl1273_core *core, u8, u16); + int (*set_audio)(struct wl1273_core *core, unsigned int); + int (*set_volume)(struct wl1273_core *core, unsigned int); +}; + +#endif /* ifndef WL1273_CORE_H */ -- cgit v0.10.2 From 87d1a50ce45168cbaec10397e876286a398052c1 Mon Sep 17 00:00:00 2001 From: Matti Aaltonen Date: Fri, 10 Dec 2010 11:41:34 -0300 Subject: [media] V4L2: WL1273 FM Radio: TI WL1273 FM radio driver This module implements V4L2 controls for the Texas Instruments WL1273 FM Radio and handles the communication with the chip. Signed-off-by: Matti J. Aaltonen Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 83567b8..3c5a473 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -452,4 +452,20 @@ config RADIO_TIMBERDALE found behind the Timberdale FPGA on the Russellville board. Enabling this driver will automatically select the DSP and tuner. +config RADIO_WL1273 + tristate "Texas Instruments WL1273 I2C FM Radio" + depends on I2C && VIDEO_V4L2 + select MFD_WL1273_CORE + select FW_LOADER + ---help--- + Choose Y here if you have this FM radio chip. + + In order to control your radio card, you will need to use programs + that are compatible with the Video For Linux 2 API. Information on + this API and pointers to "v4l2" programs may be found at + . + + To compile this driver as a module, choose M here: the + module will be called radio-wl1273. + endif # RADIO_ADAPTERS diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index f615583..d297074 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile @@ -26,5 +26,6 @@ obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o obj-$(CONFIG_RADIO_SAA7706H) += saa7706h.o obj-$(CONFIG_RADIO_TEF6862) += tef6862.o obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o +obj-$(CONFIG_RADIO_WL1273) += radio-wl1273.o EXTRA_CFLAGS += -Isound diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c new file mode 100644 index 0000000..1813790 --- /dev/null +++ b/drivers/media/radio/radio-wl1273.c @@ -0,0 +1,2331 @@ +/* + * Driver for the Texas Instruments WL1273 FM radio. + * + * Copyright (C) 2010 Nokia Corporation + * Author: Matti J. Aaltonen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_DESC "Wl1273 FM Radio" + +#define WL1273_POWER_SET_OFF 0 +#define WL1273_POWER_SET_FM BIT(0) +#define WL1273_POWER_SET_RDS BIT(1) +#define WL1273_POWER_SET_RETENTION BIT(4) + +#define WL1273_PUPD_SET_OFF 0x00 +#define WL1273_PUPD_SET_ON 0x01 +#define WL1273_PUPD_SET_RETENTION 0x10 + +#define WL1273_FREQ(x) (x * 10000 / 625) +#define WL1273_INV_FREQ(x) (x * 625 / 10000) + +/* + * static int radio_nr - The number of the radio device + * + * The default is 0. + */ +static int radio_nr; +module_param(radio_nr, int, 0); +MODULE_PARM_DESC(radio_nr, "The number of the radio device. Default = 0"); + +struct wl1273_device { + char *bus_type; + + u8 forbidden; + unsigned int preemphasis; + unsigned int spacing; + unsigned int tx_power; + unsigned int rx_frequency; + unsigned int tx_frequency; + unsigned int rangelow; + unsigned int rangehigh; + unsigned int band; + bool stereo; + + /* RDS */ + unsigned int rds_on; + struct delayed_work work; + + wait_queue_head_t read_queue; + struct mutex lock; /* for serializing fm radio operations */ + struct completion busy; + + unsigned char *buffer; + unsigned int buf_size; + unsigned int rd_index; + unsigned int wr_index; + + /* Selected interrupts */ + u16 irq_flags; + u16 irq_received; + + struct v4l2_ctrl_handler ctrl_handler; + struct v4l2_device v4l2dev; + struct video_device videodev; + struct device *dev; + struct wl1273_core *core; + struct file *owner; + char *write_buf; + unsigned int rds_users; +}; + +#define WL1273_IRQ_MASK (WL1273_FR_EVENT | \ + WL1273_POW_ENB_EVENT) + +/* + * static unsigned int rds_buf - the number of RDS buffer blocks used. + * + * The default number is 100. + */ +static unsigned int rds_buf = 100; +module_param(rds_buf, uint, 0); +MODULE_PARM_DESC(rds_buf, "Number of RDS buffer entries. Default = 100"); + +static int wl1273_fm_read_reg(struct wl1273_core *core, u8 reg, u16 *value) +{ + struct i2c_client *client = core->client; + u8 b[2]; + int r; + + r = i2c_smbus_read_i2c_block_data(client, reg, sizeof(b), b); + if (r != 2) { + dev_err(&client->dev, "%s: Read: %d fails.\n", __func__, reg); + return -EREMOTEIO; + } + + *value = (u16)b[0] << 8 | b[1]; + + return 0; +} + +static int wl1273_fm_write_cmd(struct wl1273_core *core, u8 cmd, u16 param) +{ + struct i2c_client *client = core->client; + u8 buf[] = { (param >> 8) & 0xff, param & 0xff }; + int r; + + r = i2c_smbus_write_i2c_block_data(client, cmd, sizeof(buf), buf); + if (r) { + dev_err(&client->dev, "%s: Cmd: %d fails.\n", __func__, cmd); + return r; + } + + return 0; +} + +static int wl1273_fm_write_data(struct wl1273_core *core, u8 *data, u16 len) +{ + struct i2c_client *client = core->client; + struct i2c_msg msg; + int r; + + msg.addr = client->addr; + msg.flags = 0; + msg.buf = data; + msg.len = len; + + r = i2c_transfer(client->adapter, &msg, 1); + if (r != 1) { + dev_err(&client->dev, "%s: write error.\n", __func__); + return -EREMOTEIO; + } + + return 0; +} + +static int wl1273_fm_write_fw(struct wl1273_core *core, + __u8 *fw, int len) +{ + struct i2c_client *client = core->client; + struct i2c_msg msg; + int i, r = 0; + + msg.addr = client->addr; + msg.flags = 0; + + for (i = 0; i <= len; i++) { + msg.len = fw[0]; + msg.buf = fw + 1; + + fw += msg.len + 1; + dev_dbg(&client->dev, "%s:len[%d]: %d\n", __func__, i, msg.len); + + r = i2c_transfer(client->adapter, &msg, 1); + if (r < 0 && i < len + 1) + break; + } + + dev_dbg(&client->dev, "%s: i: %d\n", __func__, i); + dev_dbg(&client->dev, "%s: len + 1: %d\n", __func__, len + 1); + + /* Last transfer always fails. */ + if (i == len || r == 1) + r = 0; + + return r; +} + +/** + * wl1273_fm_set_audio() - Set audio mode. + * @core: A pointer to the device struct. + * @new_mode: The new audio mode. + * + * Audio modes are WL1273_AUDIO_DIGITAL and WL1273_AUDIO_ANALOG. + */ +static int wl1273_fm_set_audio(struct wl1273_core *core, unsigned int new_mode) +{ + int r = 0; + + if (core->mode == WL1273_MODE_OFF || + core->mode == WL1273_MODE_SUSPENDED) + return -EPERM; + + if (core->mode == WL1273_MODE_RX && new_mode == WL1273_AUDIO_DIGITAL) { + r = wl1273_fm_write_cmd(core, WL1273_PCM_MODE_SET, + WL1273_PCM_DEF_MODE); + if (r) + goto out; + + r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET, + core->i2s_mode); + if (r) + goto out; + + r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE, + WL1273_AUDIO_ENABLE_I2S); + if (r) + goto out; + + } else if (core->mode == WL1273_MODE_RX && + new_mode == WL1273_AUDIO_ANALOG) { + r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE, + WL1273_AUDIO_ENABLE_ANALOG); + if (r) + goto out; + + } else if (core->mode == WL1273_MODE_TX && + new_mode == WL1273_AUDIO_DIGITAL) { + r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET, + core->i2s_mode); + if (r) + goto out; + + r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET, + WL1273_AUDIO_IO_SET_I2S); + if (r) + goto out; + + } else if (core->mode == WL1273_MODE_TX && + new_mode == WL1273_AUDIO_ANALOG) { + r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET, + WL1273_AUDIO_IO_SET_ANALOG); + if (r) + goto out; + } + + core->audio_mode = new_mode; +out: + return r; +} + +/** + * wl1273_fm_set_volume() - Set volume. + * @core: A pointer to the device struct. + * @volume: The new volume value. + */ +static int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume) +{ + u16 val; + int r; + + if (volume > WL1273_MAX_VOLUME) + return -EINVAL; + + if (core->volume == volume) + return 0; + + val = volume; + r = wl1273_fm_read_reg(core, WL1273_VOLUME_SET, &val); + if (r) + return r; + + core->volume = volume; + return 0; +} + +#define WL1273_FIFO_HAS_DATA(status) (1 << 5 & status) +#define WL1273_RDS_CORRECTABLE_ERROR (1 << 3) +#define WL1273_RDS_UNCORRECTABLE_ERROR (1 << 4) + +static int wl1273_fm_rds(struct wl1273_device *radio) +{ + struct wl1273_core *core = radio->core; + struct i2c_client *client = core->client; + u16 val; + u8 b0 = WL1273_RDS_DATA_GET, status; + struct v4l2_rds_data rds = { 0, 0, 0 }; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .buf = &b0, + .len = 1, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .buf = (u8 *) &rds, + .len = sizeof(rds), + } + }; + int r; + + if (core->mode != WL1273_MODE_RX) + return 0; + + r = wl1273_fm_read_reg(core, WL1273_RDS_SYNC_GET, &val); + if (r) + return r; + + if ((val & 0x01) == 0) { + /* RDS decoder not synchronized */ + return -EAGAIN; + } + + /* copy all four RDS blocks to internal buffer */ + do { + r = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); + if (r != ARRAY_SIZE(msg)) { + dev_err(radio->dev, WL1273_FM_DRIVER_NAME + ": %s: read_rds error r == %i)\n", + __func__, r); + } + + status = rds.block; + + if (!WL1273_FIFO_HAS_DATA(status)) + break; + + /* copy bits 0-2 (the block ID) to bits 3-5 */ + rds.block = V4L2_RDS_BLOCK_MSK & status; + rds.block |= rds.block << 3; + + /* copy the error bits to standard positions */ + if (WL1273_RDS_UNCORRECTABLE_ERROR & status) { + rds.block |= V4L2_RDS_BLOCK_ERROR; + rds.block &= ~V4L2_RDS_BLOCK_CORRECTED; + } else if (WL1273_RDS_CORRECTABLE_ERROR & status) { + rds.block &= ~V4L2_RDS_BLOCK_ERROR; + rds.block |= V4L2_RDS_BLOCK_CORRECTED; + } + + /* copy RDS block to internal buffer */ + memcpy(&radio->buffer[radio->wr_index], &rds, RDS_BLOCK_SIZE); + radio->wr_index += 3; + + /* wrap write pointer */ + if (radio->wr_index >= radio->buf_size) + radio->wr_index = 0; + + /* check for overflow & start over */ + if (radio->wr_index == radio->rd_index) { + dev_dbg(radio->dev, "RDS OVERFLOW"); + + radio->rd_index = 0; + radio->wr_index = 0; + break; + } + } while (WL1273_FIFO_HAS_DATA(status)); + + /* wake up read queue */ + if (radio->wr_index != radio->rd_index) + wake_up_interruptible(&radio->read_queue); + + return 0; +} + +static irqreturn_t wl1273_fm_irq_thread_handler(int irq, void *dev_id) +{ + struct wl1273_device *radio = dev_id; + struct wl1273_core *core = radio->core; + u16 flags; + int r; + + r = wl1273_fm_read_reg(core, WL1273_FLAG_GET, &flags); + if (r) + goto out; + + if (flags & WL1273_BL_EVENT) { + radio->irq_received = flags; + dev_dbg(radio->dev, "IRQ: BL\n"); + } + + if (flags & WL1273_RDS_EVENT) { + msleep(200); + + wl1273_fm_rds(radio); + } + + if (flags & WL1273_BBLK_EVENT) + dev_dbg(radio->dev, "IRQ: BBLK\n"); + + if (flags & WL1273_LSYNC_EVENT) + dev_dbg(radio->dev, "IRQ: LSYNC\n"); + + if (flags & WL1273_LEV_EVENT) { + u16 level; + + r = wl1273_fm_read_reg(core, WL1273_RSSI_LVL_GET, &level); + if (r) + goto out; + + if (level > 14) + dev_dbg(radio->dev, "IRQ: LEV: 0x%x04\n", level); + } + + if (flags & WL1273_IFFR_EVENT) + dev_dbg(radio->dev, "IRQ: IFFR\n"); + + if (flags & WL1273_PI_EVENT) + dev_dbg(radio->dev, "IRQ: PI\n"); + + if (flags & WL1273_PD_EVENT) + dev_dbg(radio->dev, "IRQ: PD\n"); + + if (flags & WL1273_STIC_EVENT) + dev_dbg(radio->dev, "IRQ: STIC\n"); + + if (flags & WL1273_MAL_EVENT) + dev_dbg(radio->dev, "IRQ: MAL\n"); + + if (flags & WL1273_POW_ENB_EVENT) { + complete(&radio->busy); + dev_dbg(radio->dev, "NOT BUSY\n"); + dev_dbg(radio->dev, "IRQ: POW_ENB\n"); + } + + if (flags & WL1273_SCAN_OVER_EVENT) + dev_dbg(radio->dev, "IRQ: SCAN_OVER\n"); + + if (flags & WL1273_ERROR_EVENT) + dev_dbg(radio->dev, "IRQ: ERROR\n"); + + if (flags & WL1273_FR_EVENT) { + u16 freq; + + dev_dbg(radio->dev, "IRQ: FR:\n"); + + if (core->mode == WL1273_MODE_RX) { + r = wl1273_fm_write_cmd(core, WL1273_TUNER_MODE_SET, + TUNER_MODE_STOP_SEARCH); + if (r) { + dev_err(radio->dev, + "%s: TUNER_MODE_SET fails: %d\n", + __func__, r); + goto out; + } + + r = wl1273_fm_read_reg(core, WL1273_FREQ_SET, &freq); + if (r) + goto out; + + if (radio->band == WL1273_BAND_JAPAN) + radio->rx_frequency = WL1273_BAND_JAPAN_LOW + + freq * 50; + else + radio->rx_frequency = WL1273_BAND_OTHER_LOW + + freq * 50; + /* + * The driver works better with this msleep, + * the documentation doesn't mention it. + */ + usleep_range(10000, 15000); + + dev_dbg(radio->dev, "%dkHz\n", radio->rx_frequency); + + } else { + r = wl1273_fm_read_reg(core, WL1273_CHANL_SET, &freq); + if (r) + goto out; + + dev_dbg(radio->dev, "%dkHz\n", freq); + } + dev_dbg(radio->dev, "%s: NOT BUSY\n", __func__); + } + +out: + wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET, + radio->irq_flags); + complete(&radio->busy); + + return IRQ_HANDLED; +} + +static int wl1273_fm_set_tx_freq(struct wl1273_device *radio, unsigned int freq) +{ + struct wl1273_core *core = radio->core; + int r = 0; + + if (freq < WL1273_BAND_TX_LOW) { + dev_err(radio->dev, + "Frequency out of range: %d < %d\n", freq, + WL1273_BAND_TX_LOW); + return -ERANGE; + } + + if (freq > WL1273_BAND_TX_HIGH) { + dev_err(radio->dev, + "Frequency out of range: %d > %d\n", freq, + WL1273_BAND_TX_HIGH); + return -ERANGE; + } + + /* + * The driver works better with this sleep, + * the documentation doesn't mention it. + */ + usleep_range(5000, 10000); + + dev_dbg(radio->dev, "%s: freq: %d kHz\n", __func__, freq); + + /* Set the current tx channel */ + r = wl1273_fm_write_cmd(core, WL1273_CHANL_SET, freq / 10); + if (r) + return r; + + INIT_COMPLETION(radio->busy); + + /* wait for the FR IRQ */ + r = wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(2000)); + if (!r) + return -ETIMEDOUT; + + dev_dbg(radio->dev, "WL1273_CHANL_SET: %d\n", r); + + /* Enable the output power */ + r = wl1273_fm_write_cmd(core, WL1273_POWER_ENB_SET, 1); + if (r) + return r; + + INIT_COMPLETION(radio->busy); + + /* wait for the POWER_ENB IRQ */ + r = wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(1000)); + if (!r) + return -ETIMEDOUT; + + radio->tx_frequency = freq; + dev_dbg(radio->dev, "WL1273_POWER_ENB_SET: %d\n", r); + + return 0; +} + +static int wl1273_fm_set_rx_freq(struct wl1273_device *radio, unsigned int freq) +{ + struct wl1273_core *core = radio->core; + int r, f; + + if (freq < radio->rangelow) { + dev_err(radio->dev, + "Frequency out of range: %d < %d\n", freq, + radio->rangelow); + r = -ERANGE; + goto err; + } + + if (freq > radio->rangehigh) { + dev_err(radio->dev, + "Frequency out of range: %d > %d\n", freq, + radio->rangehigh); + r = -ERANGE; + goto err; + } + + dev_dbg(radio->dev, "%s: %dkHz\n", __func__, freq); + + wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET, radio->irq_flags); + + if (radio->band == WL1273_BAND_JAPAN) + f = (freq - WL1273_BAND_JAPAN_LOW) / 50; + else + f = (freq - WL1273_BAND_OTHER_LOW) / 50; + + r = wl1273_fm_write_cmd(core, WL1273_FREQ_SET, f); + if (r) { + dev_err(radio->dev, "FREQ_SET fails\n"); + goto err; + } + + r = wl1273_fm_write_cmd(core, WL1273_TUNER_MODE_SET, TUNER_MODE_PRESET); + if (r) { + dev_err(radio->dev, "TUNER_MODE_SET fails\n"); + goto err; + } + + INIT_COMPLETION(radio->busy); + + r = wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(2000)); + if (!r) { + dev_err(radio->dev, "%s: TIMEOUT\n", __func__); + return -ETIMEDOUT; + } + + radio->rd_index = 0; + radio->wr_index = 0; + radio->rx_frequency = freq; + return 0; +err: + return r; +} + +static int wl1273_fm_get_freq(struct wl1273_device *radio) +{ + struct wl1273_core *core = radio->core; + unsigned int freq; + u16 f; + int r; + + if (core->mode == WL1273_MODE_RX) { + r = wl1273_fm_read_reg(core, WL1273_FREQ_SET, &f); + if (r) + return r; + + dev_dbg(radio->dev, "Freq get: 0x%04x\n", f); + if (radio->band == WL1273_BAND_JAPAN) + freq = WL1273_BAND_JAPAN_LOW + 50 * f; + else + freq = WL1273_BAND_OTHER_LOW + 50 * f; + } else { + r = wl1273_fm_read_reg(core, WL1273_CHANL_SET, &f); + if (r) + return r; + + freq = f * 10; + } + + return freq; +} + +/** + * wl1273_fm_upload_firmware_patch() - Upload the firmware. + * @radio: A pointer to the device struct. + * + * The firmware file consists of arrays of bytes where the first byte + * gives the array length. The first byte in the file gives the + * number of these arrays. + */ +static int wl1273_fm_upload_firmware_patch(struct wl1273_device *radio) +{ + struct wl1273_core *core = radio->core; + unsigned int packet_num; + const struct firmware *fw_p; + const char *fw_name = "radio-wl1273-fw.bin"; + struct device *dev = radio->dev; + __u8 *ptr; + int i, n, r; + + dev_dbg(dev, "%s:\n", __func__); + + /* + * Uploading the firmware patch is not always necessary, + * so we only print an info message. + */ + if (request_firmware(&fw_p, fw_name, dev)) { + dev_info(dev, "%s - %s not found\n", __func__, fw_name); + + return 0; + } + + ptr = (__u8 *) fw_p->data; + packet_num = ptr[0]; + dev_dbg(dev, "%s: packets: %d\n", __func__, packet_num); + + r = wl1273_fm_write_fw(core, ptr + 1, packet_num); + if (r) { + dev_err(dev, "FW upload error: %d\n", r); + goto out; + } + + /* ignore possible error here */ + wl1273_fm_write_cmd(core, WL1273_RESET, 0); + + dev_dbg(dev, "n: %d, i: %d\n", n, i); + dev_dbg(dev, "%s - download OK, r: %d\n", __func__, r); +out: + release_firmware(fw_p); + return r; +} + +static int wl1273_fm_stop(struct wl1273_device *radio) +{ + struct wl1273_core *core = radio->core; + + if (core->mode == WL1273_MODE_RX) { + int r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, + WL1273_POWER_SET_OFF); + if (r) + dev_err(radio->dev, "%s: POWER_SET fails: %d\n", + __func__, r); + } else if (core->mode == WL1273_MODE_TX) { + int r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET, + WL1273_PUPD_SET_OFF); + if (r) + dev_err(radio->dev, + "%s: PUPD_SET fails: %d\n", __func__, r); + } + + if (core->pdata->disable) { + core->pdata->disable(); + dev_dbg(radio->dev, "Back to reset\n"); + } + + return 0; +} + +static int wl1273_fm_start(struct wl1273_device *radio, int new_mode) +{ + struct wl1273_core *core = radio->core; + struct wl1273_fm_platform_data *pdata = core->pdata; + struct device *dev = radio->dev; + int r = -EINVAL; + + if (pdata->enable && core->mode == WL1273_MODE_OFF) { + dev_dbg(radio->dev, "Out of reset\n"); + + pdata->enable(); + msleep(250); + } + + if (new_mode == WL1273_MODE_RX) { + u16 val = WL1273_POWER_SET_FM; + + if (radio->rds_on) + val |= WL1273_POWER_SET_RDS; + + /* If this fails try again */ + r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, val); + if (r) { + msleep(100); + + r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, val); + if (r) { + dev_err(dev, "%s: POWER_SET fails\n", __func__); + goto fail; + } + } + + /* rds buffer configuration */ + radio->wr_index = 0; + radio->rd_index = 0; + + } else if (new_mode == WL1273_MODE_TX) { + /* If this fails try again once */ + r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET, + WL1273_PUPD_SET_ON); + if (r) { + msleep(100); + r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET, + WL1273_PUPD_SET_ON); + if (r) { + dev_err(dev, "%s: PUPD_SET fails\n", __func__); + goto fail; + } + } + + if (radio->rds_on) + r = wl1273_fm_write_cmd(core, WL1273_RDS_DATA_ENB, 1); + else + r = wl1273_fm_write_cmd(core, WL1273_RDS_DATA_ENB, 0); + } else { + dev_warn(dev, "%s: Illegal mode.\n", __func__); + } + + if (core->mode == WL1273_MODE_OFF) { + r = wl1273_fm_upload_firmware_patch(radio); + if (r) + dev_warn(dev, "Firmware upload failed.\n"); + + /* + * Sometimes the chip is in a wrong power state at this point. + * So we set the power once again. + */ + if (new_mode == WL1273_MODE_RX) { + u16 val = WL1273_POWER_SET_FM; + + if (radio->rds_on) + val |= WL1273_POWER_SET_RDS; + + r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, val); + if (r) { + dev_err(dev, "%s: POWER_SET fails\n", __func__); + goto fail; + } + } else if (new_mode == WL1273_MODE_TX) { + r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET, + WL1273_PUPD_SET_ON); + if (r) { + dev_err(dev, "%s: PUPD_SET fails\n", __func__); + goto fail; + } + } + } + + return 0; +fail: + if (pdata->disable) + pdata->disable(); + + dev_dbg(dev, "%s: return: %d\n", __func__, r); + return r; +} + +static int wl1273_fm_suspend(struct wl1273_device *radio) +{ + struct wl1273_core *core = radio->core; + int r = 0; + + /* Cannot go from OFF to SUSPENDED */ + if (core->mode == WL1273_MODE_RX) + r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, + WL1273_POWER_SET_RETENTION); + else if (core->mode == WL1273_MODE_TX) + r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET, + WL1273_PUPD_SET_RETENTION); + else + r = -EINVAL; + + if (r) { + dev_err(radio->dev, "%s: POWER_SET fails: %d\n", __func__, r); + goto out; + } + +out: + return r; +} + +static int wl1273_fm_set_mode(struct wl1273_device *radio, int mode) +{ + struct wl1273_core *core = radio->core; + struct device *dev = radio->dev; + int old_mode; + int r; + + dev_dbg(dev, "%s\n", __func__); + dev_dbg(dev, "Forbidden modes: 0x%02x\n", radio->forbidden); + + old_mode = core->mode; + if (mode & radio->forbidden) { + r = -EPERM; + goto out; + } + + switch (mode) { + case WL1273_MODE_RX: + case WL1273_MODE_TX: + r = wl1273_fm_start(radio, mode); + if (r) { + dev_err(dev, "%s: Cannot start.\n", __func__); + wl1273_fm_stop(radio); + goto out; + } + + core->mode = mode; + r = wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET, + radio->irq_flags); + if (r) { + dev_err(dev, "INT_MASK_SET fails.\n"); + goto out; + } + + /* remember previous settings */ + if (mode == WL1273_MODE_RX) { + r = wl1273_fm_set_rx_freq(radio, radio->rx_frequency); + if (r) { + dev_err(dev, "set freq fails: %d.\n", r); + goto out; + } + + r = core->set_volume(core, core->volume); + if (r) { + dev_err(dev, "set volume fails: %d.\n", r); + goto out; + } + + dev_dbg(dev, "%s: Set vol: %d.\n", __func__, + core->volume); + } else { + r = wl1273_fm_set_tx_freq(radio, radio->tx_frequency); + if (r) { + dev_err(dev, "set freq fails: %d.\n", r); + goto out; + } + } + + dev_dbg(radio->dev, "%s: Set audio mode.\n", __func__); + + r = core->set_audio(core, core->audio_mode); + if (r) + dev_err(dev, "Cannot set audio mode.\n"); + break; + + case WL1273_MODE_OFF: + r = wl1273_fm_stop(radio); + if (r) + dev_err(dev, "%s: Off fails: %d\n", __func__, r); + else + core->mode = WL1273_MODE_OFF; + + break; + + case WL1273_MODE_SUSPENDED: + r = wl1273_fm_suspend(radio); + if (r) + dev_err(dev, "%s: Suspend fails: %d\n", __func__, r); + else + core->mode = WL1273_MODE_SUSPENDED; + + break; + + default: + dev_err(dev, "%s: Unknown mode: %d\n", __func__, mode); + r = -EINVAL; + break; + } +out: + if (r) + core->mode = old_mode; + + return r; +} + +static int wl1273_fm_set_seek(struct wl1273_device *radio, + unsigned int wrap_around, + unsigned int seek_upward, + int level) +{ + struct wl1273_core *core = radio->core; + int r = 0; + unsigned int dir = (seek_upward == 0) ? 0 : 1; + unsigned int f; + + f = radio->rx_frequency; + dev_dbg(radio->dev, "rx_frequency: %d\n", f); + + if (dir && f + radio->spacing <= radio->rangehigh) + r = wl1273_fm_set_rx_freq(radio, f + radio->spacing); + else if (dir && wrap_around) + r = wl1273_fm_set_rx_freq(radio, radio->rangelow); + else if (f - radio->spacing >= radio->rangelow) + r = wl1273_fm_set_rx_freq(radio, f - radio->spacing); + else if (wrap_around) + r = wl1273_fm_set_rx_freq(radio, radio->rangehigh); + + if (r) + goto out; + + if (level < SCHAR_MIN || level > SCHAR_MAX) + return -EINVAL; + + INIT_COMPLETION(radio->busy); + dev_dbg(radio->dev, "%s: BUSY\n", __func__); + + r = wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET, radio->irq_flags); + if (r) + goto out; + + dev_dbg(radio->dev, "%s\n", __func__); + + r = wl1273_fm_write_cmd(core, WL1273_SEARCH_LVL_SET, level); + if (r) + goto out; + + r = wl1273_fm_write_cmd(core, WL1273_SEARCH_DIR_SET, dir); + if (r) + goto out; + + r = wl1273_fm_write_cmd(core, WL1273_TUNER_MODE_SET, + TUNER_MODE_AUTO_SEEK); + if (r) + goto out; + + wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(1000)); + if (!(radio->irq_received & WL1273_BL_EVENT)) + goto out; + + radio->irq_received &= ~WL1273_BL_EVENT; + + if (!wrap_around) + goto out; + + /* Wrap around */ + dev_dbg(radio->dev, "Wrap around in HW seek.\n"); + + if (seek_upward) + f = radio->rangelow; + else + f = radio->rangehigh; + + r = wl1273_fm_set_rx_freq(radio, f); + if (r) + goto out; + + INIT_COMPLETION(radio->busy); + dev_dbg(radio->dev, "%s: BUSY\n", __func__); + + r = wl1273_fm_write_cmd(core, WL1273_TUNER_MODE_SET, + TUNER_MODE_AUTO_SEEK); + if (r) + goto out; + + wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(1000)); +out: + dev_dbg(radio->dev, "%s: Err: %d\n", __func__, r); + return r; +} + +/** + * wl1273_fm_get_tx_ctune() - Get the TX tuning capacitor value. + * @radio: A pointer to the device struct. + */ +static unsigned int wl1273_fm_get_tx_ctune(struct wl1273_device *radio) +{ + struct wl1273_core *core = radio->core; + struct device *dev = radio->dev; + u16 val; + int r; + + if (core->mode == WL1273_MODE_OFF || + core->mode == WL1273_MODE_SUSPENDED) + return -EPERM; + + r = wl1273_fm_read_reg(core, WL1273_READ_FMANT_TUNE_VALUE, &val); + if (r) { + dev_err(dev, "%s: read error: %d\n", __func__, r); + goto out; + } + +out: + return val; +} + +/** + * wl1273_fm_set_preemphasis() - Set the TX pre-emphasis value. + * @radio: A pointer to the device struct. + * @preemphasis: The new pre-amphasis value. + * + * Possible pre-emphasis values are: V4L2_PREEMPHASIS_DISABLED, + * V4L2_PREEMPHASIS_50_uS and V4L2_PREEMPHASIS_75_uS. + */ +static int wl1273_fm_set_preemphasis(struct wl1273_device *radio, + unsigned int preemphasis) +{ + struct wl1273_core *core = radio->core; + int r; + u16 em; + + if (core->mode == WL1273_MODE_OFF || + core->mode == WL1273_MODE_SUSPENDED) + return -EPERM; + + mutex_lock(&core->lock); + + switch (preemphasis) { + case V4L2_PREEMPHASIS_DISABLED: + em = 1; + break; + case V4L2_PREEMPHASIS_50_uS: + em = 0; + break; + case V4L2_PREEMPHASIS_75_uS: + em = 2; + break; + default: + r = -EINVAL; + goto out; + } + + r = wl1273_fm_write_cmd(core, WL1273_PREMPH_SET, em); + if (r) + goto out; + + radio->preemphasis = preemphasis; + +out: + mutex_unlock(&core->lock); + return r; +} + +static int wl1273_fm_rds_on(struct wl1273_device *radio) +{ + struct wl1273_core *core = radio->core; + int r; + + dev_dbg(radio->dev, "%s\n", __func__); + if (radio->rds_on) + return 0; + + r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, + WL1273_POWER_SET_FM | WL1273_POWER_SET_RDS); + if (r) + goto out; + + r = wl1273_fm_set_rx_freq(radio, radio->rx_frequency); + if (r) + dev_err(radio->dev, "set freq fails: %d.\n", r); +out: + return r; +} + +static int wl1273_fm_rds_off(struct wl1273_device *radio) +{ + struct wl1273_core *core = radio->core; + int r; + + if (!radio->rds_on) + return 0; + + radio->irq_flags &= ~WL1273_RDS_EVENT; + + r = wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET, radio->irq_flags); + if (r) + goto out; + + /* stop rds reception */ + cancel_delayed_work(&radio->work); + + /* Service pending read */ + wake_up_interruptible(&radio->read_queue); + + dev_dbg(radio->dev, "%s\n", __func__); + + r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, WL1273_POWER_SET_FM); + if (r) + goto out; + + r = wl1273_fm_set_rx_freq(radio, radio->rx_frequency); + if (r) + dev_err(radio->dev, "set freq fails: %d.\n", r); +out: + dev_dbg(radio->dev, "%s: exiting...\n", __func__); + + return r; +} + +static int wl1273_fm_set_rds(struct wl1273_device *radio, unsigned int new_mode) +{ + int r = 0; + struct wl1273_core *core = radio->core; + + if (core->mode == WL1273_MODE_OFF || + core->mode == WL1273_MODE_SUSPENDED) + return -EPERM; + + if (new_mode == WL1273_RDS_RESET) { + r = wl1273_fm_write_cmd(core, WL1273_RDS_CNTRL_SET, 1); + return r; + } + + if (core->mode == WL1273_MODE_TX && new_mode == WL1273_RDS_OFF) { + r = wl1273_fm_write_cmd(core, WL1273_RDS_DATA_ENB, 0); + } else if (core->mode == WL1273_MODE_TX && new_mode == WL1273_RDS_ON) { + r = wl1273_fm_write_cmd(core, WL1273_RDS_DATA_ENB, 1); + } else if (core->mode == WL1273_MODE_RX && new_mode == WL1273_RDS_OFF) { + r = wl1273_fm_rds_off(radio); + } else if (core->mode == WL1273_MODE_RX && new_mode == WL1273_RDS_ON) { + r = wl1273_fm_rds_on(radio); + } else { + dev_err(radio->dev, "%s: Unknown mode: %d\n", + __func__, new_mode); + r = -EINVAL; + } + + if (!r) + radio->rds_on = (new_mode == WL1273_RDS_ON) ? true : false; + + return r; +} + +static ssize_t wl1273_fm_fops_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); + u16 val; + int r; + + dev_dbg(radio->dev, "%s\n", __func__); + + if (radio->core->mode != WL1273_MODE_TX) + return count; + + if (radio->rds_users == 0) { + dev_warn(radio->dev, "%s: RDS not on.\n", __func__); + return 0; + } + + if (mutex_lock_interruptible(&radio->core->lock)) + return -EINTR; + /* + * Multiple processes can open the device, but only + * one gets to write to it. + */ + if (radio->owner && radio->owner != file) { + r = -EBUSY; + goto out; + } + radio->owner = file; + + /* Manual Mode */ + if (count > 255) + val = 255; + else + val = count; + + wl1273_fm_write_cmd(radio->core, WL1273_RDS_CONFIG_DATA_SET, val); + + if (copy_from_user(radio->write_buf + 1, buf, val)) { + r = -EFAULT; + goto out; + } + + dev_dbg(radio->dev, "Count: %d\n", val); + dev_dbg(radio->dev, "From user: \"%s\"\n", radio->write_buf); + + radio->write_buf[0] = WL1273_RDS_DATA_SET; + wl1273_fm_write_data(radio->core, radio->write_buf, val + 1); + + r = val; +out: + mutex_unlock(&radio->core->lock); + + return r; +} + +static unsigned int wl1273_fm_fops_poll(struct file *file, + struct poll_table_struct *pts) +{ + struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); + struct wl1273_core *core = radio->core; + + if (radio->owner && radio->owner != file) + return -EBUSY; + + radio->owner = file; + + if (core->mode == WL1273_MODE_RX) { + poll_wait(file, &radio->read_queue, pts); + + if (radio->rd_index != radio->wr_index) + return POLLIN | POLLRDNORM; + + } else if (core->mode == WL1273_MODE_TX) { + return POLLOUT | POLLWRNORM; + } + + return 0; +} + +static int wl1273_fm_fops_open(struct file *file) +{ + struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); + struct wl1273_core *core = radio->core; + int r = 0; + + dev_dbg(radio->dev, "%s\n", __func__); + + if (core->mode == WL1273_MODE_RX && radio->rds_on && + !radio->rds_users) { + dev_dbg(radio->dev, "%s: Mode: %d\n", __func__, core->mode); + + if (mutex_lock_interruptible(&core->lock)) + return -EINTR; + + radio->irq_flags |= WL1273_RDS_EVENT; + + r = wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET, + radio->irq_flags); + if (r) { + mutex_unlock(&core->lock); + goto out; + } + + radio->rds_users++; + + mutex_unlock(&core->lock); + } +out: + return r; +} + +static int wl1273_fm_fops_release(struct file *file) +{ + struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); + struct wl1273_core *core = radio->core; + int r = 0; + + dev_dbg(radio->dev, "%s\n", __func__); + + if (radio->rds_users > 0) { + radio->rds_users--; + if (radio->rds_users == 0) { + if (mutex_lock_interruptible(&core->lock)) + return -EINTR; + + radio->irq_flags &= ~WL1273_RDS_EVENT; + + if (core->mode == WL1273_MODE_RX) { + r = wl1273_fm_write_cmd(core, + WL1273_INT_MASK_SET, + radio->irq_flags); + if (r) { + mutex_unlock(&core->lock); + goto out; + } + } + mutex_unlock(&core->lock); + } + } + + if (file == radio->owner) + radio->owner = NULL; +out: + return r; +} + +static ssize_t wl1273_fm_fops_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + int r = 0; + struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); + struct wl1273_core *core = radio->core; + unsigned int block_count = 0; + u16 val; + + dev_dbg(radio->dev, "%s\n", __func__); + + if (radio->core->mode != WL1273_MODE_RX) + return 0; + + if (radio->rds_users == 0) { + dev_warn(radio->dev, "%s: RDS not on.\n", __func__); + return 0; + } + + if (mutex_lock_interruptible(&core->lock)) + return -EINTR; + + /* + * Multiple processes can open the device, but only + * one at a time gets read access. + */ + if (radio->owner && radio->owner != file) { + r = -EBUSY; + goto out; + } + radio->owner = file; + + r = wl1273_fm_read_reg(core, WL1273_RDS_SYNC_GET, &val); + if (r) { + dev_err(radio->dev, "%s: Get RDS_SYNC fails.\n", __func__); + goto out; + } else if (val == 0) { + dev_info(radio->dev, "RDS_SYNC: Not synchronized\n"); + r = -ENODATA; + goto out; + } + + /* block if no new data available */ + while (radio->wr_index == radio->rd_index) { + if (file->f_flags & O_NONBLOCK) { + r = -EWOULDBLOCK; + goto out; + } + + dev_dbg(radio->dev, "%s: Wait for RDS data.\n", __func__); + if (wait_event_interruptible(radio->read_queue, + radio->wr_index != + radio->rd_index) < 0) { + r = -EINTR; + goto out; + } + } + + /* calculate block count from byte count */ + count /= RDS_BLOCK_SIZE; + + /* copy RDS blocks from the internal buffer and to user buffer */ + while (block_count < count) { + if (radio->rd_index == radio->wr_index) + break; + + /* always transfer complete RDS blocks */ + if (copy_to_user(buf, &radio->buffer[radio->rd_index], + RDS_BLOCK_SIZE)) + break; + + /* increment and wrap the read pointer */ + radio->rd_index += RDS_BLOCK_SIZE; + if (radio->rd_index >= radio->buf_size) + radio->rd_index = 0; + + /* increment counters */ + block_count++; + buf += RDS_BLOCK_SIZE; + r += RDS_BLOCK_SIZE; + } + +out: + dev_dbg(radio->dev, "%s: exit\n", __func__); + mutex_unlock(&core->lock); + + return r; +} + +static const struct v4l2_file_operations wl1273_fops = { + .owner = THIS_MODULE, + .read = wl1273_fm_fops_read, + .write = wl1273_fm_fops_write, + .poll = wl1273_fm_fops_poll, + .ioctl = video_ioctl2, + .open = wl1273_fm_fops_open, + .release = wl1273_fm_fops_release, +}; + +static int wl1273_fm_vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *capability) +{ + struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); + + dev_dbg(radio->dev, "%s\n", __func__); + + strlcpy(capability->driver, WL1273_FM_DRIVER_NAME, + sizeof(capability->driver)); + strlcpy(capability->card, "Texas Instruments Wl1273 FM Radio", + sizeof(capability->card)); + strlcpy(capability->bus_info, radio->bus_type, + sizeof(capability->bus_info)); + + capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | + V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_AUDIO | + V4L2_CAP_RDS_CAPTURE | V4L2_CAP_MODULATOR | + V4L2_CAP_RDS_OUTPUT; + + return 0; +} + +static int wl1273_fm_vidioc_g_input(struct file *file, void *priv, + unsigned int *i) +{ + struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); + + dev_dbg(radio->dev, "%s\n", __func__); + + *i = 0; + + return 0; +} + +static int wl1273_fm_vidioc_s_input(struct file *file, void *priv, + unsigned int i) +{ + struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); + + dev_dbg(radio->dev, "%s\n", __func__); + + if (i != 0) + return -EINVAL; + + return 0; +} + +/** + * wl1273_fm_set_tx_power() - Set the transmission power value. + * @core: A pointer to the device struct. + * @power: The new power value. + */ +static int wl1273_fm_set_tx_power(struct wl1273_device *radio, u16 power) +{ + int r; + + if (radio->core->mode == WL1273_MODE_OFF || + radio->core->mode == WL1273_MODE_SUSPENDED) + return -EPERM; + + mutex_lock(&radio->core->lock); + + /* Convert the dBuV value to chip presentation */ + r = wl1273_fm_write_cmd(radio->core, WL1273_POWER_LEV_SET, 122 - power); + if (r) + goto out; + + radio->tx_power = power; + +out: + mutex_unlock(&radio->core->lock); + return r; +} + +#define WL1273_SPACING_50kHz 1 +#define WL1273_SPACING_100kHz 2 +#define WL1273_SPACING_200kHz 4 + +static int wl1273_fm_tx_set_spacing(struct wl1273_device *radio, + unsigned int spacing) +{ + int r; + + if (spacing == 0) { + r = wl1273_fm_write_cmd(radio->core, WL1273_SCAN_SPACING_SET, + WL1273_SPACING_100kHz); + radio->spacing = 100; + } else if (spacing - 50000 < 25000) { + r = wl1273_fm_write_cmd(radio->core, WL1273_SCAN_SPACING_SET, + WL1273_SPACING_50kHz); + radio->spacing = 50; + } else if (spacing - 100000 < 50000) { + r = wl1273_fm_write_cmd(radio->core, WL1273_SCAN_SPACING_SET, + WL1273_SPACING_100kHz); + radio->spacing = 100; + } else { + r = wl1273_fm_write_cmd(radio->core, WL1273_SCAN_SPACING_SET, + WL1273_SPACING_200kHz); + radio->spacing = 200; + } + + return r; +} + +static int wl1273_fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl) +{ + struct wl1273_device *radio = ctrl->priv; + struct wl1273_core *core = radio->core; + + dev_dbg(radio->dev, "%s\n", __func__); + + if (mutex_lock_interruptible(&core->lock)) + return -EINTR; + + switch (ctrl->id) { + case V4L2_CID_TUNE_ANTENNA_CAPACITOR: + ctrl->val = wl1273_fm_get_tx_ctune(radio); + break; + + default: + dev_warn(radio->dev, "%s: Unknown IOCTL: %d\n", + __func__, ctrl->id); + break; + } + + mutex_unlock(&core->lock); + + return 0; +} + +#define WL1273_MUTE_SOFT_ENABLE (1 << 0) +#define WL1273_MUTE_AC (1 << 1) +#define WL1273_MUTE_HARD_LEFT (1 << 2) +#define WL1273_MUTE_HARD_RIGHT (1 << 3) +#define WL1273_MUTE_SOFT_FORCE (1 << 4) + +static inline struct wl1273_device *to_radio(struct v4l2_ctrl *ctrl) +{ + return container_of(ctrl->handler, struct wl1273_device, ctrl_handler); +} + +static int wl1273_fm_vidioc_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct wl1273_device *radio = to_radio(ctrl); + struct wl1273_core *core = radio->core; + int r = 0; + + dev_dbg(radio->dev, "%s\n", __func__); + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + if (mutex_lock_interruptible(&core->lock)) + return -EINTR; + + if (core->mode == WL1273_MODE_RX && ctrl->val) + r = wl1273_fm_write_cmd(core, + WL1273_MUTE_STATUS_SET, + WL1273_MUTE_HARD_LEFT | + WL1273_MUTE_HARD_RIGHT); + else if (core->mode == WL1273_MODE_RX) + r = wl1273_fm_write_cmd(core, + WL1273_MUTE_STATUS_SET, 0x0); + else if (core->mode == WL1273_MODE_TX && ctrl->val) + r = wl1273_fm_write_cmd(core, WL1273_MUTE, 1); + else if (core->mode == WL1273_MODE_TX) + r = wl1273_fm_write_cmd(core, WL1273_MUTE, 0); + + mutex_unlock(&core->lock); + break; + + case V4L2_CID_AUDIO_VOLUME: + if (ctrl->val == 0) + r = wl1273_fm_set_mode(radio, WL1273_MODE_OFF); + else + r = core->set_volume(core, core->volume); + break; + + case V4L2_CID_TUNE_PREEMPHASIS: + r = wl1273_fm_set_preemphasis(radio, ctrl->val); + break; + + case V4L2_CID_TUNE_POWER_LEVEL: + r = wl1273_fm_set_tx_power(radio, ctrl->val); + break; + + default: + dev_warn(radio->dev, "%s: Unknown IOCTL: %d\n", + __func__, ctrl->id); + break; + } + + dev_dbg(radio->dev, "%s\n", __func__); + return r; +} + +static int wl1273_fm_vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *audio) +{ + struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); + + dev_dbg(radio->dev, "%s\n", __func__); + + if (audio->index > 1) + return -EINVAL; + + strlcpy(audio->name, "Radio", sizeof(audio->name)); + audio->capability = V4L2_AUDCAP_STEREO; + + return 0; +} + +static int wl1273_fm_vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *audio) +{ + struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); + + dev_dbg(radio->dev, "%s\n", __func__); + + if (audio->index != 0) + return -EINVAL; + + return 0; +} + +#define WL1273_RDS_NOT_SYNCHRONIZED 0 +#define WL1273_RDS_SYNCHRONIZED 1 + +static int wl1273_fm_vidioc_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *tuner) +{ + struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); + struct wl1273_core *core = radio->core; + u16 val; + int r; + + dev_dbg(radio->dev, "%s\n", __func__); + + if (tuner->index > 0) + return -EINVAL; + + strlcpy(tuner->name, WL1273_FM_DRIVER_NAME, sizeof(tuner->name)); + tuner->type = V4L2_TUNER_RADIO; + + tuner->rangelow = WL1273_FREQ(WL1273_BAND_JAPAN_LOW); + tuner->rangehigh = WL1273_FREQ(WL1273_BAND_OTHER_HIGH); + + tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_RDS | + V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS_BLOCK_IO; + + if (radio->stereo) + tuner->audmode = V4L2_TUNER_MODE_STEREO; + else + tuner->audmode = V4L2_TUNER_MODE_MONO; + + if (core->mode != WL1273_MODE_RX) + return 0; + + if (mutex_lock_interruptible(&core->lock)) + return -EINTR; + + r = wl1273_fm_read_reg(core, WL1273_STEREO_GET, &val); + if (r) + goto out; + + if (val == 1) + tuner->rxsubchans = V4L2_TUNER_SUB_STEREO; + else + tuner->rxsubchans = V4L2_TUNER_SUB_MONO; + + r = wl1273_fm_read_reg(core, WL1273_RSSI_LVL_GET, &val); + if (r) + goto out; + + tuner->signal = (s16) val; + dev_dbg(radio->dev, "Signal: %d\n", tuner->signal); + + tuner->afc = 0; + + r = wl1273_fm_read_reg(core, WL1273_RDS_SYNC_GET, &val); + if (r) + goto out; + + if (val == WL1273_RDS_SYNCHRONIZED) + tuner->rxsubchans |= V4L2_TUNER_SUB_RDS; +out: + mutex_unlock(&core->lock); + + return r; +} + +static int wl1273_fm_vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *tuner) +{ + struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); + struct wl1273_core *core = radio->core; + int r = 0; + + dev_dbg(radio->dev, "%s\n", __func__); + dev_dbg(radio->dev, "tuner->index: %d\n", tuner->index); + dev_dbg(radio->dev, "tuner->name: %s\n", tuner->name); + dev_dbg(radio->dev, "tuner->capability: 0x%04x\n", tuner->capability); + dev_dbg(radio->dev, "tuner->rxsubchans: 0x%04x\n", tuner->rxsubchans); + dev_dbg(radio->dev, "tuner->rangelow: %d\n", tuner->rangelow); + dev_dbg(radio->dev, "tuner->rangehigh: %d\n", tuner->rangehigh); + + if (tuner->index > 0) + return -EINVAL; + + if (mutex_lock_interruptible(&core->lock)) + return -EINTR; + + r = wl1273_fm_set_mode(radio, WL1273_MODE_RX); + if (r) + goto out; + + if (tuner->rxsubchans & V4L2_TUNER_SUB_RDS) + r = wl1273_fm_set_rds(radio, WL1273_RDS_ON); + else + r = wl1273_fm_set_rds(radio, WL1273_RDS_OFF); + + if (r) + dev_warn(radio->dev, "%s: RDS fails: %d\n", __func__, r); + + if (tuner->audmode == V4L2_TUNER_MODE_MONO) { + r = wl1273_fm_write_cmd(core, WL1273_MOST_MODE_SET, + WL1273_RX_MONO); + if (r < 0) { + dev_warn(radio->dev, "%s: MOST_MODE fails: %d\n", + __func__, r); + goto out; + } + radio->stereo = false; + } else if (tuner->audmode == V4L2_TUNER_MODE_STEREO) { + r = wl1273_fm_write_cmd(core, WL1273_MOST_MODE_SET, + WL1273_RX_STEREO); + if (r < 0) { + dev_warn(radio->dev, "%s: MOST_MODE fails: %d\n", + __func__, r); + goto out; + } + radio->stereo = true; + } else { + dev_err(radio->dev, "%s: tuner->audmode: %d\n", + __func__, tuner->audmode); + r = -EINVAL; + goto out; + } + +out: + mutex_unlock(&core->lock); + + return r; +} + +static int wl1273_fm_vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *freq) +{ + struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); + struct wl1273_core *core = radio->core; + + dev_dbg(radio->dev, "%s\n", __func__); + + if (mutex_lock_interruptible(&core->lock)) + return -EINTR; + + freq->type = V4L2_TUNER_RADIO; + freq->frequency = WL1273_FREQ(wl1273_fm_get_freq(radio)); + + mutex_unlock(&core->lock); + + return 0; +} + +static int wl1273_fm_vidioc_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *freq) +{ + struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); + struct wl1273_core *core = radio->core; + int r; + + dev_dbg(radio->dev, "%s: %d\n", __func__, freq->frequency); + + if (freq->type != V4L2_TUNER_RADIO) { + dev_dbg(radio->dev, + "freq->type != V4L2_TUNER_RADIO: %d\n", freq->type); + return -EINVAL; + } + + if (mutex_lock_interruptible(&core->lock)) + return -EINTR; + + if (core->mode == WL1273_MODE_RX) { + dev_dbg(radio->dev, "freq: %d\n", freq->frequency); + + r = wl1273_fm_set_rx_freq(radio, + WL1273_INV_FREQ(freq->frequency)); + if (r) + dev_warn(radio->dev, WL1273_FM_DRIVER_NAME + ": set frequency failed with %d\n", r); + } else { + r = wl1273_fm_set_tx_freq(radio, + WL1273_INV_FREQ(freq->frequency)); + if (r) + dev_warn(radio->dev, WL1273_FM_DRIVER_NAME + ": set frequency failed with %d\n", r); + } + + mutex_unlock(&core->lock); + + dev_dbg(radio->dev, "wl1273_vidioc_s_frequency: DONE\n"); + return r; +} + +#define WL1273_DEFAULT_SEEK_LEVEL 7 + +static int wl1273_fm_vidioc_s_hw_freq_seek(struct file *file, void *priv, + struct v4l2_hw_freq_seek *seek) +{ + struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); + struct wl1273_core *core = radio->core; + int r; + + dev_dbg(radio->dev, "%s\n", __func__); + + if (seek->tuner != 0 || seek->type != V4L2_TUNER_RADIO) + return -EINVAL; + + if (mutex_lock_interruptible(&core->lock)) + return -EINTR; + + r = wl1273_fm_set_mode(radio, WL1273_MODE_RX); + if (r) + goto out; + + r = wl1273_fm_tx_set_spacing(radio, seek->spacing); + if (r) + dev_warn(radio->dev, "HW seek failed: %d\n", r); + + r = wl1273_fm_set_seek(radio, seek->wrap_around, seek->seek_upward, + WL1273_DEFAULT_SEEK_LEVEL); + if (r) + dev_warn(radio->dev, "HW seek failed: %d\n", r); + +out: + mutex_unlock(&core->lock); + return r; +} + +static int wl1273_fm_vidioc_s_modulator(struct file *file, void *priv, + struct v4l2_modulator *modulator) +{ + struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); + struct wl1273_core *core = radio->core; + int r = 0; + + dev_dbg(radio->dev, "%s\n", __func__); + + if (modulator->index > 0) + return -EINVAL; + + if (mutex_lock_interruptible(&core->lock)) + return -EINTR; + + r = wl1273_fm_set_mode(radio, WL1273_MODE_TX); + if (r) + goto out; + + if (modulator->txsubchans & V4L2_TUNER_SUB_RDS) + r = wl1273_fm_set_rds(radio, WL1273_RDS_ON); + else + r = wl1273_fm_set_rds(radio, WL1273_RDS_OFF); + + if (modulator->txsubchans & V4L2_TUNER_SUB_MONO) + r = wl1273_fm_write_cmd(core, WL1273_MONO_SET, WL1273_TX_MONO); + else + r = wl1273_fm_write_cmd(core, WL1273_MONO_SET, + WL1273_RX_STEREO); + if (r < 0) + dev_warn(radio->dev, WL1273_FM_DRIVER_NAME + "MONO_SET fails: %d\n", r); +out: + mutex_unlock(&core->lock); + + return r; +} + +static int wl1273_fm_vidioc_g_modulator(struct file *file, void *priv, + struct v4l2_modulator *modulator) +{ + struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); + struct wl1273_core *core = radio->core; + u16 val; + int r; + + dev_dbg(radio->dev, "%s\n", __func__); + + strlcpy(modulator->name, WL1273_FM_DRIVER_NAME, + sizeof(modulator->name)); + + modulator->rangelow = WL1273_FREQ(WL1273_BAND_JAPAN_LOW); + modulator->rangehigh = WL1273_FREQ(WL1273_BAND_OTHER_HIGH); + + modulator->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_RDS | + V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS_BLOCK_IO; + + if (core->mode != WL1273_MODE_TX) + return 0; + + if (mutex_lock_interruptible(&core->lock)) + return -EINTR; + + r = wl1273_fm_read_reg(core, WL1273_MONO_SET, &val); + if (r) + goto out; + + if (val == WL1273_TX_STEREO) + modulator->txsubchans = V4L2_TUNER_SUB_STEREO; + else + modulator->txsubchans = V4L2_TUNER_SUB_MONO; + + if (radio->rds_on) + modulator->txsubchans |= V4L2_TUNER_SUB_RDS; +out: + mutex_unlock(&core->lock); + + return 0; +} + +static int wl1273_fm_vidioc_log_status(struct file *file, void *priv) +{ + struct wl1273_device *radio = video_get_drvdata(video_devdata(file)); + struct wl1273_core *core = radio->core; + struct device *dev = radio->dev; + u16 val; + int r; + + dev_info(dev, DRIVER_DESC); + + if (core->mode == WL1273_MODE_OFF) { + dev_info(dev, "Mode: Off\n"); + return 0; + } + + if (core->mode == WL1273_MODE_SUSPENDED) { + dev_info(dev, "Mode: Suspended\n"); + return 0; + } + + r = wl1273_fm_read_reg(core, WL1273_ASIC_ID_GET, &val); + if (r) + dev_err(dev, "%s: Get ASIC_ID fails.\n", __func__); + else + dev_info(dev, "ASIC_ID: 0x%04x\n", val); + + r = wl1273_fm_read_reg(core, WL1273_ASIC_VER_GET, &val); + if (r) + dev_err(dev, "%s: Get ASIC_VER fails.\n", __func__); + else + dev_info(dev, "ASIC Version: 0x%04x\n", val); + + r = wl1273_fm_read_reg(core, WL1273_FIRM_VER_GET, &val); + if (r) + dev_err(dev, "%s: Get FIRM_VER fails.\n", __func__); + else + dev_info(dev, "FW version: %d(0x%04x)\n", val, val); + + r = wl1273_fm_read_reg(core, WL1273_BAND_SET, &val); + if (r) + dev_err(dev, "%s: Get BAND fails.\n", __func__); + else + dev_info(dev, "BAND: %d\n", val); + + if (core->mode == WL1273_MODE_TX) { + r = wl1273_fm_read_reg(core, WL1273_PUPD_SET, &val); + if (r) + dev_err(dev, "%s: Get PUPD fails.\n", __func__); + else + dev_info(dev, "PUPD: 0x%04x\n", val); + + r = wl1273_fm_read_reg(core, WL1273_CHANL_SET, &val); + if (r) + dev_err(dev, "%s: Get CHANL fails.\n", __func__); + else + dev_info(dev, "Tx frequency: %dkHz\n", val*10); + } else if (core->mode == WL1273_MODE_RX) { + int bf = radio->rangelow; + + r = wl1273_fm_read_reg(core, WL1273_FREQ_SET, &val); + if (r) + dev_err(dev, "%s: Get FREQ fails.\n", __func__); + else + dev_info(dev, "RX Frequency: %dkHz\n", bf + val*50); + + r = wl1273_fm_read_reg(core, WL1273_MOST_MODE_SET, &val); + if (r) + dev_err(dev, "%s: Get MOST_MODE fails.\n", + __func__); + else if (val == 0) + dev_info(dev, "MOST_MODE: Stereo according to blend\n"); + else if (val == 1) + dev_info(dev, "MOST_MODE: Force mono output\n"); + else + dev_info(dev, "MOST_MODE: Unexpected value: %d\n", val); + + r = wl1273_fm_read_reg(core, WL1273_MOST_BLEND_SET, &val); + if (r) + dev_err(dev, "%s: Get MOST_BLEND fails.\n", __func__); + else if (val == 0) + dev_info(dev, + "MOST_BLEND: Switched blend & hysteresis.\n"); + else if (val == 1) + dev_info(dev, "MOST_BLEND: Soft blend.\n"); + else + dev_info(dev, "MOST_BLEND: Unexpected val: %d\n", val); + + r = wl1273_fm_read_reg(core, WL1273_STEREO_GET, &val); + if (r) + dev_err(dev, "%s: Get STEREO fails.\n", __func__); + else if (val == 0) + dev_info(dev, "STEREO: Not detected\n"); + else if (val == 1) + dev_info(dev, "STEREO: Detected\n"); + else + dev_info(dev, "STEREO: Unexpected value: %d\n", val); + + r = wl1273_fm_read_reg(core, WL1273_RSSI_LVL_GET, &val); + if (r) + dev_err(dev, "%s: Get RSSI_LVL fails.\n", __func__); + else + dev_info(dev, "RX signal strength: %d\n", (s16) val); + + r = wl1273_fm_read_reg(core, WL1273_POWER_SET, &val); + if (r) + dev_err(dev, "%s: Get POWER fails.\n", __func__); + else + dev_info(dev, "POWER: 0x%04x\n", val); + + r = wl1273_fm_read_reg(core, WL1273_INT_MASK_SET, &val); + if (r) + dev_err(dev, "%s: Get INT_MASK fails.\n", __func__); + else + dev_info(dev, "INT_MASK: 0x%04x\n", val); + + r = wl1273_fm_read_reg(core, WL1273_RDS_SYNC_GET, &val); + if (r) + dev_err(dev, "%s: Get RDS_SYNC fails.\n", + __func__); + else if (val == 0) + dev_info(dev, "RDS_SYNC: Not synchronized\n"); + + else if (val == 1) + dev_info(dev, "RDS_SYNC: Synchronized\n"); + else + dev_info(dev, "RDS_SYNC: Unexpected value: %d\n", val); + + r = wl1273_fm_read_reg(core, WL1273_I2S_MODE_CONFIG_SET, &val); + if (r) + dev_err(dev, "%s: Get I2S_MODE_CONFIG fails.\n", + __func__); + else + dev_info(dev, "I2S_MODE_CONFIG: 0x%04x\n", val); + + r = wl1273_fm_read_reg(core, WL1273_VOLUME_SET, &val); + if (r) + dev_err(dev, "%s: Get VOLUME fails.\n", __func__); + else + dev_info(dev, "VOLUME: 0x%04x\n", val); + } + + return 0; +} + +static void wl1273_vdev_release(struct video_device *dev) +{ +} + +static const struct v4l2_ctrl_ops wl1273_ctrl_ops = { + .s_ctrl = wl1273_fm_vidioc_s_ctrl, + .g_volatile_ctrl = wl1273_fm_g_volatile_ctrl, +}; + +static const struct v4l2_ioctl_ops wl1273_ioctl_ops = { + .vidioc_querycap = wl1273_fm_vidioc_querycap, + .vidioc_g_input = wl1273_fm_vidioc_g_input, + .vidioc_s_input = wl1273_fm_vidioc_s_input, + .vidioc_g_audio = wl1273_fm_vidioc_g_audio, + .vidioc_s_audio = wl1273_fm_vidioc_s_audio, + .vidioc_g_tuner = wl1273_fm_vidioc_g_tuner, + .vidioc_s_tuner = wl1273_fm_vidioc_s_tuner, + .vidioc_g_frequency = wl1273_fm_vidioc_g_frequency, + .vidioc_s_frequency = wl1273_fm_vidioc_s_frequency, + .vidioc_s_hw_freq_seek = wl1273_fm_vidioc_s_hw_freq_seek, + .vidioc_g_modulator = wl1273_fm_vidioc_g_modulator, + .vidioc_s_modulator = wl1273_fm_vidioc_s_modulator, + .vidioc_log_status = wl1273_fm_vidioc_log_status, +}; + +static struct video_device wl1273_viddev_template = { + .fops = &wl1273_fops, + .ioctl_ops = &wl1273_ioctl_ops, + .name = WL1273_FM_DRIVER_NAME, + .release = wl1273_vdev_release, +}; + +static int wl1273_fm_radio_remove(struct platform_device *pdev) +{ + struct wl1273_device *radio = platform_get_drvdata(pdev); + struct wl1273_core *core = radio->core; + + dev_info(&pdev->dev, "%s.\n", __func__); + + free_irq(core->client->irq, radio); + core->pdata->free_resources(); + + v4l2_ctrl_handler_free(&radio->ctrl_handler); + video_unregister_device(&radio->videodev); + v4l2_device_unregister(&radio->v4l2dev); + kfree(radio->buffer); + kfree(radio->write_buf); + kfree(radio); + + return 0; +} + +static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev) +{ + struct wl1273_core **core = pdev->dev.platform_data; + struct wl1273_device *radio; + struct v4l2_ctrl *ctrl; + int r = 0; + + pr_debug("%s\n", __func__); + + if (!core) { + dev_err(&pdev->dev, "No platform data.\n"); + r = -EINVAL; + goto pdata_err; + } + + radio = kzalloc(sizeof(*radio), GFP_KERNEL); + if (!radio) { + r = -ENOMEM; + goto pdata_err; + } + + /* RDS buffer allocation */ + radio->buf_size = rds_buf * RDS_BLOCK_SIZE; + radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); + if (!radio->buffer) { + pr_err("Cannot allocate memory for RDS buffer.\n"); + r = -ENOMEM; + goto err_kmalloc; + } + + radio->core = *core; + radio->irq_flags = WL1273_IRQ_MASK; + radio->dev = &radio->core->client->dev; + radio->rds_on = false; + radio->core->mode = WL1273_MODE_OFF; + radio->tx_power = 118; + radio->core->audio_mode = WL1273_AUDIO_ANALOG; + radio->band = WL1273_BAND_OTHER; + radio->core->i2s_mode = WL1273_I2S_DEF_MODE; + radio->core->channel_number = 2; + radio->core->volume = WL1273_DEFAULT_VOLUME; + radio->rx_frequency = WL1273_BAND_OTHER_LOW; + radio->tx_frequency = WL1273_BAND_OTHER_HIGH; + radio->rangelow = WL1273_BAND_OTHER_LOW; + radio->rangehigh = WL1273_BAND_OTHER_HIGH; + radio->stereo = true; + radio->bus_type = "I2C"; + + radio->core->write = wl1273_fm_write_cmd; + radio->core->set_audio = wl1273_fm_set_audio; + radio->core->set_volume = wl1273_fm_set_volume; + + if (radio->core->pdata->request_resources) { + r = radio->core->pdata->request_resources(radio->core->client); + if (r) { + dev_err(radio->dev, WL1273_FM_DRIVER_NAME + ": Cannot get platform data\n"); + goto err_resources; + } + + dev_dbg(radio->dev, "irq: %d\n", radio->core->client->irq); + + r = request_threaded_irq(radio->core->client->irq, NULL, + wl1273_fm_irq_thread_handler, + IRQF_ONESHOT | IRQF_TRIGGER_FALLING, + "wl1273-fm", radio); + if (r < 0) { + dev_err(radio->dev, WL1273_FM_DRIVER_NAME + ": Unable to register IRQ handler: %d\n", r); + goto err_request_irq; + } + } else { + dev_err(radio->dev, WL1273_FM_DRIVER_NAME ": Core WL1273 IRQ" + " not configured"); + r = -EINVAL; + goto err_resources; + } + + init_completion(&radio->busy); + init_waitqueue_head(&radio->read_queue); + + radio->write_buf = kmalloc(256, GFP_KERNEL); + if (!radio->write_buf) { + r = -ENOMEM; + goto write_buf_err; + } + + radio->dev = &pdev->dev; + radio->v4l2dev.ctrl_handler = &radio->ctrl_handler; + radio->rds_users = 0; + + r = v4l2_device_register(&pdev->dev, &radio->v4l2dev); + if (r) { + dev_err(&pdev->dev, "Cannot register v4l2_device.\n"); + goto device_register_err; + } + + /* V4L2 configuration */ + memcpy(&radio->videodev, &wl1273_viddev_template, + sizeof(wl1273_viddev_template)); + + radio->videodev.v4l2_dev = &radio->v4l2dev; + + v4l2_ctrl_handler_init(&radio->ctrl_handler, 6); + + /* add in ascending ID order */ + v4l2_ctrl_new_std(&radio->ctrl_handler, &wl1273_ctrl_ops, + V4L2_CID_AUDIO_VOLUME, 0, WL1273_MAX_VOLUME, 1, + WL1273_DEFAULT_VOLUME); + + v4l2_ctrl_new_std(&radio->ctrl_handler, &wl1273_ctrl_ops, + V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); + + v4l2_ctrl_new_std_menu(&radio->ctrl_handler, &wl1273_ctrl_ops, + V4L2_CID_TUNE_PREEMPHASIS, + V4L2_PREEMPHASIS_75_uS, 0x03, + V4L2_PREEMPHASIS_50_uS); + + v4l2_ctrl_new_std(&radio->ctrl_handler, &wl1273_ctrl_ops, + V4L2_CID_TUNE_POWER_LEVEL, 91, 122, 1, 118); + + ctrl = v4l2_ctrl_new_std(&radio->ctrl_handler, &wl1273_ctrl_ops, + V4L2_CID_TUNE_ANTENNA_CAPACITOR, + 0, 255, 1, 255); + if (ctrl) + ctrl->is_volatile = 1; + + if (radio->ctrl_handler.error) { + r = radio->ctrl_handler.error; + dev_err(&pdev->dev, "Ctrl handler error: %d\n", r); + goto handler_init_err; + } + + video_set_drvdata(&radio->videodev, radio); + platform_set_drvdata(pdev, radio); + + /* register video device */ + r = video_register_device(&radio->videodev, VFL_TYPE_RADIO, radio_nr); + if (r) { + dev_err(&pdev->dev, WL1273_FM_DRIVER_NAME + ": Could not register video device\n"); + goto handler_init_err; + } + + return 0; + +handler_init_err: + v4l2_ctrl_handler_free(&radio->ctrl_handler); + v4l2_device_unregister(&radio->v4l2dev); +device_register_err: + kfree(radio->write_buf); +write_buf_err: + free_irq(radio->core->client->irq, radio); +err_request_irq: + radio->core->pdata->free_resources(); +err_resources: + kfree(radio->buffer); +err_kmalloc: + kfree(radio); +pdata_err: + return r; +} + +MODULE_ALIAS("platform:wl1273_fm_radio"); + +static struct platform_driver wl1273_fm_radio_driver = { + .probe = wl1273_fm_radio_probe, + .remove = __devexit_p(wl1273_fm_radio_remove), + .driver = { + .name = "wl1273_fm_radio", + .owner = THIS_MODULE, + }, +}; + +static int __init wl1273_fm_module_init(void) +{ + pr_info("%s\n", __func__); + return platform_driver_register(&wl1273_fm_radio_driver); +} +module_init(wl1273_fm_module_init); + +static void __exit wl1273_fm_module_exit(void) +{ + flush_scheduled_work(); + platform_driver_unregister(&wl1273_fm_radio_driver); + pr_info(DRIVER_DESC ", Exiting.\n"); +} +module_exit(wl1273_fm_module_exit); + +MODULE_AUTHOR("Matti Aaltonen "); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 4c8b8698053c986f5f5249878eab70cb028a1023 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Fri, 26 Nov 2010 14:06:35 -0300 Subject: [media] rc: ir-lirc-codec: fix potential integer overflow 'n' may be bigger than MAX_INT*sizeof(int), if so checking of truncated (int)(n/sizeof(int)) for LIRCBUF_SIZE overflow and then using nontruncated 'count' doesn't make sense. Also n may be up to sizeof(int)-1 bytes bigger than expected, so check value of (n % sizeof(int)) too. Signed-off-by: Vasiliy Kulikov Acked-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index 1e87ee8..f011c5d 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -100,7 +100,8 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf, struct lirc_codec *lirc; struct rc_dev *dev; int *txbuf; /* buffer with values to transmit */ - int ret = 0, count; + int ret = 0; + size_t count; lirc = lirc_get_pdata(file); if (!lirc) @@ -110,7 +111,7 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf, return -EINVAL; count = n / sizeof(int); - if (count > LIRCBUF_SIZE || count % 2 == 0) + if (count > LIRCBUF_SIZE || count % 2 == 0 || n % sizeof(int) != 0) return -EINVAL; txbuf = memdup_user(buf, n); -- cgit v0.10.2 From c59a9bfabfc2a6359f046652c6bfa0a82fb17a05 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 7 Dec 2010 15:50:09 -0300 Subject: [media] media: fix em28xx build, needs hardirq.h Fix em28xx build by adding hardirq.h header file: drivers/media/video/em28xx/em28xx-vbi.c:49: error: implicit declaration of function 'in_interrupt' Reported-by: Zimny Lech Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/em28xx/em28xx-vbi.c b/drivers/media/video/em28xx/em28xx-vbi.c index 7f1c4a2..2b4c9cb 100644 --- a/drivers/media/video/em28xx/em28xx-vbi.c +++ b/drivers/media/video/em28xx/em28xx-vbi.c @@ -23,6 +23,7 @@ #include #include +#include #include #include "em28xx.h" -- cgit v0.10.2 From 75aecc3af22ae9063c96457d530f281a1e2d3276 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Tue, 7 Dec 2010 19:49:24 -0300 Subject: [media] DM04/QQBOX Frontend attach change On Fri, 2010-12-03 at 09:32 -0200, Mauro Carvalho Chehab wrote: > Em 27-11-2010 11:13, Malcolm Priestley escreveu: > > Driver Version v1.73 - Frontend attach change. > > To stop double rc registration in multi tuner environment or firmware change. > > > > Signed-off-by: Malcolm Priestley > > > > > > +static int lme_name(struct dvb_usb_adapter *adap) > > +{ > > + struct lme2510_state *st = adap->dev->priv; > > + const char *desc = adap->dev->desc->name; > > + char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395"}; > > + char *name = adap->fe->ops.info.name; > > + > > + strcpy(name, desc); > > + strcat(name, fe_name[st->tuner_config]); > > Please use, instead, strlcpy/strlcat, to avoid writing outside the buffer size. > Driver Version v1.74 Amended patch with change to strlcpy/strlcat. Signed-off-by: Malcolm Priestley Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c index 1455c23..9eea418 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/drivers/media/dvb/dvb-usb/lmedm04.c @@ -584,6 +584,7 @@ static int lme2510_int_service(struct dvb_usb_adapter *adap) ret = lme2510_int_read(adap); if (ret < 0) { rc_unregister_device(rc); + info("INT Unable to start Interupt Service"); return -ENODEV; } @@ -674,7 +675,7 @@ static void lme_coldreset(struct usb_device *dev) return; } -static void lme_firmware_switch(struct usb_device *udev, int cold) +static int lme_firmware_switch(struct usb_device *udev, int cold) { const struct firmware *fw = NULL; char lme2510c_s7395[] = "dvb-usb-lme2510c-s7395.fw"; @@ -685,7 +686,7 @@ static void lme_firmware_switch(struct usb_device *udev, int cold) cold = (cold > 0) ? (cold & 1) : 0; if (udev->descriptor.idProduct == 0x1122) - return; + return 0; switch (dvb_usb_lme2510_firmware) { case 0: @@ -715,10 +716,12 @@ static void lme_firmware_switch(struct usb_device *udev, int cold) release_firmware(fw); - if (cold) + if (cold) { lme_coldreset(udev); + return -ENODEV; + } - return; + return ret; } static int lme2510_kill_urb(struct usb_data_stream *stream) @@ -786,45 +789,43 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, return (ret < 0) ? -ENODEV : 0; } +static int lme_name(struct dvb_usb_adapter *adap) +{ + struct lme2510_state *st = adap->dev->priv; + const char *desc = adap->dev->desc->name; + char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395"}; + char *name = adap->fe->ops.info.name; + + strlcpy(name, desc, 128); + strlcat(name, fe_name[st->tuner_config], 128); + + return 0; +} + static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) { - int ret = 0; struct lme2510_state *st = adap->dev->priv; - /* Interupt Start */ - ret = lme2510_int_service(adap); - if (ret < 0) { - info("INT Unable to start Interupt Service"); - return -ENODEV; - } + int ret = 0; st->i2c_talk_onoff = 1; - st->i2c_gate = 4; + st->i2c_gate = 4; adap->fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap); if (adap->fe) { info("TUN Found Frontend TDA10086"); - memcpy(&adap->fe->ops.info.name, - &"DM04_LG_TDQY-P001F DVB-S", 24); - adap->fe->ops.set_voltage = dm04_lme2510_set_voltage; st->i2c_tuner_gate_w = 4; st->i2c_tuner_gate_r = 4; st->i2c_tuner_addr = 0xc0; - if (dvb_attach(tda826x_attach, adap->fe, 0xc0, - &adap->dev->i2c_adap, 1)) { - info("TUN TDA8263 Found"); - st->tuner_config = TUNER_LG; - if (dvb_usb_lme2510_firmware != 1) { - dvb_usb_lme2510_firmware = 1; - lme_firmware_switch(adap->dev->udev, 1); - } else /*stops LG/Sharp multi tuner problems*/ - dvb_usb_lme2510_firmware = 0; - return 0; - } - kfree(adap->fe); - adap->fe = NULL; + st->tuner_config = TUNER_LG; + if (dvb_usb_lme2510_firmware != 1) { + dvb_usb_lme2510_firmware = 1; + ret = lme_firmware_switch(adap->dev->udev, 1); + } else /*stops LG/Sharp multi tuner problems*/ + dvb_usb_lme2510_firmware = 0; + goto end; } st->i2c_gate = 5; @@ -833,28 +834,64 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) if (adap->fe) { info("FE Found Stv0288"); - memcpy(&adap->fe->ops.info.name, - &"DM04_SHARP:BS2F7HZ7395", 22); - adap->fe->ops.set_voltage = dm04_lme2510_set_voltage; st->i2c_tuner_gate_w = 4; st->i2c_tuner_gate_r = 5; st->i2c_tuner_addr = 0xc0; - if (dvb_attach(ix2505v_attach , adap->fe, &lme_tuner, - &adap->dev->i2c_adap)) { - st->tuner_config = TUNER_S7395; - info("TUN Sharp IX2505V silicon tuner"); - if (dvb_usb_lme2510_firmware != 0) { - dvb_usb_lme2510_firmware = 0; - lme_firmware_switch(adap->dev->udev, 1); - } - return 0; + st->tuner_config = TUNER_S7395; + if (dvb_usb_lme2510_firmware != 0) { + dvb_usb_lme2510_firmware = 0; + ret = lme_firmware_switch(adap->dev->udev, 1); } + } else { + info("DM04 Not Supported"); + return -ENODEV; + } + +end: if (ret) { kfree(adap->fe); adap->fe = NULL; + return -ENODEV; } - info("DM04 Not Supported"); - return -ENODEV; + adap->fe->ops.set_voltage = dm04_lme2510_set_voltage; + ret = lme_name(adap); + + return ret; +} + +static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) +{ + struct lme2510_state *st = adap->dev->priv; + char *tun_msg[] = {"", "TDA8263", "IX2505V"}; + int ret = 0; + + switch (st->tuner_config) { + case TUNER_LG: + if (dvb_attach(tda826x_attach, adap->fe, 0xc0, + &adap->dev->i2c_adap, 1)) + ret = st->tuner_config; + break; + case TUNER_S7395: + if (dvb_attach(ix2505v_attach , adap->fe, &lme_tuner, + &adap->dev->i2c_adap)) + ret = st->tuner_config; + break; + default: + break; + } + + if (ret) + info("TUN Found %s tuner", tun_msg[ret]); + else { + info("TUN No tuner found --- reseting device"); + lme_coldreset(adap->dev->udev); + return -ENODEV; + } + + /* Start the Interupt & Remote*/ + ret = lme2510_int_service(adap); + + return ret; } static int lme2510_powerup(struct dvb_usb_device *d, int onoff) @@ -937,6 +974,7 @@ static struct dvb_usb_device_properties lme2510_properties = { { .streaming_ctrl = lme2510_streaming_ctrl, .frontend_attach = dm04_lme2510_frontend_attach, + .tuner_attach = dm04_lme2510_tuner, /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, @@ -957,7 +995,7 @@ static struct dvb_usb_device_properties lme2510_properties = { .generic_bulk_ctrl_endpoint = 0, .num_device_descs = 1, .devices = { - { "DM04 LME2510 DVB-S USB 2.0", + { "DM04_LME2510_DVB-S", { &lme2510_table[0], NULL }, }, @@ -975,6 +1013,7 @@ static struct dvb_usb_device_properties lme2510c_properties = { { .streaming_ctrl = lme2510_streaming_ctrl, .frontend_attach = dm04_lme2510_frontend_attach, + .tuner_attach = dm04_lme2510_tuner, /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, @@ -995,7 +1034,7 @@ static struct dvb_usb_device_properties lme2510c_properties = { .generic_bulk_ctrl_endpoint = 0, .num_device_descs = 1, .devices = { - { "DM04 LME2510C USB2.0", + { "DM04_LME2510C_DVB-S", { &lme2510_table[1], NULL }, }, } @@ -1041,7 +1080,7 @@ void lme2510_exit(struct usb_interface *intf) } static struct usb_driver lme2510_driver = { - .name = "LME2510C_DVBS", + .name = "LME2510C_DVB-S", .probe = lme2510_probe, .disconnect = lme2510_exit, .id_table = lme2510_table, @@ -1069,6 +1108,6 @@ module_init(lme2510_module_init); module_exit(lme2510_module_exit); MODULE_AUTHOR("Malcolm Priestley "); -MODULE_DESCRIPTION("LM2510(C) DVB-S USB2.0"); -MODULE_VERSION("1.71"); +MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); +MODULE_VERSION("1.74"); MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 2a72b39e516bf772e707d5a080d5d07b1c8ac0c0 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 10 Dec 2010 09:39:34 -0300 Subject: [media] zoran: bit-wise vs logical and zr->frame_num is a counter and && was intended here instead of &. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/video/zoran/zoran_device.c index b02007e..e8a2784 100644 --- a/drivers/media/video/zoran/zoran_device.c +++ b/drivers/media/video/zoran/zoran_device.c @@ -1523,7 +1523,7 @@ zoran_irq (int irq, zr->JPEG_missed > 25 || zr->JPEG_error == 1 || ((zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) && - (zr->frame_num & (zr->JPEG_missed > zr->jpg_settings.field_per_buff)))) { + (zr->frame_num && (zr->JPEG_missed > zr->jpg_settings.field_per_buff)))) { error_handler(zr, astat, stat); } -- cgit v0.10.2 From c3353330508aee4390442df2d7f6ce0ef5006185 Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Fri, 17 Dec 2010 06:40:50 -0300 Subject: [media] media: fsl-viu: fix support for streaming with mmap method Streaming using mmap didn't work in the VIU driver. We need to start/stop DMA in streamon/streamoff and free the buffers on release. Add appropriate driver extension now. Signed-off-by: Anatolij Gustschin Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/fsl-viu.c b/drivers/media/video/fsl-viu.c index b8faff2..693e9c0 100644 --- a/drivers/media/video/fsl-viu.c +++ b/drivers/media/video/fsl-viu.c @@ -915,6 +915,8 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) if (fh->type != i) return -EINVAL; + viu_start_dma(fh->dev); + return videobuf_streamon(&fh->vb_vidq); } @@ -927,6 +929,8 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) if (fh->type != i) return -EINVAL; + viu_stop_dma(fh->dev); + return videobuf_streamoff(&fh->vb_vidq); } @@ -1331,6 +1335,7 @@ static int viu_release(struct file *file) viu_stop_dma(dev); videobuf_stop(&fh->vb_vidq); + videobuf_mmap_free(&fh->vb_vidq); kfree(fh); -- cgit v0.10.2 From 10304ca65f8871ad9f6725a7480522034184f55f Mon Sep 17 00:00:00 2001 From: Sam Doshi Date: Sat, 18 Dec 2010 12:58:54 -0300 Subject: [media] drivers:media:dvb: add USB PIDs for Elgato EyeTV Sat Adds USB PIDs for the Elgato EyeTV Sat device. This device is a clone of the Terratec S7. Signed-off-by: Sam Doshi Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c index 9a7837f..57e2444 100644 --- a/drivers/media/dvb/dvb-usb/az6027.c +++ b/drivers/media/dvb/dvb-usb/az6027.c @@ -1089,6 +1089,7 @@ static struct usb_device_id az6027_usb_table[] = { { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_DVBS2CI_V2) }, { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V1) }, { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V2) }, + { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_SAT) }, { }, }; @@ -1134,7 +1135,7 @@ static struct dvb_usb_device_properties az6027_properties = { .i2c_algo = &az6027_i2c_algo, - .num_device_descs = 5, + .num_device_descs = 6, .devices = { { .name = "AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)", @@ -1156,6 +1157,10 @@ static struct dvb_usb_device_properties az6027_properties = { .name = "Technisat SkyStar USB 2 HD CI", .cold_ids = { &az6027_usb_table[4], NULL }, .warm_ids = { NULL }, + }, { + .name = "Elgato EyeTV Sat", + .cold_ids = { &az6027_usb_table[5], NULL }, + .warm_ids = { NULL }, }, { NULL }, } diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 192a40c..1a6310b 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -301,6 +301,7 @@ #define USB_PID_ELGATO_EYETV_DIVERSITY 0x0011 #define USB_PID_ELGATO_EYETV_DTT 0x0021 #define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020 +#define USB_PID_ELGATO_EYETV_SAT 0x002a #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000 #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM 0x5001 #define USB_PID_FRIIO_WHITE 0x0001 -- cgit v0.10.2 From ef330dc2e794c932fcbde3f8abd3f12780d78b47 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sat, 18 Dec 2010 19:05:02 -0300 Subject: [media] saa7164: Remove pointless conditional and save a few bytes in saa7164_downloadfirmware() Hi, release_firmware() just does nothing if passed a NULL pointer. So there's no reason to test before the call in saa7164-fw.c::saa7164_downloadfirmware(). Removing the pointless conditional also saves a few bytes. before: text data bss dec hex filename 7943 112 2144 10199 27d7 drivers/media/video/saa7164/saa7164-fw.o after: text data bss dec hex filename 7931 112 2136 10179 27c3 drivers/media/video/saa7164/saa7164-fw.o Signed-off-by: Jesper Juhl Cc: Steven Toth Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/saa7164/saa7164-fw.c b/drivers/media/video/saa7164/saa7164-fw.c index 22b0232..ebed6f7 100644 --- a/drivers/media/video/saa7164/saa7164-fw.c +++ b/drivers/media/video/saa7164/saa7164-fw.c @@ -608,8 +608,6 @@ int saa7164_downloadfirmware(struct saa7164_dev *dev) ret = 0; out: - if (fw) - release_firmware(fw); - + release_firmware(fw); return ret; } -- cgit v0.10.2 From dcd745b723efc875ec5a8f44be028bd0704b12d6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 20 Dec 2010 09:53:16 -0300 Subject: [media] timblogiw: too large value for strncpy() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a copy and paste error. It should be using sizeof(cap->driver) instead of sizeof(cap->card). Signed-off-by: Dan Carpenter Cc: Richard Rojförs Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/timblogiw.c b/drivers/media/video/timblogiw.c index cf48aa9..700c08a 100644 --- a/drivers/media/video/timblogiw.c +++ b/drivers/media/video/timblogiw.c @@ -241,7 +241,7 @@ static int timblogiw_querycap(struct file *file, void *priv, dev_dbg(&vdev->dev, "%s: Entry\n", __func__); memset(cap, 0, sizeof(*cap)); strncpy(cap->card, TIMBLOGIWIN_NAME, sizeof(cap->card)-1); - strncpy(cap->driver, DRIVER_NAME, sizeof(cap->card)-1); + strncpy(cap->driver, DRIVER_NAME, sizeof(cap->driver) - 1); strlcpy(cap->bus_info, vdev->name, sizeof(cap->bus_info)); cap->version = TIMBLOGIW_VERSION_CODE; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | -- cgit v0.10.2 From 07e80305babb27a332ce0f04a3c38ce495cbe711 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Dec 2010 14:39:25 -0300 Subject: [media] v4l: mem2mem_testdev: remove BKL usage Remove usage of BKL by usign per-device mutex. Signed-off-by: Marek Szyprowski CC: Pawel Osciak Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c index 3b19f5b..c179041 100644 --- a/drivers/media/video/mem2mem_testdev.c +++ b/drivers/media/video/mem2mem_testdev.c @@ -524,7 +524,6 @@ static int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f) { struct m2mtest_q_data *q_data; struct videobuf_queue *vq; - int ret = 0; vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); if (!vq) @@ -534,12 +533,9 @@ static int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f) if (!q_data) return -EINVAL; - mutex_lock(&vq->vb_lock); - if (videobuf_queue_is_busy(vq)) { v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__); - ret = -EBUSY; - goto out; + return -EBUSY; } q_data->fmt = find_format(f); @@ -553,9 +549,7 @@ static int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f) "Setting format for type %d, wxh: %dx%d, fmt: %d\n", f->type, q_data->width, q_data->height, q_data->fmt->fourcc); -out: - mutex_unlock(&vq->vb_lock); - return ret; + return 0; } static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, @@ -845,10 +839,12 @@ static void queue_init(void *priv, struct videobuf_queue *vq, enum v4l2_buf_type type) { struct m2mtest_ctx *ctx = priv; + struct m2mtest_dev *dev = ctx->dev; - videobuf_queue_vmalloc_init(vq, &m2mtest_qops, ctx->dev->v4l2_dev.dev, - &ctx->dev->irqlock, type, V4L2_FIELD_NONE, - sizeof(struct m2mtest_buffer), priv, NULL); + videobuf_queue_vmalloc_init(vq, &m2mtest_qops, dev->v4l2_dev.dev, + &dev->irqlock, type, V4L2_FIELD_NONE, + sizeof(struct m2mtest_buffer), priv, + &dev->dev_mutex); } @@ -920,7 +916,7 @@ static const struct v4l2_file_operations m2mtest_fops = { .open = m2mtest_open, .release = m2mtest_release, .poll = m2mtest_poll, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, .mmap = m2mtest_mmap, }; @@ -965,6 +961,7 @@ static int m2mtest_probe(struct platform_device *pdev) } *vfd = m2mtest_videodev; + vfd->lock = &dev->dev_mutex; ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); if (ret) { -- cgit v0.10.2 From a19a5cd7b328ae457f79092e711d4bd888e1ca50 Mon Sep 17 00:00:00 2001 From: Pete Eberlein Date: Mon, 20 Dec 2010 19:18:59 -0300 Subject: [media] s2255drv: remove BKL Remove BKL ioctl and use unlocked_ioctl with core-assisted locking instead. Signed-off-by: Pete Eberlein Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index a845753..cf03372 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -268,7 +268,7 @@ struct s2255_dev { struct v4l2_device v4l2_dev; atomic_t num_channels; int frames; - struct mutex lock; + struct mutex lock; /* channels[].vdev.lock */ struct mutex open_lock; struct usb_device *udev; struct usb_interface *interface; @@ -780,20 +780,14 @@ static struct videobuf_queue_ops s2255_video_qops = { static int res_get(struct s2255_fh *fh) { - struct s2255_dev *dev = fh->dev; - /* is it free? */ struct s2255_channel *channel = fh->channel; - mutex_lock(&dev->lock); - if (channel->resources) { - /* no, someone else uses it */ - mutex_unlock(&dev->lock); - return 0; - } + /* is it free? */ + if (channel->resources) + return 0; /* no, someone else uses it */ /* it's free, grab it */ channel->resources = 1; fh->resources = 1; dprintk(1, "s2255: res: get\n"); - mutex_unlock(&dev->lock); return 1; } @@ -811,11 +805,8 @@ static int res_check(struct s2255_fh *fh) static void res_free(struct s2255_fh *fh) { struct s2255_channel *channel = fh->channel; - struct s2255_dev *dev = fh->dev; - mutex_lock(&dev->lock); channel->resources = 0; fh->resources = 0; - mutex_unlock(&dev->lock); dprintk(1, "res: put\n"); } @@ -1218,7 +1209,6 @@ static int s2255_set_mode(struct s2255_channel *channel, __le32 *buffer; unsigned long chn_rev; struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev); - mutex_lock(&dev->lock); chn_rev = G_chnmap[channel->idx]; dprintk(3, "%s channel: %d\n", __func__, channel->idx); /* if JPEG, set the quality */ @@ -1235,7 +1225,6 @@ static int s2255_set_mode(struct s2255_channel *channel, buffer = kzalloc(512, GFP_KERNEL); if (buffer == NULL) { dev_err(&dev->udev->dev, "out of mem\n"); - mutex_unlock(&dev->lock); return -ENOMEM; } /* set the mode */ @@ -1260,7 +1249,6 @@ static int s2255_set_mode(struct s2255_channel *channel, } /* clear the restart flag */ channel->mode.restart = 0; - mutex_unlock(&dev->lock); dprintk(1, "%s chn %d, result: %d\n", __func__, channel->idx, res); return res; } @@ -1271,13 +1259,11 @@ static int s2255_cmd_status(struct s2255_channel *channel, u32 *pstatus) __le32 *buffer; u32 chn_rev; struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev); - mutex_lock(&dev->lock); chn_rev = G_chnmap[channel->idx]; dprintk(4, "%s chan %d\n", __func__, channel->idx); buffer = kzalloc(512, GFP_KERNEL); if (buffer == NULL) { dev_err(&dev->udev->dev, "out of mem\n"); - mutex_unlock(&dev->lock); return -ENOMEM; } /* form the get vid status command */ @@ -1297,7 +1283,6 @@ static int s2255_cmd_status(struct s2255_channel *channel, u32 *pstatus) } *pstatus = channel->vidstatus; dprintk(4, "%s, vid status %d\n", __func__, *pstatus); - mutex_unlock(&dev->lock); return res; } @@ -1816,7 +1801,8 @@ static int s2255_open(struct file *file) NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED, - sizeof(struct s2255_buffer), fh, NULL); + sizeof(struct s2255_buffer), + fh, vdev->lock); return 0; } @@ -1899,7 +1885,7 @@ static const struct v4l2_file_operations s2255_fops_v4l = { .open = s2255_open, .release = s2255_release, .poll = s2255_poll, - .ioctl = video_ioctl2, /* V4L2 ioctl handler */ + .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ .mmap = s2255_mmap_v4l, }; @@ -1969,6 +1955,7 @@ static int s2255_probe_v4l(struct s2255_dev *dev) channel->vidq.dev = dev; /* register 4 video devices */ channel->vdev = template; + channel->vdev.lock = &dev->lock; channel->vdev.v4l2_dev = &dev->v4l2_dev; video_set_drvdata(&channel->vdev, channel); if (video_nr == -1) @@ -2675,7 +2662,9 @@ static void s2255_disconnect(struct usb_interface *interface) struct s2255_dev *dev = to_s2255_dev(usb_get_intfdata(interface)); int i; int channels = atomic_read(&dev->num_channels); + mutex_lock(&dev->lock); v4l2_device_disconnect(&dev->v4l2_dev); + mutex_unlock(&dev->lock); /*see comments in the uvc_driver.c usb disconnect function */ atomic_inc(&dev->num_channels); /* unregister each video device. */ -- cgit v0.10.2 From 634b4770539de63581ccdb554426547ced6ded01 Mon Sep 17 00:00:00 2001 From: Theodore Kilgore Date: Fri, 24 Dec 2010 17:06:04 -0300 Subject: [media] gspca - sq905c: Adds the Lego Bionicle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds the Vendor:Product number of the Lego Bionicle camera to the existing gspca/sq905c.c and also a line for the camera in gspca.txt. The camera works "out of the box" with these small changes. So this is just in time for Christmas. Think of the children. Signed-off-by: Theodore Kilgore Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 6a562ee..261776e 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -366,6 +366,7 @@ t613 17a1:0128 TASCORP JPEG Webcam, NGS Cyclops vc032x 17ef:4802 Lenovo Vc0323+MI1310_SOC pac207 2001:f115 D-Link DSB-C120 sq905c 2770:9050 Disney pix micro (CIF) +sq905c 2770:9051 Lego Bionicle sq905c 2770:9052 Disney pix micro 2 (VGA) sq905c 2770:905c All 11 known cameras with this ID sq905 2770:9120 All 24 known cameras with this ID diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c index c2e88b5..8ba1995 100644 --- a/drivers/media/video/gspca/sq905c.c +++ b/drivers/media/video/gspca/sq905c.c @@ -301,6 +301,7 @@ static int sd_start(struct gspca_dev *gspca_dev) static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x2770, 0x905c)}, {USB_DEVICE(0x2770, 0x9050)}, + {USB_DEVICE(0x2770, 0x9051)}, {USB_DEVICE(0x2770, 0x9052)}, {USB_DEVICE(0x2770, 0x913d)}, {} -- cgit v0.10.2 From 3ebd17946448df50b9082412d09955c87a112721 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Sat, 25 Dec 2010 13:07:57 -0300 Subject: [media] gspca - sq930x: Don't register a webcam when there are USB errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sq930x.c b/drivers/media/video/gspca/sq930x.c index 3e4b0b9..74628ed 100644 --- a/drivers/media/video/gspca/sq930x.c +++ b/drivers/media/video/gspca/sq930x.c @@ -687,10 +687,12 @@ static void cmos_probe(struct gspca_dev *gspca_dev) if (gspca_dev->usb_buf[0] != 0) break; } - if (i >= ARRAY_SIZE(probe_order)) + if (i >= ARRAY_SIZE(probe_order)) { err("Unknown sensor"); - else - sd->sensor = probe_order[i]; + gspca_dev->usb_err = -EINVAL; + return; + } + sd->sensor = probe_order[i]; } static void mt9v111_init(struct gspca_dev *gspca_dev) @@ -867,6 +869,9 @@ static int sd_init(struct gspca_dev *gspca_dev) */ reg_r(gspca_dev, SQ930_CTRL_GET_DEV_INFO, 8); + if (gspca_dev->usb_err < 0) + return gspca_dev->usb_err; + /* it returns: * 03 00 12 93 0b f6 c9 00 live! ultra * 03 00 07 93 0b f6 ca 00 live! ultra for notebook @@ -905,10 +910,10 @@ static int sd_init(struct gspca_dev *gspca_dev) else cmos_probe(gspca_dev); } - - PDEBUG(D_PROBE, "Sensor %s", sensor_tb[sd->sensor].name); - - global_init(sd, 1); + if (gspca_dev->usb_err >= 0) { + PDEBUG(D_PROBE, "Sensor %s", sensor_tb[sd->sensor].name); + global_init(sd, 1); + } return gspca_dev->usb_err; } -- cgit v0.10.2 From efd3769269f2ef9a0ad452ea8298b3edcb2f5a62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Sat, 25 Dec 2010 13:11:54 -0300 Subject: [media] gspca - sq930x: Some detected sensors are not handled yet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These are OmniVision's OV7660 and OV9630. Don't register the webcam when they are found. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sq930x.c b/drivers/media/video/gspca/sq930x.c index 74628ed..b1d771b 100644 --- a/drivers/media/video/gspca/sq930x.c +++ b/drivers/media/video/gspca/sq930x.c @@ -693,6 +693,13 @@ static void cmos_probe(struct gspca_dev *gspca_dev) return; } sd->sensor = probe_order[i]; + switch (sd->sensor) { + case SENSOR_OV7660: + case SENSOR_OV9630: + err("Sensor %s not yet treated", sensor_tb[sd->sensor].name); + gspca_dev->usb_err = -EINVAL; + break; + } } static void mt9v111_init(struct gspca_dev *gspca_dev) -- cgit v0.10.2 From f2c5d92ecd4c69a4f86e76d19cb7663f2ebf4781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Sat, 25 Dec 2010 13:19:59 -0300 Subject: [media] gspca - sq930x: Fix a bad comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sq930x.c b/drivers/media/video/gspca/sq930x.c index b1d771b..a4a9881 100644 --- a/drivers/media/video/gspca/sq930x.c +++ b/drivers/media/video/gspca/sq930x.c @@ -912,7 +912,7 @@ static int sd_init(struct gspca_dev *gspca_dev) if (sd->sensor == SENSOR_MI0360) { /* no sensor probe for icam tracer */ - if (gspca_dev->usb_buf[5] == 0xf6) /* if CMOS */ + if (gspca_dev->usb_buf[5] == 0xf6) /* if ccd */ sd->sensor = SENSOR_ICX098BQ; else cmos_probe(gspca_dev); -- cgit v0.10.2 From 76ebc16b87592350e4ea70681855171adf73f055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Sat, 25 Dec 2010 13:22:21 -0300 Subject: [media] gspca - main: Check the isoc packet status before its length MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When an error is set for an isochronous packet, the length of the packet may be null. In this case, the error was not detected and the image was not discarded as it should be. Reported-by: Franck Bourdonnec Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 5a2274b..03381c6 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -320,12 +320,6 @@ static void fill_frame(struct gspca_dev *gspca_dev, for (i = 0; i < urb->number_of_packets; i++) { /* check the packet status and length */ - len = urb->iso_frame_desc[i].actual_length; - if (len == 0) { - if (gspca_dev->empty_packet == 0) - gspca_dev->empty_packet = 1; - continue; - } st = urb->iso_frame_desc[i].status; if (st) { err("ISOC data error: [%d] len=%d, status=%d", @@ -333,6 +327,12 @@ static void fill_frame(struct gspca_dev *gspca_dev, gspca_dev->last_packet_type = DISCARD_PACKET; continue; } + len = urb->iso_frame_desc[i].actual_length; + if (len == 0) { + if (gspca_dev->empty_packet == 0) + gspca_dev->empty_packet = 1; + continue; + } /* let the packet be analyzed by the subdriver */ PDEBUG(D_PACK, "packet [%d] o:%d l:%d", -- cgit v0.10.2 From 668f44a603dd4b3468cecd7d8d6dc525207db94e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Sat, 25 Dec 2010 13:46:14 -0300 Subject: [media] gspca: Use the global error status for get/set streamparm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also, in ov534, don't check the parm type. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 03381c6..92b5dfb 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -1708,12 +1708,13 @@ static int vidioc_g_parm(struct file *filp, void *priv, if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; - gspca_dev->usb_err = 0; - if (gspca_dev->present) - ret = gspca_dev->sd_desc->get_streamparm(gspca_dev, - parm); - else + if (gspca_dev->present) { + gspca_dev->usb_err = 0; + gspca_dev->sd_desc->get_streamparm(gspca_dev, parm); + ret = gspca_dev->usb_err; + } else { ret = -ENODEV; + } mutex_unlock(&gspca_dev->usb_lock); return ret; } @@ -1738,12 +1739,13 @@ static int vidioc_s_parm(struct file *filp, void *priv, if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; - gspca_dev->usb_err = 0; - if (gspca_dev->present) - ret = gspca_dev->sd_desc->set_streamparm(gspca_dev, - parm); - else + if (gspca_dev->present) { + gspca_dev->usb_err = 0; + gspca_dev->sd_desc->set_streamparm(gspca_dev, parm); + ret = gspca_dev->usb_err; + } else { ret = -ENODEV; + } mutex_unlock(&gspca_dev->usb_lock); return ret; } diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index d4d210b..3c8a63b 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -93,7 +93,7 @@ typedef int (*cam_reg_op) (struct gspca_dev *, struct v4l2_dbg_register *); typedef int (*cam_ident_op) (struct gspca_dev *, struct v4l2_dbg_chip_ident *); -typedef int (*cam_streamparm_op) (struct gspca_dev *, +typedef void (*cam_streamparm_op) (struct gspca_dev *, struct v4l2_streamparm *); typedef int (*cam_qmnu_op) (struct gspca_dev *, struct v4l2_querymenu *); diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 88ef03f..0edf939 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -1243,34 +1243,26 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, } /* get stream parameters (framerate) */ -static int sd_get_streamparm(struct gspca_dev *gspca_dev, +static void sd_get_streamparm(struct gspca_dev *gspca_dev, struct v4l2_streamparm *parm) { struct v4l2_captureparm *cp = &parm->parm.capture; struct v4l2_fract *tpf = &cp->timeperframe; struct sd *sd = (struct sd *) gspca_dev; - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - cp->capability |= V4L2_CAP_TIMEPERFRAME; tpf->numerator = 1; tpf->denominator = sd->frame_rate; - - return 0; } /* set stream parameters (framerate) */ -static int sd_set_streamparm(struct gspca_dev *gspca_dev, +static void sd_set_streamparm(struct gspca_dev *gspca_dev, struct v4l2_streamparm *parm) { struct v4l2_captureparm *cp = &parm->parm.capture; struct v4l2_fract *tpf = &cp->timeperframe; struct sd *sd = (struct sd *) gspca_dev; - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - /* Set requested framerate */ sd->frame_rate = tpf->denominator / tpf->numerator; if (gspca_dev->streaming) @@ -1279,8 +1271,6 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, /* Return the actual framerate */ tpf->numerator = 1; tpf->denominator = sd->frame_rate; - - return 0; } /* sub-driver description */ -- cgit v0.10.2 From 7a5a414ccb5bfc0fe277ef1a0e9d1e492a6f083c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Sat, 25 Dec 2010 13:58:45 -0300 Subject: [media] gspca - ov519: Bad detection of some ov7670 sensors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tested-by: jim smyth Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 0ed21db..e1c3b93 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -2676,8 +2676,8 @@ static void ov7xx0_configure(struct sd *sd) high = i2c_r(sd, 0x0a); low = i2c_r(sd, 0x0b); /* info("%x, %x", high, low); */ - if (high == 0x76 && low == 0x73) { - PDEBUG(D_PROBE, "Sensor is an OV7670"); + if (high == 0x76 && (low & 0xf0) == 0x70) { + PDEBUG(D_PROBE, "Sensor is an OV76%02x", low); sd->sensor = SEN_OV7670; } else { PDEBUG(D_PROBE, "Sensor is an OV7610"); -- cgit v0.10.2 From b69a219e0e97441dbeb0262cf85468b61a161399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Sat, 25 Dec 2010 14:01:42 -0300 Subject: [media] gspca - ov534_9: Remove an useless instruction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/video/gspca/ov534_9.c index e831f0d..c5244b4 100644 --- a/drivers/media/video/gspca/ov534_9.c +++ b/drivers/media/video/gspca/ov534_9.c @@ -945,7 +945,6 @@ static void setautogain(struct gspca_dev *gspca_dev) u8 val; /*fixme: should adjust agc/awb/aec by different controls */ - val = sd->autogain; val = sccb_read(gspca_dev, 0x13); /* com8 */ sccb_write(gspca_dev, 0xff, 0x00); if (sd->autogain) -- cgit v0.10.2 From 08af245de0cf6ab5f4ed008ee2bb99273774fce0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 24 Dec 2010 10:33:19 -0300 Subject: [media] V4L: remove V4L1 compatibility mode Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index c21dfc2..9ea1a6d 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -53,21 +53,6 @@ config VIDEO_ALLOW_V4L1 If you are unsure as to whether this is required, answer Y. -config VIDEO_V4L1_COMPAT - bool "Enable Video For Linux API 1 compatible Layer" if !VIDEO_ALLOW_V4L1 - depends on VIDEO_DEV - default y - ---help--- - Enables a compatibility API used by most V4L2 devices to allow - its usage with legacy applications that supports only V4L1 api. - - Documentation for the original API is included in the file - . - - User tools for this are available from - . - - If you are unsure as to whether this is required, answer Y. # # DVB Core diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index d246910..0ac5c61 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -1129,35 +1129,6 @@ static int vidioc_g_chip_ident(struct file *file, void *__fh, core, g_chip_ident, chip); } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *mbuf) -{ - struct saa7146_fh *fh = __fh; - struct videobuf_queue *q = &fh->video_q; - int err, i; - - /* fixme: number of capture buffers and sizes for v4l apps */ - int gbuffers = 2; - int gbufsize = 768 * 576 * 4; - - DEB_D(("VIDIOCGMBUF \n")); - - q = &fh->video_q; - err = videobuf_mmap_setup(q, gbuffers, gbufsize, - V4L2_MEMORY_MMAP); - if (err < 0) - return err; - - gbuffers = err; - memset(mbuf, 0, sizeof(*mbuf)); - mbuf->frames = gbuffers; - mbuf->size = gbuffers * gbufsize; - for (i = 0; i < gbuffers; i++) - mbuf->offsets[i] = i * gbufsize; - return 0; -} -#endif - const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { .vidioc_querycap = vidioc_querycap, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, @@ -1186,9 +1157,6 @@ const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, .vidioc_g_parm = vidioc_g_parm, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif }; /*********************************************************************************/ diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 482f14b..ace7b6e 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -22,10 +22,6 @@ endif obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o -ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y) - obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o -endif - # All i2c modules must come first: obj-$(CONFIG_VIDEO_TUNER) += tuner.o diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 48682af..e41e4ad 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -1809,15 +1809,6 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) -{ - struct au0828_fh *fh = priv; - - return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); -} -#endif - static struct v4l2_file_operations au0828_v4l_fops = { .owner = THIS_MODULE, .open = au0828_v4l2_open, @@ -1861,9 +1852,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_register = vidioc_s_register, #endif .vidioc_g_chip_ident = vidioc_g_chip_ident, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif }; static const struct video_device au0828_video_template = { diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 54fbab9..961d080 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -2597,31 +2597,6 @@ static int bttv_s_fmt_vid_overlay(struct file *file, void *priv, return setup_window_lock(fh, btv, &f->fmt.win, 1); } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) -{ - int retval; - unsigned int i; - struct bttv_fh *fh = priv; - - retval = __videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize, - V4L2_MEMORY_MMAP); - if (retval < 0) { - return retval; - } - - gbuffers = retval; - memset(mbuf, 0, sizeof(*mbuf)); - mbuf->frames = gbuffers; - mbuf->size = gbuffers * gbufsize; - - for (i = 0; i < gbuffers; i++) - mbuf->offsets[i] = i * gbufsize; - - return 0; -} -#endif - static int bttv_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { @@ -3354,9 +3329,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = { .vidioc_streamoff = bttv_streamoff, .vidioc_g_tuner = bttv_g_tuner, .vidioc_s_tuner = bttv_s_tuner, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif .vidioc_g_crop = bttv_g_crop, .vidioc_s_crop = bttv_s_crop, .vidioc_g_fbuf = bttv_g_fbuf, diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 46b433b..7edf80b 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -419,28 +419,6 @@ static int sync(struct camera_data *cam, int frame_nr) /****************************************************************************** * - * ioctl_get_mbuf - * - *****************************************************************************/ -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int ioctl_get_mbuf(void *arg, struct camera_data *cam) -{ - struct video_mbuf *vm; - int i; - vm = arg; - - memset(vm, 0, sizeof(*vm)); - vm->size = cam->frame_size*cam->num_frames; - vm->frames = cam->num_frames; - for (i = 0; i < cam->num_frames; i++) - vm->offsets[i] = cam->frame_size * i; - - return 0; -} -#endif - -/****************************************************************************** - * * ioctl_set_gpio * *****************************************************************************/ @@ -1380,17 +1358,6 @@ static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg) } break; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCGMBUF: - { - struct cpia2_fh *fh = file->private_data; - if(fh->prio != V4L2_PRIORITY_RECORD) { - mutex_unlock(&cam->busy_lock); - return -EBUSY; - } - break; - } -#endif default: break; } @@ -1400,11 +1367,6 @@ static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg) case CPIA2_IOC_SET_GPIO: retval = ioctl_set_gpio(arg, cam); break; -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCGMBUF: /* mmap interface */ - retval = ioctl_get_mbuf(arg, cam); - break; -#endif case VIDIOC_QUERYCAP: retval = ioctl_querycap(arg,cam); break; diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index b13b69f..7e3e8c4 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c @@ -2044,15 +2044,6 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) -{ - struct cx231xx_fh *fh = priv; - - return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); -} -#endif - /* ----------------------------------------------------------- */ /* RADIO ESPECIFIC IOCTLS */ /* ----------------------------------------------------------- */ @@ -2507,9 +2498,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, #endif -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif }; static struct video_device cx231xx_vbi_template; diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 8b2fb8a..796a797 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -1024,35 +1024,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, return 0; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf(struct file *file, void *priv, - struct video_mbuf *mbuf) -{ - struct cx23885_fh *fh = priv; - struct videobuf_queue *q; - struct v4l2_requestbuffers req; - unsigned int i; - int err; - - q = get_queue(fh); - memset(&req, 0, sizeof(req)); - req.type = q->type; - req.count = 8; - req.memory = V4L2_MEMORY_MMAP; - err = videobuf_reqbufs(q, &req); - if (err < 0) - return err; - - mbuf->frames = req.count; - mbuf->size = 0; - for (i = 0; i < mbuf->frames; i++) { - mbuf->offsets[i] = q->bufs[i]->boff; - mbuf->size += q->bufs[i]->bsize; - } - return 0; -} -#endif - static int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p) { @@ -1427,9 +1398,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 62cea95..9a37b83 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1179,15 +1179,6 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, return 0; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf) -{ - struct cx8800_fh *fh = priv; - - return videobuf_cgmbuf (get_queue(fh), mbuf, 8); -} -#endif - static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p) { struct cx8800_fh *fh = priv; @@ -1731,9 +1722,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 908e3bc..7be9bba 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1934,19 +1934,6 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) O_NONBLOCK); } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) -{ - struct em28xx_fh *fh = priv; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); - else - return videobuf_cgmbuf(&fh->vb_vbiq, mbuf, 8); -} -#endif - - /* ----------------------------------------------------------- */ /* RADIO ESPECIFIC IOCTLS */ /* ----------------------------------------------------------- */ @@ -2359,9 +2346,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_register = vidioc_s_register, .vidioc_g_chip_ident = vidioc_g_chip_ident, #endif -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif }; static const struct video_device em28xx_video_template = { diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index aaafa03..58617fc 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -852,8 +852,8 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) #endif default : - ret = v4l_compat_translate_ioctl(file, cmd, - arg, pvr2_v4l2_do_ioctl); + ret = -EINVAL; + break; } pvr2_hdw_commit_ctl(hdw); diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c index 2ef1668..8ca4d22 100644 --- a/drivers/media/video/pwc/pwc-v4l.c +++ b/drivers/media/video/pwc/pwc-v4l.c @@ -362,23 +362,6 @@ long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg) switch (cmd) { -#ifdef CONFIG_VIDEO_V4L1_COMPAT - /* mmap() functions */ - case VIDIOCGMBUF: - { - /* Tell the user program how much memory is needed for a mmap() */ - struct video_mbuf *vm = arg; - int i; - - memset(vm, 0, sizeof(*vm)); - vm->size = pwc_mbufs * pdev->len_per_image; - vm->frames = pwc_mbufs; /* double buffering should be enough for most applications */ - for (i = 0; i < pwc_mbufs; i++) - vm->offsets[i] = i * pdev->len_per_image; - break; - } -#endif - /* V4L2 Layer */ case VIDIOC_QUERYCAP: { diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index cf03372..b63f8ca 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -1097,15 +1097,6 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) return rc; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidioc_cgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) -{ - struct s2255_fh *fh = priv; - - return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); -} -#endif - /* write to the configuration pipe, synchronously */ static int s2255_write_config(struct usb_device *udev, unsigned char *pbuf, int size) @@ -1909,9 +1900,6 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidioc_cgmbuf, -#endif .vidioc_s_jpegcomp = vidioc_s_jpegcomp, .vidioc_g_jpegcomp = vidioc_g_jpegcomp, .vidioc_s_parm = vidioc_s_parm, diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index f0b1573..ad22be2 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -2211,14 +2211,6 @@ static int saa7134_overlay(struct file *file, void *f, unsigned int on) return 0; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) -{ - struct saa7134_fh *fh = file->private_data; - return videobuf_cgmbuf(saa7134_queue(fh), mbuf, 8); -} -#endif - static int saa7134_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p) { @@ -2456,9 +2448,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_streamoff = saa7134_streamoff, .vidioc_g_tuner = saa7134_g_tuner, .vidioc_s_tuner = saa7134_s_tuner, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif .vidioc_g_crop = saa7134_g_crop, .vidioc_s_crop = saa7134_s_crop, .vidioc_g_fbuf = saa7134_g_fbuf, diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 011c0c3..20da6ea 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -1273,9 +1273,6 @@ static const struct v4l2_ioctl_ops usbvision_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, -#ifdef CONFIG_VIDEO_V4L1_COMPAT -/* .vidiocgmbuf = vidiocgmbuf, */ -#endif .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 8cf61e8..9005a8d 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -1035,11 +1035,8 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) return uvc_xu_ctrl_query(chain, arg, 1); default: - if ((ret = v4l_compat_translate_ioctl(file, cmd, arg, - uvc_v4l2_do_ioctl)) == -ENOIOCTLCMD) - uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", - cmd); - return ret; + uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd); + return -EINVAL; } return ret; diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c deleted file mode 100644 index d4ac751..0000000 --- a/drivers/media/video/v4l1-compat.c +++ /dev/null @@ -1,1277 +0,0 @@ -/* - * - * Video for Linux Two - * Backward Compatibility Layer - * - * Support subroutines for providing V4L2 drivers with backward - * compatibility with applications using the old API. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Author: Bill Dirks - * et al. - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static unsigned int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "enable debug messages"); -MODULE_AUTHOR("Bill Dirks"); -MODULE_DESCRIPTION("v4l(1) compatibility layer for v4l2 drivers."); -MODULE_LICENSE("GPL"); - -#define dprintk(fmt, arg...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg);\ - } while (0) - -/* - * I O C T L T R A N S L A T I O N - * - * From here on down is the code for translating the numerous - * ioctl commands from the old API to the new API. - */ - -static int -get_v4l_control(struct file *file, - int cid, - v4l2_kioctl drv) -{ - struct v4l2_queryctrl qctrl2; - struct v4l2_control ctrl2; - int err; - - qctrl2.id = cid; - err = drv(file, VIDIOC_QUERYCTRL, &qctrl2); - if (err < 0) - dprintk("VIDIOC_QUERYCTRL: %d\n", err); - if (err == 0 && !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) { - ctrl2.id = qctrl2.id; - err = drv(file, VIDIOC_G_CTRL, &ctrl2); - if (err < 0) { - dprintk("VIDIOC_G_CTRL: %d\n", err); - return 0; - } - return DIV_ROUND_CLOSEST((ctrl2.value-qctrl2.minimum) * 65535, - qctrl2.maximum - qctrl2.minimum); - } - return 0; -} - -static int -set_v4l_control(struct file *file, - int cid, - int value, - v4l2_kioctl drv) -{ - struct v4l2_queryctrl qctrl2; - struct v4l2_control ctrl2; - int err; - - qctrl2.id = cid; - err = drv(file, VIDIOC_QUERYCTRL, &qctrl2); - if (err < 0) - dprintk("VIDIOC_QUERYCTRL: %d\n", err); - if (err == 0 && - !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED) && - !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED)) { - if (value < 0) - value = 0; - if (value > 65535) - value = 65535; - if (value && qctrl2.type == V4L2_CTRL_TYPE_BOOLEAN) - value = 65535; - ctrl2.id = qctrl2.id; - ctrl2.value = - (value * (qctrl2.maximum - qctrl2.minimum) - + 32767) - / 65535; - ctrl2.value += qctrl2.minimum; - err = drv(file, VIDIOC_S_CTRL, &ctrl2); - if (err < 0) - dprintk("VIDIOC_S_CTRL: %d\n", err); - } - return 0; -} - -/* ----------------------------------------------------------------- */ - -static const unsigned int palette2pixelformat[] = { - [VIDEO_PALETTE_GREY] = V4L2_PIX_FMT_GREY, - [VIDEO_PALETTE_RGB555] = V4L2_PIX_FMT_RGB555, - [VIDEO_PALETTE_RGB565] = V4L2_PIX_FMT_RGB565, - [VIDEO_PALETTE_RGB24] = V4L2_PIX_FMT_BGR24, - [VIDEO_PALETTE_RGB32] = V4L2_PIX_FMT_BGR32, - /* yuv packed pixel */ - [VIDEO_PALETTE_YUYV] = V4L2_PIX_FMT_YUYV, - [VIDEO_PALETTE_YUV422] = V4L2_PIX_FMT_YUYV, - [VIDEO_PALETTE_UYVY] = V4L2_PIX_FMT_UYVY, - /* yuv planar */ - [VIDEO_PALETTE_YUV410P] = V4L2_PIX_FMT_YUV410, - [VIDEO_PALETTE_YUV420] = V4L2_PIX_FMT_YUV420, - [VIDEO_PALETTE_YUV420P] = V4L2_PIX_FMT_YUV420, - [VIDEO_PALETTE_YUV411P] = V4L2_PIX_FMT_YUV411P, - [VIDEO_PALETTE_YUV422P] = V4L2_PIX_FMT_YUV422P, -}; - -static unsigned int __pure -palette_to_pixelformat(unsigned int palette) -{ - if (palette < ARRAY_SIZE(palette2pixelformat)) - return palette2pixelformat[palette]; - else - return 0; -} - -static unsigned int __attribute_const__ -pixelformat_to_palette(unsigned int pixelformat) -{ - int palette = 0; - switch (pixelformat) { - case V4L2_PIX_FMT_GREY: - palette = VIDEO_PALETTE_GREY; - break; - case V4L2_PIX_FMT_RGB555: - palette = VIDEO_PALETTE_RGB555; - break; - case V4L2_PIX_FMT_RGB565: - palette = VIDEO_PALETTE_RGB565; - break; - case V4L2_PIX_FMT_BGR24: - palette = VIDEO_PALETTE_RGB24; - break; - case V4L2_PIX_FMT_BGR32: - palette = VIDEO_PALETTE_RGB32; - break; - /* yuv packed pixel */ - case V4L2_PIX_FMT_YUYV: - palette = VIDEO_PALETTE_YUYV; - break; - case V4L2_PIX_FMT_UYVY: - palette = VIDEO_PALETTE_UYVY; - break; - /* yuv planar */ - case V4L2_PIX_FMT_YUV410: - palette = VIDEO_PALETTE_YUV420; - break; - case V4L2_PIX_FMT_YUV420: - palette = VIDEO_PALETTE_YUV420; - break; - case V4L2_PIX_FMT_YUV411P: - palette = VIDEO_PALETTE_YUV411P; - break; - case V4L2_PIX_FMT_YUV422P: - palette = VIDEO_PALETTE_YUV422P; - break; - } - return palette; -} - -/* ----------------------------------------------------------------- */ - -static int poll_one(struct file *file, struct poll_wqueues *pwq) -{ - int retval = 1; - poll_table *table; - - poll_initwait(pwq); - table = &pwq->pt; - for (;;) { - int mask; - mask = file->f_op->poll(file, table); - if (mask & POLLIN) - break; - table = NULL; - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - poll_schedule(pwq, TASK_INTERRUPTIBLE); - } - poll_freewait(pwq); - return retval; -} - -static int count_inputs( - struct file *file, - v4l2_kioctl drv) -{ - struct v4l2_input input2; - int i; - - for (i = 0;; i++) { - memset(&input2, 0, sizeof(input2)); - input2.index = i; - if (0 != drv(file, VIDIOC_ENUMINPUT, &input2)) - break; - } - return i; -} - -static int check_size( - struct file *file, - v4l2_kioctl drv, - int *maxw, - int *maxh) -{ - struct v4l2_fmtdesc desc2; - struct v4l2_format fmt2; - - memset(&desc2, 0, sizeof(desc2)); - memset(&fmt2, 0, sizeof(fmt2)); - - desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (0 != drv(file, VIDIOC_ENUM_FMT, &desc2)) - goto done; - - fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt2.fmt.pix.width = 10000; - fmt2.fmt.pix.height = 10000; - fmt2.fmt.pix.pixelformat = desc2.pixelformat; - if (0 != drv(file, VIDIOC_TRY_FMT, &fmt2)) - goto done; - - *maxw = fmt2.fmt.pix.width; - *maxh = fmt2.fmt.pix.height; - -done: - return 0; -} - -/* ----------------------------------------------------------------- */ - -static noinline long v4l1_compat_get_capabilities( - struct video_capability *cap, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_framebuffer fbuf; - struct v4l2_capability *cap2; - - cap2 = kzalloc(sizeof(*cap2), GFP_KERNEL); - if (!cap2) { - err = -ENOMEM; - return err; - } - memset(cap, 0, sizeof(*cap)); - memset(&fbuf, 0, sizeof(fbuf)); - - err = drv(file, VIDIOC_QUERYCAP, cap2); - if (err < 0) { - dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %ld\n", err); - goto done; - } - if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) { - err = drv(file, VIDIOC_G_FBUF, &fbuf); - if (err < 0) { - dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %ld\n", err); - memset(&fbuf, 0, sizeof(fbuf)); - } - err = 0; - } - - memcpy(cap->name, cap2->card, - min(sizeof(cap->name), sizeof(cap2->card))); - cap->name[sizeof(cap->name) - 1] = 0; - if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE) - cap->type |= VID_TYPE_CAPTURE; - if (cap2->capabilities & V4L2_CAP_TUNER) - cap->type |= VID_TYPE_TUNER; - if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE) - cap->type |= VID_TYPE_TELETEXT; - if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) - cap->type |= VID_TYPE_OVERLAY; - if (fbuf.capability & V4L2_FBUF_CAP_LIST_CLIPPING) - cap->type |= VID_TYPE_CLIPPING; - - cap->channels = count_inputs(file, drv); - check_size(file, drv, - &cap->maxwidth, &cap->maxheight); - cap->audios = 0; /* FIXME */ - cap->minwidth = 48; /* FIXME */ - cap->minheight = 32; /* FIXME */ - -done: - kfree(cap2); - return err; -} - -static noinline long v4l1_compat_get_frame_buffer( - struct video_buffer *buffer, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_framebuffer fbuf; - - memset(buffer, 0, sizeof(*buffer)); - memset(&fbuf, 0, sizeof(fbuf)); - - err = drv(file, VIDIOC_G_FBUF, &fbuf); - if (err < 0) { - dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %ld\n", err); - goto done; - } - buffer->base = fbuf.base; - buffer->height = fbuf.fmt.height; - buffer->width = fbuf.fmt.width; - - switch (fbuf.fmt.pixelformat) { - case V4L2_PIX_FMT_RGB332: - buffer->depth = 8; - break; - case V4L2_PIX_FMT_RGB555: - buffer->depth = 15; - break; - case V4L2_PIX_FMT_RGB565: - buffer->depth = 16; - break; - case V4L2_PIX_FMT_BGR24: - buffer->depth = 24; - break; - case V4L2_PIX_FMT_BGR32: - buffer->depth = 32; - break; - default: - buffer->depth = 0; - } - if (fbuf.fmt.bytesperline) { - buffer->bytesperline = fbuf.fmt.bytesperline; - if (!buffer->depth && buffer->width) - buffer->depth = ((fbuf.fmt.bytesperline<<3) - + (buffer->width-1)) - / buffer->width; - } else { - buffer->bytesperline = - (buffer->width * buffer->depth + 7) & 7; - buffer->bytesperline >>= 3; - } -done: - return err; -} - -static noinline long v4l1_compat_set_frame_buffer( - struct video_buffer *buffer, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_framebuffer fbuf; - - memset(&fbuf, 0, sizeof(fbuf)); - fbuf.base = buffer->base; - fbuf.fmt.height = buffer->height; - fbuf.fmt.width = buffer->width; - switch (buffer->depth) { - case 8: - fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB332; - break; - case 15: - fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB555; - break; - case 16: - fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB565; - break; - case 24: - fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR24; - break; - case 32: - fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR32; - break; - } - fbuf.fmt.bytesperline = buffer->bytesperline; - err = drv(file, VIDIOC_S_FBUF, &fbuf); - if (err < 0) - dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %ld\n", err); - return err; -} - -static noinline long v4l1_compat_get_win_cap_dimensions( - struct video_window *win, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_format *fmt; - - fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); - if (!fmt) { - err = -ENOMEM; - return err; - } - memset(win, 0, sizeof(*win)); - - fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY; - err = drv(file, VIDIOC_G_FMT, fmt); - if (err < 0) - dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %ld\n", err); - if (err == 0) { - win->x = fmt->fmt.win.w.left; - win->y = fmt->fmt.win.w.top; - win->width = fmt->fmt.win.w.width; - win->height = fmt->fmt.win.w.height; - win->chromakey = fmt->fmt.win.chromakey; - win->clips = NULL; - win->clipcount = 0; - goto done; - } - - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(file, VIDIOC_G_FMT, fmt); - if (err < 0) { - dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %ld\n", err); - goto done; - } - win->x = 0; - win->y = 0; - win->width = fmt->fmt.pix.width; - win->height = fmt->fmt.pix.height; - win->chromakey = 0; - win->clips = NULL; - win->clipcount = 0; -done: - kfree(fmt); - return err; -} - -static noinline long v4l1_compat_set_win_cap_dimensions( - struct video_window *win, - struct file *file, - v4l2_kioctl drv) -{ - long err, err1, err2; - struct v4l2_format *fmt; - - fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); - if (!fmt) { - err = -ENOMEM; - return err; - } - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - drv(file, VIDIOC_STREAMOFF, &fmt->type); - err1 = drv(file, VIDIOC_G_FMT, fmt); - if (err1 < 0) - dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %ld\n", err1); - if (err1 == 0) { - fmt->fmt.pix.width = win->width; - fmt->fmt.pix.height = win->height; - fmt->fmt.pix.field = V4L2_FIELD_ANY; - fmt->fmt.pix.bytesperline = 0; - err = drv(file, VIDIOC_S_FMT, fmt); - if (err < 0) - dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %ld\n", - err); - win->width = fmt->fmt.pix.width; - win->height = fmt->fmt.pix.height; - } - - memset(fmt, 0, sizeof(*fmt)); - fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY; - fmt->fmt.win.w.left = win->x; - fmt->fmt.win.w.top = win->y; - fmt->fmt.win.w.width = win->width; - fmt->fmt.win.w.height = win->height; - fmt->fmt.win.chromakey = win->chromakey; - fmt->fmt.win.clips = (void __user *)win->clips; - fmt->fmt.win.clipcount = win->clipcount; - err2 = drv(file, VIDIOC_S_FMT, fmt); - if (err2 < 0) - dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %ld\n", err2); - - if (err1 != 0 && err2 != 0) - err = err1; - else - err = 0; - kfree(fmt); - return err; -} - -static noinline long v4l1_compat_turn_preview_on_off( - int *on, - struct file *file, - v4l2_kioctl drv) -{ - long err; - enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if (0 == *on) { - /* dirty hack time. But v4l1 has no STREAMOFF - * equivalent in the API, and this one at - * least comes close ... */ - drv(file, VIDIOC_STREAMOFF, &captype); - } - err = drv(file, VIDIOC_OVERLAY, on); - if (err < 0) - dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %ld\n", err); - return err; -} - -static noinline long v4l1_compat_get_input_info( - struct video_channel *chan, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_input input2; - v4l2_std_id sid; - - memset(&input2, 0, sizeof(input2)); - input2.index = chan->channel; - err = drv(file, VIDIOC_ENUMINPUT, &input2); - if (err < 0) { - dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: " - "channel=%d err=%ld\n", chan->channel, err); - goto done; - } - chan->channel = input2.index; - memcpy(chan->name, input2.name, - min(sizeof(chan->name), sizeof(input2.name))); - chan->name[sizeof(chan->name) - 1] = 0; - chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0; - chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0; - switch (input2.type) { - case V4L2_INPUT_TYPE_TUNER: - chan->type = VIDEO_TYPE_TV; - break; - default: - case V4L2_INPUT_TYPE_CAMERA: - chan->type = VIDEO_TYPE_CAMERA; - break; - } - chan->norm = 0; - /* Note: G_STD might not be present for radio receivers, - * so we should ignore any errors. */ - if (drv(file, VIDIOC_G_STD, &sid) == 0) { - if (sid & V4L2_STD_PAL) - chan->norm = VIDEO_MODE_PAL; - if (sid & V4L2_STD_NTSC) - chan->norm = VIDEO_MODE_NTSC; - if (sid & V4L2_STD_SECAM) - chan->norm = VIDEO_MODE_SECAM; - if (sid == V4L2_STD_ALL) - chan->norm = VIDEO_MODE_AUTO; - } -done: - return err; -} - -static noinline long v4l1_compat_set_input( - struct video_channel *chan, - struct file *file, - v4l2_kioctl drv) -{ - long err; - v4l2_std_id sid = 0; - - err = drv(file, VIDIOC_S_INPUT, &chan->channel); - if (err < 0) - dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %ld\n", err); - switch (chan->norm) { - case VIDEO_MODE_PAL: - sid = V4L2_STD_PAL; - break; - case VIDEO_MODE_NTSC: - sid = V4L2_STD_NTSC; - break; - case VIDEO_MODE_SECAM: - sid = V4L2_STD_SECAM; - break; - case VIDEO_MODE_AUTO: - sid = V4L2_STD_ALL; - break; - } - if (0 != sid) { - err = drv(file, VIDIOC_S_STD, &sid); - if (err < 0) - dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %ld\n", err); - } - return err; -} - -static noinline long v4l1_compat_get_picture( - struct video_picture *pict, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_format *fmt; - - fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); - if (!fmt) { - err = -ENOMEM; - return err; - } - - pict->brightness = get_v4l_control(file, - V4L2_CID_BRIGHTNESS, drv); - pict->hue = get_v4l_control(file, - V4L2_CID_HUE, drv); - pict->contrast = get_v4l_control(file, - V4L2_CID_CONTRAST, drv); - pict->colour = get_v4l_control(file, - V4L2_CID_SATURATION, drv); - pict->whiteness = get_v4l_control(file, - V4L2_CID_WHITENESS, drv); - - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(file, VIDIOC_G_FMT, fmt); - if (err < 0) { - dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %ld\n", err); - goto done; - } - - if (fmt->fmt.pix.width) - { - pict->depth = ((fmt->fmt.pix.bytesperline << 3) - + (fmt->fmt.pix.width - 1)) - / fmt->fmt.pix.width; - } else { - err = -EINVAL; - goto done; - } - - pict->palette = pixelformat_to_palette( - fmt->fmt.pix.pixelformat); -done: - kfree(fmt); - return err; -} - -static noinline long v4l1_compat_set_picture( - struct video_picture *pict, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_framebuffer fbuf; - int mem_err = 0, ovl_err = 0; - struct v4l2_format *fmt; - - fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); - if (!fmt) { - err = -ENOMEM; - return err; - } - memset(&fbuf, 0, sizeof(fbuf)); - - set_v4l_control(file, - V4L2_CID_BRIGHTNESS, pict->brightness, drv); - set_v4l_control(file, - V4L2_CID_HUE, pict->hue, drv); - set_v4l_control(file, - V4L2_CID_CONTRAST, pict->contrast, drv); - set_v4l_control(file, - V4L2_CID_SATURATION, pict->colour, drv); - set_v4l_control(file, - V4L2_CID_WHITENESS, pict->whiteness, drv); - /* - * V4L1 uses this ioctl to set both memory capture and overlay - * pixel format, while V4L2 has two different ioctls for this. - * Some cards may not support one or the other, and may support - * different pixel formats for memory vs overlay. - */ - - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(file, VIDIOC_G_FMT, fmt); - /* If VIDIOC_G_FMT failed, then the driver likely doesn't - support memory capture. Trying to set the memory capture - parameters would be pointless. */ - if (err < 0) { - dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %ld\n", err); - mem_err = -1000; /* didn't even try */ - } else if (fmt->fmt.pix.pixelformat != - palette_to_pixelformat(pict->palette)) { - fmt->fmt.pix.pixelformat = palette_to_pixelformat( - pict->palette); - mem_err = drv(file, VIDIOC_S_FMT, fmt); - if (mem_err < 0) - dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n", - mem_err); - } - - err = drv(file, VIDIOC_G_FBUF, &fbuf); - /* If VIDIOC_G_FBUF failed, then the driver likely doesn't - support overlay. Trying to set the overlay parameters - would be quite pointless. */ - if (err < 0) { - dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %ld\n", err); - ovl_err = -1000; /* didn't even try */ - } else if (fbuf.fmt.pixelformat != - palette_to_pixelformat(pict->palette)) { - fbuf.fmt.pixelformat = palette_to_pixelformat( - pict->palette); - ovl_err = drv(file, VIDIOC_S_FBUF, &fbuf); - if (ovl_err < 0) - dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n", - ovl_err); - } - if (ovl_err < 0 && mem_err < 0) { - /* ioctl failed, couldn't set either parameter */ - if (mem_err != -1000) - err = mem_err; - else if (ovl_err == -EPERM) - err = 0; - else - err = ovl_err; - } else - err = 0; - kfree(fmt); - return err; -} - -static noinline long v4l1_compat_get_tuner( - struct video_tuner *tun, - struct file *file, - v4l2_kioctl drv) -{ - long err; - int i; - struct v4l2_tuner tun2; - struct v4l2_standard std2; - v4l2_std_id sid; - - memset(&tun2, 0, sizeof(tun2)); - err = drv(file, VIDIOC_G_TUNER, &tun2); - if (err < 0) { - dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %ld\n", err); - goto done; - } - memcpy(tun->name, tun2.name, - min(sizeof(tun->name), sizeof(tun2.name))); - tun->name[sizeof(tun->name) - 1] = 0; - tun->rangelow = tun2.rangelow; - tun->rangehigh = tun2.rangehigh; - tun->flags = 0; - tun->mode = VIDEO_MODE_AUTO; - - for (i = 0; i < 64; i++) { - memset(&std2, 0, sizeof(std2)); - std2.index = i; - if (0 != drv(file, VIDIOC_ENUMSTD, &std2)) - break; - if (std2.id & V4L2_STD_PAL) - tun->flags |= VIDEO_TUNER_PAL; - if (std2.id & V4L2_STD_NTSC) - tun->flags |= VIDEO_TUNER_NTSC; - if (std2.id & V4L2_STD_SECAM) - tun->flags |= VIDEO_TUNER_SECAM; - } - - /* Note: G_STD might not be present for radio receivers, - * so we should ignore any errors. */ - if (drv(file, VIDIOC_G_STD, &sid) == 0) { - if (sid & V4L2_STD_PAL) - tun->mode = VIDEO_MODE_PAL; - if (sid & V4L2_STD_NTSC) - tun->mode = VIDEO_MODE_NTSC; - if (sid & V4L2_STD_SECAM) - tun->mode = VIDEO_MODE_SECAM; - } - - if (tun2.capability & V4L2_TUNER_CAP_LOW) - tun->flags |= VIDEO_TUNER_LOW; - if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO) - tun->flags |= VIDEO_TUNER_STEREO_ON; - tun->signal = tun2.signal; -done: - return err; -} - -static noinline long v4l1_compat_select_tuner( - struct video_tuner *tun, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_tuner t;/*84 bytes on x86_64*/ - memset(&t, 0, sizeof(t)); - - t.index = tun->tuner; - - err = drv(file, VIDIOC_S_TUNER, &t); - if (err < 0) - dprintk("VIDIOCSTUNER / VIDIOC_S_TUNER: %ld\n", err); - return err; -} - -static noinline long v4l1_compat_get_frequency( - unsigned long *freq, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_frequency freq2; - memset(&freq2, 0, sizeof(freq2)); - - freq2.tuner = 0; - err = drv(file, VIDIOC_G_FREQUENCY, &freq2); - if (err < 0) - dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %ld\n", err); - if (0 == err) - *freq = freq2.frequency; - return err; -} - -static noinline long v4l1_compat_set_frequency( - unsigned long *freq, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_frequency freq2; - memset(&freq2, 0, sizeof(freq2)); - - drv(file, VIDIOC_G_FREQUENCY, &freq2); - freq2.frequency = *freq; - err = drv(file, VIDIOC_S_FREQUENCY, &freq2); - if (err < 0) - dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %ld\n", err); - return err; -} - -static noinline long v4l1_compat_get_audio( - struct video_audio *aud, - struct file *file, - v4l2_kioctl drv) -{ - long err; - int i; - struct v4l2_queryctrl qctrl2; - struct v4l2_audio aud2; - struct v4l2_tuner tun2; - memset(&aud2, 0, sizeof(aud2)); - - err = drv(file, VIDIOC_G_AUDIO, &aud2); - if (err < 0) { - dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %ld\n", err); - goto done; - } - memcpy(aud->name, aud2.name, - min(sizeof(aud->name), sizeof(aud2.name))); - aud->name[sizeof(aud->name) - 1] = 0; - aud->audio = aud2.index; - aud->flags = 0; - i = get_v4l_control(file, V4L2_CID_AUDIO_VOLUME, drv); - if (i >= 0) { - aud->volume = i; - aud->flags |= VIDEO_AUDIO_VOLUME; - } - i = get_v4l_control(file, V4L2_CID_AUDIO_BASS, drv); - if (i >= 0) { - aud->bass = i; - aud->flags |= VIDEO_AUDIO_BASS; - } - i = get_v4l_control(file, V4L2_CID_AUDIO_TREBLE, drv); - if (i >= 0) { - aud->treble = i; - aud->flags |= VIDEO_AUDIO_TREBLE; - } - i = get_v4l_control(file, V4L2_CID_AUDIO_BALANCE, drv); - if (i >= 0) { - aud->balance = i; - aud->flags |= VIDEO_AUDIO_BALANCE; - } - i = get_v4l_control(file, V4L2_CID_AUDIO_MUTE, drv); - if (i >= 0) { - if (i) - aud->flags |= VIDEO_AUDIO_MUTE; - aud->flags |= VIDEO_AUDIO_MUTABLE; - } - aud->step = 1; - qctrl2.id = V4L2_CID_AUDIO_VOLUME; - if (drv(file, VIDIOC_QUERYCTRL, &qctrl2) == 0 && - !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) - aud->step = qctrl2.step; - aud->mode = 0; - - memset(&tun2, 0, sizeof(tun2)); - err = drv(file, VIDIOC_G_TUNER, &tun2); - if (err < 0) { - dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %ld\n", err); - err = 0; - goto done; - } - - if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2) - aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO) - aud->mode = VIDEO_SOUND_STEREO; - else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO) - aud->mode = VIDEO_SOUND_MONO; -done: - return err; -} - -static noinline long v4l1_compat_set_audio( - struct video_audio *aud, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_audio aud2; - struct v4l2_tuner tun2; - - memset(&aud2, 0, sizeof(aud2)); - memset(&tun2, 0, sizeof(tun2)); - - aud2.index = aud->audio; - err = drv(file, VIDIOC_S_AUDIO, &aud2); - if (err < 0) { - dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %ld\n", err); - goto done; - } - - set_v4l_control(file, V4L2_CID_AUDIO_VOLUME, - aud->volume, drv); - set_v4l_control(file, V4L2_CID_AUDIO_BASS, - aud->bass, drv); - set_v4l_control(file, V4L2_CID_AUDIO_TREBLE, - aud->treble, drv); - set_v4l_control(file, V4L2_CID_AUDIO_BALANCE, - aud->balance, drv); - set_v4l_control(file, V4L2_CID_AUDIO_MUTE, - !!(aud->flags & VIDEO_AUDIO_MUTE), drv); - - err = drv(file, VIDIOC_G_TUNER, &tun2); - if (err < 0) - dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %ld\n", err); - if (err == 0) { - switch (aud->mode) { - default: - case VIDEO_SOUND_MONO: - case VIDEO_SOUND_LANG1: - tun2.audmode = V4L2_TUNER_MODE_MONO; - break; - case VIDEO_SOUND_STEREO: - tun2.audmode = V4L2_TUNER_MODE_STEREO; - break; - case VIDEO_SOUND_LANG2: - tun2.audmode = V4L2_TUNER_MODE_LANG2; - break; - } - err = drv(file, VIDIOC_S_TUNER, &tun2); - if (err < 0) - dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %ld\n", err); - } - err = 0; -done: - return err; -} - -static noinline long v4l1_compat_capture_frame( - struct video_mmap *mm, - struct file *file, - v4l2_kioctl drv) -{ - long err; - enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; - struct v4l2_buffer buf; - struct v4l2_format *fmt; - - fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); - if (!fmt) { - err = -ENOMEM; - return err; - } - memset(&buf, 0, sizeof(buf)); - - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(file, VIDIOC_G_FMT, fmt); - if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %ld\n", err); - goto done; - } - if (mm->width != fmt->fmt.pix.width || - mm->height != fmt->fmt.pix.height || - palette_to_pixelformat(mm->format) != - fmt->fmt.pix.pixelformat) { - /* New capture format... */ - fmt->fmt.pix.width = mm->width; - fmt->fmt.pix.height = mm->height; - fmt->fmt.pix.pixelformat = - palette_to_pixelformat(mm->format); - fmt->fmt.pix.field = V4L2_FIELD_ANY; - fmt->fmt.pix.bytesperline = 0; - err = drv(file, VIDIOC_S_FMT, fmt); - if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %ld\n", err); - goto done; - } - } - buf.index = mm->frame; - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(file, VIDIOC_QUERYBUF, &buf); - if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %ld\n", err); - goto done; - } - err = drv(file, VIDIOC_QBUF, &buf); - if (err < 0) { - dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %ld\n", err); - goto done; - } - err = drv(file, VIDIOC_STREAMON, &captype); - if (err < 0) - dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %ld\n", err); -done: - kfree(fmt); - return err; -} - -static noinline long v4l1_compat_sync( - int *i, - struct file *file, - v4l2_kioctl drv) -{ - long err; - enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; - struct v4l2_buffer buf; - struct poll_wqueues *pwq; - - memset(&buf, 0, sizeof(buf)); - buf.index = *i; - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(file, VIDIOC_QUERYBUF, &buf); - if (err < 0) { - /* No such buffer */ - dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %ld\n", err); - goto done; - } - if (!(buf.flags & V4L2_BUF_FLAG_MAPPED)) { - /* Buffer is not mapped */ - err = -EINVAL; - goto done; - } - - /* make sure capture actually runs so we don't block forever */ - err = drv(file, VIDIOC_STREAMON, &captype); - if (err < 0) { - dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %ld\n", err); - goto done; - } - - pwq = kmalloc(sizeof(*pwq), GFP_KERNEL); - /* Loop as long as the buffer is queued, but not done */ - while ((buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)) - == V4L2_BUF_FLAG_QUEUED) { - err = poll_one(file, pwq); - if (err < 0 || /* error or sleep was interrupted */ - err == 0) /* timeout? Shouldn't occur. */ - break; - err = drv(file, VIDIOC_QUERYBUF, &buf); - if (err < 0) - dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %ld\n", err); - } - kfree(pwq); - if (!(buf.flags & V4L2_BUF_FLAG_DONE)) /* not done */ - goto done; - do { - err = drv(file, VIDIOC_DQBUF, &buf); - if (err < 0) - dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %ld\n", err); - } while (err == 0 && buf.index != *i); -done: - return err; -} - -static noinline long v4l1_compat_get_vbi_format( - struct vbi_format *fmt, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_format *fmt2; - - fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); - if (!fmt2) { - err = -ENOMEM; - return err; - } - fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; - - err = drv(file, VIDIOC_G_FMT, fmt2); - if (err < 0) { - dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %ld\n", err); - goto done; - } - if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) { - err = -EINVAL; - goto done; - } - memset(fmt, 0, sizeof(*fmt)); - fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line; - fmt->sampling_rate = fmt2->fmt.vbi.sampling_rate; - fmt->sample_format = VIDEO_PALETTE_RAW; - fmt->start[0] = fmt2->fmt.vbi.start[0]; - fmt->count[0] = fmt2->fmt.vbi.count[0]; - fmt->start[1] = fmt2->fmt.vbi.start[1]; - fmt->count[1] = fmt2->fmt.vbi.count[1]; - fmt->flags = fmt2->fmt.vbi.flags & 0x03; -done: - kfree(fmt2); - return err; -} - -static noinline long v4l1_compat_set_vbi_format( - struct vbi_format *fmt, - struct file *file, - v4l2_kioctl drv) -{ - long err; - struct v4l2_format *fmt2 = NULL; - - if (VIDEO_PALETTE_RAW != fmt->sample_format) { - err = -EINVAL; - return err; - } - - fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); - if (!fmt2) { - err = -ENOMEM; - return err; - } - fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; - fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line; - fmt2->fmt.vbi.sampling_rate = fmt->sampling_rate; - fmt2->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - fmt2->fmt.vbi.start[0] = fmt->start[0]; - fmt2->fmt.vbi.count[0] = fmt->count[0]; - fmt2->fmt.vbi.start[1] = fmt->start[1]; - fmt2->fmt.vbi.count[1] = fmt->count[1]; - fmt2->fmt.vbi.flags = fmt->flags; - err = drv(file, VIDIOC_TRY_FMT, fmt2); - if (err < 0) { - dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %ld\n", err); - goto done; - } - - if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line || - fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate || - fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY || - fmt2->fmt.vbi.start[0] != fmt->start[0] || - fmt2->fmt.vbi.count[0] != fmt->count[0] || - fmt2->fmt.vbi.start[1] != fmt->start[1] || - fmt2->fmt.vbi.count[1] != fmt->count[1] || - fmt2->fmt.vbi.flags != fmt->flags) { - err = -EINVAL; - goto done; - } - err = drv(file, VIDIOC_S_FMT, fmt2); - if (err < 0) - dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %ld\n", err); -done: - kfree(fmt2); - return err; -} - -/* - * This function is exported. - */ -long -v4l_compat_translate_ioctl(struct file *file, - int cmd, - void *arg, - v4l2_kioctl drv) -{ - long err; - - switch (cmd) { - case VIDIOCGCAP: /* capability */ - err = v4l1_compat_get_capabilities(arg, file, drv); - break; - case VIDIOCGFBUF: /* get frame buffer */ - err = v4l1_compat_get_frame_buffer(arg, file, drv); - break; - case VIDIOCSFBUF: /* set frame buffer */ - err = v4l1_compat_set_frame_buffer(arg, file, drv); - break; - case VIDIOCGWIN: /* get window or capture dimensions */ - err = v4l1_compat_get_win_cap_dimensions(arg, file, drv); - break; - case VIDIOCSWIN: /* set window and/or capture dimensions */ - err = v4l1_compat_set_win_cap_dimensions(arg, file, drv); - break; - case VIDIOCCAPTURE: /* turn on/off preview */ - err = v4l1_compat_turn_preview_on_off(arg, file, drv); - break; - case VIDIOCGCHAN: /* get input information */ - err = v4l1_compat_get_input_info(arg, file, drv); - break; - case VIDIOCSCHAN: /* set input */ - err = v4l1_compat_set_input(arg, file, drv); - break; - case VIDIOCGPICT: /* get tone controls & partial capture format */ - err = v4l1_compat_get_picture(arg, file, drv); - break; - case VIDIOCSPICT: /* set tone controls & partial capture format */ - err = v4l1_compat_set_picture(arg, file, drv); - break; - case VIDIOCGTUNER: /* get tuner information */ - err = v4l1_compat_get_tuner(arg, file, drv); - break; - case VIDIOCSTUNER: /* select a tuner input */ - err = v4l1_compat_select_tuner(arg, file, drv); - break; - case VIDIOCGFREQ: /* get frequency */ - err = v4l1_compat_get_frequency(arg, file, drv); - break; - case VIDIOCSFREQ: /* set frequency */ - err = v4l1_compat_set_frequency(arg, file, drv); - break; - case VIDIOCGAUDIO: /* get audio properties/controls */ - err = v4l1_compat_get_audio(arg, file, drv); - break; - case VIDIOCSAUDIO: /* set audio controls */ - err = v4l1_compat_set_audio(arg, file, drv); - break; - case VIDIOCMCAPTURE: /* capture a frame */ - err = v4l1_compat_capture_frame(arg, file, drv); - break; - case VIDIOCSYNC: /* wait for a frame */ - err = v4l1_compat_sync(arg, file, drv); - break; - case VIDIOCGVBIFMT: /* query VBI data capture format */ - err = v4l1_compat_get_vbi_format(arg, file, drv); - break; - case VIDIOCSVBIFMT: - err = v4l1_compat_set_vbi_format(arg, file, drv); - break; - default: - err = -ENOIOCTLCMD; - break; - } - - return err; -} -EXPORT_SYMBOL(v4l_compat_translate_ioctl); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index e30e8df..425ac1e 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -22,212 +22,6 @@ #ifdef CONFIG_COMPAT -#ifdef CONFIG_VIDEO_V4L1_COMPAT -struct video_tuner32 { - compat_int_t tuner; - char name[32]; - compat_ulong_t rangelow, rangehigh; - u32 flags; /* It is really u32 in videodev.h */ - u16 mode, signal; -}; - -static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) -{ - if (!access_ok(VERIFY_READ, up, sizeof(struct video_tuner32)) || - get_user(kp->tuner, &up->tuner) || - copy_from_user(kp->name, up->name, 32) || - get_user(kp->rangelow, &up->rangelow) || - get_user(kp->rangehigh, &up->rangehigh) || - get_user(kp->flags, &up->flags) || - get_user(kp->mode, &up->mode) || - get_user(kp->signal, &up->signal)) - return -EFAULT; - return 0; -} - -static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) -{ - if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_tuner32)) || - put_user(kp->tuner, &up->tuner) || - copy_to_user(up->name, kp->name, 32) || - put_user(kp->rangelow, &up->rangelow) || - put_user(kp->rangehigh, &up->rangehigh) || - put_user(kp->flags, &up->flags) || - put_user(kp->mode, &up->mode) || - put_user(kp->signal, &up->signal)) - return -EFAULT; - return 0; -} - -struct video_buffer32 { - compat_caddr_t base; - compat_int_t height, width, depth, bytesperline; -}; - -static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up) -{ - u32 tmp; - - if (!access_ok(VERIFY_READ, up, sizeof(struct video_buffer32)) || - get_user(tmp, &up->base) || - get_user(kp->height, &up->height) || - get_user(kp->width, &up->width) || - get_user(kp->depth, &up->depth) || - get_user(kp->bytesperline, &up->bytesperline)) - return -EFAULT; - - /* This is actually a physical address stored - * as a void pointer. - */ - kp->base = (void *)(unsigned long) tmp; - - return 0; -} - -static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up) -{ - u32 tmp = (u32)((unsigned long)kp->base); - - if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_buffer32)) || - put_user(tmp, &up->base) || - put_user(kp->height, &up->height) || - put_user(kp->width, &up->width) || - put_user(kp->depth, &up->depth) || - put_user(kp->bytesperline, &up->bytesperline)) - return -EFAULT; - return 0; -} - -struct video_clip32 { - s32 x, y, width, height; /* It's really s32 in videodev.h */ - compat_caddr_t next; -}; - -struct video_window32 { - u32 x, y, width, height, chromakey, flags; - compat_caddr_t clips; - compat_int_t clipcount; -}; - -static int get_video_window32(struct video_window *kp, struct video_window32 __user *up) -{ - struct video_clip __user *uclips; - struct video_clip __user *kclips; - compat_caddr_t p; - int nclips; - - if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32))) - return -EFAULT; - - if (get_user(nclips, &up->clipcount)) - return -EFAULT; - - if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32)) || - get_user(kp->x, &up->x) || - get_user(kp->y, &up->y) || - get_user(kp->width, &up->width) || - get_user(kp->height, &up->height) || - get_user(kp->chromakey, &up->chromakey) || - get_user(kp->flags, &up->flags) || - get_user(kp->clipcount, &up->clipcount)) - return -EFAULT; - - nclips = kp->clipcount; - kp->clips = NULL; - - if (nclips == 0) - return 0; - if (get_user(p, &up->clips)) - return -EFAULT; - uclips = compat_ptr(p); - - /* If nclips < 0, then it is a clipping bitmap of size - VIDEO_CLIPMAP_SIZE */ - if (nclips < 0) { - if (!access_ok(VERIFY_READ, uclips, VIDEO_CLIPMAP_SIZE)) - return -EFAULT; - kp->clips = compat_alloc_user_space(VIDEO_CLIPMAP_SIZE); - if (copy_in_user(kp->clips, uclips, VIDEO_CLIPMAP_SIZE)) - return -EFAULT; - return 0; - } - - /* Otherwise it is an array of video_clip structs. */ - if (!access_ok(VERIFY_READ, uclips, nclips * sizeof(struct video_clip))) - return -EFAULT; - - kp->clips = compat_alloc_user_space(nclips * sizeof(struct video_clip)); - kclips = kp->clips; - while (nclips--) { - int err; - - err = copy_in_user(&kclips->x, &uclips->x, sizeof(kclips->x)); - err |= copy_in_user(&kclips->y, &uclips->y, sizeof(kclips->y)); - err |= copy_in_user(&kclips->width, &uclips->width, sizeof(kclips->width)); - err |= copy_in_user(&kclips->height, &uclips->height, sizeof(kclips->height)); - kclips->next = NULL; - if (err) - return -EFAULT; - kclips++; - uclips++; - } - return 0; -} - -/* You get back everything except the clips... */ -static int put_video_window32(struct video_window *kp, struct video_window32 __user *up) -{ - if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_window32)) || - put_user(kp->x, &up->x) || - put_user(kp->y, &up->y) || - put_user(kp->width, &up->width) || - put_user(kp->height, &up->height) || - put_user(kp->chromakey, &up->chromakey) || - put_user(kp->flags, &up->flags) || - put_user(kp->clipcount, &up->clipcount)) - return -EFAULT; - return 0; -} - -struct video_code32 { - char loadwhat[16]; /* name or tag of file being passed */ - compat_int_t datasize; - compat_uptr_t data; -}; - -static struct video_code __user *get_microcode32(struct video_code32 *kp) -{ - struct video_code __user *up; - - up = compat_alloc_user_space(sizeof(*up)); - - /* - * NOTE! We don't actually care if these fail. If the - * user address is invalid, the native ioctl will do - * the error handling for us - */ - (void) copy_to_user(up->loadwhat, kp->loadwhat, sizeof(up->loadwhat)); - (void) put_user(kp->datasize, &up->datasize); - (void) put_user(compat_ptr(kp->data), &up->data); - return up; -} - -#define VIDIOCGTUNER32 _IOWR('v', 4, struct video_tuner32) -#define VIDIOCSTUNER32 _IOW('v', 5, struct video_tuner32) -#define VIDIOCGWIN32 _IOR('v', 9, struct video_window32) -#define VIDIOCSWIN32 _IOW('v', 10, struct video_window32) -#define VIDIOCGFBUF32 _IOR('v', 11, struct video_buffer32) -#define VIDIOCSFBUF32 _IOW('v', 12, struct video_buffer32) -#define VIDIOCGFREQ32 _IOR('v', 14, u32) -#define VIDIOCSFREQ32 _IOW('v', 15, u32) -#define VIDIOCSMICROCODE32 _IOW('v', 27, struct video_code32) - -#define VIDIOCCAPTURE32 _IOW('v', 8, s32) -#define VIDIOCSYNC32 _IOW('v', 18, s32) -#define VIDIOCSWRITEMODE32 _IOW('v', 25, s32) - -#endif - static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long ret = -ENOIOCTLCMD; @@ -741,13 +535,6 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { union { -#ifdef CONFIG_VIDEO_V4L1_COMPAT - struct video_tuner vt; - struct video_buffer vb; - struct video_window vw; - struct video_code32 vc; - struct video_audio va; -#endif struct v4l2_format v2f; struct v4l2_buffer v2b; struct v4l2_framebuffer v2fb; @@ -763,17 +550,6 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar /* First, convert the command. */ switch (cmd) { -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break; - case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break; - case VIDIOCGWIN32: cmd = VIDIOCGWIN; break; - case VIDIOCSWIN32: cmd = VIDIOCSWIN; break; - case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break; - case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break; - case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break; - case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break; - case VIDIOCSMICROCODE32: cmd = VIDIOCSMICROCODE; break; -#endif case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break; case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break; case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break; @@ -800,46 +576,6 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar } switch (cmd) { -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCSTUNER: - case VIDIOCGTUNER: - err = get_video_tuner32(&karg.vt, up); - compatible_arg = 0; - break; - - case VIDIOCSFBUF: - err = get_video_buffer32(&karg.vb, up); - compatible_arg = 0; - break; - - case VIDIOCSWIN: - err = get_video_window32(&karg.vw, up); - compatible_arg = 0; - break; - - case VIDIOCGWIN: - case VIDIOCGFBUF: - case VIDIOCGFREQ: - compatible_arg = 0; - break; - - case VIDIOCSMICROCODE: - /* Copy the 32-bit "video_code32" to kernel space */ - if (copy_from_user(&karg.vc, up, sizeof(karg.vc))) - return -EFAULT; - /* Convert the 32-bit version to a 64-bit version in user space */ - up = get_microcode32(&karg.vc); - break; - - case VIDIOCSFREQ: - err = get_user(karg.vx, (u32 __user *)up); - compatible_arg = 0; - break; - - case VIDIOCCAPTURE: - case VIDIOCSYNC: - case VIDIOCSWRITEMODE: -#endif case VIDIOC_OVERLAY: case VIDIOC_STREAMON: case VIDIOC_STREAMOFF: @@ -922,23 +658,6 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar return err; switch (cmd) { -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCGTUNER: - err = put_video_tuner32(&karg.vt, up); - break; - - case VIDIOCGWIN: - err = put_video_window32(&karg.vw, up); - break; - - case VIDIOCGFBUF: - err = put_video_buffer32(&karg.vb, up); - break; - - case VIDIOCGFREQ: - err = put_user(((u32)karg.vx), (u32 __user *)up); - break; -#endif case VIDIOC_S_INPUT: case VIDIOC_S_OUTPUT: case VIDIOC_G_INPUT: @@ -981,37 +700,6 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) return ret; switch (cmd) { -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCGCAP: - case VIDIOCGCHAN: - case VIDIOCSCHAN: - case VIDIOCGTUNER32: - case VIDIOCSTUNER32: - case VIDIOCGPICT: - case VIDIOCSPICT: - case VIDIOCCAPTURE32: - case VIDIOCGWIN32: - case VIDIOCSWIN32: - case VIDIOCGFBUF32: - case VIDIOCSFBUF32: - case VIDIOCKEY: - case VIDIOCGFREQ32: - case VIDIOCSFREQ32: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - case VIDIOCSYNC32: - case VIDIOCMCAPTURE: - case VIDIOCGMBUF: - case VIDIOCGUNIT: - case VIDIOCGCAPTURE: - case VIDIOCSCAPTURE: - case VIDIOCSPLAYMODE: - case VIDIOCSWRITEMODE32: - case VIDIOCGPLAYINFO: - case VIDIOCSMICROCODE32: - case VIDIOCGVBIFMT: - case VIDIOCSVBIFMT: -#endif #ifdef __OLD_VIDIOC_ case VIDIOC_OVERLAY32_OLD: case VIDIOC_S_PARM_OLD: @@ -1096,19 +784,6 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) ret = do_video_ioctl(file, cmd, arg); break; -#ifdef CONFIG_VIDEO_V4L1_COMPAT - /* BTTV specific... */ - case _IOW('v', BASE_VIDIOCPRIVATE+0, char [256]): - case _IOR('v', BASE_VIDIOCPRIVATE+1, char [256]): - case _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int): - case _IOW('v' , BASE_VIDIOCPRIVATE+3, char [16]): /* struct bttv_pll_info */ - case _IOR('v' , BASE_VIDIOCPRIVATE+4, int): - case _IOR('v' , BASE_VIDIOCPRIVATE+5, int): - case _IOR('v' , BASE_VIDIOCPRIVATE+6, int): - case _IOR('v' , BASE_VIDIOCPRIVATE+7, int): - ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); - break; -#endif default: printk(KERN_WARNING "compat_ioctl32: " "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index dd9283f..7e47f15 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -18,12 +18,8 @@ #include #define __OLD_VIDIOC_ /* To allow fixing old calls */ -#include #include -#ifdef CONFIG_VIDEO_V4L1 -#include -#endif #include #include #include @@ -183,42 +179,6 @@ static const char *v4l2_memory_names[] = { /* ------------------------------------------------------------------ */ /* debug help functions */ - -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static const char *v4l1_ioctls[] = { - [_IOC_NR(VIDIOCGCAP)] = "VIDIOCGCAP", - [_IOC_NR(VIDIOCGCHAN)] = "VIDIOCGCHAN", - [_IOC_NR(VIDIOCSCHAN)] = "VIDIOCSCHAN", - [_IOC_NR(VIDIOCGTUNER)] = "VIDIOCGTUNER", - [_IOC_NR(VIDIOCSTUNER)] = "VIDIOCSTUNER", - [_IOC_NR(VIDIOCGPICT)] = "VIDIOCGPICT", - [_IOC_NR(VIDIOCSPICT)] = "VIDIOCSPICT", - [_IOC_NR(VIDIOCCAPTURE)] = "VIDIOCCAPTURE", - [_IOC_NR(VIDIOCGWIN)] = "VIDIOCGWIN", - [_IOC_NR(VIDIOCSWIN)] = "VIDIOCSWIN", - [_IOC_NR(VIDIOCGFBUF)] = "VIDIOCGFBUF", - [_IOC_NR(VIDIOCSFBUF)] = "VIDIOCSFBUF", - [_IOC_NR(VIDIOCKEY)] = "VIDIOCKEY", - [_IOC_NR(VIDIOCGFREQ)] = "VIDIOCGFREQ", - [_IOC_NR(VIDIOCSFREQ)] = "VIDIOCSFREQ", - [_IOC_NR(VIDIOCGAUDIO)] = "VIDIOCGAUDIO", - [_IOC_NR(VIDIOCSAUDIO)] = "VIDIOCSAUDIO", - [_IOC_NR(VIDIOCSYNC)] = "VIDIOCSYNC", - [_IOC_NR(VIDIOCMCAPTURE)] = "VIDIOCMCAPTURE", - [_IOC_NR(VIDIOCGMBUF)] = "VIDIOCGMBUF", - [_IOC_NR(VIDIOCGUNIT)] = "VIDIOCGUNIT", - [_IOC_NR(VIDIOCGCAPTURE)] = "VIDIOCGCAPTURE", - [_IOC_NR(VIDIOCSCAPTURE)] = "VIDIOCSCAPTURE", - [_IOC_NR(VIDIOCSPLAYMODE)] = "VIDIOCSPLAYMODE", - [_IOC_NR(VIDIOCSWRITEMODE)] = "VIDIOCSWRITEMODE", - [_IOC_NR(VIDIOCGPLAYINFO)] = "VIDIOCGPLAYINFO", - [_IOC_NR(VIDIOCSMICROCODE)] = "VIDIOCSMICROCODE", - [_IOC_NR(VIDIOCGVBIFMT)] = "VIDIOCGVBIFMT", - [_IOC_NR(VIDIOCSVBIFMT)] = "VIDIOCSVBIFMT" -}; -#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls) -#endif - static const char *v4l2_ioctls[] = { [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP", [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED", @@ -310,15 +270,6 @@ void v4l_printk_ioctl(unsigned int cmd) case 'd': type = "v4l2_int"; break; -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case 'v': - if (_IOC_NR(cmd) >= V4L1_IOCTLS) { - type = "v4l1"; - break; - } - printk("%s", v4l1_ioctls[_IOC_NR(cmd)]); - return; -#endif case 'V': if (_IOC_NR(cmd) >= V4L2_IOCTLS) { type = "v4l2"; @@ -622,20 +573,6 @@ static long __video_do_ioctl(struct file *file, return -EINVAL; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT - /******************************************************** - All other V4L1 calls are handled by v4l1_compat module. - Those calls will be translated into V4L2 calls, and - __video_do_ioctl will be called again, with one or more - V4L2 ioctls. - ********************************************************/ - if (_IOC_TYPE(cmd) == 'v' && cmd != VIDIOCGMBUF && - _IOC_NR(cmd) < BASE_VIDIOCPRIVATE) { - return v4l_compat_translate_ioctl(file, cmd, arg, - __video_do_ioctl); - } -#endif - if ((vfd->debug & V4L2_DEBUG_IOCTL) && !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) { v4l_print_ioctl(vfd->name, cmd); @@ -644,29 +581,6 @@ static long __video_do_ioctl(struct file *file, switch (cmd) { -#ifdef CONFIG_VIDEO_V4L1_COMPAT - /*********************************************************** - Handles calls to the obsoleted V4L1 API - Due to the nature of VIDIOCGMBUF, each driver that supports - V4L1 should implement its own handler for this ioctl. - ***********************************************************/ - - /* --- streaming capture ------------------------------------- */ - case VIDIOCGMBUF: - { - struct video_mbuf *p = arg; - - if (!ops->vidiocgmbuf) - break; - ret = ops->vidiocgmbuf(file, fh, p); - if (!ret) - dbgarg(cmd, "size=%d, frames=%d, offsets=0x%08lx\n", - p->size, p->frames, - (unsigned long)p->offsets); - break; - } -#endif - /* --- capabilities ------------------------------------------ */ case VIDIOC_QUERYCAP: { diff --git a/drivers/media/video/via-camera.c b/drivers/media/video/via-camera.c index 9eda7cc..e25aca5 100644 --- a/drivers/media/video/via-camera.c +++ b/drivers/media/video/via-camera.c @@ -1161,16 +1161,6 @@ out: return ret; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int viacam_vidiocgmbuf(struct file *filp, void *priv, - struct video_mbuf *mbuf) -{ - struct via_camera *cam = priv; - - return videobuf_cgmbuf(&cam->vb_queue, mbuf, 6); -} -#endif - /* G/S_PARM */ static int viacam_g_parm(struct file *filp, void *priv, @@ -1251,9 +1241,6 @@ static const struct v4l2_ioctl_ops viacam_ioctl_ops = { .vidioc_s_parm = viacam_s_parm, .vidioc_enum_framesizes = viacam_enum_framesizes, .vidioc_enum_frameintervals = viacam_enum_frameintervals, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = viacam_vidiocgmbuf, -#endif }; /*----------------------------------------------------------------------------*/ diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 8979f91..de4fa4e 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -1202,33 +1202,3 @@ int videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) return rc; } EXPORT_SYMBOL_GPL(videobuf_mmap_mapper); - -#ifdef CONFIG_VIDEO_V4L1_COMPAT -int videobuf_cgmbuf(struct videobuf_queue *q, - struct video_mbuf *mbuf, int count) -{ - struct v4l2_requestbuffers req; - int rc, i; - - MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - - memset(&req, 0, sizeof(req)); - req.type = q->type; - req.count = count; - req.memory = V4L2_MEMORY_MMAP; - rc = videobuf_reqbufs(q, &req); - if (rc < 0) - return rc; - - mbuf->frames = req.count; - mbuf->size = 0; - for (i = 0; i < mbuf->frames; i++) { - mbuf->offsets[i] = q->bufs[i]->boff; - mbuf->size += PAGE_ALIGN(q->bufs[i]->bsize); - } - - return 0; -} -EXPORT_SYMBOL_GPL(videobuf_cgmbuf); -#endif - diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index ab684e8..9d52060 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -570,29 +570,6 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, } last = first; -#ifdef CONFIG_VIDEO_V4L1_COMPAT - if (size != (vma->vm_end - vma->vm_start)) { - /* look for last buffer to map */ - for (last = first + 1; last < VIDEO_MAX_FRAME; last++) { - if (NULL == q->bufs[last]) - continue; - if (V4L2_MEMORY_MMAP != q->bufs[last]->memory) - continue; - if (q->bufs[last]->map) { - retval = -EBUSY; - goto done; - } - size += PAGE_ALIGN(q->bufs[last]->bsize); - if (size == (vma->vm_end - vma->vm_start)) - break; - } - if (VIDEO_MAX_FRAME == last) { - dprintk(1, "mmap app bug: size invalid [size=0x%lx]\n", - (vma->vm_end - vma->vm_start)); - goto done; - } - } -#endif /* create mapping + update buffer list */ retval = -ENOMEM; diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 9797e5a..c49c393 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -870,15 +870,6 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) file->f_flags & O_NONBLOCK); } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) -{ - struct vivi_dev *dev = video_drvdata(file); - - return videobuf_cgmbuf(&dev->vb_vidq, mbuf, 8); -} -#endif - static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { struct vivi_dev *dev = video_drvdata(file); @@ -1105,9 +1096,6 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = { .vidioc_queryctrl = vidioc_queryctrl, .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_s_ctrl = vidioc_s_ctrl, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif }; static struct video_device vivi_template = { diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c index 3c121fc..27406c3 100644 --- a/drivers/staging/cx25821/cx25821-video.c +++ b/drivers/staging/cx25821/cx25821-video.c @@ -1188,34 +1188,6 @@ int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv, return 0; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -int cx25821_vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) -{ - struct cx25821_fh *fh = priv; - struct videobuf_queue *q; - struct v4l2_requestbuffers req; - unsigned int i; - int err; - - q = get_queue(fh); - memset(&req, 0, sizeof(req)); - req.type = q->type; - req.count = 8; - req.memory = V4L2_MEMORY_MMAP; - err = videobuf_reqbufs(q, &req); - if (err < 0) - return err; - - mbuf->frames = req.count; - mbuf->size = 0; - for (i = 0; i < mbuf->frames; i++) { - mbuf->offsets[i] = q->bufs[i]->boff; - mbuf->size += q->bufs[i]->bsize; - } - return 0; -} -#endif - int cx25821_vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p) { struct cx25821_fh *fh = priv; @@ -2016,9 +1988,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_log_status = vidioc_log_status, .vidioc_g_priority = cx25821_vidioc_g_priority, .vidioc_s_priority = cx25821_vidioc_s_priority, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = cx25821_vidiocgmbuf, -#endif #ifdef TUNER_FLAG .vidioc_g_tuner = cx25821_vidioc_g_tuner, .vidioc_s_tuner = cx25821_vidioc_s_tuner, diff --git a/drivers/staging/cx25821/cx25821-video.h b/drivers/staging/cx25821/cx25821-video.h index 213f37c..f4ee805 100644 --- a/drivers/staging/cx25821/cx25821-video.h +++ b/drivers/staging/cx25821/cx25821-video.h @@ -40,11 +40,6 @@ #include #include -#ifdef CONFIG_VIDEO_V4L1_COMPAT -/* Include V4L1 specific functions. Should be removed soon */ -#include -#endif - #define TUNER_FLAG #define VIDEO_DEBUG 0 @@ -134,7 +129,6 @@ extern int cx25821_vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap); extern int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f); -extern int cx25821_vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf); extern int cx25821_vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p); extern int cx25821_vidioc_querybuf(struct file *file, void *priv, diff --git a/drivers/staging/dt3155v4l/dt3155v4l.c b/drivers/staging/dt3155v4l/dt3155v4l.c index b996697..15d7efe 100644 --- a/drivers/staging/dt3155v4l/dt3155v4l.c +++ b/drivers/staging/dt3155v4l/dt3155v4l.c @@ -876,9 +876,6 @@ static const struct v4l2_ioctl_ops dt3155_ioctl_ops = { .vidioc_s_crop = dt3155_ioc_s_crop, .vidioc_enum_framesizes = dt3155_ioc_enum_framesizes, .vidioc_enum_frameintervals = dt3155_ioc_enum_frameintervals, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = iocgmbuf, -#endif */ }; diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/staging/tm6000/tm6000-video.c index c5690b2..0dae427 100644 --- a/drivers/staging/tm6000/tm6000-video.c +++ b/drivers/staging/tm6000/tm6000-video.c @@ -986,15 +986,6 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) file->f_flags & O_NONBLOCK); } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) -{ - struct tm6000_fh *fh = priv; - - return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); -} -#endif - static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { struct tm6000_fh *fh = priv; @@ -1438,9 +1429,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_querybuf = vidioc_querybuf, .vidioc_qbuf = vidioc_qbuf, .vidioc_dqbuf = vidioc_dqbuf, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, -#endif }; static struct video_device tm6000_template = { diff --git a/include/linux/videodev.h b/include/linux/videodev.h index b19eab1..8a7aead 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -16,24 +16,7 @@ #include #include -#if defined(__MIN_V4L1) && defined (__KERNEL__) - -/* - * Used by those V4L2 core functions that need a minimum V4L1 support, - * in order to allow V4L1 Compatibilty code compilation. - */ - -struct video_mbuf -{ - int size; /* Total memory to map */ - int frames; /* Frames */ - int offsets[VIDEO_MAX_FRAME]; -}; - -#define VIDIOCGMBUF _IOR('v',20, struct video_mbuf) /* Memory map buffer info */ - -#else -#if defined(CONFIG_VIDEO_V4L1_COMPAT) || !defined (__KERNEL__) +#if defined(CONFIG_VIDEO_V4L1) || defined(CONFIG_VIDEO_V4L1_MODULE) || !defined(__KERNEL__) #define VID_TYPE_CAPTURE 1 /* Can capture */ #define VID_TYPE_TUNER 2 /* Can tune */ @@ -328,8 +311,7 @@ struct video_code #define VID_PLAY_RESET 13 #define VID_PLAY_END_MARK 14 -#endif /* CONFIG_VIDEO_V4L1_COMPAT */ -#endif /* __MIN_V4L1 */ +#endif /* CONFIG_VIDEO_V4L1 */ #endif /* __LINUX_VIDEODEV_H */ diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 06daa6e..67df375 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -14,12 +14,7 @@ #include #include #include /* need __user */ -#ifdef CONFIG_VIDEO_V4L1_COMPAT -#define __MIN_V4L1 -#include -#else #include -#endif struct v4l2_fh; @@ -113,10 +108,6 @@ struct v4l2_ioctl_ops { int (*vidioc_overlay) (struct file *file, void *fh, unsigned int i); -#ifdef CONFIG_VIDEO_V4L1_COMPAT - /* buffer type is struct vidio_mbuf * */ - int (*vidiocgmbuf) (struct file *file, void *fh, struct video_mbuf *p); -#endif int (*vidioc_g_fbuf) (struct file *file, void *fh, struct v4l2_framebuffer *a); int (*vidioc_s_fbuf) (struct file *file, void *fh, @@ -300,22 +291,15 @@ extern void v4l_printk_ioctl(unsigned int cmd); extern const char *v4l2_field_names[]; extern const char *v4l2_type_names[]; -/* Compatibility layer interface -- v4l1-compat module */ -typedef long (*v4l2_kioctl)(struct file *file, - unsigned int cmd, void *arg); -#ifdef CONFIG_VIDEO_V4L1_COMPAT -long v4l_compat_translate_ioctl(struct file *file, - int cmd, void *arg, v4l2_kioctl driver_ioctl); -#else -#define v4l_compat_translate_ioctl(file, cmd, arg, ioctl) (-EINVAL) -#endif - #ifdef CONFIG_COMPAT /* 32 Bits compatibility layer for 64 bits processors */ extern long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg); #endif +typedef long (*v4l2_kioctl)(struct file *file, + unsigned int cmd, void *arg); + /* Include support for obsoleted stuff */ extern long video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, v4l2_kioctl func); diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index 1d3835f..90ed895 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -17,10 +17,6 @@ #define _VIDEOBUF_CORE_H #include -#ifdef CONFIG_VIDEO_V4L1_COMPAT -#define __MIN_V4L1 -#include -#endif #include #define UNSET (-1U) @@ -212,10 +208,6 @@ int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b); int videobuf_dqbuf(struct videobuf_queue *q, struct v4l2_buffer *b, int nonblocking); -#ifdef CONFIG_VIDEO_V4L1_COMPAT -int videobuf_cgmbuf(struct videobuf_queue *q, - struct video_mbuf *mbuf, int count); -#endif int videobuf_streamon(struct videobuf_queue *q); int videobuf_streamoff(struct videobuf_queue *q); -- cgit v0.10.2 From ad1ecf8639e51ab8066cd4f37fd36b6b7cbdd8b3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 25 Dec 2010 06:58:01 -0300 Subject: [media] zoran: remove V4L1 compat code and zoran custom ioctls All the functionality is now handled through V4L2. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/Zoran b/Documentation/video4linux/Zoran index 00e3f92..699b60e 100644 --- a/Documentation/video4linux/Zoran +++ b/Documentation/video4linux/Zoran @@ -322,76 +322,11 @@ your IRQs and make sure the card has its own interrupts. 4. Programming interface -This driver conforms to video4linux and video4linux2, both can be used to -use the driver. Since video4linux didn't provide adequate calls to fully -use the cards' features, we've introduced several programming extensions, -which are currently officially accepted in the 2.4.x branch of the kernel. -These extensions are known as the v4l/mjpeg extensions. See zoran.h for -details (structs/ioctls). - -Information - video4linux: -http://linux.bytesex.org/v4l2/API.html -Documentation/video4linux/API.html -/usr/include/linux/videodev.h - -Information - video4linux/mjpeg extensions: -./zoran.h -(also see below) - -Information - video4linux2: -http://linuxtv.org -http://v4l2spec.bytesex.org/ -/usr/include/linux/videodev2.h - -More information on the video4linux/mjpeg extensions, by Serguei -Miridonovi and Rainer Johanni: --- -The ioctls for that interface are as follows: - -BUZIOC_G_PARAMS -BUZIOC_S_PARAMS - -Get and set the parameters of the buz. The user should always do a -BUZIOC_G_PARAMS (with a struct buz_params) to obtain the default -settings, change what he likes and then make a BUZIOC_S_PARAMS call. - -BUZIOC_REQBUFS - -Before being able to capture/playback, the user has to request -the buffers he is wanting to use. Fill the structure -zoran_requestbuffers with the size (recommended: 256*1024) and -the number (recommended 32 up to 256). There are no such restrictions -as for the Video for Linux buffers, you should LEAVE SUFFICIENT -MEMORY for your system however, else strange things will happen .... -On return, the zoran_requestbuffers structure contains number and -size of the actually allocated buffers. -You should use these numbers for doing a mmap of the buffers -into the user space. -The BUZIOC_REQBUFS ioctl also makes it happen, that the next mmap -maps the MJPEG buffer instead of the V4L buffers. - -BUZIOC_QBUF_CAPT -BUZIOC_QBUF_PLAY - -Queue a buffer for capture or playback. The first call also starts -streaming capture. When streaming capture is going on, you may -only queue further buffers or issue syncs until streaming -capture is switched off again with a argument of -1 to -a BUZIOC_QBUF_CAPT/BUZIOC_QBUF_PLAY ioctl. - -BUZIOC_SYNC - -Issue this ioctl when all buffers are queued. This ioctl will -block until the first buffer becomes free for saving its -data to disk (after BUZIOC_QBUF_CAPT) or for reuse (after BUZIOC_QBUF_PLAY). - -BUZIOC_G_STATUS - -Get the status of the input lines (video source connected/norm). +This driver conforms to video4linux2. Support for V4L1 and for the custom +zoran ioctls has been removed in kernel 2.6.38. For programming example, please, look at lavrec.c and lavplay.c code in -lavtools-1.2p2 package (URL: http://www.cicese.mx/) -and the 'examples' directory in the original Buz driver distribution. +the MJPEG-tools (http://mjpeg.sf.net/). Additional notes for software developers: @@ -402,9 +337,6 @@ Additional notes for software developers: standard is "more constant" for current country than geometry settings of a variety of TV capture cards which may work in ITU or square pixel format. --- -Please note that lavplay/lavrec are also included in the MJPEG-tools -(http://mjpeg.sf.net/). =========================== diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h index 27f0555..4bb368e 100644 --- a/drivers/media/video/zoran/zoran.h +++ b/drivers/media/video/zoran/zoran.h @@ -33,15 +33,6 @@ #include -#define ZORAN_VIDMODE_PAL 0 -#define ZORAN_VIDMODE_NTSC 1 -#define ZORAN_VIDMODE_SECAM 2 - -struct zoran_requestbuffers { - unsigned long count; /* Number of buffers for MJPEG grabbing */ - unsigned long size; /* Size PER BUFFER in bytes */ -}; - struct zoran_sync { unsigned long frame; /* number of buffer that has been free'd */ unsigned long length; /* number of code bytes in buffer (capture only) */ @@ -49,102 +40,6 @@ struct zoran_sync { struct timeval timestamp; /* timestamp */ }; -struct zoran_status { - int input; /* Input channel, has to be set prior to BUZIOC_G_STATUS */ - int signal; /* Returned: 1 if valid video signal detected */ - int norm; /* Returned: ZORAN_VIDMODE_PAL or ZORAN_VIDMODE_NTSC */ - int color; /* Returned: 1 if color signal detected */ -}; - -struct zoran_params { - - /* The following parameters can only be queried */ - - int major_version; /* Major version number of driver */ - int minor_version; /* Minor version number of driver */ - - /* Main control parameters */ - - int input; /* Input channel: 0 = Composite, 1 = S-VHS */ - int norm; /* Norm: ZORAN_VIDMODE_PAL or ZORAN_VIDMODE_NTSC */ - int decimation; /* decimation of captured video, - * enlargement of video played back. - * Valid values are 1, 2, 4 or 0. - * 0 is a special value where the user - * has full control over video scaling */ - - /* The following parameters only have to be set if decimation==0, - * for other values of decimation they provide the data how the image is captured */ - - int HorDcm; /* Horizontal decimation: 1, 2 or 4 */ - int VerDcm; /* Vertical decimation: 1 or 2 */ - int TmpDcm; /* Temporal decimation: 1 or 2, - * if TmpDcm==2 in capture every second frame is dropped, - * in playback every frame is played twice */ - int field_per_buff; /* Number of fields per buffer: 1 or 2 */ - int img_x; /* start of image in x direction */ - int img_y; /* start of image in y direction */ - int img_width; /* image width BEFORE decimation, - * must be a multiple of HorDcm*16 */ - int img_height; /* image height BEFORE decimation, - * must be a multiple of VerDcm*8 */ - - /* --- End of parameters for decimation==0 only --- */ - - /* JPEG control parameters */ - - int quality; /* Measure for quality of compressed images. - * Scales linearly with the size of the compressed images. - * Must be beetween 0 and 100, 100 is a compression - * ratio of 1:4 */ - - int odd_even; /* Which field should come first ??? */ - - int APPn; /* Number of APP segment to be written, must be 0..15 */ - int APP_len; /* Length of data in JPEG APPn segment */ - char APP_data[60]; /* Data in the JPEG APPn segment. */ - - int COM_len; /* Length of data in JPEG COM segment */ - char COM_data[60]; /* Data in JPEG COM segment */ - - unsigned long jpeg_markers; /* Which markers should go into the JPEG output. - * Unless you exactly know what you do, leave them untouched. - * Inluding less markers will make the resulting code - * smaller, but there will be fewer applications - * which can read it. - * The presence of the APP and COM marker is - * influenced by APP0_len and COM_len ONLY! */ -#define JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */ -#define JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */ -#define JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ -#define JPEG_MARKER_COM (1<<6) /* Comment segment */ -#define JPEG_MARKER_APP (1<<7) /* App segment, driver will allways use APP0 */ - - int VFIFO_FB; /* Flag for enabling Video Fifo Feedback. - * If this flag is turned on and JPEG decompressing - * is going to the screen, the decompress process - * is stopped every time the Video Fifo is full. - * This enables a smooth decompress to the screen - * but the video output signal will get scrambled */ - - /* Misc */ - - char reserved[312]; /* Makes 512 bytes for this structure */ -}; - -/* -Private IOCTL to set up for displaying MJPEG -*/ -#define BUZIOC_G_PARAMS _IOR ('v', BASE_VIDIOC_PRIVATE+0, struct zoran_params) -#define BUZIOC_S_PARAMS _IOWR('v', BASE_VIDIOC_PRIVATE+1, struct zoran_params) -#define BUZIOC_REQBUFS _IOWR('v', BASE_VIDIOC_PRIVATE+2, struct zoran_requestbuffers) -#define BUZIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOC_PRIVATE+3, int) -#define BUZIOC_QBUF_PLAY _IOW ('v', BASE_VIDIOC_PRIVATE+4, int) -#define BUZIOC_SYNC _IOR ('v', BASE_VIDIOC_PRIVATE+5, struct zoran_sync) -#define BUZIOC_G_STATUS _IOWR('v', BASE_VIDIOC_PRIVATE+6, struct zoran_status) - - -#ifdef __KERNEL__ #define MAJOR_VERSION 0 /* driver major version */ #define MINOR_VERSION 10 /* driver minor version */ @@ -507,6 +402,4 @@ static inline struct zoran *to_zoran(struct v4l2_device *v4l2_dev) #define btor(dat,adr) btwrite((dat) | btread(adr), adr) #define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr) -#endif /* __kernel__ */ - #endif diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index e520abf..9cdc3bb 100644 --- a/drivers/media/video/zoran/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c @@ -943,7 +943,7 @@ zoran_open_init_params (struct zoran *zr) memset(zr->jpg_settings.jpg_comp.COM_data, 0, sizeof(zr->jpg_settings.jpg_comp.COM_data)); zr->jpg_settings.jpg_comp.jpeg_markers = - JPEG_MARKER_DHT | JPEG_MARKER_DQT; + V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT; i = zoran_check_jpg_settings(zr, &zr->jpg_settings, 0); if (i) dprintk(1, KERN_ERR "%s: %s internal error\n", diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 67a52e8..1b67b19 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -1528,323 +1528,6 @@ zoran_set_input (struct zoran *zr, * ioctl routine */ -#ifdef CONFIG_VIDEO_V4L1_COMPAT -static long zoran_default(struct file *file, void *__fh, int cmd, void *arg) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - struct zoran_jpg_settings settings; - - switch (cmd) { - case BUZIOC_G_PARAMS: - { - struct zoran_params *bparams = arg; - - dprintk(3, KERN_DEBUG "%s: BUZIOC_G_PARAMS\n", ZR_DEVNAME(zr)); - - memset(bparams, 0, sizeof(struct zoran_params)); - bparams->major_version = MAJOR_VERSION; - bparams->minor_version = MINOR_VERSION; - - mutex_lock(&zr->resource_lock); - - if (zr->norm & V4L2_STD_NTSC) - bparams->norm = ZORAN_VIDMODE_NTSC; - else if (zr->norm & V4L2_STD_SECAM) - bparams->norm = ZORAN_VIDMODE_SECAM; - else - bparams->norm = ZORAN_VIDMODE_PAL; - - bparams->input = zr->input; - - bparams->decimation = fh->jpg_settings.decimation; - bparams->HorDcm = fh->jpg_settings.HorDcm; - bparams->VerDcm = fh->jpg_settings.VerDcm; - bparams->TmpDcm = fh->jpg_settings.TmpDcm; - bparams->field_per_buff = fh->jpg_settings.field_per_buff; - bparams->img_x = fh->jpg_settings.img_x; - bparams->img_y = fh->jpg_settings.img_y; - bparams->img_width = fh->jpg_settings.img_width; - bparams->img_height = fh->jpg_settings.img_height; - bparams->odd_even = fh->jpg_settings.odd_even; - - bparams->quality = fh->jpg_settings.jpg_comp.quality; - bparams->APPn = fh->jpg_settings.jpg_comp.APPn; - bparams->APP_len = fh->jpg_settings.jpg_comp.APP_len; - memcpy(bparams->APP_data, - fh->jpg_settings.jpg_comp.APP_data, - sizeof(bparams->APP_data)); - bparams->COM_len = zr->jpg_settings.jpg_comp.COM_len; - memcpy(bparams->COM_data, - fh->jpg_settings.jpg_comp.COM_data, - sizeof(bparams->COM_data)); - bparams->jpeg_markers = - fh->jpg_settings.jpg_comp.jpeg_markers; - - mutex_unlock(&zr->resource_lock); - - bparams->VFIFO_FB = 0; - - return 0; - } - - case BUZIOC_S_PARAMS: - { - struct zoran_params *bparams = arg; - int res = 0; - - dprintk(3, KERN_DEBUG "%s: BUZIOC_S_PARAMS\n", ZR_DEVNAME(zr)); - - settings.decimation = bparams->decimation; - settings.HorDcm = bparams->HorDcm; - settings.VerDcm = bparams->VerDcm; - settings.TmpDcm = bparams->TmpDcm; - settings.field_per_buff = bparams->field_per_buff; - settings.img_x = bparams->img_x; - settings.img_y = bparams->img_y; - settings.img_width = bparams->img_width; - settings.img_height = bparams->img_height; - settings.odd_even = bparams->odd_even; - - settings.jpg_comp.quality = bparams->quality; - settings.jpg_comp.APPn = bparams->APPn; - settings.jpg_comp.APP_len = bparams->APP_len; - memcpy(settings.jpg_comp.APP_data, bparams->APP_data, - sizeof(bparams->APP_data)); - settings.jpg_comp.COM_len = bparams->COM_len; - memcpy(settings.jpg_comp.COM_data, bparams->COM_data, - sizeof(bparams->COM_data)); - settings.jpg_comp.jpeg_markers = bparams->jpeg_markers; - - mutex_lock(&zr->resource_lock); - - if (zr->codec_mode != BUZ_MODE_IDLE) { - dprintk(1, - KERN_ERR - "%s: BUZIOC_S_PARAMS called, but Buz in capture/playback mode\n", - ZR_DEVNAME(zr)); - res = -EINVAL; - goto sparams_unlock_and_return; - } - - /* Check the params first before overwriting our - * nternal values */ - if (zoran_check_jpg_settings(zr, &settings, 0)) { - res = -EINVAL; - goto sparams_unlock_and_return; - } - - fh->jpg_settings = settings; -sparams_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - return res; - } - - case BUZIOC_REQBUFS: - { - struct zoran_requestbuffers *breq = arg; - int res = 0; - - dprintk(3, - KERN_DEBUG - "%s: BUZIOC_REQBUFS - count=%lu, size=%lu\n", - ZR_DEVNAME(zr), breq->count, breq->size); - - /* Enforce reasonable lower and upper limits */ - if (breq->count < 4) - breq->count = 4; /* Could be choosen smaller */ - if (breq->count > jpg_nbufs) - breq->count = jpg_nbufs; - breq->size = PAGE_ALIGN(breq->size); - if (breq->size < 8192) - breq->size = 8192; /* Arbitrary */ - /* breq->size is limited by 1 page for the stat_com - * tables to a Maximum of 2 MB */ - if (breq->size > jpg_bufsize) - breq->size = jpg_bufsize; - - mutex_lock(&zr->resource_lock); - - if (fh->buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: BUZIOC_REQBUFS - buffers already allocated\n", - ZR_DEVNAME(zr)); - res = -EBUSY; - goto jpgreqbuf_unlock_and_return; - } - - /* The next mmap will map the MJPEG buffers - could - * also be *_PLAY, but it doesn't matter here */ - map_mode_jpg(fh, 0); - fh->buffers.num_buffers = breq->count; - fh->buffers.buffer_size = breq->size; - - if (jpg_fbuffer_alloc(fh)) { - res = -ENOMEM; - goto jpgreqbuf_unlock_and_return; - } - -jpgreqbuf_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - return res; - } - - case BUZIOC_QBUF_CAPT: - { - int *frame = arg, res; - - dprintk(3, KERN_DEBUG "%s: BUZIOC_QBUF_CAPT - frame=%d\n", - ZR_DEVNAME(zr), *frame); - - mutex_lock(&zr->resource_lock); - res = jpg_qbuf(fh, *frame, BUZ_MODE_MOTION_COMPRESS); - mutex_unlock(&zr->resource_lock); - - return res; - } - - case BUZIOC_QBUF_PLAY: - { - int *frame = arg, res; - - dprintk(3, KERN_DEBUG "%s: BUZIOC_QBUF_PLAY - frame=%d\n", - ZR_DEVNAME(zr), *frame); - - mutex_lock(&zr->resource_lock); - res = jpg_qbuf(fh, *frame, BUZ_MODE_MOTION_DECOMPRESS); - mutex_unlock(&zr->resource_lock); - - return res; - } - - case BUZIOC_SYNC: - { - struct zoran_sync *bsync = arg; - int res; - - dprintk(3, KERN_DEBUG "%s: BUZIOC_SYNC\n", ZR_DEVNAME(zr)); - - mutex_lock(&zr->resource_lock); - - if (fh->map_mode == ZORAN_MAP_MODE_RAW) { - dprintk(2, KERN_WARNING - "%s: %s - not in jpg capture mode\n", - ZR_DEVNAME(zr), __func__); - res = -EINVAL; - } else { - res = jpg_sync(fh, bsync); - } - mutex_unlock(&zr->resource_lock); - - return res; - } - - case BUZIOC_G_STATUS: - { - struct zoran_status *bstat = arg; - int status = 0, res = 0; - v4l2_std_id norm; - - dprintk(3, KERN_DEBUG "%s: BUZIOC_G_STATUS\n", ZR_DEVNAME(zr)); - - if (zr->codec_mode != BUZ_MODE_IDLE) { - dprintk(1, - KERN_ERR - "%s: BUZIOC_G_STATUS called but Buz in capture/playback mode\n", - ZR_DEVNAME(zr)); - return -EINVAL; - } - - mutex_lock(&zr->resource_lock); - - if (zr->codec_mode != BUZ_MODE_IDLE) { - dprintk(1, - KERN_ERR - "%s: BUZIOC_G_STATUS called, but Buz in capture/playback mode\n", - ZR_DEVNAME(zr)); - res = -EINVAL; - goto gstat_unlock_and_return; - } - - decoder_call(zr, video, s_routing, - zr->card.input[bstat->input].muxsel, 0, 0); - - /* sleep 1 second */ - ssleep(1); - - /* Get status of video decoder */ - decoder_call(zr, video, querystd, &norm); - decoder_call(zr, video, g_input_status, &status); - - /* restore previous input and norm */ - decoder_call(zr, video, s_routing, - zr->card.input[zr->input].muxsel, 0, 0); -gstat_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - if (!res) { - bstat->signal = - (status & V4L2_IN_ST_NO_SIGNAL) ? 0 : 1; - if (norm & V4L2_STD_NTSC) - bstat->norm = ZORAN_VIDMODE_NTSC; - else if (norm & V4L2_STD_SECAM) - bstat->norm = ZORAN_VIDMODE_SECAM; - else - bstat->norm = ZORAN_VIDMODE_PAL; - - bstat->color = - (status & V4L2_IN_ST_NO_COLOR) ? 0 : 1; - } - - return res; - } - - default: - return -EINVAL; - } -} - -static int zoran_vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *vmbuf) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - int i, res = 0; - - - mutex_lock(&zr->resource_lock); - - if (fh->buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: VIDIOCGMBUF - buffers already allocated\n", - ZR_DEVNAME(zr)); - res = -EINVAL; - goto v4l1reqbuf_unlock_and_return; - } - - /* The next mmap will map the V4L buffers */ - map_mode_raw(fh); - - if (v4l_fbuffer_alloc(fh)) { - res = -ENOMEM; - goto v4l1reqbuf_unlock_and_return; - } - - vmbuf->size = fh->buffers.num_buffers * fh->buffers.buffer_size; - vmbuf->frames = fh->buffers.num_buffers; - for (i = 0; i < vmbuf->frames; i++) - vmbuf->offsets[i] = i * fh->buffers.buffer_size; - -v4l1reqbuf_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - return res; -} -#endif - static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability *cap) { struct zoran_fh *fh = __fh; @@ -3364,10 +3047,6 @@ static const struct v4l2_ioctl_ops zoran_ioctl_ops = { .vidioc_queryctrl = zoran_queryctrl, .vidioc_s_ctrl = zoran_s_ctrl, .vidioc_g_ctrl = zoran_g_ctrl, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidioc_default = zoran_default, - .vidiocgmbuf = zoran_vidiocgmbuf, -#endif }; /* please use zr->resource_lock consistently and kill this wrapper */ -- cgit v0.10.2 From 41d9931c5ae014fbab8bf612c70b8e7ff16f4641 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 25 Dec 2010 07:04:16 -0300 Subject: [media] videobuf-dma-sg: remove obsolete comments Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 9d52060..ddb8f4b 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -543,14 +543,6 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, retval = -EINVAL; - /* This function maintains backwards compatibility with V4L1 and will - * map more than one buffer if the vma length is equal to the combined - * size of multiple buffers than it will map them together. See - * VIDIOCGMBUF in the v4l spec - * - * TODO: Allow drivers to specify if they support this mode - */ - BUG_ON(!mem); MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); -- cgit v0.10.2 From e4ea644d3e59436f12e43df5d17fdf4fcf7c5fa7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 25 Dec 2010 07:15:22 -0300 Subject: [media] documentation: update some files to reflect the V4L1 compat removal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/meye.txt b/Documentation/video4linux/meye.txt index bf3af5f..34e2842 100644 --- a/Documentation/video4linux/meye.txt +++ b/Documentation/video4linux/meye.txt @@ -45,8 +45,6 @@ module argument syntax (= when passing the option to the module or meye.= on the kernel boot line when meye is statically linked into the kernel). Those options are: - forcev4l1: force use of V4L1 API instead of V4L2 - gbuffers: number of capture buffers, default is 2 (32 max) gbufsize: size of each capture buffer, default is 614400 @@ -79,9 +77,8 @@ Usage: Private API: ------------ - The driver supports frame grabbing with the video4linux API - (either v4l1 or v4l2), so all video4linux tools (like xawtv) - should work with this driver. + The driver supports frame grabbing with the video4linux API, + so all video4linux tools (like xawtv) should work with this driver. Besides the video4linux interface, the driver has a private interface for accessing the Motion Eye extended parameters (camera sharpness, @@ -123,7 +120,4 @@ Private API: Bugs / Todo: ------------ - - the driver could be much cleaned up by removing the v4l1 support. - However, this means all v4l1-only applications will stop working. - - 'motioneye' still uses the meye private v4l1 API extensions. diff --git a/Documentation/video4linux/videobuf b/Documentation/video4linux/videobuf index 17a1f9a..1d00d7f 100644 --- a/Documentation/video4linux/videobuf +++ b/Documentation/video4linux/videobuf @@ -247,8 +247,6 @@ calls. The relevant helper functions are: int nonblocking); int videobuf_streamon(struct videobuf_queue *q); int videobuf_streamoff(struct videobuf_queue *q); - int videobuf_cgmbuf(struct videobuf_queue *q, struct video_mbuf *mbuf, - int count); So, for example, a VIDIOC_REQBUFS call turns into a call to the driver's vidioc_reqbufs() callback which, in turn, usually only needs to locate the @@ -258,10 +256,7 @@ boilerplate in a lot of V4L2 drivers. The vidioc_streamon() and vidioc_streamoff() functions will be a bit more complex, of course, since they will also need to deal with starting and -stopping the capture engine. videobuf_cgmbuf(), called from the driver's -vidiocgmbuf() function, only exists if the V4L1 compatibility module has -been selected with CONFIG_VIDEO_V4L1_COMPAT, so its use must be surrounded -with #ifdef directives. +stopping the capture engine. Buffer allocation -- cgit v0.10.2 From 5772dcaa790851ec068afcd0d1f160d801b1126e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 25 Dec 2010 07:20:34 -0300 Subject: [media] usbvideo: remove deprecated drivers Remove ibmcam, konicawc and ultracam drivers. There are replaced by gspca drivers. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig index dfa7fc6..357860d 100644 --- a/drivers/media/video/usbvideo/Kconfig +++ b/drivers/media/video/usbvideo/Kconfig @@ -10,36 +10,3 @@ config USB_VICAM To compile this driver as a module, choose M here: the module will be called vicam. - -config USB_IBMCAM - tristate "USB IBM (Xirlink) C-it Camera support (DEPRECATED)" - depends on VIDEO_V4L1 - select VIDEO_USBVIDEO - ---help--- - This driver is DEPRECATED please use the gspca xirlink_cit module - instead. - - Say Y here if you want to connect a IBM "C-It" camera, also known as - "Xirlink PC Camera" to your computer's USB port. - - To compile this driver as a module, choose M here: the - module will be called ibmcam. - - This camera has several configuration options which - can be specified when you load the module. Read - to learn more. - -config USB_KONICAWC - tristate "USB Konica Webcam support (DEPRECATED)" - depends on VIDEO_V4L1 - select VIDEO_USBVIDEO - ---help--- - This driver is DEPRECATED (and known to crash) please use the - gspca konica module instead. - - Say Y here if you want support for webcams based on a Konica - chipset. This is known to work with the Intel YC76 webcam. - - To compile this driver as a module, choose M here: the - module will be called konicawc. - diff --git a/drivers/media/video/usbvideo/Makefile b/drivers/media/video/usbvideo/Makefile index bb52eb8..3c99a9a 100644 --- a/drivers/media/video/usbvideo/Makefile +++ b/drivers/media/video/usbvideo/Makefile @@ -1,4 +1,2 @@ obj-$(CONFIG_VIDEO_USBVIDEO) += usbvideo.o -obj-$(CONFIG_USB_IBMCAM) += ibmcam.o ultracam.o -obj-$(CONFIG_USB_KONICAWC) += konicawc.o obj-$(CONFIG_USB_VICAM) += vicam.o diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c deleted file mode 100644 index b085496..0000000 --- a/drivers/media/video/usbvideo/ibmcam.c +++ /dev/null @@ -1,3977 +0,0 @@ -/* - * USB IBM C-It Video Camera driver - * - * Supports Xirlink C-It Video Camera, IBM PC Camera, - * IBM NetCamera and Veo Stingray. - * - * This driver is based on earlier work of: - * - * (C) Copyright 1999 Johannes Erdfelt - * (C) Copyright 1999 Randy Dunlap - * - * 5/24/00 Removed optional (and unnecessary) locking of the driver while - * the device remains plugged in. Corrected race conditions in ibmcam_open - * and ibmcam_probe() routines using this as a guideline: - */ - -#include -#include -#include - -#include "usbvideo.h" - -#define IBMCAM_VENDOR_ID 0x0545 -#define IBMCAM_PRODUCT_ID 0x8080 -#define NETCAM_PRODUCT_ID 0x8002 /* IBM NetCamera, close to model 2 */ -#define VEO_800C_PRODUCT_ID 0x800C /* Veo Stingray, repackaged Model 2 */ -#define VEO_800D_PRODUCT_ID 0x800D /* Veo Stingray, repackaged Model 4 */ - -#define MAX_IBMCAM 4 /* How many devices we allow to connect */ -#define USES_IBMCAM_PUTPIXEL 0 /* 0=Fast/oops 1=Slow/secure */ - -/* Header signatures */ - -/* Model 1 header: 00 FF 00 xx */ -#define HDRSIG_MODEL1_128x96 0x06 /* U Y V Y ... */ -#define HDRSIG_MODEL1_176x144 0x0e /* U Y V Y ... */ -#define HDRSIG_MODEL1_352x288 0x00 /* V Y U Y ... */ - -#define IBMCAM_MODEL_1 1 /* XVP-501, 3 interfaces, rev. 0.02 */ -#define IBMCAM_MODEL_2 2 /* KSX-X9903, 2 interfaces, rev. 3.0a */ -#define IBMCAM_MODEL_3 3 /* KSX-X9902, 2 interfaces, rev. 3.01 */ -#define IBMCAM_MODEL_4 4 /* IBM NetCamera, 0545/8002/3.0a */ - -/* Video sizes supported */ -#define VIDEOSIZE_128x96 VIDEOSIZE(128, 96) -#define VIDEOSIZE_176x144 VIDEOSIZE(176,144) -#define VIDEOSIZE_352x288 VIDEOSIZE(352,288) -#define VIDEOSIZE_320x240 VIDEOSIZE(320,240) -#define VIDEOSIZE_352x240 VIDEOSIZE(352,240) -#define VIDEOSIZE_640x480 VIDEOSIZE(640,480) -#define VIDEOSIZE_160x120 VIDEOSIZE(160,120) - -/* Video sizes supported */ -enum { - SIZE_128x96 = 0, - SIZE_160x120, - SIZE_176x144, - SIZE_320x240, - SIZE_352x240, - SIZE_352x288, - SIZE_640x480, - /* Add/remove/rearrange items before this line */ - SIZE_LastItem -}; - -/* - * This structure lives in uvd->user field. - */ -typedef struct { - int initialized; /* Had we already sent init sequence? */ - int camera_model; /* What type of IBM camera we got? */ - int has_hdr; -} ibmcam_t; -#define IBMCAM_T(uvd) ((ibmcam_t *)((uvd)->user_data)) - -static struct usbvideo *cams; - -static int debug; - -static int flags; /* = FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */ - -static const int min_canvasWidth = 8; -static const int min_canvasHeight = 4; - -static int lighting = 1; /* Medium */ - -#define SHARPNESS_MIN 0 -#define SHARPNESS_MAX 6 -static int sharpness = 4; /* Low noise, good details */ - -#define FRAMERATE_MIN 0 -#define FRAMERATE_MAX 6 -static int framerate = -1; - -static int size = SIZE_352x288; - -/* - * Here we define several initialization variables. They may - * be used to automatically set color, hue, brightness and - * contrast to desired values. This is particularly useful in - * case of webcams (which have no controls and no on-screen - * output) and also when a client V4L software is used that - * does not have some of those controls. In any case it's - * good to have startup values as options. - * - * These values are all in [0..255] range. This simplifies - * operation. Note that actual values of V4L variables may - * be scaled up (as much as << 8). User can see that only - * on overlay output, however, or through a V4L client. - */ -static int init_brightness = 128; -static int init_contrast = 192; -static int init_color = 128; -static int init_hue = 128; -static int hue_correction = 128; - -/* Settings for camera model 2 */ -static int init_model2_rg2 = -1; -static int init_model2_sat = -1; -static int init_model2_yb = -1; - -/* 01.01.08 - Added for RCA video in support -LO */ -/* Settings for camera model 3 */ -static int init_model3_input; - -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); -module_param(flags, int, 0); -MODULE_PARM_DESC(flags, "Bitfield: 0=VIDIOCSYNC, 1=B/W, 2=show hints, 3=show stats, 4=test pattern, 5=separate frames, 6=clean frames"); -module_param(framerate, int, 0); -MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)"); -module_param(lighting, int, 0); -MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light"); -module_param(sharpness, int, 0); -MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)"); -module_param(size, int, 0); -MODULE_PARM_DESC(size, "Image size: 0=128x96 1=160x120 2=176x144 3=320x240 4=352x240 5=352x288 6=640x480 (default=5)"); -module_param(init_brightness, int, 0); -MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)"); -module_param(init_contrast, int, 0); -MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)"); -module_param(init_color, int, 0); -MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)"); -module_param(init_hue, int, 0); -MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)"); -module_param(hue_correction, int, 0); -MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)"); - -module_param(init_model2_rg2, int, 0); -MODULE_PARM_DESC(init_model2_rg2, "Model2 preconfiguration: 0-255 (default=47)"); -module_param(init_model2_sat, int, 0); -MODULE_PARM_DESC(init_model2_sat, "Model2 preconfiguration: 0-255 (default=52)"); -module_param(init_model2_yb, int, 0); -MODULE_PARM_DESC(init_model2_yb, "Model2 preconfiguration: 0-255 (default=160)"); - -/* 01.01.08 - Added for RCA video in support -LO */ -module_param(init_model3_input, int, 0); -MODULE_PARM_DESC(init_model3_input, "Model3 input: 0=CCD 1=RCA"); - -MODULE_AUTHOR ("Dmitri"); -MODULE_DESCRIPTION ("IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000"); -MODULE_LICENSE("GPL"); - -/* Still mysterious i2c commands */ -static const unsigned short unknown_88 = 0x0088; -static const unsigned short unknown_89 = 0x0089; -static const unsigned short bright_3x[3] = { 0x0031, 0x0032, 0x0033 }; -static const unsigned short contrast_14 = 0x0014; -static const unsigned short light_27 = 0x0027; -static const unsigned short sharp_13 = 0x0013; - -/* i2c commands for Model 2 cameras */ -static const unsigned short mod2_brightness = 0x001a; /* $5b .. $ee; default=$5a */ -static const unsigned short mod2_set_framerate = 0x001c; /* 0 (fast).. $1F (slow) */ -static const unsigned short mod2_color_balance_rg2 = 0x001e; /* 0 (red) .. $7F (green) */ -static const unsigned short mod2_saturation = 0x0020; /* 0 (b/w) - $7F (full color) */ -static const unsigned short mod2_color_balance_yb = 0x0022; /* 0..$7F, $50 is about right */ -static const unsigned short mod2_hue = 0x0024; /* 0..$7F, $70 is about right */ -static const unsigned short mod2_sensitivity = 0x0028; /* 0 (min) .. $1F (max) */ - -struct struct_initData { - unsigned char req; - unsigned short value; - unsigned short index; -}; - -/* - * ibmcam_size_to_videosize() - * - * This procedure converts module option 'size' into the actual - * videosize_t that defines the image size in pixels. We need - * simplified 'size' because user wants a simple enumerated list - * of choices, not an infinite set of possibilities. - */ -static videosize_t ibmcam_size_to_videosize(int size) -{ - videosize_t vs = VIDEOSIZE_352x288; - RESTRICT_TO_RANGE(size, 0, (SIZE_LastItem-1)); - switch (size) { - case SIZE_128x96: - vs = VIDEOSIZE_128x96; - break; - case SIZE_160x120: - vs = VIDEOSIZE_160x120; - break; - case SIZE_176x144: - vs = VIDEOSIZE_176x144; - break; - case SIZE_320x240: - vs = VIDEOSIZE_320x240; - break; - case SIZE_352x240: - vs = VIDEOSIZE_352x240; - break; - case SIZE_352x288: - vs = VIDEOSIZE_352x288; - break; - case SIZE_640x480: - vs = VIDEOSIZE_640x480; - break; - default: - err("size=%d. is not valid", size); - break; - } - return vs; -} - -/* - * ibmcam_find_header() - * - * Locate one of supported header markers in the queue. - * Once found, remove all preceding bytes AND the marker (4 bytes) - * from the data pump queue. Whatever follows must be video lines. - * - * History: - * 1/21/00 Created. - */ -static enum ParseState ibmcam_find_header(struct uvd *uvd) /* FIXME: Add frame here */ -{ - struct usbvideo_frame *frame; - ibmcam_t *icam; - - if ((uvd->curframe) < 0 || (uvd->curframe >= USBVIDEO_NUMFRAMES)) { - err("ibmcam_find_header: Illegal frame %d.", uvd->curframe); - return scan_EndParse; - } - icam = IBMCAM_T(uvd); - assert(icam != NULL); - frame = &uvd->frame[uvd->curframe]; - icam->has_hdr = 0; - switch (icam->camera_model) { - case IBMCAM_MODEL_1: - { - const int marker_len = 4; - while (RingQueue_GetLength(&uvd->dp) >= marker_len) { - if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && - (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF) && - (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00)) - { -#if 0 /* This code helps to detect new frame markers */ - dev_info(&uvd->dev->dev, - "Header sig: 00 FF 00 %02X\n", - RING_QUEUE_PEEK(&uvd->dp, 3)); -#endif - frame->header = RING_QUEUE_PEEK(&uvd->dp, 3); - if ((frame->header == HDRSIG_MODEL1_128x96) || - (frame->header == HDRSIG_MODEL1_176x144) || - (frame->header == HDRSIG_MODEL1_352x288)) - { -#if 0 - dev_info(&uvd->dev->dev, - "Header found.\n"); -#endif - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); - icam->has_hdr = 1; - break; - } - } - /* If we are still here then this doesn't look like a header */ - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); - } - break; - } - case IBMCAM_MODEL_2: -case IBMCAM_MODEL_4: - { - int marker_len = 0; - switch (uvd->videosize) { - case VIDEOSIZE_176x144: - marker_len = 10; - break; - default: - marker_len = 2; - break; - } - while (RingQueue_GetLength(&uvd->dp) >= marker_len) { - if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && - (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF)) - { -#if 0 - dev_info(&uvd->dev->dev, "Header found.\n"); -#endif - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); - icam->has_hdr = 1; - frame->header = HDRSIG_MODEL1_176x144; - break; - } - /* If we are still here then this doesn't look like a header */ - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); - } - break; - } - case IBMCAM_MODEL_3: - { /* - * Headers: (one precedes every frame). nc=no compression, - * bq=best quality bf=best frame rate. - * - * 176x144: 00 FF 02 { 0A=nc CA=bq EA=bf } - * 320x240: 00 FF 02 { 08=nc 28=bq 68=bf } - * 640x480: 00 FF 03 { 08=nc 28=bq 68=bf } - * - * Bytes '00 FF' seem to indicate header. Other two bytes - * encode the frame type. This is a set of bit fields that - * encode image size, compression type etc. These fields - * do NOT contain frame number because all frames carry - * the same header. - */ - const int marker_len = 4; - while (RingQueue_GetLength(&uvd->dp) >= marker_len) { - if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && - (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF) && - (RING_QUEUE_PEEK(&uvd->dp, 2) != 0xFF)) - { - /* - * Combine 2 bytes of frame type into one - * easy to use value - */ - unsigned long byte3, byte4; - - byte3 = RING_QUEUE_PEEK(&uvd->dp, 2); - byte4 = RING_QUEUE_PEEK(&uvd->dp, 3); - frame->header = (byte3 << 8) | byte4; -#if 0 - dev_info(&uvd->dev->dev, "Header found.\n"); -#endif - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); - icam->has_hdr = 1; - break; - } - /* If we are still here then this doesn't look like a header */ - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); - } - break; - } - default: - break; - } - if (!icam->has_hdr) { - if (uvd->debug > 2) - dev_info(&uvd->dev->dev, - "Skipping frame, no header\n"); - return scan_EndParse; - } - - /* Header found */ - icam->has_hdr = 1; - uvd->stats.header_count++; - frame->scanstate = ScanState_Lines; - frame->curline = 0; - - if (flags & FLAGS_FORCE_TESTPATTERN) { - usbvideo_TestPattern(uvd, 1, 1); - return scan_NextFrame; - } - return scan_Continue; -} - -/* - * ibmcam_parse_lines() - * - * Parse one line (interlaced) from the buffer, put - * decoded RGB value into the current frame buffer - * and add the written number of bytes (RGB) to - * the *pcopylen. - * - * History: - * 21-Jan-2000 Created. - * 12-Oct-2000 Reworked to reflect interlaced nature of the data. - */ -static enum ParseState ibmcam_parse_lines( - struct uvd *uvd, - struct usbvideo_frame *frame, - long *pcopylen) -{ - unsigned char *f; - ibmcam_t *icam; - unsigned int len, scanLength, scanHeight, order_uv, order_yc; - int v4l_linesize; /* V4L line offset */ - const int hue_corr = (uvd->vpic.hue - 0x8000) >> 10; /* -32..+31 */ - const int hue2_corr = (hue_correction - 128) / 4; /* -32..+31 */ - const int ccm = 128; /* Color correction median - see below */ - int y, u, v, i, frame_done=0, color_corr; - static unsigned char lineBuffer[640*3]; - unsigned const char *chromaLine, *lumaLine; - - assert(uvd != NULL); - assert(frame != NULL); - icam = IBMCAM_T(uvd); - assert(icam != NULL); - color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/ - RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1); - - v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; - - if (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_4) { - /* Model 4 frame markers do not carry image size identification */ - switch (uvd->videosize) { - case VIDEOSIZE_128x96: - case VIDEOSIZE_160x120: - case VIDEOSIZE_176x144: - scanLength = VIDEOSIZE_X(uvd->videosize); - scanHeight = VIDEOSIZE_Y(uvd->videosize); - break; - default: - err("ibmcam_parse_lines: Wrong mode."); - return scan_Out; - } - order_yc = 1; /* order_yc: true=Yc false=cY ('c'=either U or V) */ - order_uv = 1; /* Always true in this algorithm */ - } else { - switch (frame->header) { - case HDRSIG_MODEL1_128x96: - scanLength = 128; - scanHeight = 96; - order_uv = 1; /* U Y V Y ... */ - break; - case HDRSIG_MODEL1_176x144: - scanLength = 176; - scanHeight = 144; - order_uv = 1; /* U Y V Y ... */ - break; - case HDRSIG_MODEL1_352x288: - scanLength = 352; - scanHeight = 288; - order_uv = 0; /* Y V Y V ... */ - break; - default: - err("Unknown header signature 00 FF 00 %02lX", frame->header); - return scan_NextFrame; - } - /* order_yc: true=Yc false=cY ('c'=either U or V) */ - order_yc = (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_2); - } - - len = scanLength * 3; - assert(len <= sizeof(lineBuffer)); - - /* - * Lines are organized this way: - * - * I420: - * ~~~~ - * - * ___________________________________ - * |-----Y-----|---UVUVUV...UVUV-----| \ - * |-----------+---------------------| \ - * |<-- 176 -->|<------ 176*2 ------>| Total 72. lines (interlaced) - * |... ... | ... | / - * |<-- 352 -->|<------ 352*2 ------>| Total 144. lines (interlaced) - * |___________|_____________________| / - * \ \ - * lumaLine chromaLine - */ - - /* Make sure there's enough data for the entire line */ - if (RingQueue_GetLength(&uvd->dp) < len) - return scan_Out; - - /* Suck one line out of the ring queue */ - RingQueue_Dequeue(&uvd->dp, lineBuffer, len); - - /* - * Make sure that our writing into output buffer - * will not exceed the buffer. Mind that we may write - * not into current output scanline but in several after - * it as well (if we enlarge image vertically.) - */ - if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request)) - return scan_NextFrame; - - /* - * Now we are sure that entire line (representing all 'scanLength' - * pixels from the camera) is available in the buffer. We - * start copying the line left-aligned to the V4L buffer. - * If the camera line is shorter then we should pad the V4L - * buffer with something (black) to complete the line. - */ - assert(frame->data != NULL); - f = frame->data + (v4l_linesize * frame->curline); - - /* - * To obtain chrominance data from the 'chromaLine' use this: - * v = chromaLine[0]; // 0-1:[0], 2-3:[4], 4-5:[8]... - * u = chromaLine[2]; // 0-1:[2], 2-3:[6], 4-5:[10]... - * - * Indices must be calculated this way: - * v_index = (i >> 1) << 2; - * u_index = (i >> 1) << 2 + 2; - * - * where 'i' is the column number [0..VIDEOSIZE_X(frame->request)-1] - */ - lumaLine = lineBuffer; - chromaLine = lineBuffer + scanLength; - for (i = 0; i < VIDEOSIZE_X(frame->request); i++) - { - unsigned char rv, gv, bv; /* RGB components */ - - /* Check for various visual debugging hints (colorized pixels) */ - if ((flags & FLAGS_DISPLAY_HINTS) && (icam->has_hdr)) { - /* - * This is bad and should not happen. This means that - * we somehow overshoot the line and encountered new - * frame! Obviously our camera/V4L frame size is out - * of whack. This cyan dot will help you to figure - * out where exactly the new frame arrived. - */ - if (icam->has_hdr == 1) { - bv = 0; /* Yellow marker */ - gv = 0xFF; - rv = 0xFF; - } else { - bv = 0xFF; /* Cyan marker */ - gv = 0xFF; - rv = 0; - } - icam->has_hdr = 0; - goto make_pixel; - } - - /* - * Check if we are still in range. We may be out of range if our - * V4L canvas is wider or taller than the camera "native" image. - * Then we quickly fill the remainder of the line with zeros to - * make black color and quit the horizontal scanning loop. - */ - if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) { - const int j = i * V4L_BYTES_PER_PIXEL; -#if USES_IBMCAM_PUTPIXEL - /* Refresh 'f' because we don't use it much with PUTPIXEL */ - f = frame->data + (v4l_linesize * frame->curline) + j; -#endif - memset(f, 0, v4l_linesize - j); - break; - } - - y = lumaLine[i]; - if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */ - rv = gv = bv = y; - else { - int off_0, off_2; - - off_0 = (i >> 1) << 2; - off_2 = off_0 + 2; - - if (order_yc) { - off_0++; - off_2++; - } - if (!order_uv) { - off_0 += 2; - off_2 -= 2; - } - u = chromaLine[off_0] + hue_corr; - v = chromaLine[off_2] + hue2_corr; - - /* Apply color correction */ - if (color_corr != 0) { - /* Magnify up to 2 times, reduce down to zero saturation */ - u = 128 + ((ccm + color_corr) * (u - 128)) / ccm; - v = 128 + ((ccm + color_corr) * (v - 128)) / ccm; - } - YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv); - } - - make_pixel: - /* - * The purpose of creating the pixel here, in one, - * dedicated place is that we may need to make the - * pixel wider and taller than it actually is. This - * may be used if camera generates small frames for - * sake of frame rate (or any other reason.) - * - * The output data consists of B, G, R bytes - * (in this order). - */ -#if USES_IBMCAM_PUTPIXEL - RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv); -#else - *f++ = bv; - *f++ = gv; - *f++ = rv; -#endif - /* - * Typically we do not decide within a legitimate frame - * that we want to end the frame. However debugging code - * may detect marker of new frame within the data. Then - * this condition activates. The 'data' pointer is already - * pointing at the new marker, so we'd better leave it as is. - */ - if (frame_done) - break; /* End scanning of lines */ - } - /* - * Account for number of bytes that we wrote into output V4L frame. - * We do it here, after we are done with the scanline, because we - * may fill more than one output scanline if we do vertical - * enlargement. - */ - frame->curline += 2; - if (pcopylen != NULL) - *pcopylen += 2 * v4l_linesize; - frame->deinterlace = Deinterlace_FillOddLines; - - if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request))) - return scan_NextFrame; - else - return scan_Continue; -} - -/* - * ibmcam_model2_320x240_parse_lines() - * - * This procedure deals with a weird RGB format that is produced by IBM - * camera model 2 in modes 320x240 and above; 'x' below is 159 or 175, - * depending on horizontal size of the picture: - * - * <--- 160 or 176 pairs of RA,RB bytes -----> - * *-----------------------------------------* \ - * | RA0 | RB0 | RA1 | RB1 | ... | RAx | RBx | \ This is pair of horizontal lines, - * |-----+-----+-----+-----+ ... +-----+-----| *- or one interlaced line, total - * | B0 | G0 | B1 | G1 | ... | Bx | Gx | / 120 or 144 such pairs which yield - * |=====+=====+=====+=====+ ... +=====+=====| / 240 or 288 lines after deinterlacing. - * - * Each group of FOUR bytes (RAi, RBi, Bi, Gi) where i=0..frame_width/2-1 - * defines ONE pixel. Therefore this format yields 176x144 "decoded" - * resolution at best. I do not know why camera sends such format - the - * previous model (1) just used interlaced I420 and everyone was happy. - * - * I do not know what is the difference between RAi and RBi bytes. Both - * seemingly represent R component, but slightly vary in value (so that - * the picture looks a bit colored if one or another is used). I use - * them both as R component in attempt to at least partially recover the - * lost resolution. - */ -static enum ParseState ibmcam_model2_320x240_parse_lines( - struct uvd *uvd, - struct usbvideo_frame *frame, - long *pcopylen) -{ - unsigned char *f, *la, *lb; - unsigned int len; - int v4l_linesize; /* V4L line offset */ - int i, j, frame_done=0, color_corr; - int scanLength, scanHeight; - static unsigned char lineBuffer[352*2]; - - switch (uvd->videosize) { - case VIDEOSIZE_320x240: - case VIDEOSIZE_352x240: - case VIDEOSIZE_352x288: - scanLength = VIDEOSIZE_X(uvd->videosize); - scanHeight = VIDEOSIZE_Y(uvd->videosize); - break; - default: - err("ibmcam_model2_320x240_parse_lines: Wrong mode."); - return scan_Out; - } - - color_corr = (uvd->vpic.colour) >> 8; /* 0..+255 */ - v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; - - len = scanLength * 2; /* See explanation above */ - assert(len <= sizeof(lineBuffer)); - - /* Make sure there's enough data for the entire line */ - if (RingQueue_GetLength(&uvd->dp) < len) - return scan_Out; - - /* Suck one line out of the ring queue */ - RingQueue_Dequeue(&uvd->dp, lineBuffer, len); - - /* - * Make sure that our writing into output buffer - * will not exceed the buffer. Mind that we may write - * not into current output scanline but in several after - * it as well (if we enlarge image vertically.) - */ - if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request)) - return scan_NextFrame; - - la = lineBuffer; - lb = lineBuffer + scanLength; - - /* - * Now we are sure that entire line (representing all - * VIDEOSIZE_X(frame->request) - * pixels from the camera) is available in the scratch buffer. We - * start copying the line left-aligned to the V4L buffer (which - * might be larger - not smaller, hopefully). If the camera - * line is shorter then we should pad the V4L buffer with something - * (black in this case) to complete the line. - */ - f = frame->data + (v4l_linesize * frame->curline); - - /* Fill the 2-line strip */ - for (i = 0; i < VIDEOSIZE_X(frame->request); i++) { - int y, rv, gv, bv; /* RGB components */ - - j = i & (~1); - - /* Check for various visual debugging hints (colorized pixels) */ - if ((flags & FLAGS_DISPLAY_HINTS) && (IBMCAM_T(uvd)->has_hdr)) { - if (IBMCAM_T(uvd)->has_hdr == 1) { - bv = 0; /* Yellow marker */ - gv = 0xFF; - rv = 0xFF; - } else { - bv = 0xFF; /* Cyan marker */ - gv = 0xFF; - rv = 0; - } - IBMCAM_T(uvd)->has_hdr = 0; - goto make_pixel; - } - - /* - * Check if we are still in range. We may be out of range if our - * V4L canvas is wider or taller than the camera "native" image. - * Then we quickly fill the remainder of the line with zeros to - * make black color and quit the horizontal scanning loop. - */ - if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) { - const int offset = i * V4L_BYTES_PER_PIXEL; -#if USES_IBMCAM_PUTPIXEL - /* Refresh 'f' because we don't use it much with PUTPIXEL */ - f = frame->data + (v4l_linesize * frame->curline) + offset; -#endif - memset(f, 0, v4l_linesize - offset); - break; - } - - /* - * Here I use RA and RB components, one per physical pixel. - * This causes fine vertical grid on the picture but may improve - * horizontal resolution. If you prefer replicating, use this: - * rv = la[j + 0]; ... or ... rv = la[j + 1]; - * then the pixel will be replicated. - */ - rv = la[i]; - gv = lb[j + 1]; - bv = lb[j + 0]; - - y = (rv + gv + bv) / 3; /* Brightness (badly calculated) */ - - if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */ - rv = gv = bv = y; - else if (color_corr != 128) { - - /* Calculate difference between color and brightness */ - rv -= y; - gv -= y; - bv -= y; - - /* Scale differences */ - rv = (rv * color_corr) / 128; - gv = (gv * color_corr) / 128; - bv = (bv * color_corr) / 128; - - /* Reapply brightness */ - rv += y; - gv += y; - bv += y; - - /* Watch for overflows */ - RESTRICT_TO_RANGE(rv, 0, 255); - RESTRICT_TO_RANGE(gv, 0, 255); - RESTRICT_TO_RANGE(bv, 0, 255); - } - - make_pixel: - RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv); - } - /* - * Account for number of bytes that we wrote into output V4L frame. - * We do it here, after we are done with the scanline, because we - * may fill more than one output scanline if we do vertical - * enlargement. - */ - frame->curline += 2; - *pcopylen += v4l_linesize * 2; - frame->deinterlace = Deinterlace_FillOddLines; - - if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request))) - return scan_NextFrame; - else - return scan_Continue; -} - -/* - * ibmcam_model3_parse_lines() - * - * | Even lines | Odd Lines | - * -----------------------------------| - * |YYY........Y|UYVYUYVY.........UYVY| - * |YYY........Y|UYVYUYVY.........UYVY| - * |............|.....................| - * |YYY........Y|UYVYUYVY.........UYVY| - * |------------+---------------------| - * - * There is one (U, V) chroma pair for every four luma (Y) values. This - * function reads a pair of lines at a time and obtains missing chroma values - * from adjacent pixels. - */ -static enum ParseState ibmcam_model3_parse_lines( - struct uvd *uvd, - struct usbvideo_frame *frame, - long *pcopylen) -{ - unsigned char *data; - const unsigned char *color; - unsigned int len; - int v4l_linesize; /* V4L line offset */ - const int hue_corr = (uvd->vpic.hue - 0x8000) >> 10; /* -32..+31 */ - const int hue2_corr = (hue_correction - 128) / 4; /* -32..+31 */ - const int ccm = 128; /* Color correction median - see below */ - int i, u, v, rw, data_w=0, data_h=0, color_corr; - static unsigned char lineBuffer[640*3]; - int line; - - color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/ - RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1); - - v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; - - /* The header tells us what sort of data is in this frame */ - switch (frame->header) { - /* - * Uncompressed modes (that are easy to decode). - */ - case 0x0308: - data_w = 640; - data_h = 480; - break; - case 0x0208: - data_w = 320; - data_h = 240; - break; - case 0x020A: - data_w = 160; - data_h = 120; - break; - /* - * Compressed modes (ViCE - that I don't know how to decode). - */ - case 0x0328: /* 640x480, best quality compression */ - case 0x0368: /* 640x480, best frame rate compression */ - case 0x0228: /* 320x240, best quality compression */ - case 0x0268: /* 320x240, best frame rate compression */ - case 0x02CA: /* 160x120, best quality compression */ - case 0x02EA: /* 160x120, best frame rate compression */ - /* Do nothing with this - not supported */ - err("Unsupported mode $%04lx", frame->header); - return scan_NextFrame; - default: - /* Catch unknown headers, may help in learning new headers */ - err("Strange frame->header=$%08lx", frame->header); - return scan_NextFrame; - } - - /* - * Make sure that our writing into output buffer - * will not exceed the buffer. Note that we may write - * not into current output scanline but in several after - * it as well (if we enlarge image vertically.) - */ - if ((frame->curline + 1) >= data_h) { - if (uvd->debug >= 3) - dev_info(&uvd->dev->dev, - "Reached line %d. (frame is done)\n", - frame->curline); - return scan_NextFrame; - } - - /* Make sure that lineBuffer can store two lines of data */ - len = 3 * data_w; /* */ - assert(len <= sizeof(lineBuffer)); - - /* Make sure there's enough data for two lines */ - if (RingQueue_GetLength(&uvd->dp) < len) - return scan_Out; - - /* Suck two lines of data out of the ring queue */ - RingQueue_Dequeue(&uvd->dp, lineBuffer, len); - - data = lineBuffer; - color = data + data_w; /* Point to where color planes begin */ - - /* Bottom-to-top scanning */ - rw = (int)VIDEOSIZE_Y(frame->request) - (int)(frame->curline) - 1; - RESTRICT_TO_RANGE(rw, 0, VIDEOSIZE_Y(frame->request)-1); - - /* Iterate over two lines. */ - for (line = 0; line < 2; line++) { - for (i = 0; i < VIDEOSIZE_X(frame->request); i++) { - int y; - int rv, gv, bv; /* RGB components */ - - if (i >= data_w) { - RGB24_PUTPIXEL(frame, i, rw, 0, 0, 0); - continue; - } - - /* first line is YYY...Y; second is UYVY...UYVY */ - y = data[(line == 0) ? i : (i*2 + 1)]; - - /* Apply static color correction */ - u = color[(i/2)*4] + hue_corr; - v = color[(i/2)*4 + 2] + hue2_corr; - - /* Apply color correction */ - if (color_corr != 0) { - /* Magnify up to 2 times, reduce down to zero saturation */ - u = 128 + ((ccm + color_corr) * (u - 128)) / ccm; - v = 128 + ((ccm + color_corr) * (v - 128)) / ccm; - } - - - YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv); - RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv); /* No deinterlacing */ - } - - /* Check for the end of requested data */ - if (rw == 0) - break; - - /* Prepare for the second line */ - rw--; - data = lineBuffer + data_w; - } - frame->deinterlace = Deinterlace_None; - - /* - * Account for number of bytes that we wrote into output V4L frame. - * We do it here, after we are done with the scanline, because we - * may fill more than one output scanline if we do vertical - * enlargement. - */ - frame->curline += 2; - *pcopylen += 2 * v4l_linesize; - - if (frame->curline >= VIDEOSIZE_Y(frame->request)) { - if (uvd->debug >= 3) { - dev_info(&uvd->dev->dev, - "All requested lines (%ld.) done.\n", - VIDEOSIZE_Y(frame->request)); - } - return scan_NextFrame; - } else - return scan_Continue; -} - -/* - * ibmcam_model4_128x96_parse_lines() - * - * This decoder is for one strange data format that is produced by Model 4 - * camera only in 128x96 mode. This is RGB format and here is its description. - * First of all, this is non-interlaced stream, meaning that all scan lines - * are present in the datastream. There are 96 consecutive blocks of data - * that describe all 96 lines of the image. Each block is 5*128 bytes long - * and carries R, G, B components. The format of the block is shown in the - * code below. First 128*2 bytes are interleaved R and G components. Then - * we have a gap (junk data) 64 bytes long. Then follow B and something - * else, also interleaved (this makes another 128*2 bytes). After that - * probably another 64 bytes of junk follow. - * - * History: - * 10-Feb-2001 Created. - */ -static enum ParseState ibmcam_model4_128x96_parse_lines( - struct uvd *uvd, - struct usbvideo_frame *frame, - long *pcopylen) -{ - const unsigned char *data_rv, *data_gv, *data_bv; - unsigned int len; - int i, v4l_linesize; /* V4L line offset */ - const int data_w=128, data_h=96; - static unsigned char lineBuffer[128*5]; - - v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; - - /* - * Make sure that our writing into output buffer - * will not exceed the buffer. Note that we may write - * not into current output scanline but in several after - * it as well (if we enlarge image vertically.) - */ - if ((frame->curline + 1) >= data_h) { - if (uvd->debug >= 3) - dev_info(&uvd->dev->dev, - "Reached line %d. (frame is done)\n", - frame->curline); - return scan_NextFrame; - } - - /* - * RGRGRG .... RGRG_____________B?B?B? ... B?B?____________ - * <---- 128*2 ---><---- 64 ---><--- 128*2 ---><--- 64 ---> - */ - - /* Make sure there's enough data for the entire line */ - len = 5 * data_w; - assert(len <= sizeof(lineBuffer)); - - /* Make sure there's enough data for the entire line */ - if (RingQueue_GetLength(&uvd->dp) < len) - return scan_Out; - - /* Suck one line out of the ring queue */ - RingQueue_Dequeue(&uvd->dp, lineBuffer, len); - - data_rv = lineBuffer; - data_gv = lineBuffer + 1; - data_bv = lineBuffer + data_w*2 + data_w/2; - for (i = 0; i < VIDEOSIZE_X(frame->request); i++) { - int rv, gv, bv; /* RGB components */ - if (i < data_w) { - const int j = i * 2; - gv = data_rv[j]; - rv = data_gv[j]; - bv = data_bv[j]; - if (flags & FLAGS_MONOCHROME) { - unsigned long y; - y = rv + gv + bv; - y /= 3; - if (y > 0xFF) - y = 0xFF; - rv = gv = bv = (unsigned char) y; - } - } else { - rv = gv = bv = 0; - } - RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv); - } - frame->deinterlace = Deinterlace_None; - frame->curline++; - *pcopylen += v4l_linesize; - - if (frame->curline >= VIDEOSIZE_Y(frame->request)) { - if (uvd->debug >= 3) { - dev_info(&uvd->dev->dev, - "All requested lines (%ld.) done.\n", - VIDEOSIZE_Y(frame->request)); - } - return scan_NextFrame; - } else - return scan_Continue; -} - -/* - * ibmcam_ProcessIsocData() - * - * Generic routine to parse the ring queue data. It employs either - * ibmcam_find_header() or ibmcam_parse_lines() to do most - * of work. - * - * History: - * 1/21/00 Created. - */ -static void ibmcam_ProcessIsocData(struct uvd *uvd, - struct usbvideo_frame *frame) -{ - enum ParseState newstate; - long copylen = 0; - int mod = IBMCAM_T(uvd)->camera_model; - - while (1) { - newstate = scan_Out; - if (RingQueue_GetLength(&uvd->dp) > 0) { - if (frame->scanstate == ScanState_Scanning) { - newstate = ibmcam_find_header(uvd); - } else if (frame->scanstate == ScanState_Lines) { - if ((mod == IBMCAM_MODEL_2) && - ((uvd->videosize == VIDEOSIZE_352x288) || - (uvd->videosize == VIDEOSIZE_320x240) || - (uvd->videosize == VIDEOSIZE_352x240))) - { - newstate = ibmcam_model2_320x240_parse_lines( - uvd, frame, ©len); - } else if (mod == IBMCAM_MODEL_4) { - /* - * Model 4 cameras (IBM NetCamera) use Model 2 decoder (RGB) - * for 320x240 and above; 160x120 and 176x144 uses Model 1 - * decoder (YUV), and 128x96 mode uses ??? - */ - if ((uvd->videosize == VIDEOSIZE_352x288) || - (uvd->videosize == VIDEOSIZE_320x240) || - (uvd->videosize == VIDEOSIZE_352x240)) - { - newstate = ibmcam_model2_320x240_parse_lines(uvd, frame, ©len); - } else if (uvd->videosize == VIDEOSIZE_128x96) { - newstate = ibmcam_model4_128x96_parse_lines(uvd, frame, ©len); - } else { - newstate = ibmcam_parse_lines(uvd, frame, ©len); - } - } else if (mod == IBMCAM_MODEL_3) { - newstate = ibmcam_model3_parse_lines(uvd, frame, ©len); - } else { - newstate = ibmcam_parse_lines(uvd, frame, ©len); - } - } - } - if (newstate == scan_Continue) - continue; - else if ((newstate == scan_NextFrame) || (newstate == scan_Out)) - break; - else - return; /* scan_EndParse */ - } - - if (newstate == scan_NextFrame) { - frame->frameState = FrameState_Done; - uvd->curframe = -1; - uvd->stats.frame_num++; - if ((mod == IBMCAM_MODEL_2) || (mod == IBMCAM_MODEL_4)) { - /* Need software contrast adjustment for those cameras */ - frame->flags |= USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST; - } - } - - /* Update the frame's uncompressed length. */ - frame->seqRead_Length += copylen; - -#if 0 - { - static unsigned char j=0; - memset(frame->data, j++, uvd->max_frame_size); - frame->frameState = FrameState_Ready; - } -#endif -} - -/* - * ibmcam_veio() - * - * History: - * 1/27/00 Added check for dev == NULL; this happens if camera is unplugged. - */ -static int ibmcam_veio( - struct uvd *uvd, - unsigned char req, - unsigned short value, - unsigned short index) -{ - static const char proc[] = "ibmcam_veio"; - unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */; - int i; - - if (!CAMERA_IS_OPERATIONAL(uvd)) - return 0; - - if (req == 1) { - i = usb_control_msg( - uvd->dev, - usb_rcvctrlpipe(uvd->dev, 0), - req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, - value, - index, - cp, - sizeof(cp), - 1000); -#if 0 - dev_info(&uvd->dev->dev, - "USB => %02x%02x%02x%02x%02x%02x%02x%02x " - "(req=$%02x val=$%04x ind=$%04x)\n", - cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], - req, value, index); -#endif - } else { - i = usb_control_msg( - uvd->dev, - usb_sndctrlpipe(uvd->dev, 0), - req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, - value, - index, - NULL, - 0, - 1000); - } - if (i < 0) { - err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.", - proc, i); - uvd->last_error = i; - } - return i; -} - -/* - * ibmcam_calculate_fps() - * - * This procedure roughly calculates the real frame rate based - * on FPS code (framerate=NNN option). Actual FPS differs - * slightly depending on lighting conditions, so that actual frame - * rate is determined by the camera. Since I don't know how to ask - * the camera what FPS is now I have to use the FPS code instead. - * - * The FPS code is in range [0..6], 0 is slowest, 6 is fastest. - * Corresponding real FPS should be in range [3..30] frames per second. - * The conversion formula is obvious: - * - * real_fps = 3 + (fps_code * 4.5) - * - * History: - * 1/18/00 Created. - */ -static int ibmcam_calculate_fps(struct uvd *uvd) -{ - return 3 + framerate*4 + framerate/2; -} - -/* - * ibmcam_send_FF_04_02() - * - * This procedure sends magic 3-command prefix to the camera. - * The purpose of this prefix is not known. - * - * History: - * 1/2/00 Created. - */ -static void ibmcam_send_FF_04_02(struct uvd *uvd) -{ - ibmcam_veio(uvd, 0, 0x00FF, 0x0127); - ibmcam_veio(uvd, 0, 0x0004, 0x0124); - ibmcam_veio(uvd, 0, 0x0002, 0x0124); -} - -static void ibmcam_send_00_04_06(struct uvd *uvd) -{ - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x0004, 0x0124); - ibmcam_veio(uvd, 0, 0x0006, 0x0124); -} - -static void ibmcam_send_x_00(struct uvd *uvd, unsigned short x) -{ - ibmcam_veio(uvd, 0, x, 0x0127); - ibmcam_veio(uvd, 0, 0x0000, 0x0124); -} - -static void ibmcam_send_x_00_05(struct uvd *uvd, unsigned short x) -{ - ibmcam_send_x_00(uvd, x); - ibmcam_veio(uvd, 0, 0x0005, 0x0124); -} - -static void ibmcam_send_x_00_05_02(struct uvd *uvd, unsigned short x) -{ - ibmcam_veio(uvd, 0, x, 0x0127); - ibmcam_veio(uvd, 0, 0x0000, 0x0124); - ibmcam_veio(uvd, 0, 0x0005, 0x0124); - ibmcam_veio(uvd, 0, 0x0002, 0x0124); -} - -static void ibmcam_send_x_01_00_05(struct uvd *uvd, unsigned short x) -{ - ibmcam_veio(uvd, 0, x, 0x0127); - ibmcam_veio(uvd, 0, 0x0001, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0124); - ibmcam_veio(uvd, 0, 0x0005, 0x0124); -} - -static void ibmcam_send_x_00_05_02_01(struct uvd *uvd, unsigned short x) -{ - ibmcam_veio(uvd, 0, x, 0x0127); - ibmcam_veio(uvd, 0, 0x0000, 0x0124); - ibmcam_veio(uvd, 0, 0x0005, 0x0124); - ibmcam_veio(uvd, 0, 0x0002, 0x0124); - ibmcam_veio(uvd, 0, 0x0001, 0x0124); -} - -static void ibmcam_send_x_00_05_02_08_01(struct uvd *uvd, unsigned short x) -{ - ibmcam_veio(uvd, 0, x, 0x0127); - ibmcam_veio(uvd, 0, 0x0000, 0x0124); - ibmcam_veio(uvd, 0, 0x0005, 0x0124); - ibmcam_veio(uvd, 0, 0x0002, 0x0124); - ibmcam_veio(uvd, 0, 0x0008, 0x0124); - ibmcam_veio(uvd, 0, 0x0001, 0x0124); -} - -static void ibmcam_Packet_Format1(struct uvd *uvd, unsigned char fkey, unsigned char val) -{ - ibmcam_send_x_01_00_05(uvd, unknown_88); - ibmcam_send_x_00_05(uvd, fkey); - ibmcam_send_x_00_05_02_08_01(uvd, val); - ibmcam_send_x_00_05(uvd, unknown_88); - ibmcam_send_x_00_05_02_01(uvd, fkey); - ibmcam_send_x_00_05(uvd, unknown_89); - ibmcam_send_x_00(uvd, fkey); - ibmcam_send_00_04_06(uvd); - ibmcam_veio(uvd, 1, 0x0000, 0x0126); - ibmcam_send_FF_04_02(uvd); -} - -static void ibmcam_PacketFormat2(struct uvd *uvd, unsigned char fkey, unsigned char val) -{ - ibmcam_send_x_01_00_05 (uvd, unknown_88); - ibmcam_send_x_00_05 (uvd, fkey); - ibmcam_send_x_00_05_02 (uvd, val); -} - -static void ibmcam_model2_Packet2(struct uvd *uvd) -{ - ibmcam_veio(uvd, 0, 0x00ff, 0x012d); - ibmcam_veio(uvd, 0, 0xfea3, 0x0124); -} - -static void ibmcam_model2_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2) -{ - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x00ff, 0x012e); - ibmcam_veio(uvd, 0, v1, 0x012f); - ibmcam_veio(uvd, 0, 0x00ff, 0x0130); - ibmcam_veio(uvd, 0, 0xc719, 0x0124); - ibmcam_veio(uvd, 0, v2, 0x0127); - - ibmcam_model2_Packet2(uvd); -} - -/* - * ibmcam_model3_Packet1() - * - * 00_0078_012d - * 00_0097_012f - * 00_d141_0124 - * 00_0096_0127 - * 00_fea8_0124 -*/ -static void ibmcam_model3_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2) -{ - ibmcam_veio(uvd, 0, 0x0078, 0x012d); - ibmcam_veio(uvd, 0, v1, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, v2, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); -} - -static void ibmcam_model4_BrightnessPacket(struct uvd *uvd, int i) -{ - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0026, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, i, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0038, 0x012d); - ibmcam_veio(uvd, 0, 0x0004, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); -} - -/* - * ibmcam_adjust_contrast() - * - * The contrast value changes from 0 (high contrast) to 15 (low contrast). - * This is in reverse to usual order of things (such as TV controls), so - * we reverse it again here. - * - * TODO: we probably don't need to send the setup 5 times... - * - * History: - * 1/2/00 Created. - */ -static void ibmcam_adjust_contrast(struct uvd *uvd) -{ - unsigned char a_contrast = uvd->vpic.contrast >> 12; - unsigned char new_contrast; - - if (a_contrast >= 16) - a_contrast = 15; - new_contrast = 15 - a_contrast; - if (new_contrast == uvd->vpic_old.contrast) - return; - uvd->vpic_old.contrast = new_contrast; - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - { - const int ntries = 5; - int i; - for (i=0; i < ntries; i++) { - ibmcam_Packet_Format1(uvd, contrast_14, new_contrast); - ibmcam_send_FF_04_02(uvd); - } - break; - } - case IBMCAM_MODEL_2: - case IBMCAM_MODEL_4: - /* Models 2, 4 do not have this control; implemented in software. */ - break; - case IBMCAM_MODEL_3: - { /* Preset hardware values */ - static const struct { - unsigned short cv1; - unsigned short cv2; - unsigned short cv3; - } cv[7] = { - { 0x05, 0x05, 0x0f }, /* Minimum */ - { 0x04, 0x04, 0x16 }, - { 0x02, 0x03, 0x16 }, - { 0x02, 0x08, 0x16 }, - { 0x01, 0x0c, 0x16 }, - { 0x01, 0x0e, 0x16 }, - { 0x01, 0x10, 0x16 } /* Maximum */ - }; - int i = a_contrast / 2; - RESTRICT_TO_RANGE(i, 0, 6); - ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ - ibmcam_model3_Packet1(uvd, 0x0067, cv[i].cv1); - ibmcam_model3_Packet1(uvd, 0x005b, cv[i].cv2); - ibmcam_model3_Packet1(uvd, 0x005c, cv[i].cv3); - ibmcam_veio(uvd, 0, 0x0001, 0x0114); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); - break; - } - default: - break; - } -} - -/* - * ibmcam_change_lighting_conditions() - * - * Camera model 1: - * We have 3 levels of lighting conditions: 0=Bright, 1=Medium, 2=Low. - * - * Camera model 2: - * We have 16 levels of lighting, 0 for bright light and up to 15 for - * low light. But values above 5 or so are useless because camera is - * not really capable to produce anything worth viewing at such light. - * This setting may be altered only in certain camera state. - * - * Low lighting forces slower FPS. Lighting is set as a module parameter. - * - * History: - * 1/5/00 Created. - * 2/20/00 Added support for Model 2 cameras. - */ -static void ibmcam_change_lighting_conditions(struct uvd *uvd) -{ - if (debug > 0) - dev_info(&uvd->dev->dev, - "%s: Set lighting to %hu.\n", __func__, lighting); - - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - { - const int ntries = 5; - int i; - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, light_27, (unsigned short) lighting); - break; - } - case IBMCAM_MODEL_2: -#if 0 - /* - * This command apparently requires camera to be stopped. My - * experiments showed that it -is- possible to alter the lighting - * conditions setting "on the fly", but why bother? This setting does - * not work reliably in all cases, so I decided simply to leave the - * setting where Xirlink put it - in the camera setup phase. This code - * is commented out because it does not work at -any- moment, so its - * presence makes no sense. You may use it for experiments. - */ - ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop camera */ - ibmcam_model2_Packet1(uvd, mod2_sensitivity, lighting); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Start camera */ -#endif - break; - case IBMCAM_MODEL_3: - case IBMCAM_MODEL_4: - default: - break; - } -} - -/* - * ibmcam_set_sharpness() - * - * Cameras model 1 have internal smoothing feature. It is controlled by value in - * range [0..6], where 0 is most smooth and 6 is most sharp (raw image, I guess). - * Recommended value is 4. Cameras model 2 do not have this feature at all. - */ -static void ibmcam_set_sharpness(struct uvd *uvd) -{ - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - { - static const unsigned short sa[] = { 0x11, 0x13, 0x16, 0x18, 0x1a, 0x8, 0x0a }; - unsigned short i, sv; - - RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX); - if (debug > 0) - dev_info(&uvd->dev->dev, "%s: Set sharpness to %hu.\n", - __func__, sharpness); - - sv = sa[sharpness - SHARPNESS_MIN]; - for (i=0; i < 2; i++) { - ibmcam_send_x_01_00_05 (uvd, unknown_88); - ibmcam_send_x_00_05 (uvd, sharp_13); - ibmcam_send_x_00_05_02 (uvd, sv); - } - break; - } - case IBMCAM_MODEL_2: - case IBMCAM_MODEL_4: - /* Models 2, 4 do not have this control */ - break; - case IBMCAM_MODEL_3: - { /* - * "Use a table of magic numbers. - * This setting doesn't really change much. - * But that's how Windows does it." - */ - static const struct { - unsigned short sv1; - unsigned short sv2; - unsigned short sv3; - unsigned short sv4; - } sv[7] = { - { 0x00, 0x00, 0x05, 0x14 }, /* Smoothest */ - { 0x01, 0x04, 0x05, 0x14 }, - { 0x02, 0x04, 0x05, 0x14 }, - { 0x03, 0x04, 0x05, 0x14 }, - { 0x03, 0x05, 0x05, 0x14 }, - { 0x03, 0x06, 0x05, 0x14 }, - { 0x03, 0x07, 0x05, 0x14 } /* Sharpest */ - }; - RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX); - RESTRICT_TO_RANGE(sharpness, 0, 6); - ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ - ibmcam_model3_Packet1(uvd, 0x0060, sv[sharpness].sv1); - ibmcam_model3_Packet1(uvd, 0x0061, sv[sharpness].sv2); - ibmcam_model3_Packet1(uvd, 0x0062, sv[sharpness].sv3); - ibmcam_model3_Packet1(uvd, 0x0063, sv[sharpness].sv4); - ibmcam_veio(uvd, 0, 0x0001, 0x0114); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); - ibmcam_veio(uvd, 0, 0x0001, 0x0113); - break; - } - default: - break; - } -} - -/* - * ibmcam_set_brightness() - * - * This procedure changes brightness of the picture. - */ -static void ibmcam_set_brightness(struct uvd *uvd) -{ - static const unsigned short n = 1; - - if (debug > 0) - dev_info(&uvd->dev->dev, "%s: Set brightness to %hu.\n", - __func__, uvd->vpic.brightness); - - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - { - unsigned short i, j, bv[3]; - bv[0] = bv[1] = bv[2] = uvd->vpic.brightness >> 10; - if (bv[0] == (uvd->vpic_old.brightness >> 10)) - return; - uvd->vpic_old.brightness = bv[0]; - for (j=0; j < 3; j++) - for (i=0; i < n; i++) - ibmcam_Packet_Format1(uvd, bright_3x[j], bv[j]); - break; - } - case IBMCAM_MODEL_2: - { - unsigned short i, j; - i = uvd->vpic.brightness >> 12; /* 0 .. 15 */ - j = 0x60 + i * ((0xee - 0x60) / 16); /* 0x60 .. 0xee or so */ - if (uvd->vpic_old.brightness == j) - break; - uvd->vpic_old.brightness = j; - ibmcam_model2_Packet1(uvd, mod2_brightness, j); - break; - } - case IBMCAM_MODEL_3: - { - /* Model 3: Brightness range 'i' in [0x0C..0x3F] */ - unsigned short i = - 0x0C + (uvd->vpic.brightness / (0xFFFF / (0x3F - 0x0C + 1))); - RESTRICT_TO_RANGE(i, 0x0C, 0x3F); - if (uvd->vpic_old.brightness == i) - break; - uvd->vpic_old.brightness = i; - ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ - ibmcam_model3_Packet1(uvd, 0x0036, i); - ibmcam_veio(uvd, 0, 0x0001, 0x0114); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); - ibmcam_veio(uvd, 0, 0x0001, 0x0113); - break; - } - case IBMCAM_MODEL_4: - { - /* Model 4: Brightness range 'i' in [0x04..0xb4] */ - unsigned short i = 0x04 + (uvd->vpic.brightness / (0xFFFF / (0xb4 - 0x04 + 1))); - RESTRICT_TO_RANGE(i, 0x04, 0xb4); - if (uvd->vpic_old.brightness == i) - break; - uvd->vpic_old.brightness = i; - ibmcam_model4_BrightnessPacket(uvd, i); - break; - } - default: - break; - } -} - -static void ibmcam_set_hue(struct uvd *uvd) -{ - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_2: - { - unsigned short hue = uvd->vpic.hue >> 9; /* 0 .. 7F */ - if (uvd->vpic_old.hue == hue) - return; - uvd->vpic_old.hue = hue; - ibmcam_model2_Packet1(uvd, mod2_hue, hue); - /* ibmcam_model2_Packet1(uvd, mod2_saturation, sat); */ - break; - } - case IBMCAM_MODEL_3: - { -#if 0 /* This seems not to work. No problem, will fix programmatically */ - unsigned short hue = 0x05 + (uvd->vpic.hue / (0xFFFF / (0x37 - 0x05 + 1))); - RESTRICT_TO_RANGE(hue, 0x05, 0x37); - if (uvd->vpic_old.hue == hue) - return; - uvd->vpic_old.hue = hue; - ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */ - ibmcam_model3_Packet1(uvd, 0x007e, hue); - ibmcam_veio(uvd, 0, 0x0001, 0x0114); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */ - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); - ibmcam_veio(uvd, 0, 0x0001, 0x0113); -#endif - break; - } - case IBMCAM_MODEL_4: - { - unsigned short r_gain, g_gain, b_gain, hue; - - /* - * I am not sure r/g/b_gain variables exactly control gain - * of those channels. Most likely they subtly change some - * very internal image processing settings in the camera. - * In any case, here is what they do, and feel free to tweak: - * - * r_gain: seriously affects red gain - * g_gain: seriously affects green gain - * b_gain: seriously affects blue gain - * hue: changes average color from violet (0) to red (0xFF) - * - * These settings are preset for a decent white balance in - * 320x240, 352x288 modes. Low-res modes exhibit higher contrast - * and therefore may need different values here. - */ - hue = 20 + (uvd->vpic.hue >> 9); - switch (uvd->videosize) { - case VIDEOSIZE_128x96: - r_gain = 90; - g_gain = 166; - b_gain = 175; - break; - case VIDEOSIZE_160x120: - r_gain = 70; - g_gain = 166; - b_gain = 185; - break; - case VIDEOSIZE_176x144: - r_gain = 160; - g_gain = 175; - b_gain = 185; - break; - default: - r_gain = 120; - g_gain = 166; - b_gain = 175; - break; - } - RESTRICT_TO_RANGE(hue, 1, 0x7f); - - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x001e, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, g_gain, 0x0127); /* Green gain */ - ibmcam_veio(uvd, 0, r_gain, 0x012e); /* Red gain */ - ibmcam_veio(uvd, 0, b_gain, 0x0130); /* Blue gain */ - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, hue, 0x012d); /* Hue */ - ibmcam_veio(uvd, 0, 0xf545, 0x0124); - break; - } - default: - break; - } -} - -/* - * ibmcam_adjust_picture() - * - * This procedure gets called from V4L interface to update picture settings. - * Here we change brightness and contrast. - */ -static void ibmcam_adjust_picture(struct uvd *uvd) -{ - ibmcam_adjust_contrast(uvd); - ibmcam_set_brightness(uvd); - ibmcam_set_hue(uvd); -} - -static int ibmcam_model1_setup(struct uvd *uvd) -{ - const int ntries = 5; - int i; - - ibmcam_veio(uvd, 1, 0x00, 0x0128); - ibmcam_veio(uvd, 1, 0x00, 0x0100); - ibmcam_veio(uvd, 0, 0x01, 0x0100); /* LED On */ - ibmcam_veio(uvd, 1, 0x00, 0x0100); - ibmcam_veio(uvd, 0, 0x81, 0x0100); /* LED Off */ - ibmcam_veio(uvd, 1, 0x00, 0x0100); - ibmcam_veio(uvd, 0, 0x01, 0x0100); /* LED On */ - ibmcam_veio(uvd, 0, 0x01, 0x0108); - - ibmcam_veio(uvd, 0, 0x03, 0x0112); - ibmcam_veio(uvd, 1, 0x00, 0x0115); - ibmcam_veio(uvd, 0, 0x06, 0x0115); - ibmcam_veio(uvd, 1, 0x00, 0x0116); - ibmcam_veio(uvd, 0, 0x44, 0x0116); - ibmcam_veio(uvd, 1, 0x00, 0x0116); - ibmcam_veio(uvd, 0, 0x40, 0x0116); - ibmcam_veio(uvd, 1, 0x00, 0x0115); - ibmcam_veio(uvd, 0, 0x0e, 0x0115); - ibmcam_veio(uvd, 0, 0x19, 0x012c); - - ibmcam_Packet_Format1(uvd, 0x00, 0x1e); - ibmcam_Packet_Format1(uvd, 0x39, 0x0d); - ibmcam_Packet_Format1(uvd, 0x39, 0x09); - ibmcam_Packet_Format1(uvd, 0x3b, 0x00); - ibmcam_Packet_Format1(uvd, 0x28, 0x22); - ibmcam_Packet_Format1(uvd, light_27, 0); - ibmcam_Packet_Format1(uvd, 0x2b, 0x1f); - ibmcam_Packet_Format1(uvd, 0x39, 0x08); - - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x2c, 0x00); - - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x30, 0x14); - - ibmcam_PacketFormat2(uvd, 0x39, 0x02); - ibmcam_PacketFormat2(uvd, 0x01, 0xe1); - ibmcam_PacketFormat2(uvd, 0x02, 0xcd); - ibmcam_PacketFormat2(uvd, 0x03, 0xcd); - ibmcam_PacketFormat2(uvd, 0x04, 0xfa); - ibmcam_PacketFormat2(uvd, 0x3f, 0xff); - ibmcam_PacketFormat2(uvd, 0x39, 0x00); - - ibmcam_PacketFormat2(uvd, 0x39, 0x02); - ibmcam_PacketFormat2(uvd, 0x0a, 0x37); - ibmcam_PacketFormat2(uvd, 0x0b, 0xb8); - ibmcam_PacketFormat2(uvd, 0x0c, 0xf3); - ibmcam_PacketFormat2(uvd, 0x0d, 0xe3); - ibmcam_PacketFormat2(uvd, 0x0e, 0x0d); - ibmcam_PacketFormat2(uvd, 0x0f, 0xf2); - ibmcam_PacketFormat2(uvd, 0x10, 0xd5); - ibmcam_PacketFormat2(uvd, 0x11, 0xba); - ibmcam_PacketFormat2(uvd, 0x12, 0x53); - ibmcam_PacketFormat2(uvd, 0x3f, 0xff); - ibmcam_PacketFormat2(uvd, 0x39, 0x00); - - ibmcam_PacketFormat2(uvd, 0x39, 0x02); - ibmcam_PacketFormat2(uvd, 0x16, 0x00); - ibmcam_PacketFormat2(uvd, 0x17, 0x28); - ibmcam_PacketFormat2(uvd, 0x18, 0x7d); - ibmcam_PacketFormat2(uvd, 0x19, 0xbe); - ibmcam_PacketFormat2(uvd, 0x3f, 0xff); - ibmcam_PacketFormat2(uvd, 0x39, 0x00); - - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x00, 0x18); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x13, 0x18); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x14, 0x06); - - /* This is default brightness */ - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x31, 0x37); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x32, 0x46); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x33, 0x55); - - ibmcam_Packet_Format1(uvd, 0x2e, 0x04); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x2d, 0x04); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x29, 0x80); - ibmcam_Packet_Format1(uvd, 0x2c, 0x01); - ibmcam_Packet_Format1(uvd, 0x30, 0x17); - ibmcam_Packet_Format1(uvd, 0x39, 0x08); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x34, 0x00); - - ibmcam_veio(uvd, 0, 0x00, 0x0101); - ibmcam_veio(uvd, 0, 0x00, 0x010a); - - switch (uvd->videosize) { - case VIDEOSIZE_128x96: - ibmcam_veio(uvd, 0, 0x80, 0x0103); - ibmcam_veio(uvd, 0, 0x60, 0x0105); - ibmcam_veio(uvd, 0, 0x0c, 0x010b); - ibmcam_veio(uvd, 0, 0x04, 0x011b); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x0b, 0x011d); - ibmcam_veio(uvd, 0, 0x00, 0x011e); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x00, 0x0129); - break; - case VIDEOSIZE_176x144: - ibmcam_veio(uvd, 0, 0xb0, 0x0103); - ibmcam_veio(uvd, 0, 0x8f, 0x0105); - ibmcam_veio(uvd, 0, 0x06, 0x010b); - ibmcam_veio(uvd, 0, 0x04, 0x011b); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x0d, 0x011d); - ibmcam_veio(uvd, 0, 0x00, 0x011e); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x03, 0x0129); - break; - case VIDEOSIZE_352x288: - ibmcam_veio(uvd, 0, 0xb0, 0x0103); - ibmcam_veio(uvd, 0, 0x90, 0x0105); - ibmcam_veio(uvd, 0, 0x02, 0x010b); - ibmcam_veio(uvd, 0, 0x04, 0x011b); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x05, 0x011d); - ibmcam_veio(uvd, 0, 0x00, 0x011e); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x00, 0x0129); - break; - } - - ibmcam_veio(uvd, 0, 0xff, 0x012b); - - /* This is another brightness - don't know why */ - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x31, 0xc3); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x32, 0xd2); - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, 0x33, 0xe1); - - /* Default contrast */ - for (i=0; i < ntries; i++) - ibmcam_Packet_Format1(uvd, contrast_14, 0x0a); - - /* Default sharpness */ - for (i=0; i < 2; i++) - ibmcam_PacketFormat2(uvd, sharp_13, 0x1a); /* Level 4 FIXME */ - - /* Default lighting conditions */ - ibmcam_Packet_Format1(uvd, light_27, lighting); /* 0=Bright 2=Low */ - - /* Assorted init */ - - switch (uvd->videosize) { - case VIDEOSIZE_128x96: - ibmcam_Packet_Format1(uvd, 0x2b, 0x1e); - ibmcam_veio(uvd, 0, 0xc9, 0x0119); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x80, 0x0109); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x36, 0x0102); - ibmcam_veio(uvd, 0, 0x1a, 0x0104); - ibmcam_veio(uvd, 0, 0x04, 0x011a); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x2b, 0x011c); - ibmcam_veio(uvd, 0, 0x23, 0x012a); /* Same everywhere */ -#if 0 - ibmcam_veio(uvd, 0, 0x00, 0x0106); - ibmcam_veio(uvd, 0, 0x38, 0x0107); -#else - ibmcam_veio(uvd, 0, 0x02, 0x0106); - ibmcam_veio(uvd, 0, 0x2a, 0x0107); -#endif - break; - case VIDEOSIZE_176x144: - ibmcam_Packet_Format1(uvd, 0x2b, 0x1e); - ibmcam_veio(uvd, 0, 0xc9, 0x0119); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x80, 0x0109); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x04, 0x0102); - ibmcam_veio(uvd, 0, 0x02, 0x0104); - ibmcam_veio(uvd, 0, 0x04, 0x011a); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x2b, 0x011c); - ibmcam_veio(uvd, 0, 0x23, 0x012a); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x01, 0x0106); - ibmcam_veio(uvd, 0, 0xca, 0x0107); - break; - case VIDEOSIZE_352x288: - ibmcam_Packet_Format1(uvd, 0x2b, 0x1f); - ibmcam_veio(uvd, 0, 0xc9, 0x0119); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x80, 0x0109); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x08, 0x0102); - ibmcam_veio(uvd, 0, 0x01, 0x0104); - ibmcam_veio(uvd, 0, 0x04, 0x011a); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x2f, 0x011c); - ibmcam_veio(uvd, 0, 0x23, 0x012a); /* Same everywhere */ - ibmcam_veio(uvd, 0, 0x03, 0x0106); - ibmcam_veio(uvd, 0, 0xf6, 0x0107); - break; - } - return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT); -} - -static int ibmcam_model2_setup(struct uvd *uvd) -{ - ibmcam_veio(uvd, 0, 0x0000, 0x0100); /* LED on */ - ibmcam_veio(uvd, 1, 0x0000, 0x0116); - ibmcam_veio(uvd, 0, 0x0060, 0x0116); - ibmcam_veio(uvd, 0, 0x0002, 0x0112); - ibmcam_veio(uvd, 0, 0x00bc, 0x012c); - ibmcam_veio(uvd, 0, 0x0008, 0x012b); - ibmcam_veio(uvd, 0, 0x0000, 0x0108); - ibmcam_veio(uvd, 0, 0x0001, 0x0133); - ibmcam_veio(uvd, 0, 0x0001, 0x0102); - switch (uvd->videosize) { - case VIDEOSIZE_176x144: - ibmcam_veio(uvd, 0, 0x002c, 0x0103); /* All except 320x240 */ - ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */ - ibmcam_veio(uvd, 0, 0x0024, 0x0105); /* 176x144, 352x288 */ - ibmcam_veio(uvd, 0, 0x00b9, 0x010a); /* Unique to this mode */ - ibmcam_veio(uvd, 0, 0x0038, 0x0119); /* Unique to this mode */ - ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */ - ibmcam_veio(uvd, 0, 0x0090, 0x0107); /* Unique to every mode*/ - break; - case VIDEOSIZE_320x240: - ibmcam_veio(uvd, 0, 0x0028, 0x0103); /* Unique to this mode */ - ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */ - ibmcam_veio(uvd, 0, 0x001e, 0x0105); /* 320x240, 352x240 */ - ibmcam_veio(uvd, 0, 0x0039, 0x010a); /* All except 176x144 */ - ibmcam_veio(uvd, 0, 0x0070, 0x0119); /* All except 176x144 */ - ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */ - ibmcam_veio(uvd, 0, 0x0098, 0x0107); /* Unique to every mode*/ - break; - case VIDEOSIZE_352x240: - ibmcam_veio(uvd, 0, 0x002c, 0x0103); /* All except 320x240 */ - ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */ - ibmcam_veio(uvd, 0, 0x001e, 0x0105); /* 320x240, 352x240 */ - ibmcam_veio(uvd, 0, 0x0039, 0x010a); /* All except 176x144 */ - ibmcam_veio(uvd, 0, 0x0070, 0x0119); /* All except 176x144 */ - ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */ - ibmcam_veio(uvd, 0, 0x00da, 0x0107); /* Unique to every mode*/ - break; - case VIDEOSIZE_352x288: - ibmcam_veio(uvd, 0, 0x002c, 0x0103); /* All except 320x240 */ - ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */ - ibmcam_veio(uvd, 0, 0x0024, 0x0105); /* 176x144, 352x288 */ - ibmcam_veio(uvd, 0, 0x0039, 0x010a); /* All except 176x144 */ - ibmcam_veio(uvd, 0, 0x0070, 0x0119); /* All except 176x144 */ - ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */ - ibmcam_veio(uvd, 0, 0x00fe, 0x0107); /* Unique to every mode*/ - break; - } - return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT); -} - -/* - * ibmcam_model1_setup_after_video_if() - * - * This code adds finishing touches to the video data interface. - * Here we configure the frame rate and turn on the LED. - */ -static void ibmcam_model1_setup_after_video_if(struct uvd *uvd) -{ - unsigned short internal_frame_rate; - - RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX); - internal_frame_rate = FRAMERATE_MAX - framerate; /* 0=Fast 6=Slow */ - ibmcam_veio(uvd, 0, 0x01, 0x0100); /* LED On */ - ibmcam_veio(uvd, 0, internal_frame_rate, 0x0111); - ibmcam_veio(uvd, 0, 0x01, 0x0114); - ibmcam_veio(uvd, 0, 0xc0, 0x010c); -} - -static void ibmcam_model2_setup_after_video_if(struct uvd *uvd) -{ - unsigned short setup_model2_rg2, setup_model2_sat, setup_model2_yb; - - ibmcam_veio(uvd, 0, 0x0000, 0x0100); /* LED on */ - - switch (uvd->videosize) { - case VIDEOSIZE_176x144: - ibmcam_veio(uvd, 0, 0x0050, 0x0111); - ibmcam_veio(uvd, 0, 0x00d0, 0x0111); - break; - case VIDEOSIZE_320x240: - case VIDEOSIZE_352x240: - case VIDEOSIZE_352x288: - ibmcam_veio(uvd, 0, 0x0040, 0x0111); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - break; - } - ibmcam_veio(uvd, 0, 0x009b, 0x010f); - ibmcam_veio(uvd, 0, 0x00bb, 0x010f); - - /* - * Hardware settings, may affect CMOS sensor; not user controls! - * ------------------------------------------------------------- - * 0x0004: no effect - * 0x0006: hardware effect - * 0x0008: no effect - * 0x000a: stops video stream, probably important h/w setting - * 0x000c: changes color in hardware manner (not user setting) - * 0x0012: changes number of colors (does not affect speed) - * 0x002a: no effect - * 0x002c: hardware setting (related to scan lines) - * 0x002e: stops video stream, probably important h/w setting - */ - ibmcam_model2_Packet1(uvd, 0x000a, 0x005c); - ibmcam_model2_Packet1(uvd, 0x0004, 0x0000); - ibmcam_model2_Packet1(uvd, 0x0006, 0x00fb); - ibmcam_model2_Packet1(uvd, 0x0008, 0x0000); - ibmcam_model2_Packet1(uvd, 0x000c, 0x0009); - ibmcam_model2_Packet1(uvd, 0x0012, 0x000a); - ibmcam_model2_Packet1(uvd, 0x002a, 0x0000); - ibmcam_model2_Packet1(uvd, 0x002c, 0x0000); - ibmcam_model2_Packet1(uvd, 0x002e, 0x0008); - - /* - * Function 0x0030 pops up all over the place. Apparently - * it is a hardware control register, with every bit assigned to - * do something. - */ - ibmcam_model2_Packet1(uvd, 0x0030, 0x0000); - - /* - * Magic control of CMOS sensor. Only lower values like - * 0-3 work, and picture shifts left or right. Don't change. - */ - switch (uvd->videosize) { - case VIDEOSIZE_176x144: - ibmcam_model2_Packet1(uvd, 0x0014, 0x0002); - ibmcam_model2_Packet1(uvd, 0x0016, 0x0002); /* Horizontal shift */ - ibmcam_model2_Packet1(uvd, 0x0018, 0x004a); /* Another hardware setting */ - break; - case VIDEOSIZE_320x240: - ibmcam_model2_Packet1(uvd, 0x0014, 0x0009); - ibmcam_model2_Packet1(uvd, 0x0016, 0x0005); /* Horizontal shift */ - ibmcam_model2_Packet1(uvd, 0x0018, 0x0044); /* Another hardware setting */ - break; - case VIDEOSIZE_352x240: - /* This mode doesn't work as Windows programs it; changed to work */ - ibmcam_model2_Packet1(uvd, 0x0014, 0x0009); /* Windows sets this to 8 */ - ibmcam_model2_Packet1(uvd, 0x0016, 0x0003); /* Horizontal shift */ - ibmcam_model2_Packet1(uvd, 0x0018, 0x0044); /* Windows sets this to 0x0045 */ - break; - case VIDEOSIZE_352x288: - ibmcam_model2_Packet1(uvd, 0x0014, 0x0003); - ibmcam_model2_Packet1(uvd, 0x0016, 0x0002); /* Horizontal shift */ - ibmcam_model2_Packet1(uvd, 0x0018, 0x004a); /* Another hardware setting */ - break; - } - - ibmcam_model2_Packet1(uvd, mod2_brightness, 0x005a); - - /* - * We have our own frame rate setting varying from 0 (slowest) to 6 (fastest). - * The camera model 2 allows frame rate in range [0..0x1F] where 0 is also the - * slowest setting. However for all practical reasons high settings make no - * sense because USB is not fast enough to support high FPS. Be aware that - * the picture datastream will be severely disrupted if you ask for - * frame rate faster than allowed for the video size - see below: - * - * Allowable ranges (obtained experimentally on OHCI, K6-3, 450 MHz): - * ----------------------------------------------------------------- - * 176x144: [6..31] - * 320x240: [8..31] - * 352x240: [10..31] - * 352x288: [16..31] I have to raise lower threshold for stability... - * - * As usual, slower FPS provides better sensitivity. - */ - { - short hw_fps=31, i_framerate; - - RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX); - i_framerate = FRAMERATE_MAX - framerate + FRAMERATE_MIN; - switch (uvd->videosize) { - case VIDEOSIZE_176x144: - hw_fps = 6 + i_framerate*4; - break; - case VIDEOSIZE_320x240: - hw_fps = 8 + i_framerate*3; - break; - case VIDEOSIZE_352x240: - hw_fps = 10 + i_framerate*2; - break; - case VIDEOSIZE_352x288: - hw_fps = 28 + i_framerate/2; - break; - } - if (uvd->debug > 0) - dev_info(&uvd->dev->dev, "Framerate (hardware): %hd.\n", - hw_fps); - RESTRICT_TO_RANGE(hw_fps, 0, 31); - ibmcam_model2_Packet1(uvd, mod2_set_framerate, hw_fps); - } - - /* - * This setting does not visibly affect pictures; left it here - * because it was present in Windows USB data stream. This function - * does not allow arbitrary values and apparently is a bit mask, to - * be activated only at appropriate time. Don't change it randomly! - */ - switch (uvd->videosize) { - case VIDEOSIZE_176x144: - ibmcam_model2_Packet1(uvd, 0x0026, 0x00c2); - break; - case VIDEOSIZE_320x240: - ibmcam_model2_Packet1(uvd, 0x0026, 0x0044); - break; - case VIDEOSIZE_352x240: - ibmcam_model2_Packet1(uvd, 0x0026, 0x0046); - break; - case VIDEOSIZE_352x288: - ibmcam_model2_Packet1(uvd, 0x0026, 0x0048); - break; - } - - ibmcam_model2_Packet1(uvd, mod2_sensitivity, lighting); - - if (init_model2_rg2 >= 0) { - RESTRICT_TO_RANGE(init_model2_rg2, 0, 255); - setup_model2_rg2 = init_model2_rg2; - } else - setup_model2_rg2 = 0x002f; - - if (init_model2_sat >= 0) { - RESTRICT_TO_RANGE(init_model2_sat, 0, 255); - setup_model2_sat = init_model2_sat; - } else - setup_model2_sat = 0x0034; - - if (init_model2_yb >= 0) { - RESTRICT_TO_RANGE(init_model2_yb, 0, 255); - setup_model2_yb = init_model2_yb; - } else - setup_model2_yb = 0x00a0; - - ibmcam_model2_Packet1(uvd, mod2_color_balance_rg2, setup_model2_rg2); - ibmcam_model2_Packet1(uvd, mod2_saturation, setup_model2_sat); - ibmcam_model2_Packet1(uvd, mod2_color_balance_yb, setup_model2_yb); - ibmcam_model2_Packet1(uvd, mod2_hue, uvd->vpic.hue >> 9); /* 0 .. 7F */; - - /* Hardware control command */ - ibmcam_model2_Packet1(uvd, 0x0030, 0x0004); - - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go camera, go! */ - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); -} - -static void ibmcam_model4_setup_after_video_if(struct uvd *uvd) -{ - switch (uvd->videosize) { - case VIDEOSIZE_128x96: - ibmcam_veio(uvd, 0, 0x0000, 0x0100); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - ibmcam_veio(uvd, 0, 0x00bc, 0x012c); - ibmcam_veio(uvd, 0, 0x0080, 0x012b); - ibmcam_veio(uvd, 0, 0x0000, 0x0108); - ibmcam_veio(uvd, 0, 0x0001, 0x0133); - ibmcam_veio(uvd, 0, 0x009b, 0x010f); - ibmcam_veio(uvd, 0, 0x00bb, 0x010f); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x000a, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x005c, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0004, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00fb, 0x012e); - ibmcam_veio(uvd, 0, 0x0000, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x000c, 0x0127); - ibmcam_veio(uvd, 0, 0x0009, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0012, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0008, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x002a, 0x012d); - ibmcam_veio(uvd, 0, 0x0000, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0034, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x0070, 0x0119); - ibmcam_veio(uvd, 0, 0x00d2, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x005e, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x00d0, 0x0111); - ibmcam_veio(uvd, 0, 0x0039, 0x010a); - ibmcam_veio(uvd, 0, 0x0001, 0x0102); - ibmcam_veio(uvd, 0, 0x0028, 0x0103); - ibmcam_veio(uvd, 0, 0x0000, 0x0104); - ibmcam_veio(uvd, 0, 0x001e, 0x0105); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0016, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x000a, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0014, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012e); - ibmcam_veio(uvd, 0, 0x001a, 0x0130); - ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); - ibmcam_veio(uvd, 0, 0x005a, 0x012d); - ibmcam_veio(uvd, 0, 0x9545, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x0127); - ibmcam_veio(uvd, 0, 0x0018, 0x012e); - ibmcam_veio(uvd, 0, 0x0043, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x001c, 0x0127); - ibmcam_veio(uvd, 0, 0x00eb, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0032, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0036, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x001e, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0017, 0x0127); - ibmcam_veio(uvd, 0, 0x0013, 0x012e); - ibmcam_veio(uvd, 0, 0x0031, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x0017, 0x012d); - ibmcam_veio(uvd, 0, 0x0078, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0004, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - break; - case VIDEOSIZE_160x120: - ibmcam_veio(uvd, 0, 0x0000, 0x0100); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - ibmcam_veio(uvd, 0, 0x00bc, 0x012c); - ibmcam_veio(uvd, 0, 0x0080, 0x012b); - ibmcam_veio(uvd, 0, 0x0000, 0x0108); - ibmcam_veio(uvd, 0, 0x0001, 0x0133); - ibmcam_veio(uvd, 0, 0x009b, 0x010f); - ibmcam_veio(uvd, 0, 0x00bb, 0x010f); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x000a, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x005c, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0004, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00fb, 0x012e); - ibmcam_veio(uvd, 0, 0x0000, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x000c, 0x0127); - ibmcam_veio(uvd, 0, 0x0009, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0012, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0008, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x002a, 0x012d); - ibmcam_veio(uvd, 0, 0x0000, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0034, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x0038, 0x0119); - ibmcam_veio(uvd, 0, 0x00d8, 0x0107); - ibmcam_veio(uvd, 0, 0x0002, 0x0106); - ibmcam_veio(uvd, 0, 0x00d0, 0x0111); - ibmcam_veio(uvd, 0, 0x00b9, 0x010a); - ibmcam_veio(uvd, 0, 0x0001, 0x0102); - ibmcam_veio(uvd, 0, 0x0028, 0x0103); - ibmcam_veio(uvd, 0, 0x0000, 0x0104); - ibmcam_veio(uvd, 0, 0x001e, 0x0105); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0016, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x000b, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0014, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012e); - ibmcam_veio(uvd, 0, 0x001a, 0x0130); - ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); - ibmcam_veio(uvd, 0, 0x005a, 0x012d); - ibmcam_veio(uvd, 0, 0x9545, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x0127); - ibmcam_veio(uvd, 0, 0x0018, 0x012e); - ibmcam_veio(uvd, 0, 0x0043, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x001c, 0x0127); - ibmcam_veio(uvd, 0, 0x00c7, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0032, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0025, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0036, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x001e, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0048, 0x0127); - ibmcam_veio(uvd, 0, 0x0035, 0x012e); - ibmcam_veio(uvd, 0, 0x00d0, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x0048, 0x012d); - ibmcam_veio(uvd, 0, 0x0090, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x0001, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0004, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - break; - case VIDEOSIZE_176x144: - ibmcam_veio(uvd, 0, 0x0000, 0x0100); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - ibmcam_veio(uvd, 0, 0x00bc, 0x012c); - ibmcam_veio(uvd, 0, 0x0080, 0x012b); - ibmcam_veio(uvd, 0, 0x0000, 0x0108); - ibmcam_veio(uvd, 0, 0x0001, 0x0133); - ibmcam_veio(uvd, 0, 0x009b, 0x010f); - ibmcam_veio(uvd, 0, 0x00bb, 0x010f); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x000a, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x005c, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0004, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00fb, 0x012e); - ibmcam_veio(uvd, 0, 0x0000, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x000c, 0x0127); - ibmcam_veio(uvd, 0, 0x0009, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0012, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0008, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x002a, 0x012d); - ibmcam_veio(uvd, 0, 0x0000, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0034, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x0038, 0x0119); - ibmcam_veio(uvd, 0, 0x00d6, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x0018, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x00d0, 0x0111); - ibmcam_veio(uvd, 0, 0x00b9, 0x010a); - ibmcam_veio(uvd, 0, 0x0001, 0x0102); - ibmcam_veio(uvd, 0, 0x002c, 0x0103); - ibmcam_veio(uvd, 0, 0x0000, 0x0104); - ibmcam_veio(uvd, 0, 0x0024, 0x0105); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0016, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0007, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0014, 0x012d); - ibmcam_veio(uvd, 0, 0x0001, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012e); - ibmcam_veio(uvd, 0, 0x001a, 0x0130); - ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); - ibmcam_veio(uvd, 0, 0x005e, 0x012d); - ibmcam_veio(uvd, 0, 0x9545, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x0127); - ibmcam_veio(uvd, 0, 0x0018, 0x012e); - ibmcam_veio(uvd, 0, 0x0049, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x001c, 0x0127); - ibmcam_veio(uvd, 0, 0x00c7, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0032, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0028, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0036, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x001e, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0010, 0x0127); - ibmcam_veio(uvd, 0, 0x0013, 0x012e); - ibmcam_veio(uvd, 0, 0x002a, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x0010, 0x012d); - ibmcam_veio(uvd, 0, 0x006d, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x0001, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0004, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - break; - case VIDEOSIZE_320x240: - ibmcam_veio(uvd, 0, 0x0000, 0x0100); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - ibmcam_veio(uvd, 0, 0x00bc, 0x012c); - ibmcam_veio(uvd, 0, 0x0080, 0x012b); - ibmcam_veio(uvd, 0, 0x0000, 0x0108); - ibmcam_veio(uvd, 0, 0x0001, 0x0133); - ibmcam_veio(uvd, 0, 0x009b, 0x010f); - ibmcam_veio(uvd, 0, 0x00bb, 0x010f); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x000a, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x005c, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0004, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00fb, 0x012e); - ibmcam_veio(uvd, 0, 0x0000, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x000c, 0x0127); - ibmcam_veio(uvd, 0, 0x0009, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0012, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0008, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x002a, 0x012d); - ibmcam_veio(uvd, 0, 0x0000, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0034, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x0070, 0x0119); - ibmcam_veio(uvd, 0, 0x00d2, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x005e, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x00d0, 0x0111); - ibmcam_veio(uvd, 0, 0x0039, 0x010a); - ibmcam_veio(uvd, 0, 0x0001, 0x0102); - ibmcam_veio(uvd, 0, 0x0028, 0x0103); - ibmcam_veio(uvd, 0, 0x0000, 0x0104); - ibmcam_veio(uvd, 0, 0x001e, 0x0105); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0016, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x000a, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0014, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012e); - ibmcam_veio(uvd, 0, 0x001a, 0x0130); - ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); - ibmcam_veio(uvd, 0, 0x005a, 0x012d); - ibmcam_veio(uvd, 0, 0x9545, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x0127); - ibmcam_veio(uvd, 0, 0x0018, 0x012e); - ibmcam_veio(uvd, 0, 0x0043, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x001c, 0x0127); - ibmcam_veio(uvd, 0, 0x00eb, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0032, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0036, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x001e, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0017, 0x0127); - ibmcam_veio(uvd, 0, 0x0013, 0x012e); - ibmcam_veio(uvd, 0, 0x0031, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x0017, 0x012d); - ibmcam_veio(uvd, 0, 0x0078, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0004, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - break; - case VIDEOSIZE_352x288: - ibmcam_veio(uvd, 0, 0x0000, 0x0100); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - ibmcam_veio(uvd, 0, 0x00bc, 0x012c); - ibmcam_veio(uvd, 0, 0x0080, 0x012b); - ibmcam_veio(uvd, 0, 0x0000, 0x0108); - ibmcam_veio(uvd, 0, 0x0001, 0x0133); - ibmcam_veio(uvd, 0, 0x009b, 0x010f); - ibmcam_veio(uvd, 0, 0x00bb, 0x010f); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x000a, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x005c, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0004, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00fb, 0x012e); - ibmcam_veio(uvd, 0, 0x0000, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x000c, 0x0127); - ibmcam_veio(uvd, 0, 0x0009, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0012, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0008, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x002a, 0x012d); - ibmcam_veio(uvd, 0, 0x0000, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0034, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x0070, 0x0119); - ibmcam_veio(uvd, 0, 0x00f2, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x008c, 0x0107); - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x00c0, 0x0111); - ibmcam_veio(uvd, 0, 0x0039, 0x010a); - ibmcam_veio(uvd, 0, 0x0001, 0x0102); - ibmcam_veio(uvd, 0, 0x002c, 0x0103); - ibmcam_veio(uvd, 0, 0x0000, 0x0104); - ibmcam_veio(uvd, 0, 0x0024, 0x0105); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0016, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0006, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0014, 0x012d); - ibmcam_veio(uvd, 0, 0x0002, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012e); - ibmcam_veio(uvd, 0, 0x001a, 0x0130); - ibmcam_veio(uvd, 0, 0x8a0a, 0x0124); - ibmcam_veio(uvd, 0, 0x005e, 0x012d); - ibmcam_veio(uvd, 0, 0x9545, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x0127); - ibmcam_veio(uvd, 0, 0x0018, 0x012e); - ibmcam_veio(uvd, 0, 0x0049, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012f); - ibmcam_veio(uvd, 0, 0xd055, 0x0124); - ibmcam_veio(uvd, 0, 0x001c, 0x0127); - ibmcam_veio(uvd, 0, 0x00cf, 0x012e); - ibmcam_veio(uvd, 0, 0xaa28, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0032, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0x00aa, 0x0130); - ibmcam_veio(uvd, 0, 0x82a8, 0x0124); - ibmcam_veio(uvd, 0, 0x0036, 0x012d); - ibmcam_veio(uvd, 0, 0x0008, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0xfffa, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x001e, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0010, 0x0127); - ibmcam_veio(uvd, 0, 0x0013, 0x012e); - ibmcam_veio(uvd, 0, 0x0025, 0x0130); - ibmcam_veio(uvd, 0, 0x8a28, 0x0124); - ibmcam_veio(uvd, 0, 0x0010, 0x012d); - ibmcam_veio(uvd, 0, 0x0048, 0x012f); - ibmcam_veio(uvd, 0, 0xd145, 0x0124); - ibmcam_veio(uvd, 0, 0x0000, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00aa, 0x012d); - ibmcam_veio(uvd, 0, 0x0038, 0x012f); - ibmcam_veio(uvd, 0, 0xd141, 0x0124); - ibmcam_veio(uvd, 0, 0x0004, 0x0127); - ibmcam_veio(uvd, 0, 0xfea8, 0x0124); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - break; - } - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); -} - -static void ibmcam_model3_setup_after_video_if(struct uvd *uvd) -{ - int i; - /* - * 01.01.08 - Added for RCA video in support -LO - * This struct is used to init the Model3 cam to use the RCA video in port - * instead of the CCD sensor. - */ - static const struct struct_initData initData[] = { - {0, 0x0000, 0x010c}, - {0, 0x0006, 0x012c}, - {0, 0x0078, 0x012d}, - {0, 0x0046, 0x012f}, - {0, 0xd141, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfea8, 0x0124}, - {1, 0x0000, 0x0116}, - {0, 0x0064, 0x0116}, - {1, 0x0000, 0x0115}, - {0, 0x0003, 0x0115}, - {0, 0x0008, 0x0123}, - {0, 0x0000, 0x0117}, - {0, 0x0000, 0x0112}, - {0, 0x0080, 0x0100}, - {0, 0x0000, 0x0100}, - {1, 0x0000, 0x0116}, - {0, 0x0060, 0x0116}, - {0, 0x0002, 0x0112}, - {0, 0x0000, 0x0123}, - {0, 0x0001, 0x0117}, - {0, 0x0040, 0x0108}, - {0, 0x0019, 0x012c}, - {0, 0x0040, 0x0116}, - {0, 0x000a, 0x0115}, - {0, 0x000b, 0x0115}, - {0, 0x0078, 0x012d}, - {0, 0x0046, 0x012f}, - {0, 0xd141, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfea8, 0x0124}, - {0, 0x0064, 0x0116}, - {0, 0x0000, 0x0115}, - {0, 0x0001, 0x0115}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00aa, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00f2, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x000f, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00f8, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00fc, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00f9, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x003c, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0027, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0019, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0021, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0006, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0045, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002a, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x000e, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002b, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00f4, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002c, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0004, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002d, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0014, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002e, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0003, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002f, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0003, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0014, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0053, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0x0000, 0x0101}, - {0, 0x00a0, 0x0103}, - {0, 0x0078, 0x0105}, - {0, 0x0000, 0x010a}, - {0, 0x0024, 0x010b}, - {0, 0x0028, 0x0119}, - {0, 0x0088, 0x011b}, - {0, 0x0002, 0x011d}, - {0, 0x0003, 0x011e}, - {0, 0x0000, 0x0129}, - {0, 0x00fc, 0x012b}, - {0, 0x0008, 0x0102}, - {0, 0x0000, 0x0104}, - {0, 0x0008, 0x011a}, - {0, 0x0028, 0x011c}, - {0, 0x0021, 0x012a}, - {0, 0x0000, 0x0118}, - {0, 0x0000, 0x0132}, - {0, 0x0000, 0x0109}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0031, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00dc, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0032, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0020, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0030, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0008, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0x0003, 0x0106}, - {0, 0x0062, 0x0107}, - {0, 0x0003, 0x0111}, - }; -#define NUM_INIT_DATA - - unsigned short compression = 0; /* 0=none, 7=best frame rate */ - int f_rate; /* 0=Fastest 7=slowest */ - - if (IBMCAM_T(uvd)->initialized) - return; - - /* Internal frame rate is controlled by f_rate value */ - f_rate = 7 - framerate; - RESTRICT_TO_RANGE(f_rate, 0, 7); - - ibmcam_veio(uvd, 0, 0x0000, 0x0100); - ibmcam_veio(uvd, 1, 0x0000, 0x0116); - ibmcam_veio(uvd, 0, 0x0060, 0x0116); - ibmcam_veio(uvd, 0, 0x0002, 0x0112); - ibmcam_veio(uvd, 0, 0x0000, 0x0123); - ibmcam_veio(uvd, 0, 0x0001, 0x0117); - ibmcam_veio(uvd, 0, 0x0040, 0x0108); - ibmcam_veio(uvd, 0, 0x0019, 0x012c); - ibmcam_veio(uvd, 0, 0x0060, 0x0116); - ibmcam_veio(uvd, 0, 0x0002, 0x0115); - ibmcam_veio(uvd, 0, 0x0003, 0x0115); - ibmcam_veio(uvd, 1, 0x0000, 0x0115); - ibmcam_veio(uvd, 0, 0x000b, 0x0115); - ibmcam_model3_Packet1(uvd, 0x000a, 0x0040); - ibmcam_model3_Packet1(uvd, 0x000b, 0x00f6); - ibmcam_model3_Packet1(uvd, 0x000c, 0x0002); - ibmcam_model3_Packet1(uvd, 0x000d, 0x0020); - ibmcam_model3_Packet1(uvd, 0x000e, 0x0033); - ibmcam_model3_Packet1(uvd, 0x000f, 0x0007); - ibmcam_model3_Packet1(uvd, 0x0010, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0011, 0x0070); - ibmcam_model3_Packet1(uvd, 0x0012, 0x0030); - ibmcam_model3_Packet1(uvd, 0x0013, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0014, 0x0001); - ibmcam_model3_Packet1(uvd, 0x0015, 0x0001); - ibmcam_model3_Packet1(uvd, 0x0016, 0x0001); - ibmcam_model3_Packet1(uvd, 0x0017, 0x0001); - ibmcam_model3_Packet1(uvd, 0x0018, 0x0000); - ibmcam_model3_Packet1(uvd, 0x001e, 0x00c3); - ibmcam_model3_Packet1(uvd, 0x0020, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0028, 0x0010); - ibmcam_model3_Packet1(uvd, 0x0029, 0x0054); - ibmcam_model3_Packet1(uvd, 0x002a, 0x0013); - ibmcam_model3_Packet1(uvd, 0x002b, 0x0007); - ibmcam_model3_Packet1(uvd, 0x002d, 0x0028); - ibmcam_model3_Packet1(uvd, 0x002e, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0031, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0032, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0033, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0034, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0035, 0x0038); - ibmcam_model3_Packet1(uvd, 0x003a, 0x0001); - ibmcam_model3_Packet1(uvd, 0x003c, 0x001e); - ibmcam_model3_Packet1(uvd, 0x003f, 0x000a); - ibmcam_model3_Packet1(uvd, 0x0041, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0046, 0x003f); - ibmcam_model3_Packet1(uvd, 0x0047, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0050, 0x0005); - ibmcam_model3_Packet1(uvd, 0x0052, 0x001a); - ibmcam_model3_Packet1(uvd, 0x0053, 0x0003); - ibmcam_model3_Packet1(uvd, 0x005a, 0x006b); - ibmcam_model3_Packet1(uvd, 0x005d, 0x001e); - ibmcam_model3_Packet1(uvd, 0x005e, 0x0030); - ibmcam_model3_Packet1(uvd, 0x005f, 0x0041); - ibmcam_model3_Packet1(uvd, 0x0064, 0x0008); - ibmcam_model3_Packet1(uvd, 0x0065, 0x0015); - ibmcam_model3_Packet1(uvd, 0x0068, 0x000f); - ibmcam_model3_Packet1(uvd, 0x0079, 0x0000); - ibmcam_model3_Packet1(uvd, 0x007a, 0x0000); - ibmcam_model3_Packet1(uvd, 0x007c, 0x003f); - ibmcam_model3_Packet1(uvd, 0x0082, 0x000f); - ibmcam_model3_Packet1(uvd, 0x0085, 0x0000); - ibmcam_model3_Packet1(uvd, 0x0099, 0x0000); - ibmcam_model3_Packet1(uvd, 0x009b, 0x0023); - ibmcam_model3_Packet1(uvd, 0x009c, 0x0022); - ibmcam_model3_Packet1(uvd, 0x009d, 0x0096); - ibmcam_model3_Packet1(uvd, 0x009e, 0x0096); - ibmcam_model3_Packet1(uvd, 0x009f, 0x000a); - - switch (uvd->videosize) { - case VIDEOSIZE_160x120: - ibmcam_veio(uvd, 0, 0x0000, 0x0101); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x00a0, 0x0103); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x0078, 0x0105); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */ - ibmcam_veio(uvd, 0, 0x0024, 0x010b); /* Differs everywhere */ - ibmcam_veio(uvd, 0, 0x00a9, 0x0119); - ibmcam_veio(uvd, 0, 0x0016, 0x011b); - ibmcam_veio(uvd, 0, 0x0002, 0x011d); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x0003, 0x011e); /* Same on 176x144, 640x480 */ - ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */ - ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */ - ibmcam_veio(uvd, 0, 0x0018, 0x0102); - ibmcam_veio(uvd, 0, 0x0004, 0x0104); - ibmcam_veio(uvd, 0, 0x0004, 0x011a); - ibmcam_veio(uvd, 0, 0x0028, 0x011c); - ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */ - ibmcam_veio(uvd, 0, 0x0000, 0x0118); - ibmcam_veio(uvd, 0, 0x0000, 0x0132); - ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */ - ibmcam_veio(uvd, 0, compression, 0x0109); - break; - case VIDEOSIZE_320x240: - ibmcam_veio(uvd, 0, 0x0000, 0x0101); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x00a0, 0x0103); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x0078, 0x0105); /* Same on 176x144, 320x240 */ - ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */ - ibmcam_veio(uvd, 0, 0x0028, 0x010b); /* Differs everywhere */ - ibmcam_veio(uvd, 0, 0x0002, 0x011d); /* Same */ - ibmcam_veio(uvd, 0, 0x0000, 0x011e); - ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */ - ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */ - /* 4 commands from 160x120 skipped */ - ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */ - ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */ - ibmcam_veio(uvd, 0, compression, 0x0109); - ibmcam_veio(uvd, 0, 0x00d9, 0x0119); - ibmcam_veio(uvd, 0, 0x0006, 0x011b); - ibmcam_veio(uvd, 0, 0x0021, 0x0102); /* Same on 320x240, 640x480 */ - ibmcam_veio(uvd, 0, 0x0010, 0x0104); - ibmcam_veio(uvd, 0, 0x0004, 0x011a); - ibmcam_veio(uvd, 0, 0x003f, 0x011c); - ibmcam_veio(uvd, 0, 0x001c, 0x0118); - ibmcam_veio(uvd, 0, 0x0000, 0x0132); - break; - case VIDEOSIZE_640x480: - ibmcam_veio(uvd, 0, 0x00f0, 0x0105); - ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */ - ibmcam_veio(uvd, 0, 0x0038, 0x010b); /* Differs everywhere */ - ibmcam_veio(uvd, 0, 0x00d9, 0x0119); /* Same on 320x240, 640x480 */ - ibmcam_veio(uvd, 0, 0x0006, 0x011b); /* Same on 320x240, 640x480 */ - ibmcam_veio(uvd, 0, 0x0004, 0x011d); /* NC */ - ibmcam_veio(uvd, 0, 0x0003, 0x011e); /* Same on 176x144, 640x480 */ - ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */ - ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */ - ibmcam_veio(uvd, 0, 0x0021, 0x0102); /* Same on 320x240, 640x480 */ - ibmcam_veio(uvd, 0, 0x0016, 0x0104); /* NC */ - ibmcam_veio(uvd, 0, 0x0004, 0x011a); /* Same on 320x240, 640x480 */ - ibmcam_veio(uvd, 0, 0x003f, 0x011c); /* Same on 320x240, 640x480 */ - ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */ - ibmcam_veio(uvd, 0, 0x001c, 0x0118); /* Same on 320x240, 640x480 */ - ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */ - ibmcam_veio(uvd, 0, compression, 0x0109); - ibmcam_veio(uvd, 0, 0x0040, 0x0101); - ibmcam_veio(uvd, 0, 0x0040, 0x0103); - ibmcam_veio(uvd, 0, 0x0000, 0x0132); /* Same on 320x240, 640x480 */ - break; - } - ibmcam_model3_Packet1(uvd, 0x007e, 0x000e); /* Hue */ - ibmcam_model3_Packet1(uvd, 0x0036, 0x0011); /* Brightness */ - ibmcam_model3_Packet1(uvd, 0x0060, 0x0002); /* Sharpness */ - ibmcam_model3_Packet1(uvd, 0x0061, 0x0004); /* Sharpness */ - ibmcam_model3_Packet1(uvd, 0x0062, 0x0005); /* Sharpness */ - ibmcam_model3_Packet1(uvd, 0x0063, 0x0014); /* Sharpness */ - ibmcam_model3_Packet1(uvd, 0x0096, 0x00a0); /* Red gain */ - ibmcam_model3_Packet1(uvd, 0x0097, 0x0096); /* Blue gain */ - ibmcam_model3_Packet1(uvd, 0x0067, 0x0001); /* Contrast */ - ibmcam_model3_Packet1(uvd, 0x005b, 0x000c); /* Contrast */ - ibmcam_model3_Packet1(uvd, 0x005c, 0x0016); /* Contrast */ - ibmcam_model3_Packet1(uvd, 0x0098, 0x000b); - ibmcam_model3_Packet1(uvd, 0x002c, 0x0003); /* Was 1, broke 640x480 */ - ibmcam_model3_Packet1(uvd, 0x002f, 0x002a); - ibmcam_model3_Packet1(uvd, 0x0030, 0x0029); - ibmcam_model3_Packet1(uvd, 0x0037, 0x0002); - ibmcam_model3_Packet1(uvd, 0x0038, 0x0059); - ibmcam_model3_Packet1(uvd, 0x003d, 0x002e); - ibmcam_model3_Packet1(uvd, 0x003e, 0x0028); - ibmcam_model3_Packet1(uvd, 0x0078, 0x0005); - ibmcam_model3_Packet1(uvd, 0x007b, 0x0011); - ibmcam_model3_Packet1(uvd, 0x007d, 0x004b); - ibmcam_model3_Packet1(uvd, 0x007f, 0x0022); - ibmcam_model3_Packet1(uvd, 0x0080, 0x000c); - ibmcam_model3_Packet1(uvd, 0x0081, 0x000b); - ibmcam_model3_Packet1(uvd, 0x0083, 0x00fd); - ibmcam_model3_Packet1(uvd, 0x0086, 0x000b); - ibmcam_model3_Packet1(uvd, 0x0087, 0x000b); - ibmcam_model3_Packet1(uvd, 0x007e, 0x000e); - ibmcam_model3_Packet1(uvd, 0x0096, 0x00a0); /* Red gain */ - ibmcam_model3_Packet1(uvd, 0x0097, 0x0096); /* Blue gain */ - ibmcam_model3_Packet1(uvd, 0x0098, 0x000b); - - switch (uvd->videosize) { - case VIDEOSIZE_160x120: - ibmcam_veio(uvd, 0, 0x0002, 0x0106); - ibmcam_veio(uvd, 0, 0x0008, 0x0107); - ibmcam_veio(uvd, 0, f_rate, 0x0111); /* Frame rate */ - ibmcam_model3_Packet1(uvd, 0x001f, 0x0000); /* Same */ - ibmcam_model3_Packet1(uvd, 0x0039, 0x001f); /* Same */ - ibmcam_model3_Packet1(uvd, 0x003b, 0x003c); /* Same */ - ibmcam_model3_Packet1(uvd, 0x0040, 0x000a); - ibmcam_model3_Packet1(uvd, 0x0051, 0x000a); - break; - case VIDEOSIZE_320x240: - ibmcam_veio(uvd, 0, 0x0003, 0x0106); - ibmcam_veio(uvd, 0, 0x0062, 0x0107); - ibmcam_veio(uvd, 0, f_rate, 0x0111); /* Frame rate */ - ibmcam_model3_Packet1(uvd, 0x001f, 0x0000); /* Same */ - ibmcam_model3_Packet1(uvd, 0x0039, 0x001f); /* Same */ - ibmcam_model3_Packet1(uvd, 0x003b, 0x003c); /* Same */ - ibmcam_model3_Packet1(uvd, 0x0040, 0x0008); - ibmcam_model3_Packet1(uvd, 0x0051, 0x000b); - break; - case VIDEOSIZE_640x480: - ibmcam_veio(uvd, 0, 0x0002, 0x0106); /* Adjustments */ - ibmcam_veio(uvd, 0, 0x00b4, 0x0107); /* Adjustments */ - ibmcam_veio(uvd, 0, f_rate, 0x0111); /* Frame rate */ - ibmcam_model3_Packet1(uvd, 0x001f, 0x0002); /* !Same */ - ibmcam_model3_Packet1(uvd, 0x0039, 0x003e); /* !Same */ - ibmcam_model3_Packet1(uvd, 0x0040, 0x0008); - ibmcam_model3_Packet1(uvd, 0x0051, 0x000a); - break; - } - - /* 01.01.08 - Added for RCA video in support -LO */ - if(init_model3_input) { - if (debug > 0) - dev_info(&uvd->dev->dev, "Setting input to RCA.\n"); - for (i=0; i < ARRAY_SIZE(initData); i++) { - ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index); - } - } - - ibmcam_veio(uvd, 0, 0x0001, 0x0114); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); -} - -/* - * ibmcam_video_stop() - * - * This code tells camera to stop streaming. The interface remains - * configured and bandwidth - claimed. - */ -static void ibmcam_video_stop(struct uvd *uvd) -{ - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - ibmcam_veio(uvd, 0, 0x00, 0x010c); - ibmcam_veio(uvd, 0, 0x00, 0x010c); - ibmcam_veio(uvd, 0, 0x01, 0x0114); - ibmcam_veio(uvd, 0, 0xc0, 0x010c); - ibmcam_veio(uvd, 0, 0x00, 0x010c); - ibmcam_send_FF_04_02(uvd); - ibmcam_veio(uvd, 1, 0x00, 0x0100); - ibmcam_veio(uvd, 0, 0x81, 0x0100); /* LED Off */ - break; - case IBMCAM_MODEL_2: -case IBMCAM_MODEL_4: - ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop the camera */ - - ibmcam_model2_Packet1(uvd, 0x0030, 0x0004); - - ibmcam_veio(uvd, 0, 0x0080, 0x0100); /* LED Off */ - ibmcam_veio(uvd, 0, 0x0020, 0x0111); - ibmcam_veio(uvd, 0, 0x00a0, 0x0111); - - ibmcam_model2_Packet1(uvd, 0x0030, 0x0002); - - ibmcam_veio(uvd, 0, 0x0020, 0x0111); - ibmcam_veio(uvd, 0, 0x0000, 0x0112); - break; - case IBMCAM_MODEL_3: -#if 1 - ibmcam_veio(uvd, 0, 0x0000, 0x010c); - - /* Here we are supposed to select video interface alt. setting 0 */ - ibmcam_veio(uvd, 0, 0x0006, 0x012c); - - ibmcam_model3_Packet1(uvd, 0x0046, 0x0000); - - ibmcam_veio(uvd, 1, 0x0000, 0x0116); - ibmcam_veio(uvd, 0, 0x0064, 0x0116); - ibmcam_veio(uvd, 1, 0x0000, 0x0115); - ibmcam_veio(uvd, 0, 0x0003, 0x0115); - ibmcam_veio(uvd, 0, 0x0008, 0x0123); - ibmcam_veio(uvd, 0, 0x0000, 0x0117); - ibmcam_veio(uvd, 0, 0x0000, 0x0112); - ibmcam_veio(uvd, 0, 0x0080, 0x0100); - IBMCAM_T(uvd)->initialized = 0; -#endif - break; - } /* switch */ -} - -/* - * ibmcam_reinit_iso() - * - * This procedure sends couple of commands to the camera and then - * resets the video pipe. This sequence was observed to reinit the - * camera or, at least, to initiate ISO data stream. - * - * History: - * 1/2/00 Created. - */ -static void ibmcam_reinit_iso(struct uvd *uvd, int do_stop) -{ - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - if (do_stop) - ibmcam_video_stop(uvd); - ibmcam_veio(uvd, 0, 0x0001, 0x0114); - ibmcam_veio(uvd, 0, 0x00c0, 0x010c); - usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp)); - ibmcam_model1_setup_after_video_if(uvd); - break; - case IBMCAM_MODEL_2: - ibmcam_model2_setup_after_video_if(uvd); - break; - case IBMCAM_MODEL_3: - ibmcam_video_stop(uvd); - ibmcam_model3_setup_after_video_if(uvd); - break; - case IBMCAM_MODEL_4: - ibmcam_model4_setup_after_video_if(uvd); - break; - } -} - -static void ibmcam_video_start(struct uvd *uvd) -{ - ibmcam_change_lighting_conditions(uvd); - ibmcam_set_sharpness(uvd); - ibmcam_reinit_iso(uvd, 0); -} - -/* - * Return negative code on failure, 0 on success. - */ -static int ibmcam_setup_on_open(struct uvd *uvd) -{ - int setup_ok = 0; /* Success by default */ - /* Send init sequence only once, it's large! */ - if (!IBMCAM_T(uvd)->initialized) { /* FIXME rename */ - switch (IBMCAM_T(uvd)->camera_model) { - case IBMCAM_MODEL_1: - setup_ok = ibmcam_model1_setup(uvd); - break; - case IBMCAM_MODEL_2: - setup_ok = ibmcam_model2_setup(uvd); - break; - case IBMCAM_MODEL_3: - case IBMCAM_MODEL_4: - /* We do all setup when Isoc stream is requested */ - break; - } - IBMCAM_T(uvd)->initialized = (setup_ok != 0); - } - return setup_ok; -} - -static void ibmcam_configure_video(struct uvd *uvd) -{ - if (uvd == NULL) - return; - - RESTRICT_TO_RANGE(init_brightness, 0, 255); - RESTRICT_TO_RANGE(init_contrast, 0, 255); - RESTRICT_TO_RANGE(init_color, 0, 255); - RESTRICT_TO_RANGE(init_hue, 0, 255); - RESTRICT_TO_RANGE(hue_correction, 0, 255); - - memset(&uvd->vpic, 0, sizeof(uvd->vpic)); - memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); - - uvd->vpic.colour = init_color << 8; - uvd->vpic.hue = init_hue << 8; - uvd->vpic.brightness = init_brightness << 8; - uvd->vpic.contrast = init_contrast << 8; - uvd->vpic.whiteness = 105 << 8; /* This one isn't used */ - uvd->vpic.depth = 24; - uvd->vpic.palette = VIDEO_PALETTE_RGB24; - - memset(&uvd->vcap, 0, sizeof(uvd->vcap)); - strcpy(uvd->vcap.name, "IBM USB Camera"); - uvd->vcap.type = VID_TYPE_CAPTURE; - uvd->vcap.channels = 1; - uvd->vcap.audios = 0; - uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas); - uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas); - uvd->vcap.minwidth = min_canvasWidth; - uvd->vcap.minheight = min_canvasHeight; - - memset(&uvd->vchan, 0, sizeof(uvd->vchan)); - uvd->vchan.flags = 0; - uvd->vchan.tuners = 0; - uvd->vchan.channel = 0; - uvd->vchan.type = VIDEO_TYPE_CAMERA; - strcpy(uvd->vchan.name, "Camera"); -} - -/* - * ibmcam_probe() - * - * This procedure queries device descriptor and accepts the interface - * if it looks like IBM C-it camera. - * - * History: - * 22-Jan-2000 Moved camera init code to ibmcam_open() - * 27=Jan-2000 Changed to use static structures, added locking. - * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). - * 03-Jul-2000 Fixed endianness bug. - * 12-Nov-2000 Reworked to comply with new probe() signature. - * 23-Jan-2001 Added compatibility with 2.2.x kernels. - */ -static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *devid) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct uvd *uvd = NULL; - int ix, i, nas, model=0, canvasX=0, canvasY=0; - int actInterface=-1, inactInterface=-1, maxPS=0; - __u8 ifnum = intf->altsetting->desc.bInterfaceNumber; - unsigned char video_ep = 0; - - if (debug >= 1) - dev_info(&dev->dev, "ibmcam_probe(%p,%u.)\n", intf, ifnum); - - /* We don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) - return -ENODEV; - - /* Check the version/revision */ - switch (le16_to_cpu(dev->descriptor.bcdDevice)) { - case 0x0002: - if (ifnum != 2) - return -ENODEV; - model = IBMCAM_MODEL_1; - break; - case 0x030A: - if (ifnum != 0) - return -ENODEV; - if ((le16_to_cpu(dev->descriptor.idProduct) == NETCAM_PRODUCT_ID) || - (le16_to_cpu(dev->descriptor.idProduct) == VEO_800D_PRODUCT_ID)) - model = IBMCAM_MODEL_4; - else - model = IBMCAM_MODEL_2; - break; - case 0x0301: - if (ifnum != 0) - return -ENODEV; - model = IBMCAM_MODEL_3; - break; - default: - err("IBM camera with revision 0x%04x is not supported.", - le16_to_cpu(dev->descriptor.bcdDevice)); - return -ENODEV; - } - - /* Print detailed info on what we found so far */ - do { - char *brand = NULL; - switch (le16_to_cpu(dev->descriptor.idProduct)) { - case NETCAM_PRODUCT_ID: - brand = "IBM NetCamera"; - break; - case VEO_800C_PRODUCT_ID: - brand = "Veo Stingray [800C]"; - break; - case VEO_800D_PRODUCT_ID: - brand = "Veo Stingray [800D]"; - break; - case IBMCAM_PRODUCT_ID: - default: - brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */ - break; - } - dev_info(&dev->dev, - "%s USB camera found (model %d, rev. 0x%04x)\n", - brand, model, le16_to_cpu(dev->descriptor.bcdDevice)); - } while (0); - - /* Validate found interface: must have one ISO endpoint */ - nas = intf->num_altsetting; - if (debug > 0) - dev_info(&dev->dev, "Number of alternate settings=%d.\n", - nas); - if (nas < 2) { - err("Too few alternate settings for this camera!"); - return -ENODEV; - } - /* Validate all alternate settings */ - for (ix=0; ix < nas; ix++) { - const struct usb_host_interface *interface; - const struct usb_endpoint_descriptor *endpoint; - - interface = &intf->altsetting[ix]; - i = interface->desc.bAlternateSetting; - if (interface->desc.bNumEndpoints != 1) { - err("Interface %d. has %u. endpoints!", - ifnum, (unsigned)(interface->desc.bNumEndpoints)); - return -ENODEV; - } - endpoint = &interface->endpoint[0].desc; - if (video_ep == 0) - video_ep = endpoint->bEndpointAddress; - else if (video_ep != endpoint->bEndpointAddress) { - err("Alternate settings have different endpoint addresses!"); - return -ENODEV; - } - if (!usb_endpoint_xfer_isoc(endpoint)) { - err("Interface %d. has non-ISO endpoint!", ifnum); - return -ENODEV; - } - if (usb_endpoint_dir_out(endpoint)) { - err("Interface %d. has ISO OUT endpoint!", ifnum); - return -ENODEV; - } - if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) { - if (inactInterface < 0) - inactInterface = i; - else { - err("More than one inactive alt. setting!"); - return -ENODEV; - } - } else { - if (actInterface < 0) { - actInterface = i; - maxPS = le16_to_cpu(endpoint->wMaxPacketSize); - if (debug > 0) - dev_info(&dev->dev, - "Active setting=%d. " - "maxPS=%d.\n", i, maxPS); - } else - err("More than one active alt. setting! Ignoring #%d.", i); - } - } - if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) { - err("Failed to recognize the camera!"); - return -ENODEV; - } - - /* Validate options */ - switch (model) { - case IBMCAM_MODEL_1: - RESTRICT_TO_RANGE(lighting, 0, 2); - RESTRICT_TO_RANGE(size, SIZE_128x96, SIZE_352x288); - if (framerate < 0) - framerate = 2; - canvasX = 352; - canvasY = 288; - break; - case IBMCAM_MODEL_2: - RESTRICT_TO_RANGE(lighting, 0, 15); - RESTRICT_TO_RANGE(size, SIZE_176x144, SIZE_352x240); - if (framerate < 0) - framerate = 2; - canvasX = 352; - canvasY = 240; - break; - case IBMCAM_MODEL_3: - RESTRICT_TO_RANGE(lighting, 0, 15); /* FIXME */ - switch (size) { - case SIZE_160x120: - canvasX = 160; - canvasY = 120; - if (framerate < 0) - framerate = 2; - RESTRICT_TO_RANGE(framerate, 0, 5); - break; - default: - dev_info(&dev->dev, "IBM camera: using 320x240\n"); - size = SIZE_320x240; - /* No break here */ - case SIZE_320x240: - canvasX = 320; - canvasY = 240; - if (framerate < 0) - framerate = 3; - RESTRICT_TO_RANGE(framerate, 0, 5); - break; - case SIZE_640x480: - canvasX = 640; - canvasY = 480; - framerate = 0; /* Slowest, and maybe even that is too fast */ - break; - } - break; - case IBMCAM_MODEL_4: - RESTRICT_TO_RANGE(lighting, 0, 2); - switch (size) { - case SIZE_128x96: - canvasX = 128; - canvasY = 96; - break; - case SIZE_160x120: - canvasX = 160; - canvasY = 120; - break; - default: - dev_info(&dev->dev, "IBM NetCamera: using 176x144\n"); - size = SIZE_176x144; - /* No break here */ - case SIZE_176x144: - canvasX = 176; - canvasY = 144; - break; - case SIZE_320x240: - canvasX = 320; - canvasY = 240; - break; - case SIZE_352x288: - canvasX = 352; - canvasY = 288; - break; - } - break; - default: - err("IBM camera: Model %d. not supported!", model); - return -ENODEV; - } - - uvd = usbvideo_AllocateDevice(cams); - if (uvd != NULL) { - /* Here uvd is a fully allocated uvd object */ - uvd->flags = flags; - uvd->debug = debug; - uvd->dev = dev; - uvd->iface = ifnum; - uvd->ifaceAltInactive = inactInterface; - uvd->ifaceAltActive = actInterface; - uvd->video_endp = video_ep; - uvd->iso_packet_len = maxPS; - uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24; - uvd->defaultPalette = VIDEO_PALETTE_RGB24; - uvd->canvas = VIDEOSIZE(canvasX, canvasY); - uvd->videosize = ibmcam_size_to_videosize(size); - - /* Initialize ibmcam-specific data */ - assert(IBMCAM_T(uvd) != NULL); - IBMCAM_T(uvd)->camera_model = model; - IBMCAM_T(uvd)->initialized = 0; - - ibmcam_configure_video(uvd); - - i = usbvideo_RegisterVideoDevice(uvd); - if (i != 0) { - err("usbvideo_RegisterVideoDevice() failed."); - uvd = NULL; - } - } - usb_set_intfdata (intf, uvd); - return 0; -} - - -static struct usb_device_id id_table[] = { - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) }, /* Model 1 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) }, /* Model 3 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */ - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */ - { } /* Terminating entry */ -}; - -/* - * ibmcam_init() - * - * This code is run to initialize the driver. - * - * History: - * 1/27/00 Reworked to use statically allocated ibmcam structures. - * 21/10/00 Completely redesigned to use usbvideo services. - */ -static int __init ibmcam_init(void) -{ - struct usbvideo_cb cbTbl; - memset(&cbTbl, 0, sizeof(cbTbl)); - cbTbl.probe = ibmcam_probe; - cbTbl.setupOnOpen = ibmcam_setup_on_open; - cbTbl.videoStart = ibmcam_video_start; - cbTbl.videoStop = ibmcam_video_stop; - cbTbl.processData = ibmcam_ProcessIsocData; - cbTbl.postProcess = usbvideo_DeinterlaceFrame; - cbTbl.adjustPicture = ibmcam_adjust_picture; - cbTbl.getFPS = ibmcam_calculate_fps; - return usbvideo_register( - &cams, - MAX_IBMCAM, - sizeof(ibmcam_t), - "ibmcam", - &cbTbl, - THIS_MODULE, - id_table); -} - -static void __exit ibmcam_cleanup(void) -{ - usbvideo_Deregister(&cams); -} - -MODULE_DEVICE_TABLE(usb, id_table); - -module_init(ibmcam_init); -module_exit(ibmcam_cleanup); diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c deleted file mode 100644 index 562e1d1..0000000 --- a/drivers/media/video/usbvideo/konicawc.c +++ /dev/null @@ -1,992 +0,0 @@ -/* - * konicawc.c - konica webcam driver - * - * Author: Simon Evans - * - * Copyright (C) 2002 Simon Evans - * - * Licence: GPL - * - * Driver for USB webcams based on Konica chipset. This - * chipset is used in Intel YC76 camera. - * - */ - -#include -#include -#include -#include -#include - -#include "usbvideo.h" - -#define MAX_BRIGHTNESS 108 -#define MAX_CONTRAST 108 -#define MAX_SATURATION 108 -#define MAX_SHARPNESS 108 -#define MAX_WHITEBAL 372 -#define MAX_SPEED 6 - - -#define MAX_CAMERAS 1 - -#define DRIVER_VERSION "v1.4" -#define DRIVER_DESC "Konica Webcam driver" - -enum ctrl_req { - SetWhitebal = 0x01, - SetBrightness = 0x02, - SetSharpness = 0x03, - SetContrast = 0x04, - SetSaturation = 0x05, -}; - - -enum frame_sizes { - SIZE_160X120 = 0, - SIZE_160X136 = 1, - SIZE_176X144 = 2, - SIZE_320X240 = 3, - -}; - -#define MAX_FRAME_SIZE SIZE_320X240 - -static struct usbvideo *cams; - -#ifdef CONFIG_USB_DEBUG -static int debug; -#define DEBUG(n, format, arg...) \ - if (n <= debug) { \ - printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \ - } -#else -#define DEBUG(n, arg...) -static const int debug; -#endif - - -/* Some default values for initial camera settings, - can be set by modprobe */ - -static int size; -static int speed = 6; /* Speed (fps) 0 (slowest) to 6 (fastest) */ -static int brightness = MAX_BRIGHTNESS/2; -static int contrast = MAX_CONTRAST/2; -static int saturation = MAX_SATURATION/2; -static int sharpness = MAX_SHARPNESS/2; -static int whitebal = 3*(MAX_WHITEBAL/4); - -static const int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 }; - -/* These FPS speeds are from the windows config box. They are - * indexed on size (0-2) and speed (0-6). Divide by 3 to get the - * real fps. - */ - -static const int spd_to_fps[][7] = { { 24, 40, 48, 60, 72, 80, 100 }, - { 24, 40, 48, 60, 72, 80, 100 }, - { 18, 30, 36, 45, 54, 60, 75 }, - { 6, 10, 12, 15, 18, 21, 25 } }; - -struct cam_size { - u16 width; - u16 height; - u8 cmd; -}; - -static const struct cam_size camera_sizes[] = { { 160, 120, 0x7 }, - { 160, 136, 0xa }, - { 176, 144, 0x4 }, - { 320, 240, 0x5 } }; - -struct konicawc { - u8 brightness; /* camera uses 0 - 9, x11 for real value */ - u8 contrast; /* as above */ - u8 saturation; /* as above */ - u8 sharpness; /* as above */ - u8 white_bal; /* 0 - 33, x11 for real value */ - u8 speed; /* Stored as 0 - 6, used as index in spd_to_* (above) */ - u8 size; /* Frame Size */ - int height; - int width; - struct urb *sts_urb[USBVIDEO_NUMSBUF]; - u8 sts_buf[USBVIDEO_NUMSBUF][FRAMES_PER_DESC]; - struct urb *last_data_urb; - int lastframe; - int cur_frame_size; /* number of bytes in current frame size */ - int maxline; /* number of lines per frame */ - int yplanesz; /* Number of bytes in the Y plane */ - unsigned int buttonsts:1; -#ifdef CONFIG_INPUT - struct input_dev *input; - char input_physname[64]; -#endif -}; - - -#define konicawc_set_misc(uvd, req, value, index) konicawc_ctrl_msg(uvd, USB_DIR_OUT, req, value, index, NULL, 0) -#define konicawc_get_misc(uvd, req, value, index, buf, sz) konicawc_ctrl_msg(uvd, USB_DIR_IN, req, value, index, buf, sz) -#define konicawc_set_value(uvd, value, index) konicawc_ctrl_msg(uvd, USB_DIR_OUT, 2, value, index, NULL, 0) - - -static int konicawc_ctrl_msg(struct uvd *uvd, u8 dir, u8 request, u16 value, u16 index, void *buf, int len) -{ - int retval = usb_control_msg(uvd->dev, - dir ? usb_rcvctrlpipe(uvd->dev, 0) : usb_sndctrlpipe(uvd->dev, 0), - request, 0x40 | dir, value, index, buf, len, 1000); - return retval < 0 ? retval : 0; -} - - -static inline void konicawc_camera_on(struct uvd *uvd) -{ - DEBUG(0, "camera on"); - konicawc_set_misc(uvd, 0x2, 1, 0x0b); -} - - -static inline void konicawc_camera_off(struct uvd *uvd) -{ - DEBUG(0, "camera off"); - konicawc_set_misc(uvd, 0x2, 0, 0x0b); -} - - -static void konicawc_set_camera_size(struct uvd *uvd) -{ - struct konicawc *cam = (struct konicawc *)uvd->user_data; - - konicawc_set_misc(uvd, 0x2, camera_sizes[cam->size].cmd, 0x08); - cam->width = camera_sizes[cam->size].width; - cam->height = camera_sizes[cam->size].height; - cam->yplanesz = cam->height * cam->width; - cam->cur_frame_size = (cam->yplanesz * 3) / 2; - cam->maxline = cam->yplanesz / 256; - uvd->videosize = VIDEOSIZE(cam->width, cam->height); -} - - -static int konicawc_setup_on_open(struct uvd *uvd) -{ - struct konicawc *cam = (struct konicawc *)uvd->user_data; - - DEBUG(1, "setting brightness to %d (%d)", cam->brightness, - cam->brightness * 11); - konicawc_set_value(uvd, cam->brightness, SetBrightness); - DEBUG(1, "setting white balance to %d (%d)", cam->white_bal, - cam->white_bal * 11); - konicawc_set_value(uvd, cam->white_bal, SetWhitebal); - DEBUG(1, "setting contrast to %d (%d)", cam->contrast, - cam->contrast * 11); - konicawc_set_value(uvd, cam->contrast, SetContrast); - DEBUG(1, "setting saturation to %d (%d)", cam->saturation, - cam->saturation * 11); - konicawc_set_value(uvd, cam->saturation, SetSaturation); - DEBUG(1, "setting sharpness to %d (%d)", cam->sharpness, - cam->sharpness * 11); - konicawc_set_value(uvd, cam->sharpness, SetSharpness); - konicawc_set_camera_size(uvd); - cam->lastframe = -2; - cam->buttonsts = 0; - return 0; -} - - -static void konicawc_adjust_picture(struct uvd *uvd) -{ - struct konicawc *cam = (struct konicawc *)uvd->user_data; - - konicawc_camera_off(uvd); - DEBUG(1, "new brightness: %d", uvd->vpic.brightness); - uvd->vpic.brightness = (uvd->vpic.brightness > MAX_BRIGHTNESS) ? MAX_BRIGHTNESS : uvd->vpic.brightness; - if(cam->brightness != uvd->vpic.brightness / 11) { - cam->brightness = uvd->vpic.brightness / 11; - DEBUG(1, "setting brightness to %d (%d)", cam->brightness, - cam->brightness * 11); - konicawc_set_value(uvd, cam->brightness, SetBrightness); - } - - DEBUG(1, "new contrast: %d", uvd->vpic.contrast); - uvd->vpic.contrast = (uvd->vpic.contrast > MAX_CONTRAST) ? MAX_CONTRAST : uvd->vpic.contrast; - if(cam->contrast != uvd->vpic.contrast / 11) { - cam->contrast = uvd->vpic.contrast / 11; - DEBUG(1, "setting contrast to %d (%d)", cam->contrast, - cam->contrast * 11); - konicawc_set_value(uvd, cam->contrast, SetContrast); - } - konicawc_camera_on(uvd); -} - -#ifdef CONFIG_INPUT - -static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev) -{ - struct input_dev *input_dev; - int error; - - usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); - strlcat(cam->input_physname, "/input0", sizeof(cam->input_physname)); - - cam->input = input_dev = input_allocate_device(); - if (!input_dev) { - dev_warn(&dev->dev, - "Not enough memory for camera's input device\n"); - return; - } - - input_dev->name = "Konicawc snapshot button"; - input_dev->phys = cam->input_physname; - usb_to_input_id(dev, &input_dev->id); - input_dev->dev.parent = &dev->dev; - - input_dev->evbit[0] = BIT_MASK(EV_KEY); - input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA); - - error = input_register_device(cam->input); - if (error) { - dev_warn(&dev->dev, - "Failed to register camera's input device, err: %d\n", - error); - input_free_device(cam->input); - cam->input = NULL; - } -} - -static void konicawc_unregister_input(struct konicawc *cam) -{ - if (cam->input) { - input_unregister_device(cam->input); - cam->input = NULL; - } -} - -static void konicawc_report_buttonstat(struct konicawc *cam) -{ - if (cam->input) { - input_report_key(cam->input, KEY_CAMERA, cam->buttonsts); - input_sync(cam->input); - } -} - -#else - -static inline void konicawc_register_input(struct konicawc *cam, struct usb_device *dev) { } -static inline void konicawc_unregister_input(struct konicawc *cam) { } -static inline void konicawc_report_buttonstat(struct konicawc *cam) { } - -#endif /* CONFIG_INPUT */ - -static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct urb *stsurb) -{ - char *cdata; - int i, totlen = 0; - unsigned char *status = stsurb->transfer_buffer; - int keep = 0, discard = 0, bad = 0; - struct konicawc *cam = (struct konicawc *)uvd->user_data; - - for (i = 0; i < dataurb->number_of_packets; i++) { - int button = cam->buttonsts; - unsigned char sts; - int n = dataurb->iso_frame_desc[i].actual_length; - int st = dataurb->iso_frame_desc[i].status; - cdata = dataurb->transfer_buffer + - dataurb->iso_frame_desc[i].offset; - - /* Detect and ignore errored packets */ - if (st < 0) { - DEBUG(1, "Data error: packet=%d. len=%d. status=%d.", - i, n, st); - uvd->stats.iso_err_count++; - continue; - } - - /* Detect and ignore empty packets */ - if (n <= 0) { - uvd->stats.iso_skip_count++; - continue; - } - - /* See what the status data said about the packet */ - sts = *(status+stsurb->iso_frame_desc[i].offset); - - /* sts: 0x80-0xff: frame start with frame number (ie 0-7f) - * otherwise: - * bit 0 0: keep packet - * 1: drop packet (padding data) - * - * bit 4 0 button not clicked - * 1 button clicked - * button is used to `take a picture' (in software) - */ - - if(sts < 0x80) { - button = !!(sts & 0x40); - sts &= ~0x40; - } - - /* work out the button status, but don't do - anything with it for now */ - - if(button != cam->buttonsts) { - DEBUG(2, "button: %sclicked", button ? "" : "un"); - cam->buttonsts = button; - konicawc_report_buttonstat(cam); - } - - if(sts == 0x01) { /* drop frame */ - discard++; - continue; - } - - if((sts > 0x01) && (sts < 0x80)) { - dev_info(&uvd->dev->dev, "unknown status %2.2x\n", - sts); - bad++; - continue; - } - if(!sts && cam->lastframe == -2) { - DEBUG(2, "dropping frame looking for image start"); - continue; - } - - keep++; - if(sts & 0x80) { /* frame start */ - unsigned char marker[] = { 0, 0xff, 0, 0x00 }; - - if(cam->lastframe == -2) { - DEBUG(2, "found initial image"); - cam->lastframe = -1; - } - - marker[3] = sts & 0x7F; - RingQueue_Enqueue(&uvd->dp, marker, 4); - totlen += 4; - } - - totlen += n; /* Little local accounting */ - RingQueue_Enqueue(&uvd->dp, cdata, n); - } - DEBUG(8, "finished: keep = %d discard = %d bad = %d added %d bytes", - keep, discard, bad, totlen); - return totlen; -} - - -static void resubmit_urb(struct uvd *uvd, struct urb *urb) -{ - int i, ret; - for (i = 0; i < FRAMES_PER_DESC; i++) { - urb->iso_frame_desc[i].status = 0; - } - urb->dev = uvd->dev; - urb->status = 0; - ret = usb_submit_urb(urb, GFP_ATOMIC); - DEBUG(3, "submitting urb of length %d", urb->transfer_buffer_length); - if(ret) - err("usb_submit_urb error (%d)", ret); - -} - - -static void konicawc_isoc_irq(struct urb *urb) -{ - struct uvd *uvd = urb->context; - struct konicawc *cam = (struct konicawc *)uvd->user_data; - - /* We don't want to do anything if we are about to be removed! */ - if (!CAMERA_IS_OPERATIONAL(uvd)) - return; - - if (!uvd->streaming) { - DEBUG(1, "Not streaming, but interrupt!"); - return; - } - - DEBUG(3, "got frame %d len = %d buflen =%d", urb->start_frame, urb->actual_length, urb->transfer_buffer_length); - - uvd->stats.urb_count++; - - if (urb->transfer_buffer_length > 32) { - cam->last_data_urb = urb; - return; - } - /* Copy the data received into ring queue */ - if(cam->last_data_urb) { - int len = 0; - if(urb->start_frame != cam->last_data_urb->start_frame) - err("Lost sync on frames"); - else if (!urb->status && !cam->last_data_urb->status) - len = konicawc_compress_iso(uvd, cam->last_data_urb, urb); - - resubmit_urb(uvd, cam->last_data_urb); - resubmit_urb(uvd, urb); - cam->last_data_urb = NULL; - uvd->stats.urb_length = len; - uvd->stats.data_count += len; - if(len) - RingQueue_WakeUpInterruptible(&uvd->dp); - return; - } - return; -} - - -static int konicawc_start_data(struct uvd *uvd) -{ - struct usb_device *dev = uvd->dev; - int i, errFlag; - struct konicawc *cam = (struct konicawc *)uvd->user_data; - int pktsz; - struct usb_interface *intf; - struct usb_host_interface *interface = NULL; - - intf = usb_ifnum_to_if(dev, uvd->iface); - if (intf) - interface = usb_altnum_to_altsetting(intf, - spd_to_iface[cam->speed]); - if (!interface) - return -ENXIO; - pktsz = le16_to_cpu(interface->endpoint[1].desc.wMaxPacketSize); - DEBUG(1, "pktsz = %d", pktsz); - if (!CAMERA_IS_OPERATIONAL(uvd)) { - err("Camera is not operational"); - return -EFAULT; - } - uvd->curframe = -1; - konicawc_camera_on(uvd); - /* Alternate interface 1 is is the biggest frame size */ - i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive); - if (i < 0) { - err("usb_set_interface error"); - uvd->last_error = i; - return -EBUSY; - } - - /* We double buffer the Iso lists */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - int j, k; - struct urb *urb = uvd->sbuf[i].urb; - urb->dev = dev; - urb->context = uvd; - urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp); - urb->interval = 1; - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = uvd->sbuf[i].data; - urb->complete = konicawc_isoc_irq; - urb->number_of_packets = FRAMES_PER_DESC; - urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC; - for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = pktsz; - } - - urb = cam->sts_urb[i]; - urb->dev = dev; - urb->context = uvd; - urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp-1); - urb->interval = 1; - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = cam->sts_buf[i]; - urb->complete = konicawc_isoc_irq; - urb->number_of_packets = FRAMES_PER_DESC; - urb->transfer_buffer_length = FRAMES_PER_DESC; - for (j=0; j < FRAMES_PER_DESC; j++) { - urb->iso_frame_desc[j].offset = j; - urb->iso_frame_desc[j].length = 1; - } - } - - cam->last_data_urb = NULL; - - /* Submit all URBs */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - errFlag = usb_submit_urb(cam->sts_urb[i], GFP_KERNEL); - if (errFlag) - err("usb_submit_isoc(%d) ret %d", i, errFlag); - - errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL); - if (errFlag) - err ("usb_submit_isoc(%d) ret %d", i, errFlag); - } - - uvd->streaming = 1; - DEBUG(1, "streaming=1 video_endp=$%02x", uvd->video_endp); - return 0; -} - - -static void konicawc_stop_data(struct uvd *uvd) -{ - int i, j; - struct konicawc *cam; - - if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) - return; - - konicawc_camera_off(uvd); - uvd->streaming = 0; - cam = (struct konicawc *)uvd->user_data; - cam->last_data_urb = NULL; - - /* Unschedule all of the iso td's */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - usb_kill_urb(uvd->sbuf[i].urb); - usb_kill_urb(cam->sts_urb[i]); - } - - if (!uvd->remove_pending) { - /* Set packet size to 0 */ - j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive); - if (j < 0) { - err("usb_set_interface() error %d.", j); - uvd->last_error = j; - } - } -} - - -static void konicawc_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame) -{ - struct konicawc *cam = (struct konicawc *)uvd->user_data; - int maxline = cam->maxline; - int yplanesz = cam->yplanesz; - - assert(frame != NULL); - - DEBUG(5, "maxline = %d yplanesz = %d", maxline, yplanesz); - DEBUG(3, "Frame state = %d", frame->scanstate); - - if(frame->scanstate == ScanState_Scanning) { - int drop = 0; - int curframe; - int fdrops = 0; - DEBUG(3, "Searching for marker, queue len = %d", RingQueue_GetLength(&uvd->dp)); - while(RingQueue_GetLength(&uvd->dp) >= 4) { - if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && - (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) && - (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) && - (RING_QUEUE_PEEK(&uvd->dp, 3) < 0x80)) { - curframe = RING_QUEUE_PEEK(&uvd->dp, 3); - if(cam->lastframe >= 0) { - fdrops = (0x80 + curframe - cam->lastframe) & 0x7F; - fdrops--; - if(fdrops) { - dev_info(&uvd->dev->dev, - "Dropped %d frames " - "(%d -> %d)\n", - fdrops, - cam->lastframe, - curframe); - } - } - cam->lastframe = curframe; - frame->curline = 0; - frame->scanstate = ScanState_Lines; - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4); - break; - } - RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); - drop++; - } - if(drop) - DEBUG(2, "dropped %d bytes looking for new frame", drop); - } - - if(frame->scanstate == ScanState_Scanning) - return; - - /* Try to move data from queue into frame buffer - * We get data in blocks of 384 bytes made up of: - * 256 Y, 64 U, 64 V. - * This needs to be written out as a Y plane, a U plane and a V plane. - */ - - while ( frame->curline < maxline && (RingQueue_GetLength(&uvd->dp) >= 384)) { - /* Y */ - RingQueue_Dequeue(&uvd->dp, frame->data + (frame->curline * 256), 256); - /* U */ - RingQueue_Dequeue(&uvd->dp, frame->data + yplanesz + (frame->curline * 64), 64); - /* V */ - RingQueue_Dequeue(&uvd->dp, frame->data + (5 * yplanesz)/4 + (frame->curline * 64), 64); - frame->seqRead_Length += 384; - frame->curline++; - } - /* See if we filled the frame */ - if (frame->curline == maxline) { - DEBUG(5, "got whole frame"); - - frame->frameState = FrameState_Done_Hold; - frame->curline = 0; - uvd->curframe = -1; - uvd->stats.frame_num++; - } -} - - -static int konicawc_find_fps(int size, int fps) -{ - int i; - - fps *= 3; - DEBUG(1, "konica_find_fps: size = %d fps = %d", size, fps); - if(fps <= spd_to_fps[size][0]) - return 0; - - if(fps >= spd_to_fps[size][MAX_SPEED]) - return MAX_SPEED; - - for(i = 0; i < MAX_SPEED; i++) { - if((fps >= spd_to_fps[size][i]) && (fps <= spd_to_fps[size][i+1])) { - DEBUG(2, "fps %d between %d and %d", fps, i, i+1); - if( (fps - spd_to_fps[size][i]) < (spd_to_fps[size][i+1] - fps)) - return i; - else - return i+1; - } - } - return MAX_SPEED+1; -} - - -static int konicawc_set_video_mode(struct uvd *uvd, struct video_window *vw) -{ - struct konicawc *cam = (struct konicawc *)uvd->user_data; - int newspeed = cam->speed; - int newsize; - int x = vw->width; - int y = vw->height; - int fps = vw->flags; - - if(x > 0 && y > 0) { - DEBUG(2, "trying to find size %d,%d", x, y); - for(newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) { - if((camera_sizes[newsize].width == x) && (camera_sizes[newsize].height == y)) - break; - } - } else { - newsize = cam->size; - } - - if(newsize > MAX_FRAME_SIZE) { - DEBUG(1, "couldn't find size %d,%d", x, y); - return -EINVAL; - } - - if(fps > 0) { - DEBUG(1, "trying to set fps to %d", fps); - newspeed = konicawc_find_fps(newsize, fps); - DEBUG(1, "find_fps returned %d (%d)", newspeed, spd_to_fps[newsize][newspeed]); - } - - if(newspeed > MAX_SPEED) - return -EINVAL; - - DEBUG(1, "setting size to %d speed to %d", newsize, newspeed); - if((newsize == cam->size) && (newspeed == cam->speed)) { - DEBUG(1, "Nothing to do"); - return 0; - } - DEBUG(0, "setting to %dx%d @ %d fps", camera_sizes[newsize].width, - camera_sizes[newsize].height, spd_to_fps[newsize][newspeed]/3); - - konicawc_stop_data(uvd); - uvd->ifaceAltActive = spd_to_iface[newspeed]; - DEBUG(1, "new interface = %d", uvd->ifaceAltActive); - cam->speed = newspeed; - - if(cam->size != newsize) { - cam->size = newsize; - konicawc_set_camera_size(uvd); - } - - /* Flush the input queue and clear any current frame in progress */ - - RingQueue_Flush(&uvd->dp); - cam->lastframe = -2; - if(uvd->curframe != -1) { - uvd->frame[uvd->curframe].curline = 0; - uvd->frame[uvd->curframe].seqRead_Length = 0; - uvd->frame[uvd->curframe].seqRead_Index = 0; - } - - konicawc_start_data(uvd); - return 0; -} - - -static int konicawc_calculate_fps(struct uvd *uvd) -{ - struct konicawc *cam = uvd->user_data; - return spd_to_fps[cam->size][cam->speed]/3; -} - - -static void konicawc_configure_video(struct uvd *uvd) -{ - struct konicawc *cam = (struct konicawc *)uvd->user_data; - u8 buf[2]; - - memset(&uvd->vpic, 0, sizeof(uvd->vpic)); - memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); - - RESTRICT_TO_RANGE(brightness, 0, MAX_BRIGHTNESS); - RESTRICT_TO_RANGE(contrast, 0, MAX_CONTRAST); - RESTRICT_TO_RANGE(saturation, 0, MAX_SATURATION); - RESTRICT_TO_RANGE(sharpness, 0, MAX_SHARPNESS); - RESTRICT_TO_RANGE(whitebal, 0, MAX_WHITEBAL); - - cam->brightness = brightness / 11; - cam->contrast = contrast / 11; - cam->saturation = saturation / 11; - cam->sharpness = sharpness / 11; - cam->white_bal = whitebal / 11; - - uvd->vpic.colour = 108; - uvd->vpic.hue = 108; - uvd->vpic.brightness = brightness; - uvd->vpic.contrast = contrast; - uvd->vpic.whiteness = whitebal; - uvd->vpic.depth = 6; - uvd->vpic.palette = VIDEO_PALETTE_YUV420P; - - memset(&uvd->vcap, 0, sizeof(uvd->vcap)); - strcpy(uvd->vcap.name, "Konica Webcam"); - uvd->vcap.type = VID_TYPE_CAPTURE; - uvd->vcap.channels = 1; - uvd->vcap.audios = 0; - uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width; - uvd->vcap.minheight = camera_sizes[SIZE_160X120].height; - uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width; - uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height; - - memset(&uvd->vchan, 0, sizeof(uvd->vchan)); - uvd->vchan.flags = 0 ; - uvd->vchan.tuners = 0; - uvd->vchan.channel = 0; - uvd->vchan.type = VIDEO_TYPE_CAMERA; - strcpy(uvd->vchan.name, "Camera"); - - /* Talk to device */ - DEBUG(1, "device init"); - if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2)) - DEBUG(2, "3,10 -> %2.2x %2.2x", buf[0], buf[1]); - if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2)) - DEBUG(2, "3,10 -> %2.2x %2.2x", buf[0], buf[1]); - if(konicawc_set_misc(uvd, 0x2, 0, 0xd)) - DEBUG(2, "2,0,d failed"); - DEBUG(1, "setting initial values"); -} - -static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id *devid) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct uvd *uvd = NULL; - int ix, i, nas; - int actInterface=-1, inactInterface=-1, maxPS=0; - unsigned char video_ep = 0; - - DEBUG(1, "konicawc_probe(%p)", intf); - - /* We don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) - return -ENODEV; - - dev_info(&intf->dev, "Konica Webcam (rev. 0x%04x)\n", - le16_to_cpu(dev->descriptor.bcdDevice)); - RESTRICT_TO_RANGE(speed, 0, MAX_SPEED); - - /* Validate found interface: must have one ISO endpoint */ - nas = intf->num_altsetting; - if (nas != 8) { - err("Incorrect number of alternate settings (%d) for this camera!", nas); - return -ENODEV; - } - /* Validate all alternate settings */ - for (ix=0; ix < nas; ix++) { - const struct usb_host_interface *interface; - const struct usb_endpoint_descriptor *endpoint; - - interface = &intf->altsetting[ix]; - i = interface->desc.bAlternateSetting; - if (interface->desc.bNumEndpoints != 2) { - err("Interface %d. has %u. endpoints!", - interface->desc.bInterfaceNumber, - (unsigned)(interface->desc.bNumEndpoints)); - return -ENODEV; - } - endpoint = &interface->endpoint[1].desc; - DEBUG(1, "found endpoint: addr: 0x%2.2x maxps = 0x%4.4x", - endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize)); - if (video_ep == 0) - video_ep = endpoint->bEndpointAddress; - else if (video_ep != endpoint->bEndpointAddress) { - err("Alternate settings have different endpoint addresses!"); - return -ENODEV; - } - if (!usb_endpoint_xfer_isoc(endpoint)) { - err("Interface %d. has non-ISO endpoint!", - interface->desc.bInterfaceNumber); - return -ENODEV; - } - if (usb_endpoint_dir_out(endpoint)) { - err("Interface %d. has ISO OUT endpoint!", - interface->desc.bInterfaceNumber); - return -ENODEV; - } - if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) { - if (inactInterface < 0) - inactInterface = i; - else { - err("More than one inactive alt. setting!"); - return -ENODEV; - } - } else { - if (i == spd_to_iface[speed]) { - /* This one is the requested one */ - actInterface = i; - } - } - if (le16_to_cpu(endpoint->wMaxPacketSize) > maxPS) - maxPS = le16_to_cpu(endpoint->wMaxPacketSize); - } - if(actInterface == -1) { - err("Cant find required endpoint"); - return -ENODEV; - } - - DEBUG(1, "Selecting requested active setting=%d. maxPS=%d.", actInterface, maxPS); - - uvd = usbvideo_AllocateDevice(cams); - if (uvd != NULL) { - struct konicawc *cam = (struct konicawc *)(uvd->user_data); - /* Here uvd is a fully allocated uvd object */ - for(i = 0; i < USBVIDEO_NUMSBUF; i++) { - cam->sts_urb[i] = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); - if(cam->sts_urb[i] == NULL) { - while(i--) { - usb_free_urb(cam->sts_urb[i]); - } - err("can't allocate urbs"); - return -ENOMEM; - } - } - cam->speed = speed; - RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240); - cam->width = camera_sizes[size].width; - cam->height = camera_sizes[size].height; - cam->size = size; - - uvd->flags = 0; - uvd->debug = debug; - uvd->dev = dev; - uvd->iface = intf->altsetting->desc.bInterfaceNumber; - uvd->ifaceAltInactive = inactInterface; - uvd->ifaceAltActive = actInterface; - uvd->video_endp = video_ep; - uvd->iso_packet_len = maxPS; - uvd->paletteBits = 1L << VIDEO_PALETTE_YUV420P; - uvd->defaultPalette = VIDEO_PALETTE_YUV420P; - uvd->canvas = VIDEOSIZE(320, 240); - uvd->videosize = VIDEOSIZE(cam->width, cam->height); - - /* Initialize konicawc specific data */ - konicawc_configure_video(uvd); - - i = usbvideo_RegisterVideoDevice(uvd); - uvd->max_frame_size = (320 * 240 * 3)/2; - if (i != 0) { - err("usbvideo_RegisterVideoDevice() failed."); - uvd = NULL; - } - - konicawc_register_input(cam, dev); - } - - if (uvd) { - usb_set_intfdata (intf, uvd); - return 0; - } - return -EIO; -} - - -static void konicawc_free_uvd(struct uvd *uvd) -{ - int i; - struct konicawc *cam = (struct konicawc *)uvd->user_data; - - konicawc_unregister_input(cam); - - for (i = 0; i < USBVIDEO_NUMSBUF; i++) { - usb_free_urb(cam->sts_urb[i]); - cam->sts_urb[i] = NULL; - } -} - - -static struct usb_device_id id_table[] = { - { USB_DEVICE(0x04c8, 0x0720) }, /* Intel YC 76 */ - { } /* Terminating entry */ -}; - - -static int __init konicawc_init(void) -{ - struct usbvideo_cb cbTbl; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - memset(&cbTbl, 0, sizeof(cbTbl)); - cbTbl.probe = konicawc_probe; - cbTbl.setupOnOpen = konicawc_setup_on_open; - cbTbl.processData = konicawc_process_isoc; - cbTbl.getFPS = konicawc_calculate_fps; - cbTbl.setVideoMode = konicawc_set_video_mode; - cbTbl.startDataPump = konicawc_start_data; - cbTbl.stopDataPump = konicawc_stop_data; - cbTbl.adjustPicture = konicawc_adjust_picture; - cbTbl.userFree = konicawc_free_uvd; - return usbvideo_register( - &cams, - MAX_CAMERAS, - sizeof(struct konicawc), - "konicawc", - &cbTbl, - THIS_MODULE, - id_table); -} - - -static void __exit konicawc_cleanup(void) -{ - usbvideo_Deregister(&cams); -} - - -MODULE_DEVICE_TABLE(usb, id_table); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Simon Evans "); -MODULE_DESCRIPTION(DRIVER_DESC); -module_param(speed, int, 0); -MODULE_PARM_DESC(speed, "Initial speed: 0 (slowest) - 6 (fastest)"); -module_param(size, int, 0); -MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 160x136 2: 176x144 3: 320x240"); -module_param(brightness, int, 0); -MODULE_PARM_DESC(brightness, "Initial brightness 0 - 108"); -module_param(contrast, int, 0); -MODULE_PARM_DESC(contrast, "Initial contrast 0 - 108"); -module_param(saturation, int, 0); -MODULE_PARM_DESC(saturation, "Initial saturation 0 - 108"); -module_param(sharpness, int, 0); -MODULE_PARM_DESC(sharpness, "Initial brightness 0 - 108"); -module_param(whitebal, int, 0); -MODULE_PARM_DESC(whitebal, "Initial white balance 0 - 363"); - -#ifdef CONFIG_USB_DEBUG -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); -#endif - -module_init(konicawc_init); -module_exit(konicawc_cleanup); diff --git a/drivers/media/video/usbvideo/ultracam.c b/drivers/media/video/usbvideo/ultracam.c deleted file mode 100644 index fbd1b63..0000000 --- a/drivers/media/video/usbvideo/ultracam.c +++ /dev/null @@ -1,685 +0,0 @@ -/* - * USB NB Camera driver - * - * HISTORY: - * 25-Dec-2002 Dmitri Removed lighting, sharpness parameters, methods. - */ - -#include -#include -#include - -#include "usbvideo.h" - -#define ULTRACAM_VENDOR_ID 0x0461 -#define ULTRACAM_PRODUCT_ID 0x0813 - -#define MAX_CAMERAS 4 /* How many devices we allow to connect */ - -/* - * This structure lives in uvd_t->user field. - */ -typedef struct { - int initialized; /* Had we already sent init sequence? */ - int camera_model; /* What type of IBM camera we got? */ - int has_hdr; -} ultracam_t; -#define ULTRACAM_T(uvd) ((ultracam_t *)((uvd)->user_data)) - -static struct usbvideo *cams = NULL; - -static int debug; - -static int flags; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */ - -static const int min_canvasWidth = 8; -static const int min_canvasHeight = 4; - -#define FRAMERATE_MIN 0 -#define FRAMERATE_MAX 6 -static int framerate = -1; - -/* - * Here we define several initialization variables. They may - * be used to automatically set color, hue, brightness and - * contrast to desired values. This is particularly useful in - * case of webcams (which have no controls and no on-screen - * output) and also when a client V4L software is used that - * does not have some of those controls. In any case it's - * good to have startup values as options. - * - * These values are all in [0..255] range. This simplifies - * operation. Note that actual values of V4L variables may - * be scaled up (as much as << 8). User can see that only - * on overlay output, however, or through a V4L client. - */ -static int init_brightness = 128; -static int init_contrast = 192; -static int init_color = 128; -static int init_hue = 128; -static int hue_correction = 128; - -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); -module_param(flags, int, 0); -MODULE_PARM_DESC(flags, - "Bitfield: 0=VIDIOCSYNC, " - "1=B/W, " - "2=show hints, " - "3=show stats, " - "4=test pattern, " - "5=separate frames, " - "6=clean frames"); -module_param(framerate, int, 0); -MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)"); - -module_param(init_brightness, int, 0); -MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)"); -module_param(init_contrast, int, 0); -MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)"); -module_param(init_color, int, 0); -MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)"); -module_param(init_hue, int, 0); -MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)"); -module_param(hue_correction, int, 0); -MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)"); - -/* - * ultracam_ProcessIsocData() - * - * Generic routine to parse the ring queue data. It employs either - * ultracam_find_header() or ultracam_parse_lines() to do most - * of work. - * - * 02-Nov-2000 First (mostly dummy) version. - * 06-Nov-2000 Rewrote to dump all data into frame. - */ -static void ultracam_ProcessIsocData(struct uvd *uvd, struct usbvideo_frame *frame) -{ - int n; - - assert(uvd != NULL); - assert(frame != NULL); - - /* Try to move data from queue into frame buffer */ - n = RingQueue_GetLength(&uvd->dp); - if (n > 0) { - int m; - /* See how much spare we have left */ - m = uvd->max_frame_size - frame->seqRead_Length; - if (n > m) - n = m; - /* Now move that much data into frame buffer */ - RingQueue_Dequeue( - &uvd->dp, - frame->data + frame->seqRead_Length, - m); - frame->seqRead_Length += m; - } - /* See if we filled the frame */ - if (frame->seqRead_Length >= uvd->max_frame_size) { - frame->frameState = FrameState_Done; - uvd->curframe = -1; - uvd->stats.frame_num++; - } -} - -/* - * ultracam_veio() - * - * History: - * 1/27/00 Added check for dev == NULL; this happens if camera is unplugged. - */ -static int ultracam_veio( - struct uvd *uvd, - unsigned char req, - unsigned short value, - unsigned short index, - int is_out) -{ - static const char proc[] = "ultracam_veio"; - unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */; - int i; - - if (!CAMERA_IS_OPERATIONAL(uvd)) - return 0; - - if (!is_out) { - i = usb_control_msg( - uvd->dev, - usb_rcvctrlpipe(uvd->dev, 0), - req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - index, - cp, - sizeof(cp), - 1000); -#if 1 - dev_info(&uvd->dev->dev, - "USB => %02x%02x%02x%02x%02x%02x%02x%02x " - "(req=$%02x val=$%04x ind=$%04x)\n", - cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], - req, value, index); -#endif - } else { - i = usb_control_msg( - uvd->dev, - usb_sndctrlpipe(uvd->dev, 0), - req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - index, - NULL, - 0, - 1000); - } - if (i < 0) { - err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.", - proc, i); - uvd->last_error = i; - } - return i; -} - -/* - * ultracam_calculate_fps() - */ -static int ultracam_calculate_fps(struct uvd *uvd) -{ - return 3 + framerate*4 + framerate/2; -} - -/* - * ultracam_adjust_contrast() - */ -static void ultracam_adjust_contrast(struct uvd *uvd) -{ -} - -/* - * ultracam_set_brightness() - * - * This procedure changes brightness of the picture. - */ -static void ultracam_set_brightness(struct uvd *uvd) -{ -} - -static void ultracam_set_hue(struct uvd *uvd) -{ -} - -/* - * ultracam_adjust_picture() - * - * This procedure gets called from V4L interface to update picture settings. - * Here we change brightness and contrast. - */ -static void ultracam_adjust_picture(struct uvd *uvd) -{ - ultracam_adjust_contrast(uvd); - ultracam_set_brightness(uvd); - ultracam_set_hue(uvd); -} - -/* - * ultracam_video_stop() - * - * This code tells camera to stop streaming. The interface remains - * configured and bandwidth - claimed. - */ -static void ultracam_video_stop(struct uvd *uvd) -{ -} - -/* - * ultracam_reinit_iso() - * - * This procedure sends couple of commands to the camera and then - * resets the video pipe. This sequence was observed to reinit the - * camera or, at least, to initiate ISO data stream. - */ -static void ultracam_reinit_iso(struct uvd *uvd, int do_stop) -{ -} - -static void ultracam_video_start(struct uvd *uvd) -{ - ultracam_reinit_iso(uvd, 0); -} - -static int ultracam_resetPipe(struct uvd *uvd) -{ - usb_clear_halt(uvd->dev, uvd->video_endp); - return 0; -} - -static int ultracam_alternateSetting(struct uvd *uvd, int setting) -{ - static const char proc[] = "ultracam_alternateSetting"; - int i; - i = usb_set_interface(uvd->dev, uvd->iface, setting); - if (i < 0) { - err("%s: usb_set_interface error", proc); - uvd->last_error = i; - return -EBUSY; - } - return 0; -} - -/* - * Return negative code on failure, 0 on success. - */ -static int ultracam_setup_on_open(struct uvd *uvd) -{ - int setup_ok = 0; /* Success by default */ - /* Send init sequence only once, it's large! */ - if (!ULTRACAM_T(uvd)->initialized) { - ultracam_alternateSetting(uvd, 0x04); - ultracam_alternateSetting(uvd, 0x00); - ultracam_veio(uvd, 0x02, 0x0004, 0x000b, 1); - ultracam_veio(uvd, 0x02, 0x0001, 0x0005, 1); - ultracam_veio(uvd, 0x02, 0x8000, 0x0000, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1); - ultracam_veio(uvd, 0x00, 0x00b0, 0x0001, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0002, 1); - ultracam_veio(uvd, 0x00, 0x000c, 0x0003, 1); - ultracam_veio(uvd, 0x00, 0x000b, 0x0004, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0005, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0006, 1); - ultracam_veio(uvd, 0x00, 0x0079, 0x0007, 1); - ultracam_veio(uvd, 0x00, 0x003b, 0x0008, 1); - ultracam_veio(uvd, 0x00, 0x0002, 0x000f, 1); - ultracam_veio(uvd, 0x00, 0x0001, 0x0010, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0011, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00bf, 1); - ultracam_veio(uvd, 0x00, 0x0001, 0x00c0, 1); - ultracam_veio(uvd, 0x00, 0x0010, 0x00cb, 1); - ultracam_veio(uvd, 0x01, 0x00a4, 0x0001, 1); - ultracam_veio(uvd, 0x01, 0x0010, 0x0002, 1); - ultracam_veio(uvd, 0x01, 0x0066, 0x0007, 1); - ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1); - ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1); - ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1); - ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1); - ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1); - ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1); - ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1); - ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1); - ultracam_veio(uvd, 0x01, 0x000b, 0x0011, 1); - ultracam_veio(uvd, 0x01, 0x0001, 0x0012, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0013, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0014, 1); - ultracam_veio(uvd, 0x01, 0x0087, 0x0051, 1); - ultracam_veio(uvd, 0x01, 0x0040, 0x0052, 1); - ultracam_veio(uvd, 0x01, 0x0058, 0x0053, 1); - ultracam_veio(uvd, 0x01, 0x0040, 0x0054, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0040, 1); - ultracam_veio(uvd, 0x01, 0x0010, 0x0041, 1); - ultracam_veio(uvd, 0x01, 0x0020, 0x0042, 1); - ultracam_veio(uvd, 0x01, 0x0030, 0x0043, 1); - ultracam_veio(uvd, 0x01, 0x0040, 0x0044, 1); - ultracam_veio(uvd, 0x01, 0x0050, 0x0045, 1); - ultracam_veio(uvd, 0x01, 0x0060, 0x0046, 1); - ultracam_veio(uvd, 0x01, 0x0070, 0x0047, 1); - ultracam_veio(uvd, 0x01, 0x0080, 0x0048, 1); - ultracam_veio(uvd, 0x01, 0x0090, 0x0049, 1); - ultracam_veio(uvd, 0x01, 0x00a0, 0x004a, 1); - ultracam_veio(uvd, 0x01, 0x00b0, 0x004b, 1); - ultracam_veio(uvd, 0x01, 0x00c0, 0x004c, 1); - ultracam_veio(uvd, 0x01, 0x00d0, 0x004d, 1); - ultracam_veio(uvd, 0x01, 0x00e0, 0x004e, 1); - ultracam_veio(uvd, 0x01, 0x00f0, 0x004f, 1); - ultracam_veio(uvd, 0x01, 0x00ff, 0x0050, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0056, 1); - ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0004, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0002, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0020, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0040, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0017, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x00c0, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x02, 0xc040, 0x0001, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0008, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x0009, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000b, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000c, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000d, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000e, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000f, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x0010, 0); - ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1); - ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1); - ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1); - ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1); - ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1); - ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1); - ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1); - ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0001, 0); - ultracam_veio(uvd, 0x01, 0x0064, 0x0001, 1); - ultracam_veio(uvd, 0x01, 0x0059, 0x0051, 1); - ultracam_veio(uvd, 0x01, 0x003f, 0x0052, 1); - ultracam_veio(uvd, 0x01, 0x0094, 0x0053, 1); - ultracam_veio(uvd, 0x01, 0x00ff, 0x0011, 1); - ultracam_veio(uvd, 0x01, 0x0003, 0x0012, 1); - ultracam_veio(uvd, 0x01, 0x00f7, 0x0013, 1); - ultracam_veio(uvd, 0x00, 0x0009, 0x0011, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0001, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1); - ultracam_veio(uvd, 0x00, 0x0020, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0010, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_alternateSetting(uvd, 0x04); - ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1); - ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1); - ultracam_veio(uvd, 0x02, 0x0000, 0x0006, 1); - ultracam_veio(uvd, 0x02, 0x9000, 0x0007, 1); - ultracam_veio(uvd, 0x02, 0x0042, 0x0001, 1); - ultracam_veio(uvd, 0x02, 0x0000, 0x000b, 0); - ultracam_resetPipe(uvd); - ULTRACAM_T(uvd)->initialized = (setup_ok != 0); - } - return setup_ok; -} - -static void ultracam_configure_video(struct uvd *uvd) -{ - if (uvd == NULL) - return; - - RESTRICT_TO_RANGE(init_brightness, 0, 255); - RESTRICT_TO_RANGE(init_contrast, 0, 255); - RESTRICT_TO_RANGE(init_color, 0, 255); - RESTRICT_TO_RANGE(init_hue, 0, 255); - RESTRICT_TO_RANGE(hue_correction, 0, 255); - - memset(&uvd->vpic, 0, sizeof(uvd->vpic)); - memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); - - uvd->vpic.colour = init_color << 8; - uvd->vpic.hue = init_hue << 8; - uvd->vpic.brightness = init_brightness << 8; - uvd->vpic.contrast = init_contrast << 8; - uvd->vpic.whiteness = 105 << 8; /* This one isn't used */ - uvd->vpic.depth = 24; - uvd->vpic.palette = VIDEO_PALETTE_RGB24; - - memset(&uvd->vcap, 0, sizeof(uvd->vcap)); - strcpy(uvd->vcap.name, "IBM Ultra Camera"); - uvd->vcap.type = VID_TYPE_CAPTURE; - uvd->vcap.channels = 1; - uvd->vcap.audios = 0; - uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas); - uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas); - uvd->vcap.minwidth = min_canvasWidth; - uvd->vcap.minheight = min_canvasHeight; - - memset(&uvd->vchan, 0, sizeof(uvd->vchan)); - uvd->vchan.flags = 0; - uvd->vchan.tuners = 0; - uvd->vchan.channel = 0; - uvd->vchan.type = VIDEO_TYPE_CAMERA; - strcpy(uvd->vchan.name, "Camera"); -} - -/* - * ultracam_probe() - * - * This procedure queries device descriptor and accepts the interface - * if it looks like our camera. - * - * History: - * 12-Nov-2000 Reworked to comply with new probe() signature. - * 23-Jan-2001 Added compatibility with 2.2.x kernels. - */ -static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id *devid) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct uvd *uvd = NULL; - int ix, i, nas; - int actInterface=-1, inactInterface=-1, maxPS=0; - unsigned char video_ep = 0; - - if (debug >= 1) - dev_info(&intf->dev, "ultracam_probe\n"); - - /* We don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) - return -ENODEV; - - dev_info(&intf->dev, "IBM Ultra camera found (rev. 0x%04x)\n", - le16_to_cpu(dev->descriptor.bcdDevice)); - - /* Validate found interface: must have one ISO endpoint */ - nas = intf->num_altsetting; - if (debug > 0) - dev_info(&intf->dev, "Number of alternate settings=%d.\n", - nas); - if (nas < 8) { - err("Too few alternate settings for this camera!"); - return -ENODEV; - } - /* Validate all alternate settings */ - for (ix=0; ix < nas; ix++) { - const struct usb_host_interface *interface; - const struct usb_endpoint_descriptor *endpoint; - - interface = &intf->altsetting[ix]; - i = interface->desc.bAlternateSetting; - if (interface->desc.bNumEndpoints != 1) { - err("Interface %d. has %u. endpoints!", - interface->desc.bInterfaceNumber, - (unsigned)(interface->desc.bNumEndpoints)); - return -ENODEV; - } - endpoint = &interface->endpoint[0].desc; - if (video_ep == 0) - video_ep = endpoint->bEndpointAddress; - else if (video_ep != endpoint->bEndpointAddress) { - err("Alternate settings have different endpoint addresses!"); - return -ENODEV; - } - if (!usb_endpoint_xfer_isoc(endpoint)) { - err("Interface %d. has non-ISO endpoint!", - interface->desc.bInterfaceNumber); - return -ENODEV; - } - if (usb_endpoint_dir_out(endpoint)) { - err("Interface %d. has ISO OUT endpoint!", - interface->desc.bInterfaceNumber); - return -ENODEV; - } - if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) { - if (inactInterface < 0) - inactInterface = i; - else { - err("More than one inactive alt. setting!"); - return -ENODEV; - } - } else { - if (actInterface < 0) { - actInterface = i; - maxPS = le16_to_cpu(endpoint->wMaxPacketSize); - if (debug > 0) - dev_info(&intf->dev, - "Active setting=%d. " - "maxPS=%d.\n", i, maxPS); - } else { - /* Got another active alt. setting */ - if (maxPS < le16_to_cpu(endpoint->wMaxPacketSize)) { - /* This one is better! */ - actInterface = i; - maxPS = le16_to_cpu(endpoint->wMaxPacketSize); - if (debug > 0) { - dev_info(&intf->dev, - "Even better ctive " - "setting=%d. " - "maxPS=%d.\n", - i, maxPS); - } - } - } - } - } - if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) { - err("Failed to recognize the camera!"); - return -ENODEV; - } - - uvd = usbvideo_AllocateDevice(cams); - if (uvd != NULL) { - /* Here uvd is a fully allocated uvd object */ - uvd->flags = flags; - uvd->debug = debug; - uvd->dev = dev; - uvd->iface = intf->altsetting->desc.bInterfaceNumber; - uvd->ifaceAltInactive = inactInterface; - uvd->ifaceAltActive = actInterface; - uvd->video_endp = video_ep; - uvd->iso_packet_len = maxPS; - uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24; - uvd->defaultPalette = VIDEO_PALETTE_RGB24; - uvd->canvas = VIDEOSIZE(640, 480); /* FIXME */ - uvd->videosize = uvd->canvas; /* ultracam_size_to_videosize(size);*/ - - /* Initialize ibmcam-specific data */ - assert(ULTRACAM_T(uvd) != NULL); - ULTRACAM_T(uvd)->camera_model = 0; /* Not used yet */ - ULTRACAM_T(uvd)->initialized = 0; - - ultracam_configure_video(uvd); - - i = usbvideo_RegisterVideoDevice(uvd); - if (i != 0) { - err("usbvideo_RegisterVideoDevice() failed."); - uvd = NULL; - } - } - - if (uvd) { - usb_set_intfdata (intf, uvd); - return 0; - } - return -EIO; -} - - -static struct usb_device_id id_table[] = { - { USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID) }, - { } /* Terminating entry */ -}; - -/* - * ultracam_init() - * - * This code is run to initialize the driver. - */ -static int __init ultracam_init(void) -{ - struct usbvideo_cb cbTbl; - memset(&cbTbl, 0, sizeof(cbTbl)); - cbTbl.probe = ultracam_probe; - cbTbl.setupOnOpen = ultracam_setup_on_open; - cbTbl.videoStart = ultracam_video_start; - cbTbl.videoStop = ultracam_video_stop; - cbTbl.processData = ultracam_ProcessIsocData; - cbTbl.postProcess = usbvideo_DeinterlaceFrame; - cbTbl.adjustPicture = ultracam_adjust_picture; - cbTbl.getFPS = ultracam_calculate_fps; - return usbvideo_register( - &cams, - MAX_CAMERAS, - sizeof(ultracam_t), - "ultracam", - &cbTbl, - THIS_MODULE, - id_table); -} - -static void __exit ultracam_cleanup(void) -{ - usbvideo_Deregister(&cams); -} - -MODULE_DEVICE_TABLE(usb, id_table); -MODULE_LICENSE("GPL"); - -module_init(ultracam_init); -module_exit(ultracam_cleanup); -- cgit v0.10.2 From 745da4280f272840976d47afba22ed853f07e1b2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 25 Dec 2010 07:27:47 -0300 Subject: [media] usbvideo: deprecate the vicam driver Move usbvideo to staging and mark it deprecated. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 4b751ef..3655b30 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -915,8 +915,6 @@ source "drivers/media/video/cx231xx/Kconfig" source "drivers/media/video/usbvision/Kconfig" -source "drivers/media/video/usbvideo/Kconfig" - source "drivers/media/video/et61x251/Kconfig" config USB_SE401 diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index ace7b6e..2f2e3ac 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -133,10 +133,6 @@ obj-$(CONFIG_USB_GSPCA) += gspca/ obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/ -obj-$(CONFIG_USB_IBMCAM) += usbvideo/ -obj-$(CONFIG_USB_KONICAWC) += usbvideo/ -obj-$(CONFIG_USB_VICAM) += usbvideo/ -obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += usbvideo/ obj-$(CONFIG_USB_S2255) += s2255drv.o obj-$(CONFIG_VIDEO_IVTV) += ivtv/ diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig deleted file mode 100644 index 357860d..0000000 --- a/drivers/media/video/usbvideo/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -config VIDEO_USBVIDEO - tristate - -config USB_VICAM - tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)" - depends on VIDEO_V4L1 && EXPERIMENTAL - select VIDEO_USBVIDEO - ---help--- - Say Y here if you have 3com homeconnect camera (vicam). - - To compile this driver as a module, choose M here: the - module will be called vicam. diff --git a/drivers/media/video/usbvideo/Makefile b/drivers/media/video/usbvideo/Makefile deleted file mode 100644 index 3c99a9a..0000000 --- a/drivers/media/video/usbvideo/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_VIDEO_USBVIDEO) += usbvideo.o -obj-$(CONFIG_USB_VICAM) += vicam.o diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c deleted file mode 100644 index f1fcf97..0000000 --- a/drivers/media/video/usbvideo/usbvideo.c +++ /dev/null @@ -1,2230 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "usbvideo.h" - -#if defined(MAP_NR) -#define virt_to_page(v) MAP_NR(v) /* Kernels 2.2.x */ -#endif - -static int video_nr = -1; -module_param(video_nr, int, 0); - -/* - * Local prototypes. - */ -static void usbvideo_Disconnect(struct usb_interface *intf); -static void usbvideo_CameraRelease(struct uvd *uvd); - -static long usbvideo_v4l_ioctl(struct file *file, - unsigned int cmd, unsigned long arg); -static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma); -static int usbvideo_v4l_open(struct file *file); -static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos); -static int usbvideo_v4l_close(struct file *file); - -static int usbvideo_StartDataPump(struct uvd *uvd); -static void usbvideo_StopDataPump(struct uvd *uvd); -static int usbvideo_GetFrame(struct uvd *uvd, int frameNum); -static int usbvideo_NewFrame(struct uvd *uvd, int framenum); -static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd, - struct usbvideo_frame *frame); - -/*******************************/ -/* Memory management functions */ -/*******************************/ -static void *usbvideo_rvmalloc(unsigned long size) -{ - void *mem; - unsigned long adr; - - size = PAGE_ALIGN(size); - mem = vmalloc_32(size); - if (!mem) - return NULL; - - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long) mem; - while (size > 0) { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - return mem; -} - -static void usbvideo_rvfree(void *mem, unsigned long size) -{ - unsigned long adr; - - if (!mem) - return; - - adr = (unsigned long) mem; - while ((long) size > 0) { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - vfree(mem); -} - -static void RingQueue_Initialize(struct RingQueue *rq) -{ - assert(rq != NULL); - init_waitqueue_head(&rq->wqh); -} - -static void RingQueue_Allocate(struct RingQueue *rq, int rqLen) -{ - /* Make sure the requested size is a power of 2 and - round up if necessary. This allows index wrapping - using masks rather than modulo */ - - int i = 1; - assert(rq != NULL); - assert(rqLen > 0); - - while(rqLen >> i) - i++; - if(rqLen != 1 << (i-1)) - rqLen = 1 << i; - - rq->length = rqLen; - rq->ri = rq->wi = 0; - rq->queue = usbvideo_rvmalloc(rq->length); - assert(rq->queue != NULL); -} - -static int RingQueue_IsAllocated(const struct RingQueue *rq) -{ - if (rq == NULL) - return 0; - return (rq->queue != NULL) && (rq->length > 0); -} - -static void RingQueue_Free(struct RingQueue *rq) -{ - assert(rq != NULL); - if (RingQueue_IsAllocated(rq)) { - usbvideo_rvfree(rq->queue, rq->length); - rq->queue = NULL; - rq->length = 0; - } -} - -int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len) -{ - int rql, toread; - - assert(rq != NULL); - assert(dst != NULL); - - rql = RingQueue_GetLength(rq); - if(!rql) - return 0; - - /* Clip requested length to available data */ - if(len > rql) - len = rql; - - toread = len; - if(rq->ri > rq->wi) { - /* Read data from tail */ - int read = (toread < (rq->length - rq->ri)) ? toread : rq->length - rq->ri; - memcpy(dst, rq->queue + rq->ri, read); - toread -= read; - dst += read; - rq->ri = (rq->ri + read) & (rq->length-1); - } - if(toread) { - /* Read data from head */ - memcpy(dst, rq->queue + rq->ri, toread); - rq->ri = (rq->ri + toread) & (rq->length-1); - } - return len; -} - -EXPORT_SYMBOL(RingQueue_Dequeue); - -int RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n) -{ - int enqueued = 0; - - assert(rq != NULL); - assert(cdata != NULL); - assert(rq->length > 0); - while (n > 0) { - int m, q_avail; - - /* Calculate the largest chunk that fits the tail of the ring */ - q_avail = rq->length - rq->wi; - if (q_avail <= 0) { - rq->wi = 0; - q_avail = rq->length; - } - m = n; - assert(q_avail > 0); - if (m > q_avail) - m = q_avail; - - memcpy(rq->queue + rq->wi, cdata, m); - RING_QUEUE_ADVANCE_INDEX(rq, wi, m); - cdata += m; - enqueued += m; - n -= m; - } - return enqueued; -} - -EXPORT_SYMBOL(RingQueue_Enqueue); - -static void RingQueue_InterruptibleSleepOn(struct RingQueue *rq) -{ - assert(rq != NULL); - interruptible_sleep_on(&rq->wqh); -} - -void RingQueue_WakeUpInterruptible(struct RingQueue *rq) -{ - assert(rq != NULL); - if (waitqueue_active(&rq->wqh)) - wake_up_interruptible(&rq->wqh); -} - -EXPORT_SYMBOL(RingQueue_WakeUpInterruptible); - -void RingQueue_Flush(struct RingQueue *rq) -{ - assert(rq != NULL); - rq->ri = 0; - rq->wi = 0; -} - -EXPORT_SYMBOL(RingQueue_Flush); - - -/* - * usbvideo_VideosizeToString() - * - * This procedure converts given videosize value to readable string. - * - * History: - * 07-Aug-2000 Created. - * 19-Oct-2000 Reworked for usbvideo module. - */ -static void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs) -{ - char tmp[40]; - int n; - - n = 1 + sprintf(tmp, "%ldx%ld", VIDEOSIZE_X(vs), VIDEOSIZE_Y(vs)); - assert(n < sizeof(tmp)); - if ((buf == NULL) || (bufLen < n)) - err("usbvideo_VideosizeToString: buffer is too small."); - else - memmove(buf, tmp, n); -} - -/* - * usbvideo_OverlayChar() - * - * History: - * 01-Feb-2000 Created. - */ -static void usbvideo_OverlayChar(struct uvd *uvd, struct usbvideo_frame *frame, - int x, int y, int ch) -{ - static const unsigned short digits[16] = { - 0xF6DE, /* 0 */ - 0x2492, /* 1 */ - 0xE7CE, /* 2 */ - 0xE79E, /* 3 */ - 0xB792, /* 4 */ - 0xF39E, /* 5 */ - 0xF3DE, /* 6 */ - 0xF492, /* 7 */ - 0xF7DE, /* 8 */ - 0xF79E, /* 9 */ - 0x77DA, /* a */ - 0xD75C, /* b */ - 0xF24E, /* c */ - 0xD6DC, /* d */ - 0xF34E, /* e */ - 0xF348 /* f */ - }; - unsigned short digit; - int ix, iy; - int value; - - if ((uvd == NULL) || (frame == NULL)) - return; - - value = hex_to_bin(ch); - if (value < 0) - return; - digit = digits[value]; - - for (iy=0; iy < 5; iy++) { - for (ix=0; ix < 3; ix++) { - if (digit & 0x8000) { - if (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24)) { -/* TODO */ RGB24_PUTPIXEL(frame, x+ix, y+iy, 0xFF, 0xFF, 0xFF); - } - } - digit = digit << 1; - } - } -} - -/* - * usbvideo_OverlayString() - * - * History: - * 01-Feb-2000 Created. - */ -static void usbvideo_OverlayString(struct uvd *uvd, struct usbvideo_frame *frame, - int x, int y, const char *str) -{ - while (*str) { - usbvideo_OverlayChar(uvd, frame, x, y, *str); - str++; - x += 4; /* 3 pixels character + 1 space */ - } -} - -/* - * usbvideo_OverlayStats() - * - * Overlays important debugging information. - * - * History: - * 01-Feb-2000 Created. - */ -static void usbvideo_OverlayStats(struct uvd *uvd, struct usbvideo_frame *frame) -{ - const int y_diff = 8; - char tmp[16]; - int x = 10, y=10; - long i, j, barLength; - const int qi_x1 = 60, qi_y1 = 10; - const int qi_x2 = VIDEOSIZE_X(frame->request) - 10, qi_h = 10; - - /* Call the user callback, see if we may proceed after that */ - if (VALID_CALLBACK(uvd, overlayHook)) { - if (GET_CALLBACK(uvd, overlayHook)(uvd, frame) < 0) - return; - } - - /* - * We draw a (mostly) hollow rectangle with qi_xxx coordinates. - * Left edge symbolizes the queue index 0; right edge symbolizes - * the full capacity of the queue. - */ - barLength = qi_x2 - qi_x1 - 2; - if ((barLength > 10) && (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24))) { -/* TODO */ long u_lo, u_hi, q_used; - long m_ri, m_wi, m_lo, m_hi; - - /* - * Determine fill zones (used areas of the queue): - * 0 xxxxxxx u_lo ...... uvd->dp.ri xxxxxxxx u_hi ..... uvd->dp.length - * - * if u_lo < 0 then there is no first filler. - */ - - q_used = RingQueue_GetLength(&uvd->dp); - if ((uvd->dp.ri + q_used) >= uvd->dp.length) { - u_hi = uvd->dp.length; - u_lo = (q_used + uvd->dp.ri) & (uvd->dp.length-1); - } else { - u_hi = (q_used + uvd->dp.ri); - u_lo = -1; - } - - /* Convert byte indices into screen units */ - m_ri = qi_x1 + ((barLength * uvd->dp.ri) / uvd->dp.length); - m_wi = qi_x1 + ((barLength * uvd->dp.wi) / uvd->dp.length); - m_lo = (u_lo > 0) ? (qi_x1 + ((barLength * u_lo) / uvd->dp.length)) : -1; - m_hi = qi_x1 + ((barLength * u_hi) / uvd->dp.length); - - for (j=qi_y1; j < (qi_y1 + qi_h); j++) { - for (i=qi_x1; i < qi_x2; i++) { - /* Draw border lines */ - if ((j == qi_y1) || (j == (qi_y1 + qi_h - 1)) || - (i == qi_x1) || (i == (qi_x2 - 1))) { - RGB24_PUTPIXEL(frame, i, j, 0xFF, 0xFF, 0xFF); - continue; - } - /* For all other points the Y coordinate does not matter */ - if ((i >= m_ri) && (i <= (m_ri + 3))) { - RGB24_PUTPIXEL(frame, i, j, 0x00, 0xFF, 0x00); - } else if ((i >= m_wi) && (i <= (m_wi + 3))) { - RGB24_PUTPIXEL(frame, i, j, 0xFF, 0x00, 0x00); - } else if ((i < m_lo) || ((i > m_ri) && (i < m_hi))) - RGB24_PUTPIXEL(frame, i, j, 0x00, 0x00, 0xFF); - } - } - } - - sprintf(tmp, "%8lx", uvd->stats.frame_num); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8lx", uvd->stats.urb_count); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8lx", uvd->stats.urb_length); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8lx", uvd->stats.data_count); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8lx", uvd->stats.header_count); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8lx", uvd->stats.iso_skip_count); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8lx", uvd->stats.iso_err_count); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8x", uvd->vpic.colour); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8x", uvd->vpic.hue); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8x", uvd->vpic.brightness >> 8); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8x", uvd->vpic.contrast >> 12); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; - - sprintf(tmp, "%8d", uvd->vpic.whiteness >> 8); - usbvideo_OverlayString(uvd, frame, x, y, tmp); - y += y_diff; -} - -/* - * usbvideo_ReportStatistics() - * - * This procedure prints packet and transfer statistics. - * - * History: - * 14-Jan-2000 Corrected default multiplier. - */ -static void usbvideo_ReportStatistics(const struct uvd *uvd) -{ - if ((uvd != NULL) && (uvd->stats.urb_count > 0)) { - unsigned long allPackets, badPackets, goodPackets, percent; - allPackets = uvd->stats.urb_count * CAMERA_URB_FRAMES; - badPackets = uvd->stats.iso_skip_count + uvd->stats.iso_err_count; - goodPackets = allPackets - badPackets; - /* Calculate percentage wisely, remember integer limits */ - assert(allPackets != 0); - if (goodPackets < (((unsigned long)-1)/100)) - percent = (100 * goodPackets) / allPackets; - else - percent = goodPackets / (allPackets / 100); - dev_info(&uvd->dev->dev, - "Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%\n", - allPackets, badPackets, percent); - if (uvd->iso_packet_len > 0) { - unsigned long allBytes, xferBytes; - char multiplier = ' '; - allBytes = allPackets * uvd->iso_packet_len; - xferBytes = uvd->stats.data_count; - assert(allBytes != 0); - if (xferBytes < (((unsigned long)-1)/100)) - percent = (100 * xferBytes) / allBytes; - else - percent = xferBytes / (allBytes / 100); - /* Scale xferBytes for easy reading */ - if (xferBytes > 10*1024) { - xferBytes /= 1024; - multiplier = 'K'; - if (xferBytes > 10*1024) { - xferBytes /= 1024; - multiplier = 'M'; - if (xferBytes > 10*1024) { - xferBytes /= 1024; - multiplier = 'G'; - if (xferBytes > 10*1024) { - xferBytes /= 1024; - multiplier = 'T'; - } - } - } - } - dev_info(&uvd->dev->dev, - "Transfer Statistics: Transferred=%lu%cB Usage=%lu%%\n", - xferBytes, multiplier, percent); - } - } -} - -/* - * usbvideo_TestPattern() - * - * Procedure forms a test pattern (yellow grid on blue background). - * - * Parameters: - * fullframe: if TRUE then entire frame is filled, otherwise the procedure - * continues from the current scanline. - * pmode 0: fill the frame with solid blue color (like on VCR or TV) - * 1: Draw a colored grid - * - * History: - * 01-Feb-2000 Created. - */ -void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode) -{ - struct usbvideo_frame *frame; - int num_cell = 0; - int scan_length = 0; - static int num_pass; - - if (uvd == NULL) { - err("%s: uvd == NULL", __func__); - return; - } - if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) { - err("%s: uvd->curframe=%d.", __func__, uvd->curframe); - return; - } - - /* Grab the current frame */ - frame = &uvd->frame[uvd->curframe]; - - /* Optionally start at the beginning */ - if (fullframe) { - frame->curline = 0; - frame->seqRead_Length = 0; - } -#if 0 - { /* For debugging purposes only */ - char tmp[20]; - usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request); - dev_info(&uvd->dev->dev, "testpattern: frame=%s\n", tmp); - } -#endif - /* Form every scan line */ - for (; frame->curline < VIDEOSIZE_Y(frame->request); frame->curline++) { - int i; - unsigned char *f = frame->data + - (VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL * frame->curline); - for (i=0; i < VIDEOSIZE_X(frame->request); i++) { - unsigned char cb=0x80; - unsigned char cg = 0; - unsigned char cr = 0; - - if (pmode == 1) { - if (frame->curline % 32 == 0) - cb = 0, cg = cr = 0xFF; - else if (i % 32 == 0) { - if (frame->curline % 32 == 1) - num_cell++; - cb = 0, cg = cr = 0xFF; - } else { - cb = ((num_cell*7) + num_pass) & 0xFF; - cg = ((num_cell*5) + num_pass*2) & 0xFF; - cr = ((num_cell*3) + num_pass*3) & 0xFF; - } - } else { - /* Just the blue screen */ - } - - *f++ = cb; - *f++ = cg; - *f++ = cr; - scan_length += 3; - } - } - - frame->frameState = FrameState_Done; - frame->seqRead_Length += scan_length; - ++num_pass; - - /* We do this unconditionally, regardless of FLAGS_OVERLAY_STATS */ - usbvideo_OverlayStats(uvd, frame); -} - -EXPORT_SYMBOL(usbvideo_TestPattern); - - -#ifdef DEBUG -/* - * usbvideo_HexDump() - * - * A debugging tool. Prints hex dumps. - * - * History: - * 29-Jul-2000 Added printing of offsets. - */ -void usbvideo_HexDump(const unsigned char *data, int len) -{ - const int bytes_per_line = 32; - char tmp[128]; /* 32*3 + 5 */ - int i, k; - - for (i=k=0; len > 0; i++, len--) { - if (i > 0 && ((i % bytes_per_line) == 0)) { - printk("%s\n", tmp); - k=0; - } - if ((i % bytes_per_line) == 0) - k += sprintf(&tmp[k], "%04x: ", i); - k += sprintf(&tmp[k], "%02x ", data[i]); - } - if (k > 0) - printk("%s\n", tmp); -} - -EXPORT_SYMBOL(usbvideo_HexDump); - -#endif - -/* ******************************************************************** */ - -/* XXX: this piece of crap really wants some error handling.. */ -static int usbvideo_ClientIncModCount(struct uvd *uvd) -{ - if (uvd == NULL) { - err("%s: uvd == NULL", __func__); - return -EINVAL; - } - if (uvd->handle == NULL) { - err("%s: uvd->handle == NULL", __func__); - return -EINVAL; - } - if (!try_module_get(uvd->handle->md_module)) { - err("%s: try_module_get() == 0", __func__); - return -ENODEV; - } - return 0; -} - -static void usbvideo_ClientDecModCount(struct uvd *uvd) -{ - if (uvd == NULL) { - err("%s: uvd == NULL", __func__); - return; - } - if (uvd->handle == NULL) { - err("%s: uvd->handle == NULL", __func__); - return; - } - if (uvd->handle->md_module == NULL) { - err("%s: uvd->handle->md_module == NULL", __func__); - return; - } - module_put(uvd->handle->md_module); -} - -int usbvideo_register( - struct usbvideo **pCams, - const int num_cams, - const int num_extra, - const char *driverName, - const struct usbvideo_cb *cbTbl, - struct module *md, - const struct usb_device_id *id_table) -{ - struct usbvideo *cams; - int i, base_size, result; - - /* Check parameters for sanity */ - if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) { - err("%s: Illegal call", __func__); - return -EINVAL; - } - - /* Check registration callback - must be set! */ - if (cbTbl->probe == NULL) { - err("%s: probe() is required!", __func__); - return -EINVAL; - } - - base_size = num_cams * sizeof(struct uvd) + sizeof(struct usbvideo); - cams = kzalloc(base_size, GFP_KERNEL); - if (cams == NULL) { - err("Failed to allocate %d. bytes for usbvideo struct", base_size); - return -ENOMEM; - } - dbg("%s: Allocated $%p (%d. bytes) for %d. cameras", - __func__, cams, base_size, num_cams); - - /* Copy callbacks, apply defaults for those that are not set */ - memmove(&cams->cb, cbTbl, sizeof(cams->cb)); - if (cams->cb.getFrame == NULL) - cams->cb.getFrame = usbvideo_GetFrame; - if (cams->cb.disconnect == NULL) - cams->cb.disconnect = usbvideo_Disconnect; - if (cams->cb.startDataPump == NULL) - cams->cb.startDataPump = usbvideo_StartDataPump; - if (cams->cb.stopDataPump == NULL) - cams->cb.stopDataPump = usbvideo_StopDataPump; - - cams->num_cameras = num_cams; - cams->cam = (struct uvd *) &cams[1]; - cams->md_module = md; - mutex_init(&cams->lock); /* to 1 == available */ - - for (i = 0; i < num_cams; i++) { - struct uvd *up = &cams->cam[i]; - - up->handle = cams; - - /* Allocate user_data separately because of kmalloc's limits */ - if (num_extra > 0) { - up->user_size = num_cams * num_extra; - up->user_data = kmalloc(up->user_size, GFP_KERNEL); - if (up->user_data == NULL) { - err("%s: Failed to allocate user_data (%d. bytes)", - __func__, up->user_size); - while (i) { - up = &cams->cam[--i]; - kfree(up->user_data); - } - kfree(cams); - return -ENOMEM; - } - dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)", - __func__, i, up->user_data, up->user_size); - } - } - - /* - * Register ourselves with USB stack. - */ - strcpy(cams->drvName, (driverName != NULL) ? driverName : "Unknown"); - cams->usbdrv.name = cams->drvName; - cams->usbdrv.probe = cams->cb.probe; - cams->usbdrv.disconnect = cams->cb.disconnect; - cams->usbdrv.id_table = id_table; - - /* - * Update global handle to usbvideo. This is very important - * because probe() can be called before usb_register() returns. - * If the handle is not yet updated then the probe() will fail. - */ - *pCams = cams; - result = usb_register(&cams->usbdrv); - if (result) { - for (i = 0; i < num_cams; i++) { - struct uvd *up = &cams->cam[i]; - kfree(up->user_data); - } - kfree(cams); - } - - return result; -} - -EXPORT_SYMBOL(usbvideo_register); - -/* - * usbvideo_Deregister() - * - * Procedure frees all usbvideo and user data structures. Be warned that - * if you had some dynamically allocated components in ->user field then - * you should free them before calling here. - */ -void usbvideo_Deregister(struct usbvideo **pCams) -{ - struct usbvideo *cams; - int i; - - if (pCams == NULL) { - err("%s: pCams == NULL", __func__); - return; - } - cams = *pCams; - if (cams == NULL) { - err("%s: cams == NULL", __func__); - return; - } - - dbg("%s: Deregistering %s driver.", __func__, cams->drvName); - usb_deregister(&cams->usbdrv); - - dbg("%s: Deallocating cams=$%p (%d. cameras)", __func__, cams, cams->num_cameras); - for (i=0; i < cams->num_cameras; i++) { - struct uvd *up = &cams->cam[i]; - int warning = 0; - - if (up->user_data != NULL) { - if (up->user_size <= 0) - ++warning; - } else { - if (up->user_size > 0) - ++warning; - } - if (warning) { - err("%s: Warning: user_data=$%p user_size=%d.", - __func__, up->user_data, up->user_size); - } else { - dbg("%s: Freeing %d. $%p->user_data=$%p", - __func__, i, up, up->user_data); - kfree(up->user_data); - } - } - /* Whole array was allocated in one chunk */ - dbg("%s: Freed %d uvd structures", - __func__, cams->num_cameras); - kfree(cams); - *pCams = NULL; -} - -EXPORT_SYMBOL(usbvideo_Deregister); - -/* - * usbvideo_Disconnect() - * - * This procedure stops all driver activity. Deallocation of - * the interface-private structure (pointed by 'ptr') is done now - * (if we don't have any open files) or later, when those files - * are closed. After that driver should be removable. - * - * This code handles surprise removal. The uvd->user is a counter which - * increments on open() and decrements on close(). If we see here that - * this counter is not 0 then we have a client who still has us opened. - * We set uvd->remove_pending flag as early as possible, and after that - * all access to the camera will gracefully fail. These failures should - * prompt client to (eventually) close the video device, and then - in - * usbvideo_v4l_close() - we decrement uvd->uvd_used and usage counter. - * - * History: - * 22-Jan-2000 Added polling of MOD_IN_USE to delay removal until all users gone. - * 27-Jan-2000 Reworked to allow pending disconnects; see xxx_close() - * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). - * 19-Oct-2000 Moved to usbvideo module. - */ -static void usbvideo_Disconnect(struct usb_interface *intf) -{ - struct uvd *uvd = usb_get_intfdata (intf); - int i; - - if (uvd == NULL) { - err("%s($%p): Illegal call.", __func__, intf); - return; - } - - usb_set_intfdata (intf, NULL); - - usbvideo_ClientIncModCount(uvd); - if (uvd->debug > 0) - dev_info(&intf->dev, "%s(%p.)\n", __func__, intf); - - mutex_lock(&uvd->lock); - uvd->remove_pending = 1; /* Now all ISO data will be ignored */ - - /* At this time we ask to cancel outstanding URBs */ - GET_CALLBACK(uvd, stopDataPump)(uvd); - - for (i=0; i < USBVIDEO_NUMSBUF; i++) - usb_free_urb(uvd->sbuf[i].urb); - - usb_put_dev(uvd->dev); - uvd->dev = NULL; /* USB device is no more */ - - video_unregister_device(&uvd->vdev); - if (uvd->debug > 0) - dev_info(&intf->dev, "%s: Video unregistered.\n", __func__); - - if (uvd->user) - dev_info(&intf->dev, "%s: In use, disconnect pending.\n", - __func__); - else - usbvideo_CameraRelease(uvd); - mutex_unlock(&uvd->lock); - dev_info(&intf->dev, "USB camera disconnected.\n"); - - usbvideo_ClientDecModCount(uvd); -} - -/* - * usbvideo_CameraRelease() - * - * This code does final release of uvd. This happens - * after the device is disconnected -and- all clients - * closed their files. - * - * History: - * 27-Jan-2000 Created. - */ -static void usbvideo_CameraRelease(struct uvd *uvd) -{ - if (uvd == NULL) { - err("%s: Illegal call", __func__); - return; - } - - RingQueue_Free(&uvd->dp); - if (VALID_CALLBACK(uvd, userFree)) - GET_CALLBACK(uvd, userFree)(uvd); - uvd->uvd_used = 0; /* This is atomic, no need to take mutex */ -} - -/* - * usbvideo_find_struct() - * - * This code searches the array of preallocated (static) structures - * and returns index of the first one that isn't in use. Returns -1 - * if there are no free structures. - * - * History: - * 27-Jan-2000 Created. - */ -static int usbvideo_find_struct(struct usbvideo *cams) -{ - int u, rv = -1; - - if (cams == NULL) { - err("No usbvideo handle?"); - return -1; - } - mutex_lock(&cams->lock); - for (u = 0; u < cams->num_cameras; u++) { - struct uvd *uvd = &cams->cam[u]; - if (!uvd->uvd_used) /* This one is free */ - { - uvd->uvd_used = 1; /* In use now */ - mutex_init(&uvd->lock); /* to 1 == available */ - uvd->dev = NULL; - rv = u; - break; - } - } - mutex_unlock(&cams->lock); - return rv; -} - -static const struct v4l2_file_operations usbvideo_fops = { - .owner = THIS_MODULE, - .open = usbvideo_v4l_open, - .release =usbvideo_v4l_close, - .read = usbvideo_v4l_read, - .mmap = usbvideo_v4l_mmap, - .ioctl = usbvideo_v4l_ioctl, -}; -static const struct video_device usbvideo_template = { - .fops = &usbvideo_fops, -}; - -struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams) -{ - int i, devnum; - struct uvd *uvd = NULL; - - if (cams == NULL) { - err("No usbvideo handle?"); - return NULL; - } - - devnum = usbvideo_find_struct(cams); - if (devnum == -1) { - err("IBM USB camera driver: Too many devices!"); - return NULL; - } - uvd = &cams->cam[devnum]; - dbg("Device entry #%d. at $%p", devnum, uvd); - - /* Not relying upon caller we increase module counter ourselves */ - usbvideo_ClientIncModCount(uvd); - - mutex_lock(&uvd->lock); - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - uvd->sbuf[i].urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); - if (uvd->sbuf[i].urb == NULL) { - err("usb_alloc_urb(%d.) failed.", FRAMES_PER_DESC); - uvd->uvd_used = 0; - uvd = NULL; - goto allocate_done; - } - } - uvd->user=0; - uvd->remove_pending = 0; - uvd->last_error = 0; - RingQueue_Initialize(&uvd->dp); - - /* Initialize video device structure */ - uvd->vdev = usbvideo_template; - sprintf(uvd->vdev.name, "%.20s USB Camera", cams->drvName); - /* - * The client is free to overwrite those because we - * return control to the client's probe function right now. - */ -allocate_done: - mutex_unlock(&uvd->lock); - usbvideo_ClientDecModCount(uvd); - return uvd; -} - -EXPORT_SYMBOL(usbvideo_AllocateDevice); - -int usbvideo_RegisterVideoDevice(struct uvd *uvd) -{ - char tmp1[20], tmp2[20]; /* Buffers for printing */ - - if (uvd == NULL) { - err("%s: Illegal call.", __func__); - return -EINVAL; - } - if (uvd->video_endp == 0) { - dev_info(&uvd->dev->dev, - "%s: No video endpoint specified; data pump disabled.\n", - __func__); - } - if (uvd->paletteBits == 0) { - err("%s: No palettes specified!", __func__); - return -EINVAL; - } - if (uvd->defaultPalette == 0) { - dev_info(&uvd->dev->dev, "%s: No default palette!\n", - __func__); - } - - uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) * - VIDEOSIZE_Y(uvd->canvas) * V4L_BYTES_PER_PIXEL; - usbvideo_VideosizeToString(tmp1, sizeof(tmp1), uvd->videosize); - usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas); - - if (uvd->debug > 0) { - dev_info(&uvd->dev->dev, - "%s: iface=%d. endpoint=$%02x paletteBits=$%08lx\n", - __func__, uvd->iface, uvd->video_endp, - uvd->paletteBits); - } - if (uvd->dev == NULL) { - err("%s: uvd->dev == NULL", __func__); - return -EINVAL; - } - uvd->vdev.parent = &uvd->dev->dev; - uvd->vdev.release = video_device_release_empty; - if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { - err("%s: video_register_device failed", __func__); - return -EPIPE; - } - if (uvd->debug > 1) { - dev_info(&uvd->dev->dev, - "%s: video_register_device() successful\n", __func__); - } - - dev_info(&uvd->dev->dev, "%s on %s: canvas=%s videosize=%s\n", - (uvd->handle != NULL) ? uvd->handle->drvName : "???", - video_device_node_name(&uvd->vdev), tmp2, tmp1); - - usb_get_dev(uvd->dev); - return 0; -} - -EXPORT_SYMBOL(usbvideo_RegisterVideoDevice); - -/* ******************************************************************** */ - -static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct uvd *uvd = file->private_data; - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end-vma->vm_start; - unsigned long page, pos; - - if (!CAMERA_IS_OPERATIONAL(uvd)) - return -EFAULT; - - if (size > (((USBVIDEO_NUMFRAMES * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) - return -EINVAL; - - pos = (unsigned long) uvd->fbuf; - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) - return -EAGAIN; - - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - - return 0; -} - -/* - * usbvideo_v4l_open() - * - * This is part of Video 4 Linux API. The driver can be opened by one - * client only (checks internal counter 'uvdser'). The procedure - * then allocates buffers needed for video processing. - * - * History: - * 22-Jan-2000 Rewrote, moved scratch buffer allocation here. Now the - * camera is also initialized here (once per connect), at - * expense of V4L client (it waits on open() call). - * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. - * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). - */ -static int usbvideo_v4l_open(struct file *file) -{ - struct video_device *dev = video_devdata(file); - struct uvd *uvd = (struct uvd *) dev; - const int sb_size = FRAMES_PER_DESC * uvd->iso_packet_len; - int i, errCode = 0; - - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev); - - if (usbvideo_ClientIncModCount(uvd) < 0) - return -ENODEV; - mutex_lock(&uvd->lock); - - if (uvd->user) { - err("%s: Someone tried to open an already opened device!", __func__); - errCode = -EBUSY; - } else { - /* Clear statistics */ - memset(&uvd->stats, 0, sizeof(uvd->stats)); - - /* Clean pointers so we know if we allocated something */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) - uvd->sbuf[i].data = NULL; - - /* Allocate memory for the frame buffers */ - uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size; - uvd->fbuf = usbvideo_rvmalloc(uvd->fbuf_size); - RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE); - if ((uvd->fbuf == NULL) || - (!RingQueue_IsAllocated(&uvd->dp))) { - err("%s: Failed to allocate fbuf or dp", __func__); - errCode = -ENOMEM; - } else { - /* Allocate all buffers */ - for (i=0; i < USBVIDEO_NUMFRAMES; i++) { - uvd->frame[i].frameState = FrameState_Unused; - uvd->frame[i].data = uvd->fbuf + i*(uvd->max_frame_size); - /* - * Set default sizes in case IOCTL (VIDIOCMCAPTURE) - * is not used (using read() instead). - */ - uvd->frame[i].canvas = uvd->canvas; - uvd->frame[i].seqRead_Index = 0; - } - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - uvd->sbuf[i].data = kmalloc(sb_size, GFP_KERNEL); - if (uvd->sbuf[i].data == NULL) { - errCode = -ENOMEM; - break; - } - } - } - if (errCode != 0) { - /* Have to free all that memory */ - if (uvd->fbuf != NULL) { - usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size); - uvd->fbuf = NULL; - } - RingQueue_Free(&uvd->dp); - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - kfree(uvd->sbuf[i].data); - uvd->sbuf[i].data = NULL; - } - } - } - - /* If so far no errors then we shall start the camera */ - if (errCode == 0) { - /* Start data pump if we have valid endpoint */ - if (uvd->video_endp != 0) - errCode = GET_CALLBACK(uvd, startDataPump)(uvd); - if (errCode == 0) { - if (VALID_CALLBACK(uvd, setupOnOpen)) { - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, - "%s: setupOnOpen callback\n", - __func__); - errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd); - if (errCode < 0) { - err("%s: setupOnOpen callback failed (%d.).", - __func__, errCode); - } else if (uvd->debug > 1) { - dev_info(&uvd->dev->dev, - "%s: setupOnOpen callback successful\n", - __func__); - } - } - if (errCode == 0) { - uvd->settingsAdjusted = 0; - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, - "%s: Open succeeded.\n", - __func__); - uvd->user++; - file->private_data = uvd; - } - } - } - mutex_unlock(&uvd->lock); - if (errCode != 0) - usbvideo_ClientDecModCount(uvd); - if (uvd->debug > 0) - dev_info(&uvd->dev->dev, "%s: Returning %d.\n", __func__, - errCode); - return errCode; -} - -/* - * usbvideo_v4l_close() - * - * This is part of Video 4 Linux API. The procedure - * stops streaming and deallocates all buffers that were earlier - * allocated in usbvideo_v4l_open(). - * - * History: - * 22-Jan-2000 Moved scratch buffer deallocation here. - * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. - * 24-May-2000 Moved MOD_DEC_USE_COUNT outside of code that can sleep. - */ -static int usbvideo_v4l_close(struct file *file) -{ - struct video_device *dev = file->private_data; - struct uvd *uvd = (struct uvd *) dev; - int i; - - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev); - - mutex_lock(&uvd->lock); - GET_CALLBACK(uvd, stopDataPump)(uvd); - usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size); - uvd->fbuf = NULL; - RingQueue_Free(&uvd->dp); - - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - kfree(uvd->sbuf[i].data); - uvd->sbuf[i].data = NULL; - } - -#if USBVIDEO_REPORT_STATS - usbvideo_ReportStatistics(uvd); -#endif - - uvd->user--; - if (uvd->remove_pending) { - if (uvd->debug > 0) - dev_info(&uvd->dev->dev, "%s: Final disconnect.\n", - __func__); - usbvideo_CameraRelease(uvd); - } - mutex_unlock(&uvd->lock); - usbvideo_ClientDecModCount(uvd); - - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, "%s: Completed.\n", __func__); - file->private_data = NULL; - return 0; -} - -/* - * usbvideo_v4l_ioctl() - * - * This is part of Video 4 Linux API. The procedure handles ioctl() calls. - * - * History: - * 22-Jan-2000 Corrected VIDIOCSPICT to reject unsupported settings. - */ -static long usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) -{ - struct uvd *uvd = file->private_data; - - if (!CAMERA_IS_OPERATIONAL(uvd)) - return -EIO; - - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability *b = arg; - *b = uvd->vcap; - return 0; - } - case VIDIOCGCHAN: - { - struct video_channel *v = arg; - *v = uvd->vchan; - return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *v = arg; - if (v->channel != 0) - return -EINVAL; - return 0; - } - case VIDIOCGPICT: - { - struct video_picture *pic = arg; - *pic = uvd->vpic; - return 0; - } - case VIDIOCSPICT: - { - struct video_picture *pic = arg; - /* - * Use temporary 'video_picture' structure to preserve our - * own settings (such as color depth, palette) that we - * aren't allowing everyone (V4L client) to change. - */ - uvd->vpic.brightness = pic->brightness; - uvd->vpic.hue = pic->hue; - uvd->vpic.colour = pic->colour; - uvd->vpic.contrast = pic->contrast; - uvd->settingsAdjusted = 0; /* Will force new settings */ - return 0; - } - case VIDIOCSWIN: - { - struct video_window *vw = arg; - - if(VALID_CALLBACK(uvd, setVideoMode)) { - return GET_CALLBACK(uvd, setVideoMode)(uvd, vw); - } - - if (vw->flags) - return -EINVAL; - if (vw->clipcount) - return -EINVAL; - if (vw->width != VIDEOSIZE_X(uvd->canvas)) - return -EINVAL; - if (vw->height != VIDEOSIZE_Y(uvd->canvas)) - return -EINVAL; - - return 0; - } - case VIDIOCGWIN: - { - struct video_window *vw = arg; - - vw->x = 0; - vw->y = 0; - vw->width = VIDEOSIZE_X(uvd->videosize); - vw->height = VIDEOSIZE_Y(uvd->videosize); - vw->chromakey = 0; - if (VALID_CALLBACK(uvd, getFPS)) - vw->flags = GET_CALLBACK(uvd, getFPS)(uvd); - else - vw->flags = 10; /* FIXME: do better! */ - return 0; - } - case VIDIOCGMBUF: - { - struct video_mbuf *vm = arg; - int i; - - memset(vm, 0, sizeof(*vm)); - vm->size = uvd->max_frame_size * USBVIDEO_NUMFRAMES; - vm->frames = USBVIDEO_NUMFRAMES; - for(i = 0; i < USBVIDEO_NUMFRAMES; i++) - vm->offsets[i] = i * uvd->max_frame_size; - - return 0; - } - case VIDIOCMCAPTURE: - { - struct video_mmap *vm = arg; - - if (uvd->debug >= 1) { - dev_info(&uvd->dev->dev, - "VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.\n", - vm->frame, vm->width, vm->height, vm->format); - } - /* - * Check if the requested size is supported. If the requestor - * requests too big a frame then we may be tricked into accessing - * outside of own preallocated frame buffer (in uvd->frame). - * This will cause oops or a security hole. Theoretically, we - * could only clamp the size down to acceptable bounds, but then - * we'd need to figure out how to insert our smaller buffer into - * larger caller's buffer... this is not an easy question. So we - * here just flatly reject too large requests, assuming that the - * caller will resubmit with smaller size. Callers should know - * what size we support (returned by VIDIOCGCAP). However vidcat, - * for one, does not care and allows to ask for any size. - */ - if ((vm->width > VIDEOSIZE_X(uvd->canvas)) || - (vm->height > VIDEOSIZE_Y(uvd->canvas))) { - if (uvd->debug > 0) { - dev_info(&uvd->dev->dev, - "VIDIOCMCAPTURE: Size=%dx%d " - "too large; allowed only up " - "to %ldx%ld\n", vm->width, - vm->height, - VIDEOSIZE_X(uvd->canvas), - VIDEOSIZE_Y(uvd->canvas)); - } - return -EINVAL; - } - /* Check if the palette is supported */ - if (((1L << vm->format) & uvd->paletteBits) == 0) { - if (uvd->debug > 0) { - dev_info(&uvd->dev->dev, - "VIDIOCMCAPTURE: format=%d. " - "not supported " - "(paletteBits=$%08lx)\n", - vm->format, uvd->paletteBits); - } - return -EINVAL; - } - if ((vm->frame < 0) || (vm->frame >= USBVIDEO_NUMFRAMES)) { - err("VIDIOCMCAPTURE: vm.frame=%d. !E [0-%d]", vm->frame, USBVIDEO_NUMFRAMES-1); - return -EINVAL; - } - if (uvd->frame[vm->frame].frameState == FrameState_Grabbing) { - /* Not an error - can happen */ - } - uvd->frame[vm->frame].request = VIDEOSIZE(vm->width, vm->height); - uvd->frame[vm->frame].palette = vm->format; - - /* Mark it as ready */ - uvd->frame[vm->frame].frameState = FrameState_Ready; - - return usbvideo_NewFrame(uvd, vm->frame); - } - case VIDIOCSYNC: - { - int *frameNum = arg; - int ret; - - if (*frameNum < 0 || *frameNum >= USBVIDEO_NUMFRAMES) - return -EINVAL; - - if (uvd->debug >= 1) - dev_info(&uvd->dev->dev, - "VIDIOCSYNC: syncing to frame %d.\n", - *frameNum); - if (uvd->flags & FLAGS_NO_DECODING) - ret = usbvideo_GetFrame(uvd, *frameNum); - else if (VALID_CALLBACK(uvd, getFrame)) { - ret = GET_CALLBACK(uvd, getFrame)(uvd, *frameNum); - if ((ret < 0) && (uvd->debug >= 1)) { - err("VIDIOCSYNC: getFrame() returned %d.", ret); - } - } else { - err("VIDIOCSYNC: getFrame is not set"); - ret = -EFAULT; - } - - /* - * The frame is in FrameState_Done_Hold state. Release it - * right now because its data is already mapped into - * the user space and it's up to the application to - * make use of it until it asks for another frame. - */ - uvd->frame[*frameNum].frameState = FrameState_Unused; - return ret; - } - case VIDIOCGFBUF: - { - struct video_buffer *vb = arg; - - memset(vb, 0, sizeof(*vb)); - return 0; - } - case VIDIOCKEY: - return 0; - - case VIDIOCCAPTURE: - return -EINVAL; - - case VIDIOCSFBUF: - - case VIDIOCGTUNER: - case VIDIOCSTUNER: - - case VIDIOCGFREQ: - case VIDIOCSFREQ: - - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - return -EINVAL; - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static long usbvideo_v4l_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(file, cmd, arg, usbvideo_v4l_do_ioctl); -} - -/* - * usbvideo_v4l_read() - * - * This is mostly boring stuff. We simply ask for a frame and when it - * arrives copy all the video data from it into user space. There is - * no obvious need to override this method. - * - * History: - * 20-Oct-2000 Created. - * 01-Nov-2000 Added mutex (uvd->lock). - */ -static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct uvd *uvd = file->private_data; - int noblock = file->f_flags & O_NONBLOCK; - int frmx = -1, i; - struct usbvideo_frame *frame; - - if (!CAMERA_IS_OPERATIONAL(uvd) || (buf == NULL)) - return -EFAULT; - - if (uvd->debug >= 1) - dev_info(&uvd->dev->dev, - "%s: %Zd. bytes, noblock=%d.\n", - __func__, count, noblock); - - mutex_lock(&uvd->lock); - - /* See if a frame is completed, then use it. */ - for(i = 0; i < USBVIDEO_NUMFRAMES; i++) { - if ((uvd->frame[i].frameState == FrameState_Done) || - (uvd->frame[i].frameState == FrameState_Done_Hold) || - (uvd->frame[i].frameState == FrameState_Error)) { - frmx = i; - break; - } - } - - /* FIXME: If we don't start a frame here then who ever does? */ - if (noblock && (frmx == -1)) { - count = -EAGAIN; - goto read_done; - } - - /* - * If no FrameState_Done, look for a FrameState_Grabbing state. - * See if a frame is in process (grabbing), then use it. - * We will need to wait until it becomes cooked, of course. - */ - if (frmx == -1) { - for(i = 0; i < USBVIDEO_NUMFRAMES; i++) { - if (uvd->frame[i].frameState == FrameState_Grabbing) { - frmx = i; - break; - } - } - } - - /* - * If no frame is active, start one. We don't care which one - * it will be, so #0 is as good as any. - * In read access mode we don't have convenience of VIDIOCMCAPTURE - * to specify the requested palette (video format) on per-frame - * basis. This means that we have to return data in -some- format - * and just hope that the client knows what to do with it. - * The default format is configured in uvd->defaultPalette field - * as one of VIDEO_PALETTE_xxx values. We stuff it into the new - * frame and initiate the frame filling process. - */ - if (frmx == -1) { - if (uvd->defaultPalette == 0) { - err("%s: No default palette; don't know what to do!", __func__); - count = -EFAULT; - goto read_done; - } - frmx = 0; - /* - * We have no per-frame control over video size. - * Therefore we only can use whatever size was - * specified as default. - */ - uvd->frame[frmx].request = uvd->videosize; - uvd->frame[frmx].palette = uvd->defaultPalette; - uvd->frame[frmx].frameState = FrameState_Ready; - usbvideo_NewFrame(uvd, frmx); - /* Now frame 0 is supposed to start filling... */ - } - - /* - * Get a pointer to the active frame. It is either previously - * completed frame or frame in progress but not completed yet. - */ - frame = &uvd->frame[frmx]; - - /* - * Sit back & wait until the frame gets filled and postprocessed. - * If we fail to get the picture [in time] then return the error. - * In this call we specify that we want the frame to be waited for, - * postprocessed and switched into FrameState_Done_Hold state. This - * state is used to hold the frame as "fully completed" between - * subsequent partial reads of the same frame. - */ - if (frame->frameState != FrameState_Done_Hold) { - long rv = -EFAULT; - if (uvd->flags & FLAGS_NO_DECODING) - rv = usbvideo_GetFrame(uvd, frmx); - else if (VALID_CALLBACK(uvd, getFrame)) - rv = GET_CALLBACK(uvd, getFrame)(uvd, frmx); - else - err("getFrame is not set"); - if ((rv != 0) || (frame->frameState != FrameState_Done_Hold)) { - count = rv; - goto read_done; - } - } - - /* - * Copy bytes to user space. We allow for partial reads, which - * means that the user application can request read less than - * the full frame size. It is up to the application to issue - * subsequent calls until entire frame is read. - * - * First things first, make sure we don't copy more than we - * have - even if the application wants more. That would be - * a big security embarassment! - */ - if ((count + frame->seqRead_Index) > frame->seqRead_Length) - count = frame->seqRead_Length - frame->seqRead_Index; - - /* - * Copy requested amount of data to user space. We start - * copying from the position where we last left it, which - * will be zero for a new frame (not read before). - */ - if (copy_to_user(buf, frame->data + frame->seqRead_Index, count)) { - count = -EFAULT; - goto read_done; - } - - /* Update last read position */ - frame->seqRead_Index += count; - if (uvd->debug >= 1) { - err("%s: {copy} count used=%Zd, new seqRead_Index=%ld", - __func__, count, frame->seqRead_Index); - } - - /* Finally check if the frame is done with and "release" it */ - if (frame->seqRead_Index >= frame->seqRead_Length) { - /* All data has been read */ - frame->seqRead_Index = 0; - - /* Mark it as available to be used again. */ - uvd->frame[frmx].frameState = FrameState_Unused; - if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) { - err("%s: usbvideo_NewFrame failed.", __func__); - } - } -read_done: - mutex_unlock(&uvd->lock); - return count; -} - -/* - * Make all of the blocks of data contiguous - */ -static int usbvideo_CompressIsochronous(struct uvd *uvd, struct urb *urb) -{ - char *cdata; - int i, totlen = 0; - - for (i = 0; i < urb->number_of_packets; i++) { - int n = urb->iso_frame_desc[i].actual_length; - int st = urb->iso_frame_desc[i].status; - - cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - - /* Detect and ignore errored packets */ - if (st < 0) { - if (uvd->debug >= 1) - err("Data error: packet=%d. len=%d. status=%d.", i, n, st); - uvd->stats.iso_err_count++; - continue; - } - - /* Detect and ignore empty packets */ - if (n <= 0) { - uvd->stats.iso_skip_count++; - continue; - } - totlen += n; /* Little local accounting */ - RingQueue_Enqueue(&uvd->dp, cdata, n); - } - return totlen; -} - -static void usbvideo_IsocIrq(struct urb *urb) -{ - int i, ret, len; - struct uvd *uvd = urb->context; - - /* We don't want to do anything if we are about to be removed! */ - if (!CAMERA_IS_OPERATIONAL(uvd)) - return; -#if 0 - if (urb->actual_length > 0) { - dev_info(&uvd->dev->dev, - "urb=$%p status=%d. errcount=%d. length=%d.\n", - urb, urb->status, urb->error_count, - urb->actual_length); - } else { - static int c = 0; - if (c++ % 100 == 0) - dev_info(&uvd->dev->dev, "No Isoc data\n"); - } -#endif - - if (!uvd->streaming) { - if (uvd->debug >= 1) - dev_info(&uvd->dev->dev, - "Not streaming, but interrupt!\n"); - return; - } - - uvd->stats.urb_count++; - if (urb->actual_length <= 0) - goto urb_done_with; - - /* Copy the data received into ring queue */ - len = usbvideo_CompressIsochronous(uvd, urb); - uvd->stats.urb_length = len; - if (len <= 0) - goto urb_done_with; - - /* Here we got some data */ - uvd->stats.data_count += len; - RingQueue_WakeUpInterruptible(&uvd->dp); - -urb_done_with: - for (i = 0; i < FRAMES_PER_DESC; i++) { - urb->iso_frame_desc[i].status = 0; - urb->iso_frame_desc[i].actual_length = 0; - } - urb->status = 0; - urb->dev = uvd->dev; - ret = usb_submit_urb (urb, GFP_KERNEL); - if(ret) - err("usb_submit_urb error (%d)", ret); - return; -} - -/* - * usbvideo_StartDataPump() - * - * History: - * 27-Jan-2000 Used ibmcam->iface, ibmcam->ifaceAltActive instead - * of hardcoded values. Simplified by using for loop, - * allowed any number of URBs. - */ -static int usbvideo_StartDataPump(struct uvd *uvd) -{ - struct usb_device *dev = uvd->dev; - int i, errFlag; - - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd); - - if (!CAMERA_IS_OPERATIONAL(uvd)) { - err("%s: Camera is not operational", __func__); - return -EFAULT; - } - uvd->curframe = -1; - - /* Alternate interface 1 is is the biggest frame size */ - i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive); - if (i < 0) { - err("%s: usb_set_interface error", __func__); - uvd->last_error = i; - return -EBUSY; - } - if (VALID_CALLBACK(uvd, videoStart)) - GET_CALLBACK(uvd, videoStart)(uvd); - else - err("%s: videoStart not set", __func__); - - /* We double buffer the Iso lists */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - int j, k; - struct urb *urb = uvd->sbuf[i].urb; - urb->dev = dev; - urb->context = uvd; - urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp); - urb->interval = 1; - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = uvd->sbuf[i].data; - urb->complete = usbvideo_IsocIrq; - urb->number_of_packets = FRAMES_PER_DESC; - urb->transfer_buffer_length = uvd->iso_packet_len * FRAMES_PER_DESC; - for (j=k=0; j < FRAMES_PER_DESC; j++, k += uvd->iso_packet_len) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = uvd->iso_packet_len; - } - } - - /* Submit all URBs */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL); - if (errFlag) - err("%s: usb_submit_isoc(%d) ret %d", __func__, i, errFlag); - } - - uvd->streaming = 1; - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, - "%s: streaming=1 video_endp=$%02x\n", __func__, - uvd->video_endp); - return 0; -} - -/* - * usbvideo_StopDataPump() - * - * This procedure stops streaming and deallocates URBs. Then it - * activates zero-bandwidth alt. setting of the video interface. - * - * History: - * 22-Jan-2000 Corrected order of actions to work after surprise removal. - * 27-Jan-2000 Used uvd->iface, uvd->ifaceAltInactive instead of hardcoded values. - */ -static void usbvideo_StopDataPump(struct uvd *uvd) -{ - int i, j; - - if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) - return; - - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd); - - /* Unschedule all of the iso td's */ - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - usb_kill_urb(uvd->sbuf[i].urb); - } - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, "%s: streaming=0\n", __func__); - uvd->streaming = 0; - - if (!uvd->remove_pending) { - /* Invoke minidriver's magic to stop the camera */ - if (VALID_CALLBACK(uvd, videoStop)) - GET_CALLBACK(uvd, videoStop)(uvd); - else - err("%s: videoStop not set", __func__); - - /* Set packet size to 0 */ - j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive); - if (j < 0) { - err("%s: usb_set_interface() error %d.", __func__, j); - uvd->last_error = j; - } - } -} - -/* - * usbvideo_NewFrame() - * - * History: - * 29-Mar-00 Added copying of previous frame into the current one. - * 6-Aug-00 Added model 3 video sizes, removed redundant width, height. - */ -static int usbvideo_NewFrame(struct uvd *uvd, int framenum) -{ - struct usbvideo_frame *frame; - int n; - - if (uvd->debug > 1) - dev_info(&uvd->dev->dev, "usbvideo_NewFrame($%p,%d.)\n", uvd, - framenum); - - /* If we're not grabbing a frame right now and the other frame is */ - /* ready to be grabbed into, then use it instead */ - if (uvd->curframe != -1) - return 0; - - /* If necessary we adjust picture settings between frames */ - if (!uvd->settingsAdjusted) { - if (VALID_CALLBACK(uvd, adjustPicture)) - GET_CALLBACK(uvd, adjustPicture)(uvd); - uvd->settingsAdjusted = 1; - } - - n = (framenum + 1) % USBVIDEO_NUMFRAMES; - if (uvd->frame[n].frameState == FrameState_Ready) - framenum = n; - - frame = &uvd->frame[framenum]; - - frame->frameState = FrameState_Grabbing; - frame->scanstate = ScanState_Scanning; - frame->seqRead_Length = 0; /* Accumulated in xxx_parse_data() */ - frame->deinterlace = Deinterlace_None; - frame->flags = 0; /* No flags yet, up to minidriver (or us) to set them */ - uvd->curframe = framenum; - - /* - * Normally we would want to copy previous frame into the current one - * before we even start filling it with data; this allows us to stop - * filling at any moment; top portion of the frame will be new and - * bottom portion will stay as it was in previous frame. If we don't - * do that then missing chunks of video stream will result in flickering - * portions of old data whatever it was before. - * - * If we choose not to copy previous frame (to, for example, save few - * bus cycles - the frame can be pretty large!) then we have an option - * to clear the frame before using. If we experience losses in this - * mode then missing picture will be black (no flickering). - * - * Finally, if user chooses not to clean the current frame before - * filling it with data then the old data will be visible if we fail - * to refill entire frame with new data. - */ - if (!(uvd->flags & FLAGS_SEPARATE_FRAMES)) { - /* This copies previous frame into this one to mask losses */ - int prev = (framenum - 1 + USBVIDEO_NUMFRAMES) % USBVIDEO_NUMFRAMES; - memmove(frame->data, uvd->frame[prev].data, uvd->max_frame_size); - } else { - if (uvd->flags & FLAGS_CLEAN_FRAMES) { - /* This provides a "clean" frame but slows things down */ - memset(frame->data, 0, uvd->max_frame_size); - } - } - return 0; -} - -/* - * usbvideo_CollectRawData() - * - * This procedure can be used instead of 'processData' callback if you - * only want to dump the raw data from the camera into the output - * device (frame buffer). You can look at it with V4L client, but the - * image will be unwatchable. The main purpose of this code and of the - * mode FLAGS_NO_DECODING is debugging and capturing of datastreams from - * new, unknown cameras. This procedure will be automatically invoked - * instead of the specified callback handler when uvd->flags has bit - * FLAGS_NO_DECODING set. Therefore, any regular build of any driver - * based on usbvideo can use this feature at any time. - */ -static void usbvideo_CollectRawData(struct uvd *uvd, struct usbvideo_frame *frame) -{ - int n; - - assert(uvd != NULL); - assert(frame != NULL); - - /* Try to move data from queue into frame buffer */ - n = RingQueue_GetLength(&uvd->dp); - if (n > 0) { - int m; - /* See how much space we have left */ - m = uvd->max_frame_size - frame->seqRead_Length; - if (n > m) - n = m; - /* Now move that much data into frame buffer */ - RingQueue_Dequeue( - &uvd->dp, - frame->data + frame->seqRead_Length, - m); - frame->seqRead_Length += m; - } - /* See if we filled the frame */ - if (frame->seqRead_Length >= uvd->max_frame_size) { - frame->frameState = FrameState_Done; - uvd->curframe = -1; - uvd->stats.frame_num++; - } -} - -static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) -{ - struct usbvideo_frame *frame = &uvd->frame[frameNum]; - - if (uvd->debug >= 2) - dev_info(&uvd->dev->dev, "%s($%p,%d.)\n", __func__, uvd, - frameNum); - - switch (frame->frameState) { - case FrameState_Unused: - if (uvd->debug >= 2) - dev_info(&uvd->dev->dev, "%s: FrameState_Unused\n", - __func__); - return -EINVAL; - case FrameState_Ready: - case FrameState_Grabbing: - case FrameState_Error: - { - int ntries, signalPending; - redo: - if (!CAMERA_IS_OPERATIONAL(uvd)) { - if (uvd->debug >= 2) - dev_info(&uvd->dev->dev, - "%s: Camera is not operational (1)\n", - __func__); - return -EIO; - } - ntries = 0; - do { - RingQueue_InterruptibleSleepOn(&uvd->dp); - signalPending = signal_pending(current); - if (!CAMERA_IS_OPERATIONAL(uvd)) { - if (uvd->debug >= 2) - dev_info(&uvd->dev->dev, - "%s: Camera is not " - "operational (2)\n", __func__); - return -EIO; - } - assert(uvd->fbuf != NULL); - if (signalPending) { - if (uvd->debug >= 2) - dev_info(&uvd->dev->dev, - "%s: Signal=$%08x\n", __func__, - signalPending); - if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) { - usbvideo_TestPattern(uvd, 1, 0); - uvd->curframe = -1; - uvd->stats.frame_num++; - if (uvd->debug >= 2) - dev_info(&uvd->dev->dev, - "%s: Forced test " - "pattern screen\n", - __func__); - return 0; - } else { - /* Standard answer: Interrupted! */ - if (uvd->debug >= 2) - dev_info(&uvd->dev->dev, - "%s: Interrupted!\n", - __func__); - return -EINTR; - } - } else { - /* No signals - we just got new data in dp queue */ - if (uvd->flags & FLAGS_NO_DECODING) - usbvideo_CollectRawData(uvd, frame); - else if (VALID_CALLBACK(uvd, processData)) - GET_CALLBACK(uvd, processData)(uvd, frame); - else - err("%s: processData not set", __func__); - } - } while (frame->frameState == FrameState_Grabbing); - if (uvd->debug >= 2) { - dev_info(&uvd->dev->dev, - "%s: Grabbing done; state=%d. (%lu. bytes)\n", - __func__, frame->frameState, - frame->seqRead_Length); - } - if (frame->frameState == FrameState_Error) { - int ret = usbvideo_NewFrame(uvd, frameNum); - if (ret < 0) { - err("%s: usbvideo_NewFrame() failed (%d.)", __func__, ret); - return ret; - } - goto redo; - } - /* Note that we fall through to meet our destiny below */ - } - case FrameState_Done: - /* - * Do all necessary postprocessing of data prepared in - * "interrupt" code and the collecting code above. The - * frame gets marked as FrameState_Done by queue parsing code. - * This status means that we collected enough data and - * most likely processed it as we went through. However - * the data may need postprocessing, such as deinterlacing - * or picture adjustments implemented in software (horror!) - * - * As soon as the frame becomes "final" it gets promoted to - * FrameState_Done_Hold status where it will remain until the - * caller consumed all the video data from the frame. Then - * the empty shell of ex-frame is thrown out for dogs to eat. - * But we, worried about pets, will recycle the frame! - */ - uvd->stats.frame_num++; - if ((uvd->flags & FLAGS_NO_DECODING) == 0) { - if (VALID_CALLBACK(uvd, postProcess)) - GET_CALLBACK(uvd, postProcess)(uvd, frame); - if (frame->flags & USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST) - usbvideo_SoftwareContrastAdjustment(uvd, frame); - } - frame->frameState = FrameState_Done_Hold; - if (uvd->debug >= 2) - dev_info(&uvd->dev->dev, - "%s: Entered FrameState_Done_Hold state.\n", - __func__); - return 0; - - case FrameState_Done_Hold: - /* - * We stay in this state indefinitely until someone external, - * like ioctl() or read() call finishes digesting the frame - * data. Then it will mark the frame as FrameState_Unused and - * it will be released back into the wild to roam freely. - */ - if (uvd->debug >= 2) - dev_info(&uvd->dev->dev, - "%s: FrameState_Done_Hold state.\n", - __func__); - return 0; - } - - /* Catch-all for other cases. We shall not be here. */ - err("%s: Invalid state %d.", __func__, frame->frameState); - frame->frameState = FrameState_Unused; - return 0; -} - -/* - * usbvideo_DeinterlaceFrame() - * - * This procedure deinterlaces the given frame. Some cameras produce - * only half of scanlines - sometimes only even lines, sometimes only - * odd lines. The deinterlacing method is stored in frame->deinterlace - * variable. - * - * Here we scan the frame vertically and replace missing scanlines with - * average between surrounding ones - before and after. If we have no - * line above then we just copy next line. Similarly, if we need to - * create a last line then preceding line is used. - */ -void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame) -{ - if ((uvd == NULL) || (frame == NULL)) - return; - - if ((frame->deinterlace == Deinterlace_FillEvenLines) || - (frame->deinterlace == Deinterlace_FillOddLines)) - { - const int v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; - int i = (frame->deinterlace == Deinterlace_FillEvenLines) ? 0 : 1; - - for (; i < VIDEOSIZE_Y(frame->request); i += 2) { - const unsigned char *fs1, *fs2; - unsigned char *fd; - int ip, in, j; /* Previous and next lines */ - - /* - * Need to average lines before and after 'i'. - * If we go out of bounds seeking those lines then - * we point back to existing line. - */ - ip = i - 1; /* First, get rough numbers */ - in = i + 1; - - /* Now validate */ - if (ip < 0) - ip = in; - if (in >= VIDEOSIZE_Y(frame->request)) - in = ip; - - /* Sanity check */ - if ((ip < 0) || (in < 0) || - (ip >= VIDEOSIZE_Y(frame->request)) || - (in >= VIDEOSIZE_Y(frame->request))) - { - err("Error: ip=%d. in=%d. req.height=%ld.", - ip, in, VIDEOSIZE_Y(frame->request)); - break; - } - - /* Now we need to average lines 'ip' and 'in' to produce line 'i' */ - fs1 = frame->data + (v4l_linesize * ip); - fs2 = frame->data + (v4l_linesize * in); - fd = frame->data + (v4l_linesize * i); - - /* Average lines around destination */ - for (j=0; j < v4l_linesize; j++) { - fd[j] = (unsigned char)((((unsigned) fs1[j]) + - ((unsigned)fs2[j])) >> 1); - } - } - } - - /* Optionally display statistics on the screen */ - if (uvd->flags & FLAGS_OVERLAY_STATS) - usbvideo_OverlayStats(uvd, frame); -} - -EXPORT_SYMBOL(usbvideo_DeinterlaceFrame); - -/* - * usbvideo_SoftwareContrastAdjustment() - * - * This code adjusts the contrast of the frame, assuming RGB24 format. - * As most software image processing, this job is CPU-intensive. - * Get a camera that supports hardware adjustment! - * - * History: - * 09-Feb-2001 Created. - */ -static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd, - struct usbvideo_frame *frame) -{ - int i, j, v4l_linesize; - signed long adj; - const int ccm = 128; /* Color correction median - see below */ - - if ((uvd == NULL) || (frame == NULL)) { - err("%s: Illegal call.", __func__); - return; - } - adj = (uvd->vpic.contrast - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/ - RESTRICT_TO_RANGE(adj, -ccm, ccm+1); - if (adj == 0) { - /* In rare case of no adjustment */ - return; - } - v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; - for (i=0; i < VIDEOSIZE_Y(frame->request); i++) { - unsigned char *fd = frame->data + (v4l_linesize * i); - for (j=0; j < v4l_linesize; j++) { - signed long v = (signed long) fd[j]; - /* Magnify up to 2 times, reduce down to zero */ - v = 128 + ((ccm + adj) * (v - 128)) / ccm; - RESTRICT_TO_RANGE(v, 0, 0xFF); /* Must flatten tails */ - fd[j] = (unsigned char) v; - } - } -} - -MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/usbvideo/usbvideo.h b/drivers/media/video/usbvideo/usbvideo.h deleted file mode 100644 index c66985b..0000000 --- a/drivers/media/video/usbvideo/usbvideo.h +++ /dev/null @@ -1,395 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#ifndef usbvideo_h -#define usbvideo_h - -#include -#include -#include -#include -#include - -/* Most helpful debugging aid */ -#define assert(expr) ((void) ((expr) ? 0 : (err("assert failed at line %d",__LINE__)))) - -#define USBVIDEO_REPORT_STATS 1 /* Set to 0 to block statistics on close */ - -/* Bit flags (options) */ -#define FLAGS_RETRY_VIDIOCSYNC (1 << 0) -#define FLAGS_MONOCHROME (1 << 1) -#define FLAGS_DISPLAY_HINTS (1 << 2) -#define FLAGS_OVERLAY_STATS (1 << 3) -#define FLAGS_FORCE_TESTPATTERN (1 << 4) -#define FLAGS_SEPARATE_FRAMES (1 << 5) -#define FLAGS_CLEAN_FRAMES (1 << 6) -#define FLAGS_NO_DECODING (1 << 7) - -/* Bit flags for frames (apply to the frame where they are specified) */ -#define USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST (1 << 0) - -/* Camera capabilities (maximum) */ -#define CAMERA_URB_FRAMES 32 -#define CAMERA_MAX_ISO_PACKET 1023 /* 1022 actually sent by camera */ -#define FRAMES_PER_DESC (CAMERA_URB_FRAMES) -#define FRAME_SIZE_PER_DESC (CAMERA_MAX_ISO_PACKET) - -/* This macro restricts an int variable to an inclusive range */ -#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); } - -#define V4L_BYTES_PER_PIXEL 3 /* Because we produce RGB24 */ - -/* - * Use this macro to construct constants for different video sizes. - * We have to deal with different video sizes that have to be - * configured in the device or compared against when we receive - * a data. Normally one would define a bunch of VIDEOSIZE_x_by_y - * #defines and that's the end of story. However this solution - * does not allow to convert between real pixel sizes and the - * constant (integer) value that may be used to tag a frame or - * whatever. The set of macros below constructs videosize constants - * from the pixel size and allows to reconstruct the pixel size - * from the combined value later. - */ -#define VIDEOSIZE(x,y) (((x) & 0xFFFFL) | (((y) & 0xFFFFL) << 16)) -#define VIDEOSIZE_X(vs) ((vs) & 0xFFFFL) -#define VIDEOSIZE_Y(vs) (((vs) >> 16) & 0xFFFFL) -typedef unsigned long videosize_t; - -/* - * This macro checks if the camera is still operational. The 'uvd' - * pointer must be valid, uvd->dev must be valid, we are not - * removing the device and the device has not erred on us. - */ -#define CAMERA_IS_OPERATIONAL(uvd) (\ - (uvd != NULL) && \ - ((uvd)->dev != NULL) && \ - ((uvd)->last_error == 0) && \ - (!(uvd)->remove_pending)) - -/* - * We use macros to do YUV -> RGB conversion because this is - * very important for speed and totally unimportant for size. - * - * YUV -> RGB Conversion - * --------------------- - * - * B = 1.164*(Y-16) + 2.018*(V-128) - * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128) - * R = 1.164*(Y-16) + 1.596*(U-128) - * - * If you fancy integer arithmetics (as you should), hear this: - * - * 65536*B = 76284*(Y-16) + 132252*(V-128) - * 65536*G = 76284*(Y-16) - 53281*(U-128) - 25625*(V-128) - * 65536*R = 76284*(Y-16) + 104595*(U-128) - * - * Make sure the output values are within [0..255] range. - */ -#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x))) -#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \ - int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \ - mm_y = (my) - 16; \ - mm_u = (mu) - 128; \ - mm_v = (mv) - 128; \ - mm_yc= mm_y * 76284; \ - mm_b = (mm_yc + 132252*mm_v ) >> 16; \ - mm_g = (mm_yc - 53281*mm_u - 25625*mm_v ) >> 16; \ - mm_r = (mm_yc + 104595*mm_u ) >> 16; \ - mb = LIMIT_RGB(mm_b); \ - mg = LIMIT_RGB(mm_g); \ - mr = LIMIT_RGB(mm_r); \ -} - -#define RING_QUEUE_SIZE (128*1024) /* Must be a power of 2 */ -#define RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) & ((rq)->length-1) -#define RING_QUEUE_DEQUEUE_BYTES(rq,n) RING_QUEUE_ADVANCE_INDEX(rq,ri,n) -#define RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) & ((rq)->length-1)]) - -struct RingQueue { - unsigned char *queue; /* Data from the Isoc data pump */ - int length; /* How many bytes allocated for the queue */ - int wi; /* That's where we write */ - int ri; /* Read from here until you hit write index */ - wait_queue_head_t wqh; /* Processes waiting */ -}; - -enum ScanState { - ScanState_Scanning, /* Scanning for header */ - ScanState_Lines /* Parsing lines */ -}; - -/* Completion states of the data parser */ -enum ParseState { - scan_Continue, /* Just parse next item */ - scan_NextFrame, /* Frame done, send it to V4L */ - scan_Out, /* Not enough data for frame */ - scan_EndParse /* End parsing */ -}; - -enum FrameState { - FrameState_Unused, /* Unused (no MCAPTURE) */ - FrameState_Ready, /* Ready to start grabbing */ - FrameState_Grabbing, /* In the process of being grabbed into */ - FrameState_Done, /* Finished grabbing, but not been synced yet */ - FrameState_Done_Hold, /* Are syncing or reading */ - FrameState_Error, /* Something bad happened while processing */ -}; - -/* - * Some frames may contain only even or odd lines. This type - * specifies what type of deinterlacing is required. - */ -enum Deinterlace { - Deinterlace_None=0, - Deinterlace_FillOddLines, - Deinterlace_FillEvenLines -}; - -#define USBVIDEO_NUMFRAMES 2 /* How many frames we work with */ -#define USBVIDEO_NUMSBUF 2 /* How many URBs linked in a ring */ - -/* This structure represents one Isoc request - URB and buffer */ -struct usbvideo_sbuf { - char *data; - struct urb *urb; -}; - -struct usbvideo_frame { - char *data; /* Frame buffer */ - unsigned long header; /* Significant bits from the header */ - - videosize_t canvas; /* The canvas (max. image) allocated */ - videosize_t request; /* That's what the application asked for */ - unsigned short palette; /* The desired format */ - - enum FrameState frameState;/* State of grabbing */ - enum ScanState scanstate; /* State of scanning */ - enum Deinterlace deinterlace; - int flags; /* USBVIDEO_FRAME_FLAG_xxx bit flags */ - - int curline; /* Line of frame we're working on */ - - long seqRead_Length; /* Raw data length of frame */ - long seqRead_Index; /* Amount of data that has been already read */ - - void *user; /* Additional data that user may need */ -}; - -/* Statistics that can be overlaid on screen */ -struct usbvideo_statistics { - unsigned long frame_num; /* Sequential number of the frame */ - unsigned long urb_count; /* How many URBs we received so far */ - unsigned long urb_length; /* Length of last URB */ - unsigned long data_count; /* How many bytes we received */ - unsigned long header_count; /* How many frame headers we found */ - unsigned long iso_skip_count; /* How many empty ISO packets received */ - unsigned long iso_err_count; /* How many bad ISO packets received */ -}; - -struct usbvideo; - -struct uvd { - struct video_device vdev; /* Must be the first field! */ - struct usb_device *dev; - struct usbvideo *handle; /* Points back to the struct usbvideo */ - void *user_data; /* Camera-dependent data */ - int user_size; /* Size of that camera-dependent data */ - int debug; /* Debug level for usbvideo */ - unsigned char iface; /* Video interface number */ - unsigned char video_endp; - unsigned char ifaceAltActive; - unsigned char ifaceAltInactive; /* Alt settings */ - unsigned long flags; /* FLAGS_USBVIDEO_xxx */ - unsigned long paletteBits; /* Which palettes we accept? */ - unsigned short defaultPalette; /* What palette to use for read() */ - struct mutex lock; - int user; /* user count for exclusive use */ - - videosize_t videosize; /* Current setting */ - videosize_t canvas; /* This is the width,height of the V4L canvas */ - int max_frame_size; /* Bytes in one video frame */ - - int uvd_used; /* Is this structure in use? */ - int streaming; /* Are we streaming Isochronous? */ - int grabbing; /* Are we grabbing? */ - int settingsAdjusted; /* Have we adjusted contrast etc.? */ - int last_error; /* What calamity struck us? */ - - char *fbuf; /* Videodev buffer area */ - int fbuf_size; /* Videodev buffer size */ - - int curframe; - int iso_packet_len; /* Videomode-dependent, saves bus bandwidth */ - - struct RingQueue dp; /* Isoc data pump */ - struct usbvideo_frame frame[USBVIDEO_NUMFRAMES]; - struct usbvideo_sbuf sbuf[USBVIDEO_NUMSBUF]; - - volatile int remove_pending; /* If set then about to exit */ - - struct video_picture vpic, vpic_old; /* Picture settings */ - struct video_capability vcap; /* Video capabilities */ - struct video_channel vchan; /* May be used for tuner support */ - struct usbvideo_statistics stats; - char videoName[32]; /* Holds name like "video7" */ -}; - -/* - * usbvideo callbacks (virtual methods). They are set when usbvideo - * services are registered. All of these default to NULL, except those - * that default to usbvideo-provided methods. - */ -struct usbvideo_cb { - int (*probe)(struct usb_interface *, const struct usb_device_id *); - void (*userFree)(struct uvd *); - void (*disconnect)(struct usb_interface *); - int (*setupOnOpen)(struct uvd *); - void (*videoStart)(struct uvd *); - void (*videoStop)(struct uvd *); - void (*processData)(struct uvd *, struct usbvideo_frame *); - void (*postProcess)(struct uvd *, struct usbvideo_frame *); - void (*adjustPicture)(struct uvd *); - int (*getFPS)(struct uvd *); - int (*overlayHook)(struct uvd *, struct usbvideo_frame *); - int (*getFrame)(struct uvd *, int); - int (*startDataPump)(struct uvd *uvd); - void (*stopDataPump)(struct uvd *uvd); - int (*setVideoMode)(struct uvd *uvd, struct video_window *vw); -}; - -struct usbvideo { - int num_cameras; /* As allocated */ - struct usb_driver usbdrv; /* Interface to the USB stack */ - char drvName[80]; /* Driver name */ - struct mutex lock; /* Mutex protecting camera structures */ - struct usbvideo_cb cb; /* Table of callbacks (virtual methods) */ - struct video_device vdt; /* Video device template */ - struct uvd *cam; /* Array of camera structures */ - struct module *md_module; /* Minidriver module */ -}; - - -/* - * This macro retrieves callback address from the struct uvd object. - * No validity checks are done here, so be sure to check the - * callback beforehand with VALID_CALLBACK. - */ -#define GET_CALLBACK(uvd,cbName) ((uvd)->handle->cb.cbName) - -/* - * This macro returns either callback pointer or NULL. This is safe - * macro, meaning that most of components of data structures involved - * may be NULL - this only results in NULL being returned. You may - * wish to use this macro to make sure that the callback is callable. - * However keep in mind that those checks take time. - */ -#define VALID_CALLBACK(uvd,cbName) ((((uvd) != NULL) && \ - ((uvd)->handle != NULL)) ? GET_CALLBACK(uvd,cbName) : NULL) - -int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len); -int RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n); -void RingQueue_WakeUpInterruptible(struct RingQueue *rq); -void RingQueue_Flush(struct RingQueue *rq); - -static inline int RingQueue_GetLength(const struct RingQueue *rq) -{ - return (rq->wi - rq->ri + rq->length) & (rq->length-1); -} - -static inline int RingQueue_GetFreeSpace(const struct RingQueue *rq) -{ - return rq->length - RingQueue_GetLength(rq); -} - -void usbvideo_DrawLine( - struct usbvideo_frame *frame, - int x1, int y1, - int x2, int y2, - unsigned char cr, unsigned char cg, unsigned char cb); -void usbvideo_HexDump(const unsigned char *data, int len); -void usbvideo_SayAndWait(const char *what); -void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode); - -/* Memory allocation routines */ -unsigned long usbvideo_kvirt_to_pa(unsigned long adr); - -int usbvideo_register( - struct usbvideo **pCams, - const int num_cams, - const int num_extra, - const char *driverName, - const struct usbvideo_cb *cbTable, - struct module *md, - const struct usb_device_id *id_table); -struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams); -int usbvideo_RegisterVideoDevice(struct uvd *uvd); -void usbvideo_Deregister(struct usbvideo **uvt); - -int usbvideo_v4l_initialize(struct video_device *dev); - -void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame); - -/* - * This code performs bounds checking - use it when working with - * new formats, or else you may get oopses all over the place. - * If pixel falls out of bounds then it gets shoved back (as close - * to place of offence as possible) and is painted bright red. - * - * There are two important concepts: frame width, height and - * V4L canvas width, height. The former is the area requested by - * the application -for this very frame-. The latter is the largest - * possible frame that we can serve (we advertise that via V4L ioctl). - * The frame data is expected to be formatted as lines of length - * VIDEOSIZE_X(fr->request), total VIDEOSIZE_Y(frame->request) lines. - */ -static inline void RGB24_PUTPIXEL( - struct usbvideo_frame *fr, - int ix, int iy, - unsigned char vr, - unsigned char vg, - unsigned char vb) -{ - register unsigned char *pf; - int limiter = 0, mx, my; - mx = ix; - my = iy; - if (mx < 0) { - mx=0; - limiter++; - } else if (mx >= VIDEOSIZE_X((fr)->request)) { - mx= VIDEOSIZE_X((fr)->request) - 1; - limiter++; - } - if (my < 0) { - my = 0; - limiter++; - } else if (my >= VIDEOSIZE_Y((fr)->request)) { - my = VIDEOSIZE_Y((fr)->request) - 1; - limiter++; - } - pf = (fr)->data + V4L_BYTES_PER_PIXEL*((iy)*VIDEOSIZE_X((fr)->request) + (ix)); - if (limiter) { - *pf++ = 0; - *pf++ = 0; - *pf++ = 0xFF; - } else { - *pf++ = (vb); - *pf++ = (vg); - *pf++ = (vr); - } -} - -#endif /* usbvideo_h */ diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c deleted file mode 100644 index dc17cce..0000000 --- a/drivers/media/video/usbvideo/vicam.c +++ /dev/null @@ -1,952 +0,0 @@ -/* - * USB ViCam WebCam driver - * Copyright (c) 2002 Joe Burks (jburks@wavicle.org), - * Christopher L Cheney (ccheney@cheney.cx), - * Pavel Machek (pavel@ucw.cz), - * John Tyner (jtyner@cs.ucr.edu), - * Monroe Williams (monroe@pobox.com) - * - * Supports 3COM HomeConnect PC Digital WebCam - * Supports Compro PS39U WebCam - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This source code is based heavily on the CPiA webcam driver which was - * written by Peter Pregler, Scott J. Bertin and Johannes Erdfelt - * - * Portions of this code were also copied from usbvideo.c - * - * Special thanks to the whole team at Sourceforge for help making - * this driver become a reality. Notably: - * Andy Armstrong who reverse engineered the color encoding and - * Pavel Machek and Chris Cheney who worked on reverse engineering the - * camera controls and wrote the first generation driver. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "usbvideo.h" - -// #define VICAM_DEBUG - -#ifdef VICAM_DEBUG -#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __func__, lineno, ##args) -#define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args) -#else -#define DBG(fmn,args...) do {} while(0) -#endif - -#define DRIVER_AUTHOR "Joe Burks, jburks@wavicle.org" -#define DRIVER_DESC "ViCam WebCam Driver" - -/* Define these values to match your device */ -#define USB_VICAM_VENDOR_ID 0x04c1 -#define USB_VICAM_PRODUCT_ID 0x009d -#define USB_COMPRO_VENDOR_ID 0x0602 -#define USB_COMPRO_PRODUCT_ID 0x1001 - -#define VICAM_BYTES_PER_PIXEL 3 -#define VICAM_MAX_READ_SIZE (512*242+128) -#define VICAM_MAX_FRAME_SIZE (VICAM_BYTES_PER_PIXEL*320*240) -#define VICAM_FRAMES 2 - -#define VICAM_HEADER_SIZE 64 - -/* rvmalloc / rvfree copied from usbvideo.c - * - * Not sure why these are not yet non-statics which I can reference through - * usbvideo.h the same as it is in 2.4.20. I bet this will get fixed sometime - * in the future. - * -*/ -static void *rvmalloc(unsigned long size) -{ - void *mem; - unsigned long adr; - - size = PAGE_ALIGN(size); - mem = vmalloc_32(size); - if (!mem) - return NULL; - - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long) mem; - while (size > 0) { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - return mem; -} - -static void rvfree(void *mem, unsigned long size) -{ - unsigned long adr; - - if (!mem) - return; - - adr = (unsigned long) mem; - while ((long) size > 0) { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - vfree(mem); -} - -struct vicam_camera { - u16 shutter_speed; // capture shutter speed - u16 gain; // capture gain - - u8 *raw_image; // raw data captured from the camera - u8 *framebuf; // processed data in RGB24 format - u8 *cntrlbuf; // area used to send control msgs - - struct video_device vdev; // v4l video device - struct usb_device *udev; // usb device - - /* guard against simultaneous accesses to the camera */ - struct mutex cam_lock; - - int is_initialized; - u8 open_count; - u8 bulkEndpoint; - int needsDummyRead; -}; - -static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id); -static void vicam_disconnect(struct usb_interface *intf); -static void read_frame(struct vicam_camera *cam, int framenum); -static void vicam_decode_color(const u8 *, u8 *); - -static int __send_control_msg(struct vicam_camera *cam, - u8 request, - u16 value, - u16 index, - unsigned char *cp, - u16 size) -{ - int status; - - /* cp must be memory that has been allocated by kmalloc */ - - status = usb_control_msg(cam->udev, - usb_sndctrlpipe(cam->udev, 0), - request, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, value, index, - cp, size, 1000); - - status = min(status, 0); - - if (status < 0) { - printk(KERN_INFO "Failed sending control message, error %d.\n", - status); - } - - return status; -} - -static int send_control_msg(struct vicam_camera *cam, - u8 request, - u16 value, - u16 index, - unsigned char *cp, - u16 size) -{ - int status = -ENODEV; - mutex_lock(&cam->cam_lock); - if (cam->udev) { - status = __send_control_msg(cam, request, value, - index, cp, size); - } - mutex_unlock(&cam->cam_lock); - return status; -} -static int -initialize_camera(struct vicam_camera *cam) -{ - int err; - const struct ihex_binrec *rec; - const struct firmware *uninitialized_var(fw); - - err = request_ihex_firmware(&fw, "vicam/firmware.fw", &cam->udev->dev); - if (err) { - printk(KERN_ERR "Failed to load \"vicam/firmware.fw\": %d\n", - err); - return err; - } - - for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) { - memcpy(cam->cntrlbuf, rec->data, be16_to_cpu(rec->len)); - - err = send_control_msg(cam, 0xff, 0, 0, - cam->cntrlbuf, be16_to_cpu(rec->len)); - if (err) - break; - } - - release_firmware(fw); - - return err; -} - -static int -set_camera_power(struct vicam_camera *cam, int state) -{ - int status; - - if ((status = send_control_msg(cam, 0x50, state, 0, NULL, 0)) < 0) - return status; - - if (state) { - send_control_msg(cam, 0x55, 1, 0, NULL, 0); - } - - return 0; -} - -static long -vicam_ioctl(struct file *file, unsigned int ioctlnr, unsigned long arg) -{ - void __user *user_arg = (void __user *)arg; - struct vicam_camera *cam = file->private_data; - long retval = 0; - - if (!cam) - return -ENODEV; - - switch (ioctlnr) { - /* query capabilities */ - case VIDIOCGCAP: - { - struct video_capability b; - - DBG("VIDIOCGCAP\n"); - memset(&b, 0, sizeof(b)); - strcpy(b.name, "ViCam-based Camera"); - b.type = VID_TYPE_CAPTURE; - b.channels = 1; - b.audios = 0; - b.maxwidth = 320; /* VIDEOSIZE_CIF */ - b.maxheight = 240; - b.minwidth = 320; /* VIDEOSIZE_48_48 */ - b.minheight = 240; - - if (copy_to_user(user_arg, &b, sizeof(b))) - retval = -EFAULT; - - break; - } - /* get/set video source - we are a camera and nothing else */ - case VIDIOCGCHAN: - { - struct video_channel v; - - DBG("VIDIOCGCHAN\n"); - if (copy_from_user(&v, user_arg, sizeof(v))) { - retval = -EFAULT; - break; - } - if (v.channel != 0) { - retval = -EINVAL; - break; - } - - v.channel = 0; - strcpy(v.name, "Camera"); - v.tuners = 0; - v.flags = 0; - v.type = VIDEO_TYPE_CAMERA; - v.norm = 0; - - if (copy_to_user(user_arg, &v, sizeof(v))) - retval = -EFAULT; - break; - } - - case VIDIOCSCHAN: - { - int v; - - if (copy_from_user(&v, user_arg, sizeof(v))) - retval = -EFAULT; - DBG("VIDIOCSCHAN %d\n", v); - - if (retval == 0 && v != 0) - retval = -EINVAL; - - break; - } - - /* image properties */ - case VIDIOCGPICT: - { - struct video_picture vp; - DBG("VIDIOCGPICT\n"); - memset(&vp, 0, sizeof (struct video_picture)); - vp.brightness = cam->gain << 8; - vp.depth = 24; - vp.palette = VIDEO_PALETTE_RGB24; - if (copy_to_user(user_arg, &vp, sizeof (struct video_picture))) - retval = -EFAULT; - break; - } - - case VIDIOCSPICT: - { - struct video_picture vp; - - if (copy_from_user(&vp, user_arg, sizeof(vp))) { - retval = -EFAULT; - break; - } - - DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth, - vp.palette); - - cam->gain = vp.brightness >> 8; - - if (vp.depth != 24 - || vp.palette != VIDEO_PALETTE_RGB24) - retval = -EINVAL; - - break; - } - - /* get/set capture window */ - case VIDIOCGWIN: - { - struct video_window vw; - vw.x = 0; - vw.y = 0; - vw.width = 320; - vw.height = 240; - vw.chromakey = 0; - vw.flags = 0; - vw.clips = NULL; - vw.clipcount = 0; - - DBG("VIDIOCGWIN\n"); - - if (copy_to_user(user_arg, (void *)&vw, sizeof(vw))) - retval = -EFAULT; - - // I'm not sure what the deal with a capture window is, it is very poorly described - // in the doc. So I won't support it now. - break; - } - - case VIDIOCSWIN: - { - - struct video_window vw; - - if (copy_from_user(&vw, user_arg, sizeof(vw))) { - retval = -EFAULT; - break; - } - - DBG("VIDIOCSWIN %d x %d\n", vw.width, vw.height); - - if ( vw.width != 320 || vw.height != 240 ) - retval = -EFAULT; - - break; - } - - /* mmap interface */ - case VIDIOCGMBUF: - { - struct video_mbuf vm; - int i; - - DBG("VIDIOCGMBUF\n"); - memset(&vm, 0, sizeof (vm)); - vm.size = - VICAM_MAX_FRAME_SIZE * VICAM_FRAMES; - vm.frames = VICAM_FRAMES; - for (i = 0; i < VICAM_FRAMES; i++) - vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i; - - if (copy_to_user(user_arg, (void *)&vm, sizeof(vm))) - retval = -EFAULT; - - break; - } - - case VIDIOCMCAPTURE: - { - struct video_mmap vm; - // int video_size; - - if (copy_from_user((void *)&vm, user_arg, sizeof(vm))) { - retval = -EFAULT; - break; - } - - DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format); - - if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 ) - retval = -EINVAL; - - // in theory right here we'd start the image capturing - // (fill in a bulk urb and submit it asynchronously) - // - // Instead we're going to do a total hack job for now and - // retrieve the frame in VIDIOCSYNC - - break; - } - - case VIDIOCSYNC: - { - int frame; - - if (copy_from_user((void *)&frame, user_arg, sizeof(int))) { - retval = -EFAULT; - break; - } - DBG("VIDIOCSYNC: %d\n", frame); - - read_frame(cam, frame); - vicam_decode_color(cam->raw_image, - cam->framebuf + - frame * VICAM_MAX_FRAME_SIZE ); - - break; - } - - /* pointless to implement overlay with this camera */ - case VIDIOCCAPTURE: - case VIDIOCGFBUF: - case VIDIOCSFBUF: - case VIDIOCKEY: - retval = -EINVAL; - break; - - /* tuner interface - we have none */ - case VIDIOCGTUNER: - case VIDIOCSTUNER: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - retval = -EINVAL; - break; - - /* audio interface - we have none */ - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - retval = -EINVAL; - break; - default: - retval = -ENOIOCTLCMD; - break; - } - - return retval; -} - -static int -vicam_open(struct file *file) -{ - struct vicam_camera *cam = video_drvdata(file); - - DBG("open\n"); - - if (!cam) { - printk(KERN_ERR - "vicam video_device improperly initialized"); - return -EINVAL; - } - - /* cam_lock/open_count protects us from simultaneous opens - * ... for now. we probably shouldn't rely on this fact forever. - */ - - mutex_lock(&cam->cam_lock); - if (cam->open_count > 0) { - printk(KERN_INFO - "vicam_open called on already opened camera"); - mutex_unlock(&cam->cam_lock); - return -EBUSY; - } - - cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL); - if (!cam->raw_image) { - mutex_unlock(&cam->cam_lock); - return -ENOMEM; - } - - cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); - if (!cam->framebuf) { - kfree(cam->raw_image); - mutex_unlock(&cam->cam_lock); - return -ENOMEM; - } - - cam->cntrlbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!cam->cntrlbuf) { - kfree(cam->raw_image); - rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); - mutex_unlock(&cam->cam_lock); - return -ENOMEM; - } - - cam->needsDummyRead = 1; - cam->open_count++; - - file->private_data = cam; - mutex_unlock(&cam->cam_lock); - - - // First upload firmware, then turn the camera on - - if (!cam->is_initialized) { - initialize_camera(cam); - - cam->is_initialized = 1; - } - - set_camera_power(cam, 1); - - return 0; -} - -static int -vicam_close(struct file *file) -{ - struct vicam_camera *cam = file->private_data; - int open_count; - struct usb_device *udev; - - DBG("close\n"); - - /* it's not the end of the world if - * we fail to turn the camera off. - */ - - set_camera_power(cam, 0); - - kfree(cam->raw_image); - rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); - kfree(cam->cntrlbuf); - - mutex_lock(&cam->cam_lock); - - cam->open_count--; - open_count = cam->open_count; - udev = cam->udev; - - mutex_unlock(&cam->cam_lock); - - if (!open_count && !udev) { - kfree(cam); - } - - return 0; -} - -static void vicam_decode_color(const u8 *data, u8 *rgb) -{ - /* vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB - * Copyright (C) 2002 Monroe Williams (monroe@pobox.com) - */ - - int i, prevY, nextY; - - prevY = 512; - nextY = 512; - - data += VICAM_HEADER_SIZE; - - for( i = 0; i < 240; i++, data += 512 ) { - const int y = ( i * 242 ) / 240; - - int j, prevX, nextX; - int Y, Cr, Cb; - - if ( y == 242 - 1 ) { - nextY = -512; - } - - prevX = 1; - nextX = 1; - - for ( j = 0; j < 320; j++, rgb += 3 ) { - const int x = ( j * 512 ) / 320; - const u8 * const src = &data[x]; - - if ( x == 512 - 1 ) { - nextX = -1; - } - - Cr = ( src[prevX] - src[0] ) + - ( src[nextX] - src[0] ); - Cr /= 2; - - Cb = ( src[prevY] - src[prevX + prevY] ) + - ( src[prevY] - src[nextX + prevY] ) + - ( src[nextY] - src[prevX + nextY] ) + - ( src[nextY] - src[nextX + nextY] ); - Cb /= 4; - - Y = 1160 * ( src[0] + ( Cr / 2 ) - 16 ); - - if ( i & 1 ) { - int Ct = Cr; - Cr = Cb; - Cb = Ct; - } - - if ( ( x ^ i ) & 1 ) { - Cr = -Cr; - Cb = -Cb; - } - - rgb[0] = clamp( ( ( Y + ( 2017 * Cb ) ) + - 500 ) / 900, 0, 255 ); - rgb[1] = clamp( ( ( Y - ( 392 * Cb ) - - ( 813 * Cr ) ) + - 500 ) / 1000, 0, 255 ); - rgb[2] = clamp( ( ( Y + ( 1594 * Cr ) ) + - 500 ) / 1300, 0, 255 ); - - prevX = -1; - } - - prevY = -512; - } -} - -static void -read_frame(struct vicam_camera *cam, int framenum) -{ - unsigned char *request = cam->cntrlbuf; - int realShutter; - int n; - int actual_length; - - if (cam->needsDummyRead) { - cam->needsDummyRead = 0; - read_frame(cam, framenum); - } - - memset(request, 0, 16); - request[0] = cam->gain; // 0 = 0% gain, FF = 100% gain - - request[1] = 0; // 512x242 capture - - request[2] = 0x90; // the function of these two bytes - request[3] = 0x07; // is not yet understood - - if (cam->shutter_speed > 60) { - // Short exposure - realShutter = - ((-15631900 / cam->shutter_speed) + 260533) / 1000; - request[4] = realShutter & 0xFF; - request[5] = (realShutter >> 8) & 0xFF; - request[6] = 0x03; - request[7] = 0x01; - } else { - // Long exposure - realShutter = 15600 / cam->shutter_speed - 1; - request[4] = 0; - request[5] = 0; - request[6] = realShutter & 0xFF; - request[7] = realShutter >> 8; - } - - // Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0 - request[8] = 0; - // bytes 9-15 do not seem to affect exposure or image quality - - mutex_lock(&cam->cam_lock); - - if (!cam->udev) { - goto done; - } - - n = __send_control_msg(cam, 0x51, 0x80, 0, request, 16); - - if (n < 0) { - printk(KERN_ERR - " Problem sending frame capture control message"); - goto done; - } - - n = usb_bulk_msg(cam->udev, - usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint), - cam->raw_image, - 512 * 242 + 128, &actual_length, 10000); - - if (n < 0) { - printk(KERN_ERR "Problem during bulk read of frame data: %d\n", - n); - } - - done: - mutex_unlock(&cam->cam_lock); -} - -static ssize_t -vicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos ) -{ - struct vicam_camera *cam = file->private_data; - - DBG("read %d bytes.\n", (int) count); - - if (*ppos >= VICAM_MAX_FRAME_SIZE) { - *ppos = 0; - return 0; - } - - if (*ppos == 0) { - read_frame(cam, 0); - vicam_decode_color(cam->raw_image, - cam->framebuf + - 0 * VICAM_MAX_FRAME_SIZE); - } - - count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos); - - if (copy_to_user(buf, &cam->framebuf[*ppos], count)) { - count = -EFAULT; - } else { - *ppos += count; - } - - if (count == VICAM_MAX_FRAME_SIZE) { - *ppos = 0; - } - - return count; -} - - -static int -vicam_mmap(struct file *file, struct vm_area_struct *vma) -{ - // TODO: allocate the raw frame buffer if necessary - unsigned long page, pos; - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end-vma->vm_start; - struct vicam_camera *cam = file->private_data; - - if (!cam) - return -ENODEV; - - DBG("vicam_mmap: %ld\n", size); - - /* We let mmap allocate as much as it wants because Linux was adding 2048 bytes - * to the size the application requested for mmap and it was screwing apps up. - if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE) - return -EINVAL; - */ - - pos = (unsigned long)cam->framebuf; - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) - return -EAGAIN; - - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - - return 0; -} - -static const struct v4l2_file_operations vicam_fops = { - .owner = THIS_MODULE, - .open = vicam_open, - .release = vicam_close, - .read = vicam_read, - .mmap = vicam_mmap, - .ioctl = vicam_ioctl, -}; - -static struct video_device vicam_template = { - .name = "ViCam-based USB Camera", - .fops = &vicam_fops, - .release = video_device_release_empty, -}; - -/* table of devices that work with this driver */ -static struct usb_device_id vicam_table[] = { - {USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)}, - {USB_DEVICE(USB_COMPRO_VENDOR_ID, USB_COMPRO_PRODUCT_ID)}, - {} /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, vicam_table); - -static struct usb_driver vicam_driver = { - .name = "vicam", - .probe = vicam_probe, - .disconnect = vicam_disconnect, - .id_table = vicam_table -}; - -/** - * vicam_probe - * @intf: the interface - * @id: the device id - * - * Called by the usb core when a new device is connected that it thinks - * this driver might be interested in. - */ -static int -vicam_probe( struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - int bulkEndpoint = 0; - const struct usb_host_interface *interface; - const struct usb_endpoint_descriptor *endpoint; - struct vicam_camera *cam; - - printk(KERN_INFO "ViCam based webcam connected\n"); - - interface = intf->cur_altsetting; - - DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n", - interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints)); - endpoint = &interface->endpoint[0].desc; - - if (usb_endpoint_is_bulk_in(endpoint)) { - /* we found a bulk in endpoint */ - bulkEndpoint = endpoint->bEndpointAddress; - } else { - printk(KERN_ERR - "No bulk in endpoint was found ?! (this is bad)\n"); - } - - if ((cam = - kzalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) { - printk(KERN_WARNING - "could not allocate kernel memory for vicam_camera struct\n"); - return -ENOMEM; - } - - - cam->shutter_speed = 15; - - mutex_init(&cam->cam_lock); - - memcpy(&cam->vdev, &vicam_template, sizeof(vicam_template)); - video_set_drvdata(&cam->vdev, cam); - - cam->udev = dev; - cam->bulkEndpoint = bulkEndpoint; - - if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) < 0) { - kfree(cam); - printk(KERN_WARNING "video_register_device failed\n"); - return -EIO; - } - - printk(KERN_INFO "ViCam webcam driver now controlling device %s\n", - video_device_node_name(&cam->vdev)); - - usb_set_intfdata (intf, cam); - - return 0; -} - -static void -vicam_disconnect(struct usb_interface *intf) -{ - int open_count; - struct vicam_camera *cam = usb_get_intfdata (intf); - usb_set_intfdata (intf, NULL); - - /* we must unregister the device before taking its - * cam_lock. This is because the video open call - * holds the same lock as video unregister. if we - * unregister inside of the cam_lock and open also - * uses the cam_lock, we get deadlock. - */ - - video_unregister_device(&cam->vdev); - - /* stop the camera from being used */ - - mutex_lock(&cam->cam_lock); - - /* mark the camera as gone */ - - cam->udev = NULL; - - /* the only thing left to do is synchronize with - * our close/release function on who should release - * the camera memory. if there are any users using the - * camera, it's their job. if there are no users, - * it's ours. - */ - - open_count = cam->open_count; - - mutex_unlock(&cam->cam_lock); - - if (!open_count) { - kfree(cam); - } - - printk(KERN_DEBUG "ViCam-based WebCam disconnected\n"); -} - -/* - */ -static int __init -usb_vicam_init(void) -{ - int retval; - DBG(KERN_INFO "ViCam-based WebCam driver startup\n"); - retval = usb_register(&vicam_driver); - if (retval) - printk(KERN_WARNING "usb_register failed!\n"); - return retval; -} - -static void __exit -usb_vicam_exit(void) -{ - DBG(KERN_INFO - "ViCam-based WebCam driver shutdown\n"); - - usb_deregister(&vicam_driver); -} - -module_init(usb_vicam_init); -module_exit(usb_vicam_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE("vicam/firmware.fw"); diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 5eafdf4..a402a56 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -55,6 +55,8 @@ source "drivers/staging/cpia/Kconfig" source "drivers/staging/stradis/Kconfig" +source "drivers/staging/usbvideo/Kconfig" + source "drivers/staging/usbip/Kconfig" source "drivers/staging/winbond/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index a97a955..d4eb714 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_VIDEO_CX25821) += cx25821/ obj-$(CONFIG_VIDEO_TM6000) += tm6000/ obj-$(CONFIG_VIDEO_CPIA) += cpia/ obj-$(CONFIG_VIDEO_STRADIS) += stradis/ +obj-$(CONFIG_USB_VICAM) += usbvideo/ obj-$(CONFIG_LIRC_STAGING) += lirc/ obj-$(CONFIG_USB_IP_COMMON) += usbip/ obj-$(CONFIG_W35UND) += winbond/ diff --git a/drivers/staging/usbvideo/Kconfig b/drivers/staging/usbvideo/Kconfig new file mode 100644 index 0000000..aae863e --- /dev/null +++ b/drivers/staging/usbvideo/Kconfig @@ -0,0 +1,15 @@ +config VIDEO_USBVIDEO + tristate + +config USB_VICAM + tristate "USB 3com HomeConnect (aka vicam) support (DEPRECATED)" + depends on VIDEO_V4L1 && EXPERIMENTAL + select VIDEO_USBVIDEO + ---help--- + Say Y here if you have 3com homeconnect camera (vicam). + + This driver uses the deprecated V4L1 API and will be removed in + 2.6.39, unless someone converts it to the V4L2 API. + + To compile this driver as a module, choose M here: the + module will be called vicam. diff --git a/drivers/staging/usbvideo/Makefile b/drivers/staging/usbvideo/Makefile new file mode 100644 index 0000000..3c99a9a --- /dev/null +++ b/drivers/staging/usbvideo/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_VIDEO_USBVIDEO) += usbvideo.o +obj-$(CONFIG_USB_VICAM) += vicam.o diff --git a/drivers/staging/usbvideo/usbvideo.c b/drivers/staging/usbvideo/usbvideo.c new file mode 100644 index 0000000..f1fcf97 --- /dev/null +++ b/drivers/staging/usbvideo/usbvideo.c @@ -0,0 +1,2230 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "usbvideo.h" + +#if defined(MAP_NR) +#define virt_to_page(v) MAP_NR(v) /* Kernels 2.2.x */ +#endif + +static int video_nr = -1; +module_param(video_nr, int, 0); + +/* + * Local prototypes. + */ +static void usbvideo_Disconnect(struct usb_interface *intf); +static void usbvideo_CameraRelease(struct uvd *uvd); + +static long usbvideo_v4l_ioctl(struct file *file, + unsigned int cmd, unsigned long arg); +static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma); +static int usbvideo_v4l_open(struct file *file); +static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos); +static int usbvideo_v4l_close(struct file *file); + +static int usbvideo_StartDataPump(struct uvd *uvd); +static void usbvideo_StopDataPump(struct uvd *uvd); +static int usbvideo_GetFrame(struct uvd *uvd, int frameNum); +static int usbvideo_NewFrame(struct uvd *uvd, int framenum); +static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd, + struct usbvideo_frame *frame); + +/*******************************/ +/* Memory management functions */ +/*******************************/ +static void *usbvideo_rvmalloc(unsigned long size) +{ + void *mem; + unsigned long adr; + + size = PAGE_ALIGN(size); + mem = vmalloc_32(size); + if (!mem) + return NULL; + + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr = (unsigned long) mem; + while (size > 0) { + SetPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + return mem; +} + +static void usbvideo_rvfree(void *mem, unsigned long size) +{ + unsigned long adr; + + if (!mem) + return; + + adr = (unsigned long) mem; + while ((long) size > 0) { + ClearPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + vfree(mem); +} + +static void RingQueue_Initialize(struct RingQueue *rq) +{ + assert(rq != NULL); + init_waitqueue_head(&rq->wqh); +} + +static void RingQueue_Allocate(struct RingQueue *rq, int rqLen) +{ + /* Make sure the requested size is a power of 2 and + round up if necessary. This allows index wrapping + using masks rather than modulo */ + + int i = 1; + assert(rq != NULL); + assert(rqLen > 0); + + while(rqLen >> i) + i++; + if(rqLen != 1 << (i-1)) + rqLen = 1 << i; + + rq->length = rqLen; + rq->ri = rq->wi = 0; + rq->queue = usbvideo_rvmalloc(rq->length); + assert(rq->queue != NULL); +} + +static int RingQueue_IsAllocated(const struct RingQueue *rq) +{ + if (rq == NULL) + return 0; + return (rq->queue != NULL) && (rq->length > 0); +} + +static void RingQueue_Free(struct RingQueue *rq) +{ + assert(rq != NULL); + if (RingQueue_IsAllocated(rq)) { + usbvideo_rvfree(rq->queue, rq->length); + rq->queue = NULL; + rq->length = 0; + } +} + +int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len) +{ + int rql, toread; + + assert(rq != NULL); + assert(dst != NULL); + + rql = RingQueue_GetLength(rq); + if(!rql) + return 0; + + /* Clip requested length to available data */ + if(len > rql) + len = rql; + + toread = len; + if(rq->ri > rq->wi) { + /* Read data from tail */ + int read = (toread < (rq->length - rq->ri)) ? toread : rq->length - rq->ri; + memcpy(dst, rq->queue + rq->ri, read); + toread -= read; + dst += read; + rq->ri = (rq->ri + read) & (rq->length-1); + } + if(toread) { + /* Read data from head */ + memcpy(dst, rq->queue + rq->ri, toread); + rq->ri = (rq->ri + toread) & (rq->length-1); + } + return len; +} + +EXPORT_SYMBOL(RingQueue_Dequeue); + +int RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n) +{ + int enqueued = 0; + + assert(rq != NULL); + assert(cdata != NULL); + assert(rq->length > 0); + while (n > 0) { + int m, q_avail; + + /* Calculate the largest chunk that fits the tail of the ring */ + q_avail = rq->length - rq->wi; + if (q_avail <= 0) { + rq->wi = 0; + q_avail = rq->length; + } + m = n; + assert(q_avail > 0); + if (m > q_avail) + m = q_avail; + + memcpy(rq->queue + rq->wi, cdata, m); + RING_QUEUE_ADVANCE_INDEX(rq, wi, m); + cdata += m; + enqueued += m; + n -= m; + } + return enqueued; +} + +EXPORT_SYMBOL(RingQueue_Enqueue); + +static void RingQueue_InterruptibleSleepOn(struct RingQueue *rq) +{ + assert(rq != NULL); + interruptible_sleep_on(&rq->wqh); +} + +void RingQueue_WakeUpInterruptible(struct RingQueue *rq) +{ + assert(rq != NULL); + if (waitqueue_active(&rq->wqh)) + wake_up_interruptible(&rq->wqh); +} + +EXPORT_SYMBOL(RingQueue_WakeUpInterruptible); + +void RingQueue_Flush(struct RingQueue *rq) +{ + assert(rq != NULL); + rq->ri = 0; + rq->wi = 0; +} + +EXPORT_SYMBOL(RingQueue_Flush); + + +/* + * usbvideo_VideosizeToString() + * + * This procedure converts given videosize value to readable string. + * + * History: + * 07-Aug-2000 Created. + * 19-Oct-2000 Reworked for usbvideo module. + */ +static void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs) +{ + char tmp[40]; + int n; + + n = 1 + sprintf(tmp, "%ldx%ld", VIDEOSIZE_X(vs), VIDEOSIZE_Y(vs)); + assert(n < sizeof(tmp)); + if ((buf == NULL) || (bufLen < n)) + err("usbvideo_VideosizeToString: buffer is too small."); + else + memmove(buf, tmp, n); +} + +/* + * usbvideo_OverlayChar() + * + * History: + * 01-Feb-2000 Created. + */ +static void usbvideo_OverlayChar(struct uvd *uvd, struct usbvideo_frame *frame, + int x, int y, int ch) +{ + static const unsigned short digits[16] = { + 0xF6DE, /* 0 */ + 0x2492, /* 1 */ + 0xE7CE, /* 2 */ + 0xE79E, /* 3 */ + 0xB792, /* 4 */ + 0xF39E, /* 5 */ + 0xF3DE, /* 6 */ + 0xF492, /* 7 */ + 0xF7DE, /* 8 */ + 0xF79E, /* 9 */ + 0x77DA, /* a */ + 0xD75C, /* b */ + 0xF24E, /* c */ + 0xD6DC, /* d */ + 0xF34E, /* e */ + 0xF348 /* f */ + }; + unsigned short digit; + int ix, iy; + int value; + + if ((uvd == NULL) || (frame == NULL)) + return; + + value = hex_to_bin(ch); + if (value < 0) + return; + digit = digits[value]; + + for (iy=0; iy < 5; iy++) { + for (ix=0; ix < 3; ix++) { + if (digit & 0x8000) { + if (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24)) { +/* TODO */ RGB24_PUTPIXEL(frame, x+ix, y+iy, 0xFF, 0xFF, 0xFF); + } + } + digit = digit << 1; + } + } +} + +/* + * usbvideo_OverlayString() + * + * History: + * 01-Feb-2000 Created. + */ +static void usbvideo_OverlayString(struct uvd *uvd, struct usbvideo_frame *frame, + int x, int y, const char *str) +{ + while (*str) { + usbvideo_OverlayChar(uvd, frame, x, y, *str); + str++; + x += 4; /* 3 pixels character + 1 space */ + } +} + +/* + * usbvideo_OverlayStats() + * + * Overlays important debugging information. + * + * History: + * 01-Feb-2000 Created. + */ +static void usbvideo_OverlayStats(struct uvd *uvd, struct usbvideo_frame *frame) +{ + const int y_diff = 8; + char tmp[16]; + int x = 10, y=10; + long i, j, barLength; + const int qi_x1 = 60, qi_y1 = 10; + const int qi_x2 = VIDEOSIZE_X(frame->request) - 10, qi_h = 10; + + /* Call the user callback, see if we may proceed after that */ + if (VALID_CALLBACK(uvd, overlayHook)) { + if (GET_CALLBACK(uvd, overlayHook)(uvd, frame) < 0) + return; + } + + /* + * We draw a (mostly) hollow rectangle with qi_xxx coordinates. + * Left edge symbolizes the queue index 0; right edge symbolizes + * the full capacity of the queue. + */ + barLength = qi_x2 - qi_x1 - 2; + if ((barLength > 10) && (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24))) { +/* TODO */ long u_lo, u_hi, q_used; + long m_ri, m_wi, m_lo, m_hi; + + /* + * Determine fill zones (used areas of the queue): + * 0 xxxxxxx u_lo ...... uvd->dp.ri xxxxxxxx u_hi ..... uvd->dp.length + * + * if u_lo < 0 then there is no first filler. + */ + + q_used = RingQueue_GetLength(&uvd->dp); + if ((uvd->dp.ri + q_used) >= uvd->dp.length) { + u_hi = uvd->dp.length; + u_lo = (q_used + uvd->dp.ri) & (uvd->dp.length-1); + } else { + u_hi = (q_used + uvd->dp.ri); + u_lo = -1; + } + + /* Convert byte indices into screen units */ + m_ri = qi_x1 + ((barLength * uvd->dp.ri) / uvd->dp.length); + m_wi = qi_x1 + ((barLength * uvd->dp.wi) / uvd->dp.length); + m_lo = (u_lo > 0) ? (qi_x1 + ((barLength * u_lo) / uvd->dp.length)) : -1; + m_hi = qi_x1 + ((barLength * u_hi) / uvd->dp.length); + + for (j=qi_y1; j < (qi_y1 + qi_h); j++) { + for (i=qi_x1; i < qi_x2; i++) { + /* Draw border lines */ + if ((j == qi_y1) || (j == (qi_y1 + qi_h - 1)) || + (i == qi_x1) || (i == (qi_x2 - 1))) { + RGB24_PUTPIXEL(frame, i, j, 0xFF, 0xFF, 0xFF); + continue; + } + /* For all other points the Y coordinate does not matter */ + if ((i >= m_ri) && (i <= (m_ri + 3))) { + RGB24_PUTPIXEL(frame, i, j, 0x00, 0xFF, 0x00); + } else if ((i >= m_wi) && (i <= (m_wi + 3))) { + RGB24_PUTPIXEL(frame, i, j, 0xFF, 0x00, 0x00); + } else if ((i < m_lo) || ((i > m_ri) && (i < m_hi))) + RGB24_PUTPIXEL(frame, i, j, 0x00, 0x00, 0xFF); + } + } + } + + sprintf(tmp, "%8lx", uvd->stats.frame_num); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", uvd->stats.urb_count); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", uvd->stats.urb_length); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", uvd->stats.data_count); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", uvd->stats.header_count); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", uvd->stats.iso_skip_count); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", uvd->stats.iso_err_count); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8x", uvd->vpic.colour); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8x", uvd->vpic.hue); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8x", uvd->vpic.brightness >> 8); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8x", uvd->vpic.contrast >> 12); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8d", uvd->vpic.whiteness >> 8); + usbvideo_OverlayString(uvd, frame, x, y, tmp); + y += y_diff; +} + +/* + * usbvideo_ReportStatistics() + * + * This procedure prints packet and transfer statistics. + * + * History: + * 14-Jan-2000 Corrected default multiplier. + */ +static void usbvideo_ReportStatistics(const struct uvd *uvd) +{ + if ((uvd != NULL) && (uvd->stats.urb_count > 0)) { + unsigned long allPackets, badPackets, goodPackets, percent; + allPackets = uvd->stats.urb_count * CAMERA_URB_FRAMES; + badPackets = uvd->stats.iso_skip_count + uvd->stats.iso_err_count; + goodPackets = allPackets - badPackets; + /* Calculate percentage wisely, remember integer limits */ + assert(allPackets != 0); + if (goodPackets < (((unsigned long)-1)/100)) + percent = (100 * goodPackets) / allPackets; + else + percent = goodPackets / (allPackets / 100); + dev_info(&uvd->dev->dev, + "Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%\n", + allPackets, badPackets, percent); + if (uvd->iso_packet_len > 0) { + unsigned long allBytes, xferBytes; + char multiplier = ' '; + allBytes = allPackets * uvd->iso_packet_len; + xferBytes = uvd->stats.data_count; + assert(allBytes != 0); + if (xferBytes < (((unsigned long)-1)/100)) + percent = (100 * xferBytes) / allBytes; + else + percent = xferBytes / (allBytes / 100); + /* Scale xferBytes for easy reading */ + if (xferBytes > 10*1024) { + xferBytes /= 1024; + multiplier = 'K'; + if (xferBytes > 10*1024) { + xferBytes /= 1024; + multiplier = 'M'; + if (xferBytes > 10*1024) { + xferBytes /= 1024; + multiplier = 'G'; + if (xferBytes > 10*1024) { + xferBytes /= 1024; + multiplier = 'T'; + } + } + } + } + dev_info(&uvd->dev->dev, + "Transfer Statistics: Transferred=%lu%cB Usage=%lu%%\n", + xferBytes, multiplier, percent); + } + } +} + +/* + * usbvideo_TestPattern() + * + * Procedure forms a test pattern (yellow grid on blue background). + * + * Parameters: + * fullframe: if TRUE then entire frame is filled, otherwise the procedure + * continues from the current scanline. + * pmode 0: fill the frame with solid blue color (like on VCR or TV) + * 1: Draw a colored grid + * + * History: + * 01-Feb-2000 Created. + */ +void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode) +{ + struct usbvideo_frame *frame; + int num_cell = 0; + int scan_length = 0; + static int num_pass; + + if (uvd == NULL) { + err("%s: uvd == NULL", __func__); + return; + } + if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) { + err("%s: uvd->curframe=%d.", __func__, uvd->curframe); + return; + } + + /* Grab the current frame */ + frame = &uvd->frame[uvd->curframe]; + + /* Optionally start at the beginning */ + if (fullframe) { + frame->curline = 0; + frame->seqRead_Length = 0; + } +#if 0 + { /* For debugging purposes only */ + char tmp[20]; + usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request); + dev_info(&uvd->dev->dev, "testpattern: frame=%s\n", tmp); + } +#endif + /* Form every scan line */ + for (; frame->curline < VIDEOSIZE_Y(frame->request); frame->curline++) { + int i; + unsigned char *f = frame->data + + (VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL * frame->curline); + for (i=0; i < VIDEOSIZE_X(frame->request); i++) { + unsigned char cb=0x80; + unsigned char cg = 0; + unsigned char cr = 0; + + if (pmode == 1) { + if (frame->curline % 32 == 0) + cb = 0, cg = cr = 0xFF; + else if (i % 32 == 0) { + if (frame->curline % 32 == 1) + num_cell++; + cb = 0, cg = cr = 0xFF; + } else { + cb = ((num_cell*7) + num_pass) & 0xFF; + cg = ((num_cell*5) + num_pass*2) & 0xFF; + cr = ((num_cell*3) + num_pass*3) & 0xFF; + } + } else { + /* Just the blue screen */ + } + + *f++ = cb; + *f++ = cg; + *f++ = cr; + scan_length += 3; + } + } + + frame->frameState = FrameState_Done; + frame->seqRead_Length += scan_length; + ++num_pass; + + /* We do this unconditionally, regardless of FLAGS_OVERLAY_STATS */ + usbvideo_OverlayStats(uvd, frame); +} + +EXPORT_SYMBOL(usbvideo_TestPattern); + + +#ifdef DEBUG +/* + * usbvideo_HexDump() + * + * A debugging tool. Prints hex dumps. + * + * History: + * 29-Jul-2000 Added printing of offsets. + */ +void usbvideo_HexDump(const unsigned char *data, int len) +{ + const int bytes_per_line = 32; + char tmp[128]; /* 32*3 + 5 */ + int i, k; + + for (i=k=0; len > 0; i++, len--) { + if (i > 0 && ((i % bytes_per_line) == 0)) { + printk("%s\n", tmp); + k=0; + } + if ((i % bytes_per_line) == 0) + k += sprintf(&tmp[k], "%04x: ", i); + k += sprintf(&tmp[k], "%02x ", data[i]); + } + if (k > 0) + printk("%s\n", tmp); +} + +EXPORT_SYMBOL(usbvideo_HexDump); + +#endif + +/* ******************************************************************** */ + +/* XXX: this piece of crap really wants some error handling.. */ +static int usbvideo_ClientIncModCount(struct uvd *uvd) +{ + if (uvd == NULL) { + err("%s: uvd == NULL", __func__); + return -EINVAL; + } + if (uvd->handle == NULL) { + err("%s: uvd->handle == NULL", __func__); + return -EINVAL; + } + if (!try_module_get(uvd->handle->md_module)) { + err("%s: try_module_get() == 0", __func__); + return -ENODEV; + } + return 0; +} + +static void usbvideo_ClientDecModCount(struct uvd *uvd) +{ + if (uvd == NULL) { + err("%s: uvd == NULL", __func__); + return; + } + if (uvd->handle == NULL) { + err("%s: uvd->handle == NULL", __func__); + return; + } + if (uvd->handle->md_module == NULL) { + err("%s: uvd->handle->md_module == NULL", __func__); + return; + } + module_put(uvd->handle->md_module); +} + +int usbvideo_register( + struct usbvideo **pCams, + const int num_cams, + const int num_extra, + const char *driverName, + const struct usbvideo_cb *cbTbl, + struct module *md, + const struct usb_device_id *id_table) +{ + struct usbvideo *cams; + int i, base_size, result; + + /* Check parameters for sanity */ + if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) { + err("%s: Illegal call", __func__); + return -EINVAL; + } + + /* Check registration callback - must be set! */ + if (cbTbl->probe == NULL) { + err("%s: probe() is required!", __func__); + return -EINVAL; + } + + base_size = num_cams * sizeof(struct uvd) + sizeof(struct usbvideo); + cams = kzalloc(base_size, GFP_KERNEL); + if (cams == NULL) { + err("Failed to allocate %d. bytes for usbvideo struct", base_size); + return -ENOMEM; + } + dbg("%s: Allocated $%p (%d. bytes) for %d. cameras", + __func__, cams, base_size, num_cams); + + /* Copy callbacks, apply defaults for those that are not set */ + memmove(&cams->cb, cbTbl, sizeof(cams->cb)); + if (cams->cb.getFrame == NULL) + cams->cb.getFrame = usbvideo_GetFrame; + if (cams->cb.disconnect == NULL) + cams->cb.disconnect = usbvideo_Disconnect; + if (cams->cb.startDataPump == NULL) + cams->cb.startDataPump = usbvideo_StartDataPump; + if (cams->cb.stopDataPump == NULL) + cams->cb.stopDataPump = usbvideo_StopDataPump; + + cams->num_cameras = num_cams; + cams->cam = (struct uvd *) &cams[1]; + cams->md_module = md; + mutex_init(&cams->lock); /* to 1 == available */ + + for (i = 0; i < num_cams; i++) { + struct uvd *up = &cams->cam[i]; + + up->handle = cams; + + /* Allocate user_data separately because of kmalloc's limits */ + if (num_extra > 0) { + up->user_size = num_cams * num_extra; + up->user_data = kmalloc(up->user_size, GFP_KERNEL); + if (up->user_data == NULL) { + err("%s: Failed to allocate user_data (%d. bytes)", + __func__, up->user_size); + while (i) { + up = &cams->cam[--i]; + kfree(up->user_data); + } + kfree(cams); + return -ENOMEM; + } + dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)", + __func__, i, up->user_data, up->user_size); + } + } + + /* + * Register ourselves with USB stack. + */ + strcpy(cams->drvName, (driverName != NULL) ? driverName : "Unknown"); + cams->usbdrv.name = cams->drvName; + cams->usbdrv.probe = cams->cb.probe; + cams->usbdrv.disconnect = cams->cb.disconnect; + cams->usbdrv.id_table = id_table; + + /* + * Update global handle to usbvideo. This is very important + * because probe() can be called before usb_register() returns. + * If the handle is not yet updated then the probe() will fail. + */ + *pCams = cams; + result = usb_register(&cams->usbdrv); + if (result) { + for (i = 0; i < num_cams; i++) { + struct uvd *up = &cams->cam[i]; + kfree(up->user_data); + } + kfree(cams); + } + + return result; +} + +EXPORT_SYMBOL(usbvideo_register); + +/* + * usbvideo_Deregister() + * + * Procedure frees all usbvideo and user data structures. Be warned that + * if you had some dynamically allocated components in ->user field then + * you should free them before calling here. + */ +void usbvideo_Deregister(struct usbvideo **pCams) +{ + struct usbvideo *cams; + int i; + + if (pCams == NULL) { + err("%s: pCams == NULL", __func__); + return; + } + cams = *pCams; + if (cams == NULL) { + err("%s: cams == NULL", __func__); + return; + } + + dbg("%s: Deregistering %s driver.", __func__, cams->drvName); + usb_deregister(&cams->usbdrv); + + dbg("%s: Deallocating cams=$%p (%d. cameras)", __func__, cams, cams->num_cameras); + for (i=0; i < cams->num_cameras; i++) { + struct uvd *up = &cams->cam[i]; + int warning = 0; + + if (up->user_data != NULL) { + if (up->user_size <= 0) + ++warning; + } else { + if (up->user_size > 0) + ++warning; + } + if (warning) { + err("%s: Warning: user_data=$%p user_size=%d.", + __func__, up->user_data, up->user_size); + } else { + dbg("%s: Freeing %d. $%p->user_data=$%p", + __func__, i, up, up->user_data); + kfree(up->user_data); + } + } + /* Whole array was allocated in one chunk */ + dbg("%s: Freed %d uvd structures", + __func__, cams->num_cameras); + kfree(cams); + *pCams = NULL; +} + +EXPORT_SYMBOL(usbvideo_Deregister); + +/* + * usbvideo_Disconnect() + * + * This procedure stops all driver activity. Deallocation of + * the interface-private structure (pointed by 'ptr') is done now + * (if we don't have any open files) or later, when those files + * are closed. After that driver should be removable. + * + * This code handles surprise removal. The uvd->user is a counter which + * increments on open() and decrements on close(). If we see here that + * this counter is not 0 then we have a client who still has us opened. + * We set uvd->remove_pending flag as early as possible, and after that + * all access to the camera will gracefully fail. These failures should + * prompt client to (eventually) close the video device, and then - in + * usbvideo_v4l_close() - we decrement uvd->uvd_used and usage counter. + * + * History: + * 22-Jan-2000 Added polling of MOD_IN_USE to delay removal until all users gone. + * 27-Jan-2000 Reworked to allow pending disconnects; see xxx_close() + * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). + * 19-Oct-2000 Moved to usbvideo module. + */ +static void usbvideo_Disconnect(struct usb_interface *intf) +{ + struct uvd *uvd = usb_get_intfdata (intf); + int i; + + if (uvd == NULL) { + err("%s($%p): Illegal call.", __func__, intf); + return; + } + + usb_set_intfdata (intf, NULL); + + usbvideo_ClientIncModCount(uvd); + if (uvd->debug > 0) + dev_info(&intf->dev, "%s(%p.)\n", __func__, intf); + + mutex_lock(&uvd->lock); + uvd->remove_pending = 1; /* Now all ISO data will be ignored */ + + /* At this time we ask to cancel outstanding URBs */ + GET_CALLBACK(uvd, stopDataPump)(uvd); + + for (i=0; i < USBVIDEO_NUMSBUF; i++) + usb_free_urb(uvd->sbuf[i].urb); + + usb_put_dev(uvd->dev); + uvd->dev = NULL; /* USB device is no more */ + + video_unregister_device(&uvd->vdev); + if (uvd->debug > 0) + dev_info(&intf->dev, "%s: Video unregistered.\n", __func__); + + if (uvd->user) + dev_info(&intf->dev, "%s: In use, disconnect pending.\n", + __func__); + else + usbvideo_CameraRelease(uvd); + mutex_unlock(&uvd->lock); + dev_info(&intf->dev, "USB camera disconnected.\n"); + + usbvideo_ClientDecModCount(uvd); +} + +/* + * usbvideo_CameraRelease() + * + * This code does final release of uvd. This happens + * after the device is disconnected -and- all clients + * closed their files. + * + * History: + * 27-Jan-2000 Created. + */ +static void usbvideo_CameraRelease(struct uvd *uvd) +{ + if (uvd == NULL) { + err("%s: Illegal call", __func__); + return; + } + + RingQueue_Free(&uvd->dp); + if (VALID_CALLBACK(uvd, userFree)) + GET_CALLBACK(uvd, userFree)(uvd); + uvd->uvd_used = 0; /* This is atomic, no need to take mutex */ +} + +/* + * usbvideo_find_struct() + * + * This code searches the array of preallocated (static) structures + * and returns index of the first one that isn't in use. Returns -1 + * if there are no free structures. + * + * History: + * 27-Jan-2000 Created. + */ +static int usbvideo_find_struct(struct usbvideo *cams) +{ + int u, rv = -1; + + if (cams == NULL) { + err("No usbvideo handle?"); + return -1; + } + mutex_lock(&cams->lock); + for (u = 0; u < cams->num_cameras; u++) { + struct uvd *uvd = &cams->cam[u]; + if (!uvd->uvd_used) /* This one is free */ + { + uvd->uvd_used = 1; /* In use now */ + mutex_init(&uvd->lock); /* to 1 == available */ + uvd->dev = NULL; + rv = u; + break; + } + } + mutex_unlock(&cams->lock); + return rv; +} + +static const struct v4l2_file_operations usbvideo_fops = { + .owner = THIS_MODULE, + .open = usbvideo_v4l_open, + .release =usbvideo_v4l_close, + .read = usbvideo_v4l_read, + .mmap = usbvideo_v4l_mmap, + .ioctl = usbvideo_v4l_ioctl, +}; +static const struct video_device usbvideo_template = { + .fops = &usbvideo_fops, +}; + +struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams) +{ + int i, devnum; + struct uvd *uvd = NULL; + + if (cams == NULL) { + err("No usbvideo handle?"); + return NULL; + } + + devnum = usbvideo_find_struct(cams); + if (devnum == -1) { + err("IBM USB camera driver: Too many devices!"); + return NULL; + } + uvd = &cams->cam[devnum]; + dbg("Device entry #%d. at $%p", devnum, uvd); + + /* Not relying upon caller we increase module counter ourselves */ + usbvideo_ClientIncModCount(uvd); + + mutex_lock(&uvd->lock); + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + uvd->sbuf[i].urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); + if (uvd->sbuf[i].urb == NULL) { + err("usb_alloc_urb(%d.) failed.", FRAMES_PER_DESC); + uvd->uvd_used = 0; + uvd = NULL; + goto allocate_done; + } + } + uvd->user=0; + uvd->remove_pending = 0; + uvd->last_error = 0; + RingQueue_Initialize(&uvd->dp); + + /* Initialize video device structure */ + uvd->vdev = usbvideo_template; + sprintf(uvd->vdev.name, "%.20s USB Camera", cams->drvName); + /* + * The client is free to overwrite those because we + * return control to the client's probe function right now. + */ +allocate_done: + mutex_unlock(&uvd->lock); + usbvideo_ClientDecModCount(uvd); + return uvd; +} + +EXPORT_SYMBOL(usbvideo_AllocateDevice); + +int usbvideo_RegisterVideoDevice(struct uvd *uvd) +{ + char tmp1[20], tmp2[20]; /* Buffers for printing */ + + if (uvd == NULL) { + err("%s: Illegal call.", __func__); + return -EINVAL; + } + if (uvd->video_endp == 0) { + dev_info(&uvd->dev->dev, + "%s: No video endpoint specified; data pump disabled.\n", + __func__); + } + if (uvd->paletteBits == 0) { + err("%s: No palettes specified!", __func__); + return -EINVAL; + } + if (uvd->defaultPalette == 0) { + dev_info(&uvd->dev->dev, "%s: No default palette!\n", + __func__); + } + + uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) * + VIDEOSIZE_Y(uvd->canvas) * V4L_BYTES_PER_PIXEL; + usbvideo_VideosizeToString(tmp1, sizeof(tmp1), uvd->videosize); + usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas); + + if (uvd->debug > 0) { + dev_info(&uvd->dev->dev, + "%s: iface=%d. endpoint=$%02x paletteBits=$%08lx\n", + __func__, uvd->iface, uvd->video_endp, + uvd->paletteBits); + } + if (uvd->dev == NULL) { + err("%s: uvd->dev == NULL", __func__); + return -EINVAL; + } + uvd->vdev.parent = &uvd->dev->dev; + uvd->vdev.release = video_device_release_empty; + if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { + err("%s: video_register_device failed", __func__); + return -EPIPE; + } + if (uvd->debug > 1) { + dev_info(&uvd->dev->dev, + "%s: video_register_device() successful\n", __func__); + } + + dev_info(&uvd->dev->dev, "%s on %s: canvas=%s videosize=%s\n", + (uvd->handle != NULL) ? uvd->handle->drvName : "???", + video_device_node_name(&uvd->vdev), tmp2, tmp1); + + usb_get_dev(uvd->dev); + return 0; +} + +EXPORT_SYMBOL(usbvideo_RegisterVideoDevice); + +/* ******************************************************************** */ + +static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct uvd *uvd = file->private_data; + unsigned long start = vma->vm_start; + unsigned long size = vma->vm_end-vma->vm_start; + unsigned long page, pos; + + if (!CAMERA_IS_OPERATIONAL(uvd)) + return -EFAULT; + + if (size > (((USBVIDEO_NUMFRAMES * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) + return -EINVAL; + + pos = (unsigned long) uvd->fbuf; + while (size > 0) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) + return -EAGAIN; + + start += PAGE_SIZE; + pos += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + + return 0; +} + +/* + * usbvideo_v4l_open() + * + * This is part of Video 4 Linux API. The driver can be opened by one + * client only (checks internal counter 'uvdser'). The procedure + * then allocates buffers needed for video processing. + * + * History: + * 22-Jan-2000 Rewrote, moved scratch buffer allocation here. Now the + * camera is also initialized here (once per connect), at + * expense of V4L client (it waits on open() call). + * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. + * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). + */ +static int usbvideo_v4l_open(struct file *file) +{ + struct video_device *dev = video_devdata(file); + struct uvd *uvd = (struct uvd *) dev; + const int sb_size = FRAMES_PER_DESC * uvd->iso_packet_len; + int i, errCode = 0; + + if (uvd->debug > 1) + dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev); + + if (usbvideo_ClientIncModCount(uvd) < 0) + return -ENODEV; + mutex_lock(&uvd->lock); + + if (uvd->user) { + err("%s: Someone tried to open an already opened device!", __func__); + errCode = -EBUSY; + } else { + /* Clear statistics */ + memset(&uvd->stats, 0, sizeof(uvd->stats)); + + /* Clean pointers so we know if we allocated something */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) + uvd->sbuf[i].data = NULL; + + /* Allocate memory for the frame buffers */ + uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size; + uvd->fbuf = usbvideo_rvmalloc(uvd->fbuf_size); + RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE); + if ((uvd->fbuf == NULL) || + (!RingQueue_IsAllocated(&uvd->dp))) { + err("%s: Failed to allocate fbuf or dp", __func__); + errCode = -ENOMEM; + } else { + /* Allocate all buffers */ + for (i=0; i < USBVIDEO_NUMFRAMES; i++) { + uvd->frame[i].frameState = FrameState_Unused; + uvd->frame[i].data = uvd->fbuf + i*(uvd->max_frame_size); + /* + * Set default sizes in case IOCTL (VIDIOCMCAPTURE) + * is not used (using read() instead). + */ + uvd->frame[i].canvas = uvd->canvas; + uvd->frame[i].seqRead_Index = 0; + } + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + uvd->sbuf[i].data = kmalloc(sb_size, GFP_KERNEL); + if (uvd->sbuf[i].data == NULL) { + errCode = -ENOMEM; + break; + } + } + } + if (errCode != 0) { + /* Have to free all that memory */ + if (uvd->fbuf != NULL) { + usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size); + uvd->fbuf = NULL; + } + RingQueue_Free(&uvd->dp); + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + kfree(uvd->sbuf[i].data); + uvd->sbuf[i].data = NULL; + } + } + } + + /* If so far no errors then we shall start the camera */ + if (errCode == 0) { + /* Start data pump if we have valid endpoint */ + if (uvd->video_endp != 0) + errCode = GET_CALLBACK(uvd, startDataPump)(uvd); + if (errCode == 0) { + if (VALID_CALLBACK(uvd, setupOnOpen)) { + if (uvd->debug > 1) + dev_info(&uvd->dev->dev, + "%s: setupOnOpen callback\n", + __func__); + errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd); + if (errCode < 0) { + err("%s: setupOnOpen callback failed (%d.).", + __func__, errCode); + } else if (uvd->debug > 1) { + dev_info(&uvd->dev->dev, + "%s: setupOnOpen callback successful\n", + __func__); + } + } + if (errCode == 0) { + uvd->settingsAdjusted = 0; + if (uvd->debug > 1) + dev_info(&uvd->dev->dev, + "%s: Open succeeded.\n", + __func__); + uvd->user++; + file->private_data = uvd; + } + } + } + mutex_unlock(&uvd->lock); + if (errCode != 0) + usbvideo_ClientDecModCount(uvd); + if (uvd->debug > 0) + dev_info(&uvd->dev->dev, "%s: Returning %d.\n", __func__, + errCode); + return errCode; +} + +/* + * usbvideo_v4l_close() + * + * This is part of Video 4 Linux API. The procedure + * stops streaming and deallocates all buffers that were earlier + * allocated in usbvideo_v4l_open(). + * + * History: + * 22-Jan-2000 Moved scratch buffer deallocation here. + * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. + * 24-May-2000 Moved MOD_DEC_USE_COUNT outside of code that can sleep. + */ +static int usbvideo_v4l_close(struct file *file) +{ + struct video_device *dev = file->private_data; + struct uvd *uvd = (struct uvd *) dev; + int i; + + if (uvd->debug > 1) + dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev); + + mutex_lock(&uvd->lock); + GET_CALLBACK(uvd, stopDataPump)(uvd); + usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size); + uvd->fbuf = NULL; + RingQueue_Free(&uvd->dp); + + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + kfree(uvd->sbuf[i].data); + uvd->sbuf[i].data = NULL; + } + +#if USBVIDEO_REPORT_STATS + usbvideo_ReportStatistics(uvd); +#endif + + uvd->user--; + if (uvd->remove_pending) { + if (uvd->debug > 0) + dev_info(&uvd->dev->dev, "%s: Final disconnect.\n", + __func__); + usbvideo_CameraRelease(uvd); + } + mutex_unlock(&uvd->lock); + usbvideo_ClientDecModCount(uvd); + + if (uvd->debug > 1) + dev_info(&uvd->dev->dev, "%s: Completed.\n", __func__); + file->private_data = NULL; + return 0; +} + +/* + * usbvideo_v4l_ioctl() + * + * This is part of Video 4 Linux API. The procedure handles ioctl() calls. + * + * History: + * 22-Jan-2000 Corrected VIDIOCSPICT to reject unsupported settings. + */ +static long usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg) +{ + struct uvd *uvd = file->private_data; + + if (!CAMERA_IS_OPERATIONAL(uvd)) + return -EIO; + + switch (cmd) { + case VIDIOCGCAP: + { + struct video_capability *b = arg; + *b = uvd->vcap; + return 0; + } + case VIDIOCGCHAN: + { + struct video_channel *v = arg; + *v = uvd->vchan; + return 0; + } + case VIDIOCSCHAN: + { + struct video_channel *v = arg; + if (v->channel != 0) + return -EINVAL; + return 0; + } + case VIDIOCGPICT: + { + struct video_picture *pic = arg; + *pic = uvd->vpic; + return 0; + } + case VIDIOCSPICT: + { + struct video_picture *pic = arg; + /* + * Use temporary 'video_picture' structure to preserve our + * own settings (such as color depth, palette) that we + * aren't allowing everyone (V4L client) to change. + */ + uvd->vpic.brightness = pic->brightness; + uvd->vpic.hue = pic->hue; + uvd->vpic.colour = pic->colour; + uvd->vpic.contrast = pic->contrast; + uvd->settingsAdjusted = 0; /* Will force new settings */ + return 0; + } + case VIDIOCSWIN: + { + struct video_window *vw = arg; + + if(VALID_CALLBACK(uvd, setVideoMode)) { + return GET_CALLBACK(uvd, setVideoMode)(uvd, vw); + } + + if (vw->flags) + return -EINVAL; + if (vw->clipcount) + return -EINVAL; + if (vw->width != VIDEOSIZE_X(uvd->canvas)) + return -EINVAL; + if (vw->height != VIDEOSIZE_Y(uvd->canvas)) + return -EINVAL; + + return 0; + } + case VIDIOCGWIN: + { + struct video_window *vw = arg; + + vw->x = 0; + vw->y = 0; + vw->width = VIDEOSIZE_X(uvd->videosize); + vw->height = VIDEOSIZE_Y(uvd->videosize); + vw->chromakey = 0; + if (VALID_CALLBACK(uvd, getFPS)) + vw->flags = GET_CALLBACK(uvd, getFPS)(uvd); + else + vw->flags = 10; /* FIXME: do better! */ + return 0; + } + case VIDIOCGMBUF: + { + struct video_mbuf *vm = arg; + int i; + + memset(vm, 0, sizeof(*vm)); + vm->size = uvd->max_frame_size * USBVIDEO_NUMFRAMES; + vm->frames = USBVIDEO_NUMFRAMES; + for(i = 0; i < USBVIDEO_NUMFRAMES; i++) + vm->offsets[i] = i * uvd->max_frame_size; + + return 0; + } + case VIDIOCMCAPTURE: + { + struct video_mmap *vm = arg; + + if (uvd->debug >= 1) { + dev_info(&uvd->dev->dev, + "VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.\n", + vm->frame, vm->width, vm->height, vm->format); + } + /* + * Check if the requested size is supported. If the requestor + * requests too big a frame then we may be tricked into accessing + * outside of own preallocated frame buffer (in uvd->frame). + * This will cause oops or a security hole. Theoretically, we + * could only clamp the size down to acceptable bounds, but then + * we'd need to figure out how to insert our smaller buffer into + * larger caller's buffer... this is not an easy question. So we + * here just flatly reject too large requests, assuming that the + * caller will resubmit with smaller size. Callers should know + * what size we support (returned by VIDIOCGCAP). However vidcat, + * for one, does not care and allows to ask for any size. + */ + if ((vm->width > VIDEOSIZE_X(uvd->canvas)) || + (vm->height > VIDEOSIZE_Y(uvd->canvas))) { + if (uvd->debug > 0) { + dev_info(&uvd->dev->dev, + "VIDIOCMCAPTURE: Size=%dx%d " + "too large; allowed only up " + "to %ldx%ld\n", vm->width, + vm->height, + VIDEOSIZE_X(uvd->canvas), + VIDEOSIZE_Y(uvd->canvas)); + } + return -EINVAL; + } + /* Check if the palette is supported */ + if (((1L << vm->format) & uvd->paletteBits) == 0) { + if (uvd->debug > 0) { + dev_info(&uvd->dev->dev, + "VIDIOCMCAPTURE: format=%d. " + "not supported " + "(paletteBits=$%08lx)\n", + vm->format, uvd->paletteBits); + } + return -EINVAL; + } + if ((vm->frame < 0) || (vm->frame >= USBVIDEO_NUMFRAMES)) { + err("VIDIOCMCAPTURE: vm.frame=%d. !E [0-%d]", vm->frame, USBVIDEO_NUMFRAMES-1); + return -EINVAL; + } + if (uvd->frame[vm->frame].frameState == FrameState_Grabbing) { + /* Not an error - can happen */ + } + uvd->frame[vm->frame].request = VIDEOSIZE(vm->width, vm->height); + uvd->frame[vm->frame].palette = vm->format; + + /* Mark it as ready */ + uvd->frame[vm->frame].frameState = FrameState_Ready; + + return usbvideo_NewFrame(uvd, vm->frame); + } + case VIDIOCSYNC: + { + int *frameNum = arg; + int ret; + + if (*frameNum < 0 || *frameNum >= USBVIDEO_NUMFRAMES) + return -EINVAL; + + if (uvd->debug >= 1) + dev_info(&uvd->dev->dev, + "VIDIOCSYNC: syncing to frame %d.\n", + *frameNum); + if (uvd->flags & FLAGS_NO_DECODING) + ret = usbvideo_GetFrame(uvd, *frameNum); + else if (VALID_CALLBACK(uvd, getFrame)) { + ret = GET_CALLBACK(uvd, getFrame)(uvd, *frameNum); + if ((ret < 0) && (uvd->debug >= 1)) { + err("VIDIOCSYNC: getFrame() returned %d.", ret); + } + } else { + err("VIDIOCSYNC: getFrame is not set"); + ret = -EFAULT; + } + + /* + * The frame is in FrameState_Done_Hold state. Release it + * right now because its data is already mapped into + * the user space and it's up to the application to + * make use of it until it asks for another frame. + */ + uvd->frame[*frameNum].frameState = FrameState_Unused; + return ret; + } + case VIDIOCGFBUF: + { + struct video_buffer *vb = arg; + + memset(vb, 0, sizeof(*vb)); + return 0; + } + case VIDIOCKEY: + return 0; + + case VIDIOCCAPTURE: + return -EINVAL; + + case VIDIOCSFBUF: + + case VIDIOCGTUNER: + case VIDIOCSTUNER: + + case VIDIOCGFREQ: + case VIDIOCSFREQ: + + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + return -EINVAL; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static long usbvideo_v4l_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + return video_usercopy(file, cmd, arg, usbvideo_v4l_do_ioctl); +} + +/* + * usbvideo_v4l_read() + * + * This is mostly boring stuff. We simply ask for a frame and when it + * arrives copy all the video data from it into user space. There is + * no obvious need to override this method. + * + * History: + * 20-Oct-2000 Created. + * 01-Nov-2000 Added mutex (uvd->lock). + */ +static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct uvd *uvd = file->private_data; + int noblock = file->f_flags & O_NONBLOCK; + int frmx = -1, i; + struct usbvideo_frame *frame; + + if (!CAMERA_IS_OPERATIONAL(uvd) || (buf == NULL)) + return -EFAULT; + + if (uvd->debug >= 1) + dev_info(&uvd->dev->dev, + "%s: %Zd. bytes, noblock=%d.\n", + __func__, count, noblock); + + mutex_lock(&uvd->lock); + + /* See if a frame is completed, then use it. */ + for(i = 0; i < USBVIDEO_NUMFRAMES; i++) { + if ((uvd->frame[i].frameState == FrameState_Done) || + (uvd->frame[i].frameState == FrameState_Done_Hold) || + (uvd->frame[i].frameState == FrameState_Error)) { + frmx = i; + break; + } + } + + /* FIXME: If we don't start a frame here then who ever does? */ + if (noblock && (frmx == -1)) { + count = -EAGAIN; + goto read_done; + } + + /* + * If no FrameState_Done, look for a FrameState_Grabbing state. + * See if a frame is in process (grabbing), then use it. + * We will need to wait until it becomes cooked, of course. + */ + if (frmx == -1) { + for(i = 0; i < USBVIDEO_NUMFRAMES; i++) { + if (uvd->frame[i].frameState == FrameState_Grabbing) { + frmx = i; + break; + } + } + } + + /* + * If no frame is active, start one. We don't care which one + * it will be, so #0 is as good as any. + * In read access mode we don't have convenience of VIDIOCMCAPTURE + * to specify the requested palette (video format) on per-frame + * basis. This means that we have to return data in -some- format + * and just hope that the client knows what to do with it. + * The default format is configured in uvd->defaultPalette field + * as one of VIDEO_PALETTE_xxx values. We stuff it into the new + * frame and initiate the frame filling process. + */ + if (frmx == -1) { + if (uvd->defaultPalette == 0) { + err("%s: No default palette; don't know what to do!", __func__); + count = -EFAULT; + goto read_done; + } + frmx = 0; + /* + * We have no per-frame control over video size. + * Therefore we only can use whatever size was + * specified as default. + */ + uvd->frame[frmx].request = uvd->videosize; + uvd->frame[frmx].palette = uvd->defaultPalette; + uvd->frame[frmx].frameState = FrameState_Ready; + usbvideo_NewFrame(uvd, frmx); + /* Now frame 0 is supposed to start filling... */ + } + + /* + * Get a pointer to the active frame. It is either previously + * completed frame or frame in progress but not completed yet. + */ + frame = &uvd->frame[frmx]; + + /* + * Sit back & wait until the frame gets filled and postprocessed. + * If we fail to get the picture [in time] then return the error. + * In this call we specify that we want the frame to be waited for, + * postprocessed and switched into FrameState_Done_Hold state. This + * state is used to hold the frame as "fully completed" between + * subsequent partial reads of the same frame. + */ + if (frame->frameState != FrameState_Done_Hold) { + long rv = -EFAULT; + if (uvd->flags & FLAGS_NO_DECODING) + rv = usbvideo_GetFrame(uvd, frmx); + else if (VALID_CALLBACK(uvd, getFrame)) + rv = GET_CALLBACK(uvd, getFrame)(uvd, frmx); + else + err("getFrame is not set"); + if ((rv != 0) || (frame->frameState != FrameState_Done_Hold)) { + count = rv; + goto read_done; + } + } + + /* + * Copy bytes to user space. We allow for partial reads, which + * means that the user application can request read less than + * the full frame size. It is up to the application to issue + * subsequent calls until entire frame is read. + * + * First things first, make sure we don't copy more than we + * have - even if the application wants more. That would be + * a big security embarassment! + */ + if ((count + frame->seqRead_Index) > frame->seqRead_Length) + count = frame->seqRead_Length - frame->seqRead_Index; + + /* + * Copy requested amount of data to user space. We start + * copying from the position where we last left it, which + * will be zero for a new frame (not read before). + */ + if (copy_to_user(buf, frame->data + frame->seqRead_Index, count)) { + count = -EFAULT; + goto read_done; + } + + /* Update last read position */ + frame->seqRead_Index += count; + if (uvd->debug >= 1) { + err("%s: {copy} count used=%Zd, new seqRead_Index=%ld", + __func__, count, frame->seqRead_Index); + } + + /* Finally check if the frame is done with and "release" it */ + if (frame->seqRead_Index >= frame->seqRead_Length) { + /* All data has been read */ + frame->seqRead_Index = 0; + + /* Mark it as available to be used again. */ + uvd->frame[frmx].frameState = FrameState_Unused; + if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) { + err("%s: usbvideo_NewFrame failed.", __func__); + } + } +read_done: + mutex_unlock(&uvd->lock); + return count; +} + +/* + * Make all of the blocks of data contiguous + */ +static int usbvideo_CompressIsochronous(struct uvd *uvd, struct urb *urb) +{ + char *cdata; + int i, totlen = 0; + + for (i = 0; i < urb->number_of_packets; i++) { + int n = urb->iso_frame_desc[i].actual_length; + int st = urb->iso_frame_desc[i].status; + + cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset; + + /* Detect and ignore errored packets */ + if (st < 0) { + if (uvd->debug >= 1) + err("Data error: packet=%d. len=%d. status=%d.", i, n, st); + uvd->stats.iso_err_count++; + continue; + } + + /* Detect and ignore empty packets */ + if (n <= 0) { + uvd->stats.iso_skip_count++; + continue; + } + totlen += n; /* Little local accounting */ + RingQueue_Enqueue(&uvd->dp, cdata, n); + } + return totlen; +} + +static void usbvideo_IsocIrq(struct urb *urb) +{ + int i, ret, len; + struct uvd *uvd = urb->context; + + /* We don't want to do anything if we are about to be removed! */ + if (!CAMERA_IS_OPERATIONAL(uvd)) + return; +#if 0 + if (urb->actual_length > 0) { + dev_info(&uvd->dev->dev, + "urb=$%p status=%d. errcount=%d. length=%d.\n", + urb, urb->status, urb->error_count, + urb->actual_length); + } else { + static int c = 0; + if (c++ % 100 == 0) + dev_info(&uvd->dev->dev, "No Isoc data\n"); + } +#endif + + if (!uvd->streaming) { + if (uvd->debug >= 1) + dev_info(&uvd->dev->dev, + "Not streaming, but interrupt!\n"); + return; + } + + uvd->stats.urb_count++; + if (urb->actual_length <= 0) + goto urb_done_with; + + /* Copy the data received into ring queue */ + len = usbvideo_CompressIsochronous(uvd, urb); + uvd->stats.urb_length = len; + if (len <= 0) + goto urb_done_with; + + /* Here we got some data */ + uvd->stats.data_count += len; + RingQueue_WakeUpInterruptible(&uvd->dp); + +urb_done_with: + for (i = 0; i < FRAMES_PER_DESC; i++) { + urb->iso_frame_desc[i].status = 0; + urb->iso_frame_desc[i].actual_length = 0; + } + urb->status = 0; + urb->dev = uvd->dev; + ret = usb_submit_urb (urb, GFP_KERNEL); + if(ret) + err("usb_submit_urb error (%d)", ret); + return; +} + +/* + * usbvideo_StartDataPump() + * + * History: + * 27-Jan-2000 Used ibmcam->iface, ibmcam->ifaceAltActive instead + * of hardcoded values. Simplified by using for loop, + * allowed any number of URBs. + */ +static int usbvideo_StartDataPump(struct uvd *uvd) +{ + struct usb_device *dev = uvd->dev; + int i, errFlag; + + if (uvd->debug > 1) + dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd); + + if (!CAMERA_IS_OPERATIONAL(uvd)) { + err("%s: Camera is not operational", __func__); + return -EFAULT; + } + uvd->curframe = -1; + + /* Alternate interface 1 is is the biggest frame size */ + i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive); + if (i < 0) { + err("%s: usb_set_interface error", __func__); + uvd->last_error = i; + return -EBUSY; + } + if (VALID_CALLBACK(uvd, videoStart)) + GET_CALLBACK(uvd, videoStart)(uvd); + else + err("%s: videoStart not set", __func__); + + /* We double buffer the Iso lists */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + int j, k; + struct urb *urb = uvd->sbuf[i].urb; + urb->dev = dev; + urb->context = uvd; + urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp); + urb->interval = 1; + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = uvd->sbuf[i].data; + urb->complete = usbvideo_IsocIrq; + urb->number_of_packets = FRAMES_PER_DESC; + urb->transfer_buffer_length = uvd->iso_packet_len * FRAMES_PER_DESC; + for (j=k=0; j < FRAMES_PER_DESC; j++, k += uvd->iso_packet_len) { + urb->iso_frame_desc[j].offset = k; + urb->iso_frame_desc[j].length = uvd->iso_packet_len; + } + } + + /* Submit all URBs */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL); + if (errFlag) + err("%s: usb_submit_isoc(%d) ret %d", __func__, i, errFlag); + } + + uvd->streaming = 1; + if (uvd->debug > 1) + dev_info(&uvd->dev->dev, + "%s: streaming=1 video_endp=$%02x\n", __func__, + uvd->video_endp); + return 0; +} + +/* + * usbvideo_StopDataPump() + * + * This procedure stops streaming and deallocates URBs. Then it + * activates zero-bandwidth alt. setting of the video interface. + * + * History: + * 22-Jan-2000 Corrected order of actions to work after surprise removal. + * 27-Jan-2000 Used uvd->iface, uvd->ifaceAltInactive instead of hardcoded values. + */ +static void usbvideo_StopDataPump(struct uvd *uvd) +{ + int i, j; + + if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) + return; + + if (uvd->debug > 1) + dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd); + + /* Unschedule all of the iso td's */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + usb_kill_urb(uvd->sbuf[i].urb); + } + if (uvd->debug > 1) + dev_info(&uvd->dev->dev, "%s: streaming=0\n", __func__); + uvd->streaming = 0; + + if (!uvd->remove_pending) { + /* Invoke minidriver's magic to stop the camera */ + if (VALID_CALLBACK(uvd, videoStop)) + GET_CALLBACK(uvd, videoStop)(uvd); + else + err("%s: videoStop not set", __func__); + + /* Set packet size to 0 */ + j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive); + if (j < 0) { + err("%s: usb_set_interface() error %d.", __func__, j); + uvd->last_error = j; + } + } +} + +/* + * usbvideo_NewFrame() + * + * History: + * 29-Mar-00 Added copying of previous frame into the current one. + * 6-Aug-00 Added model 3 video sizes, removed redundant width, height. + */ +static int usbvideo_NewFrame(struct uvd *uvd, int framenum) +{ + struct usbvideo_frame *frame; + int n; + + if (uvd->debug > 1) + dev_info(&uvd->dev->dev, "usbvideo_NewFrame($%p,%d.)\n", uvd, + framenum); + + /* If we're not grabbing a frame right now and the other frame is */ + /* ready to be grabbed into, then use it instead */ + if (uvd->curframe != -1) + return 0; + + /* If necessary we adjust picture settings between frames */ + if (!uvd->settingsAdjusted) { + if (VALID_CALLBACK(uvd, adjustPicture)) + GET_CALLBACK(uvd, adjustPicture)(uvd); + uvd->settingsAdjusted = 1; + } + + n = (framenum + 1) % USBVIDEO_NUMFRAMES; + if (uvd->frame[n].frameState == FrameState_Ready) + framenum = n; + + frame = &uvd->frame[framenum]; + + frame->frameState = FrameState_Grabbing; + frame->scanstate = ScanState_Scanning; + frame->seqRead_Length = 0; /* Accumulated in xxx_parse_data() */ + frame->deinterlace = Deinterlace_None; + frame->flags = 0; /* No flags yet, up to minidriver (or us) to set them */ + uvd->curframe = framenum; + + /* + * Normally we would want to copy previous frame into the current one + * before we even start filling it with data; this allows us to stop + * filling at any moment; top portion of the frame will be new and + * bottom portion will stay as it was in previous frame. If we don't + * do that then missing chunks of video stream will result in flickering + * portions of old data whatever it was before. + * + * If we choose not to copy previous frame (to, for example, save few + * bus cycles - the frame can be pretty large!) then we have an option + * to clear the frame before using. If we experience losses in this + * mode then missing picture will be black (no flickering). + * + * Finally, if user chooses not to clean the current frame before + * filling it with data then the old data will be visible if we fail + * to refill entire frame with new data. + */ + if (!(uvd->flags & FLAGS_SEPARATE_FRAMES)) { + /* This copies previous frame into this one to mask losses */ + int prev = (framenum - 1 + USBVIDEO_NUMFRAMES) % USBVIDEO_NUMFRAMES; + memmove(frame->data, uvd->frame[prev].data, uvd->max_frame_size); + } else { + if (uvd->flags & FLAGS_CLEAN_FRAMES) { + /* This provides a "clean" frame but slows things down */ + memset(frame->data, 0, uvd->max_frame_size); + } + } + return 0; +} + +/* + * usbvideo_CollectRawData() + * + * This procedure can be used instead of 'processData' callback if you + * only want to dump the raw data from the camera into the output + * device (frame buffer). You can look at it with V4L client, but the + * image will be unwatchable. The main purpose of this code and of the + * mode FLAGS_NO_DECODING is debugging and capturing of datastreams from + * new, unknown cameras. This procedure will be automatically invoked + * instead of the specified callback handler when uvd->flags has bit + * FLAGS_NO_DECODING set. Therefore, any regular build of any driver + * based on usbvideo can use this feature at any time. + */ +static void usbvideo_CollectRawData(struct uvd *uvd, struct usbvideo_frame *frame) +{ + int n; + + assert(uvd != NULL); + assert(frame != NULL); + + /* Try to move data from queue into frame buffer */ + n = RingQueue_GetLength(&uvd->dp); + if (n > 0) { + int m; + /* See how much space we have left */ + m = uvd->max_frame_size - frame->seqRead_Length; + if (n > m) + n = m; + /* Now move that much data into frame buffer */ + RingQueue_Dequeue( + &uvd->dp, + frame->data + frame->seqRead_Length, + m); + frame->seqRead_Length += m; + } + /* See if we filled the frame */ + if (frame->seqRead_Length >= uvd->max_frame_size) { + frame->frameState = FrameState_Done; + uvd->curframe = -1; + uvd->stats.frame_num++; + } +} + +static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) +{ + struct usbvideo_frame *frame = &uvd->frame[frameNum]; + + if (uvd->debug >= 2) + dev_info(&uvd->dev->dev, "%s($%p,%d.)\n", __func__, uvd, + frameNum); + + switch (frame->frameState) { + case FrameState_Unused: + if (uvd->debug >= 2) + dev_info(&uvd->dev->dev, "%s: FrameState_Unused\n", + __func__); + return -EINVAL; + case FrameState_Ready: + case FrameState_Grabbing: + case FrameState_Error: + { + int ntries, signalPending; + redo: + if (!CAMERA_IS_OPERATIONAL(uvd)) { + if (uvd->debug >= 2) + dev_info(&uvd->dev->dev, + "%s: Camera is not operational (1)\n", + __func__); + return -EIO; + } + ntries = 0; + do { + RingQueue_InterruptibleSleepOn(&uvd->dp); + signalPending = signal_pending(current); + if (!CAMERA_IS_OPERATIONAL(uvd)) { + if (uvd->debug >= 2) + dev_info(&uvd->dev->dev, + "%s: Camera is not " + "operational (2)\n", __func__); + return -EIO; + } + assert(uvd->fbuf != NULL); + if (signalPending) { + if (uvd->debug >= 2) + dev_info(&uvd->dev->dev, + "%s: Signal=$%08x\n", __func__, + signalPending); + if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) { + usbvideo_TestPattern(uvd, 1, 0); + uvd->curframe = -1; + uvd->stats.frame_num++; + if (uvd->debug >= 2) + dev_info(&uvd->dev->dev, + "%s: Forced test " + "pattern screen\n", + __func__); + return 0; + } else { + /* Standard answer: Interrupted! */ + if (uvd->debug >= 2) + dev_info(&uvd->dev->dev, + "%s: Interrupted!\n", + __func__); + return -EINTR; + } + } else { + /* No signals - we just got new data in dp queue */ + if (uvd->flags & FLAGS_NO_DECODING) + usbvideo_CollectRawData(uvd, frame); + else if (VALID_CALLBACK(uvd, processData)) + GET_CALLBACK(uvd, processData)(uvd, frame); + else + err("%s: processData not set", __func__); + } + } while (frame->frameState == FrameState_Grabbing); + if (uvd->debug >= 2) { + dev_info(&uvd->dev->dev, + "%s: Grabbing done; state=%d. (%lu. bytes)\n", + __func__, frame->frameState, + frame->seqRead_Length); + } + if (frame->frameState == FrameState_Error) { + int ret = usbvideo_NewFrame(uvd, frameNum); + if (ret < 0) { + err("%s: usbvideo_NewFrame() failed (%d.)", __func__, ret); + return ret; + } + goto redo; + } + /* Note that we fall through to meet our destiny below */ + } + case FrameState_Done: + /* + * Do all necessary postprocessing of data prepared in + * "interrupt" code and the collecting code above. The + * frame gets marked as FrameState_Done by queue parsing code. + * This status means that we collected enough data and + * most likely processed it as we went through. However + * the data may need postprocessing, such as deinterlacing + * or picture adjustments implemented in software (horror!) + * + * As soon as the frame becomes "final" it gets promoted to + * FrameState_Done_Hold status where it will remain until the + * caller consumed all the video data from the frame. Then + * the empty shell of ex-frame is thrown out for dogs to eat. + * But we, worried about pets, will recycle the frame! + */ + uvd->stats.frame_num++; + if ((uvd->flags & FLAGS_NO_DECODING) == 0) { + if (VALID_CALLBACK(uvd, postProcess)) + GET_CALLBACK(uvd, postProcess)(uvd, frame); + if (frame->flags & USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST) + usbvideo_SoftwareContrastAdjustment(uvd, frame); + } + frame->frameState = FrameState_Done_Hold; + if (uvd->debug >= 2) + dev_info(&uvd->dev->dev, + "%s: Entered FrameState_Done_Hold state.\n", + __func__); + return 0; + + case FrameState_Done_Hold: + /* + * We stay in this state indefinitely until someone external, + * like ioctl() or read() call finishes digesting the frame + * data. Then it will mark the frame as FrameState_Unused and + * it will be released back into the wild to roam freely. + */ + if (uvd->debug >= 2) + dev_info(&uvd->dev->dev, + "%s: FrameState_Done_Hold state.\n", + __func__); + return 0; + } + + /* Catch-all for other cases. We shall not be here. */ + err("%s: Invalid state %d.", __func__, frame->frameState); + frame->frameState = FrameState_Unused; + return 0; +} + +/* + * usbvideo_DeinterlaceFrame() + * + * This procedure deinterlaces the given frame. Some cameras produce + * only half of scanlines - sometimes only even lines, sometimes only + * odd lines. The deinterlacing method is stored in frame->deinterlace + * variable. + * + * Here we scan the frame vertically and replace missing scanlines with + * average between surrounding ones - before and after. If we have no + * line above then we just copy next line. Similarly, if we need to + * create a last line then preceding line is used. + */ +void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame) +{ + if ((uvd == NULL) || (frame == NULL)) + return; + + if ((frame->deinterlace == Deinterlace_FillEvenLines) || + (frame->deinterlace == Deinterlace_FillOddLines)) + { + const int v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; + int i = (frame->deinterlace == Deinterlace_FillEvenLines) ? 0 : 1; + + for (; i < VIDEOSIZE_Y(frame->request); i += 2) { + const unsigned char *fs1, *fs2; + unsigned char *fd; + int ip, in, j; /* Previous and next lines */ + + /* + * Need to average lines before and after 'i'. + * If we go out of bounds seeking those lines then + * we point back to existing line. + */ + ip = i - 1; /* First, get rough numbers */ + in = i + 1; + + /* Now validate */ + if (ip < 0) + ip = in; + if (in >= VIDEOSIZE_Y(frame->request)) + in = ip; + + /* Sanity check */ + if ((ip < 0) || (in < 0) || + (ip >= VIDEOSIZE_Y(frame->request)) || + (in >= VIDEOSIZE_Y(frame->request))) + { + err("Error: ip=%d. in=%d. req.height=%ld.", + ip, in, VIDEOSIZE_Y(frame->request)); + break; + } + + /* Now we need to average lines 'ip' and 'in' to produce line 'i' */ + fs1 = frame->data + (v4l_linesize * ip); + fs2 = frame->data + (v4l_linesize * in); + fd = frame->data + (v4l_linesize * i); + + /* Average lines around destination */ + for (j=0; j < v4l_linesize; j++) { + fd[j] = (unsigned char)((((unsigned) fs1[j]) + + ((unsigned)fs2[j])) >> 1); + } + } + } + + /* Optionally display statistics on the screen */ + if (uvd->flags & FLAGS_OVERLAY_STATS) + usbvideo_OverlayStats(uvd, frame); +} + +EXPORT_SYMBOL(usbvideo_DeinterlaceFrame); + +/* + * usbvideo_SoftwareContrastAdjustment() + * + * This code adjusts the contrast of the frame, assuming RGB24 format. + * As most software image processing, this job is CPU-intensive. + * Get a camera that supports hardware adjustment! + * + * History: + * 09-Feb-2001 Created. + */ +static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd, + struct usbvideo_frame *frame) +{ + int i, j, v4l_linesize; + signed long adj; + const int ccm = 128; /* Color correction median - see below */ + + if ((uvd == NULL) || (frame == NULL)) { + err("%s: Illegal call.", __func__); + return; + } + adj = (uvd->vpic.contrast - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/ + RESTRICT_TO_RANGE(adj, -ccm, ccm+1); + if (adj == 0) { + /* In rare case of no adjustment */ + return; + } + v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; + for (i=0; i < VIDEOSIZE_Y(frame->request); i++) { + unsigned char *fd = frame->data + (v4l_linesize * i); + for (j=0; j < v4l_linesize; j++) { + signed long v = (signed long) fd[j]; + /* Magnify up to 2 times, reduce down to zero */ + v = 128 + ((ccm + adj) * (v - 128)) / ccm; + RESTRICT_TO_RANGE(v, 0, 0xFF); /* Must flatten tails */ + fd[j] = (unsigned char) v; + } + } +} + +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/usbvideo/usbvideo.h b/drivers/staging/usbvideo/usbvideo.h new file mode 100644 index 0000000..c66985b --- /dev/null +++ b/drivers/staging/usbvideo/usbvideo.h @@ -0,0 +1,395 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef usbvideo_h +#define usbvideo_h + +#include +#include +#include +#include +#include + +/* Most helpful debugging aid */ +#define assert(expr) ((void) ((expr) ? 0 : (err("assert failed at line %d",__LINE__)))) + +#define USBVIDEO_REPORT_STATS 1 /* Set to 0 to block statistics on close */ + +/* Bit flags (options) */ +#define FLAGS_RETRY_VIDIOCSYNC (1 << 0) +#define FLAGS_MONOCHROME (1 << 1) +#define FLAGS_DISPLAY_HINTS (1 << 2) +#define FLAGS_OVERLAY_STATS (1 << 3) +#define FLAGS_FORCE_TESTPATTERN (1 << 4) +#define FLAGS_SEPARATE_FRAMES (1 << 5) +#define FLAGS_CLEAN_FRAMES (1 << 6) +#define FLAGS_NO_DECODING (1 << 7) + +/* Bit flags for frames (apply to the frame where they are specified) */ +#define USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST (1 << 0) + +/* Camera capabilities (maximum) */ +#define CAMERA_URB_FRAMES 32 +#define CAMERA_MAX_ISO_PACKET 1023 /* 1022 actually sent by camera */ +#define FRAMES_PER_DESC (CAMERA_URB_FRAMES) +#define FRAME_SIZE_PER_DESC (CAMERA_MAX_ISO_PACKET) + +/* This macro restricts an int variable to an inclusive range */ +#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); } + +#define V4L_BYTES_PER_PIXEL 3 /* Because we produce RGB24 */ + +/* + * Use this macro to construct constants for different video sizes. + * We have to deal with different video sizes that have to be + * configured in the device or compared against when we receive + * a data. Normally one would define a bunch of VIDEOSIZE_x_by_y + * #defines and that's the end of story. However this solution + * does not allow to convert between real pixel sizes and the + * constant (integer) value that may be used to tag a frame or + * whatever. The set of macros below constructs videosize constants + * from the pixel size and allows to reconstruct the pixel size + * from the combined value later. + */ +#define VIDEOSIZE(x,y) (((x) & 0xFFFFL) | (((y) & 0xFFFFL) << 16)) +#define VIDEOSIZE_X(vs) ((vs) & 0xFFFFL) +#define VIDEOSIZE_Y(vs) (((vs) >> 16) & 0xFFFFL) +typedef unsigned long videosize_t; + +/* + * This macro checks if the camera is still operational. The 'uvd' + * pointer must be valid, uvd->dev must be valid, we are not + * removing the device and the device has not erred on us. + */ +#define CAMERA_IS_OPERATIONAL(uvd) (\ + (uvd != NULL) && \ + ((uvd)->dev != NULL) && \ + ((uvd)->last_error == 0) && \ + (!(uvd)->remove_pending)) + +/* + * We use macros to do YUV -> RGB conversion because this is + * very important for speed and totally unimportant for size. + * + * YUV -> RGB Conversion + * --------------------- + * + * B = 1.164*(Y-16) + 2.018*(V-128) + * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128) + * R = 1.164*(Y-16) + 1.596*(U-128) + * + * If you fancy integer arithmetics (as you should), hear this: + * + * 65536*B = 76284*(Y-16) + 132252*(V-128) + * 65536*G = 76284*(Y-16) - 53281*(U-128) - 25625*(V-128) + * 65536*R = 76284*(Y-16) + 104595*(U-128) + * + * Make sure the output values are within [0..255] range. + */ +#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x))) +#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \ + int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \ + mm_y = (my) - 16; \ + mm_u = (mu) - 128; \ + mm_v = (mv) - 128; \ + mm_yc= mm_y * 76284; \ + mm_b = (mm_yc + 132252*mm_v ) >> 16; \ + mm_g = (mm_yc - 53281*mm_u - 25625*mm_v ) >> 16; \ + mm_r = (mm_yc + 104595*mm_u ) >> 16; \ + mb = LIMIT_RGB(mm_b); \ + mg = LIMIT_RGB(mm_g); \ + mr = LIMIT_RGB(mm_r); \ +} + +#define RING_QUEUE_SIZE (128*1024) /* Must be a power of 2 */ +#define RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) & ((rq)->length-1) +#define RING_QUEUE_DEQUEUE_BYTES(rq,n) RING_QUEUE_ADVANCE_INDEX(rq,ri,n) +#define RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) & ((rq)->length-1)]) + +struct RingQueue { + unsigned char *queue; /* Data from the Isoc data pump */ + int length; /* How many bytes allocated for the queue */ + int wi; /* That's where we write */ + int ri; /* Read from here until you hit write index */ + wait_queue_head_t wqh; /* Processes waiting */ +}; + +enum ScanState { + ScanState_Scanning, /* Scanning for header */ + ScanState_Lines /* Parsing lines */ +}; + +/* Completion states of the data parser */ +enum ParseState { + scan_Continue, /* Just parse next item */ + scan_NextFrame, /* Frame done, send it to V4L */ + scan_Out, /* Not enough data for frame */ + scan_EndParse /* End parsing */ +}; + +enum FrameState { + FrameState_Unused, /* Unused (no MCAPTURE) */ + FrameState_Ready, /* Ready to start grabbing */ + FrameState_Grabbing, /* In the process of being grabbed into */ + FrameState_Done, /* Finished grabbing, but not been synced yet */ + FrameState_Done_Hold, /* Are syncing or reading */ + FrameState_Error, /* Something bad happened while processing */ +}; + +/* + * Some frames may contain only even or odd lines. This type + * specifies what type of deinterlacing is required. + */ +enum Deinterlace { + Deinterlace_None=0, + Deinterlace_FillOddLines, + Deinterlace_FillEvenLines +}; + +#define USBVIDEO_NUMFRAMES 2 /* How many frames we work with */ +#define USBVIDEO_NUMSBUF 2 /* How many URBs linked in a ring */ + +/* This structure represents one Isoc request - URB and buffer */ +struct usbvideo_sbuf { + char *data; + struct urb *urb; +}; + +struct usbvideo_frame { + char *data; /* Frame buffer */ + unsigned long header; /* Significant bits from the header */ + + videosize_t canvas; /* The canvas (max. image) allocated */ + videosize_t request; /* That's what the application asked for */ + unsigned short palette; /* The desired format */ + + enum FrameState frameState;/* State of grabbing */ + enum ScanState scanstate; /* State of scanning */ + enum Deinterlace deinterlace; + int flags; /* USBVIDEO_FRAME_FLAG_xxx bit flags */ + + int curline; /* Line of frame we're working on */ + + long seqRead_Length; /* Raw data length of frame */ + long seqRead_Index; /* Amount of data that has been already read */ + + void *user; /* Additional data that user may need */ +}; + +/* Statistics that can be overlaid on screen */ +struct usbvideo_statistics { + unsigned long frame_num; /* Sequential number of the frame */ + unsigned long urb_count; /* How many URBs we received so far */ + unsigned long urb_length; /* Length of last URB */ + unsigned long data_count; /* How many bytes we received */ + unsigned long header_count; /* How many frame headers we found */ + unsigned long iso_skip_count; /* How many empty ISO packets received */ + unsigned long iso_err_count; /* How many bad ISO packets received */ +}; + +struct usbvideo; + +struct uvd { + struct video_device vdev; /* Must be the first field! */ + struct usb_device *dev; + struct usbvideo *handle; /* Points back to the struct usbvideo */ + void *user_data; /* Camera-dependent data */ + int user_size; /* Size of that camera-dependent data */ + int debug; /* Debug level for usbvideo */ + unsigned char iface; /* Video interface number */ + unsigned char video_endp; + unsigned char ifaceAltActive; + unsigned char ifaceAltInactive; /* Alt settings */ + unsigned long flags; /* FLAGS_USBVIDEO_xxx */ + unsigned long paletteBits; /* Which palettes we accept? */ + unsigned short defaultPalette; /* What palette to use for read() */ + struct mutex lock; + int user; /* user count for exclusive use */ + + videosize_t videosize; /* Current setting */ + videosize_t canvas; /* This is the width,height of the V4L canvas */ + int max_frame_size; /* Bytes in one video frame */ + + int uvd_used; /* Is this structure in use? */ + int streaming; /* Are we streaming Isochronous? */ + int grabbing; /* Are we grabbing? */ + int settingsAdjusted; /* Have we adjusted contrast etc.? */ + int last_error; /* What calamity struck us? */ + + char *fbuf; /* Videodev buffer area */ + int fbuf_size; /* Videodev buffer size */ + + int curframe; + int iso_packet_len; /* Videomode-dependent, saves bus bandwidth */ + + struct RingQueue dp; /* Isoc data pump */ + struct usbvideo_frame frame[USBVIDEO_NUMFRAMES]; + struct usbvideo_sbuf sbuf[USBVIDEO_NUMSBUF]; + + volatile int remove_pending; /* If set then about to exit */ + + struct video_picture vpic, vpic_old; /* Picture settings */ + struct video_capability vcap; /* Video capabilities */ + struct video_channel vchan; /* May be used for tuner support */ + struct usbvideo_statistics stats; + char videoName[32]; /* Holds name like "video7" */ +}; + +/* + * usbvideo callbacks (virtual methods). They are set when usbvideo + * services are registered. All of these default to NULL, except those + * that default to usbvideo-provided methods. + */ +struct usbvideo_cb { + int (*probe)(struct usb_interface *, const struct usb_device_id *); + void (*userFree)(struct uvd *); + void (*disconnect)(struct usb_interface *); + int (*setupOnOpen)(struct uvd *); + void (*videoStart)(struct uvd *); + void (*videoStop)(struct uvd *); + void (*processData)(struct uvd *, struct usbvideo_frame *); + void (*postProcess)(struct uvd *, struct usbvideo_frame *); + void (*adjustPicture)(struct uvd *); + int (*getFPS)(struct uvd *); + int (*overlayHook)(struct uvd *, struct usbvideo_frame *); + int (*getFrame)(struct uvd *, int); + int (*startDataPump)(struct uvd *uvd); + void (*stopDataPump)(struct uvd *uvd); + int (*setVideoMode)(struct uvd *uvd, struct video_window *vw); +}; + +struct usbvideo { + int num_cameras; /* As allocated */ + struct usb_driver usbdrv; /* Interface to the USB stack */ + char drvName[80]; /* Driver name */ + struct mutex lock; /* Mutex protecting camera structures */ + struct usbvideo_cb cb; /* Table of callbacks (virtual methods) */ + struct video_device vdt; /* Video device template */ + struct uvd *cam; /* Array of camera structures */ + struct module *md_module; /* Minidriver module */ +}; + + +/* + * This macro retrieves callback address from the struct uvd object. + * No validity checks are done here, so be sure to check the + * callback beforehand with VALID_CALLBACK. + */ +#define GET_CALLBACK(uvd,cbName) ((uvd)->handle->cb.cbName) + +/* + * This macro returns either callback pointer or NULL. This is safe + * macro, meaning that most of components of data structures involved + * may be NULL - this only results in NULL being returned. You may + * wish to use this macro to make sure that the callback is callable. + * However keep in mind that those checks take time. + */ +#define VALID_CALLBACK(uvd,cbName) ((((uvd) != NULL) && \ + ((uvd)->handle != NULL)) ? GET_CALLBACK(uvd,cbName) : NULL) + +int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len); +int RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n); +void RingQueue_WakeUpInterruptible(struct RingQueue *rq); +void RingQueue_Flush(struct RingQueue *rq); + +static inline int RingQueue_GetLength(const struct RingQueue *rq) +{ + return (rq->wi - rq->ri + rq->length) & (rq->length-1); +} + +static inline int RingQueue_GetFreeSpace(const struct RingQueue *rq) +{ + return rq->length - RingQueue_GetLength(rq); +} + +void usbvideo_DrawLine( + struct usbvideo_frame *frame, + int x1, int y1, + int x2, int y2, + unsigned char cr, unsigned char cg, unsigned char cb); +void usbvideo_HexDump(const unsigned char *data, int len); +void usbvideo_SayAndWait(const char *what); +void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode); + +/* Memory allocation routines */ +unsigned long usbvideo_kvirt_to_pa(unsigned long adr); + +int usbvideo_register( + struct usbvideo **pCams, + const int num_cams, + const int num_extra, + const char *driverName, + const struct usbvideo_cb *cbTable, + struct module *md, + const struct usb_device_id *id_table); +struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams); +int usbvideo_RegisterVideoDevice(struct uvd *uvd); +void usbvideo_Deregister(struct usbvideo **uvt); + +int usbvideo_v4l_initialize(struct video_device *dev); + +void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame); + +/* + * This code performs bounds checking - use it when working with + * new formats, or else you may get oopses all over the place. + * If pixel falls out of bounds then it gets shoved back (as close + * to place of offence as possible) and is painted bright red. + * + * There are two important concepts: frame width, height and + * V4L canvas width, height. The former is the area requested by + * the application -for this very frame-. The latter is the largest + * possible frame that we can serve (we advertise that via V4L ioctl). + * The frame data is expected to be formatted as lines of length + * VIDEOSIZE_X(fr->request), total VIDEOSIZE_Y(frame->request) lines. + */ +static inline void RGB24_PUTPIXEL( + struct usbvideo_frame *fr, + int ix, int iy, + unsigned char vr, + unsigned char vg, + unsigned char vb) +{ + register unsigned char *pf; + int limiter = 0, mx, my; + mx = ix; + my = iy; + if (mx < 0) { + mx=0; + limiter++; + } else if (mx >= VIDEOSIZE_X((fr)->request)) { + mx= VIDEOSIZE_X((fr)->request) - 1; + limiter++; + } + if (my < 0) { + my = 0; + limiter++; + } else if (my >= VIDEOSIZE_Y((fr)->request)) { + my = VIDEOSIZE_Y((fr)->request) - 1; + limiter++; + } + pf = (fr)->data + V4L_BYTES_PER_PIXEL*((iy)*VIDEOSIZE_X((fr)->request) + (ix)); + if (limiter) { + *pf++ = 0; + *pf++ = 0; + *pf++ = 0xFF; + } else { + *pf++ = (vb); + *pf++ = (vg); + *pf++ = (vr); + } +} + +#endif /* usbvideo_h */ diff --git a/drivers/staging/usbvideo/vicam.c b/drivers/staging/usbvideo/vicam.c new file mode 100644 index 0000000..dc17cce --- /dev/null +++ b/drivers/staging/usbvideo/vicam.c @@ -0,0 +1,952 @@ +/* + * USB ViCam WebCam driver + * Copyright (c) 2002 Joe Burks (jburks@wavicle.org), + * Christopher L Cheney (ccheney@cheney.cx), + * Pavel Machek (pavel@ucw.cz), + * John Tyner (jtyner@cs.ucr.edu), + * Monroe Williams (monroe@pobox.com) + * + * Supports 3COM HomeConnect PC Digital WebCam + * Supports Compro PS39U WebCam + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * This source code is based heavily on the CPiA webcam driver which was + * written by Peter Pregler, Scott J. Bertin and Johannes Erdfelt + * + * Portions of this code were also copied from usbvideo.c + * + * Special thanks to the whole team at Sourceforge for help making + * this driver become a reality. Notably: + * Andy Armstrong who reverse engineered the color encoding and + * Pavel Machek and Chris Cheney who worked on reverse engineering the + * camera controls and wrote the first generation driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "usbvideo.h" + +// #define VICAM_DEBUG + +#ifdef VICAM_DEBUG +#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __func__, lineno, ##args) +#define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args) +#else +#define DBG(fmn,args...) do {} while(0) +#endif + +#define DRIVER_AUTHOR "Joe Burks, jburks@wavicle.org" +#define DRIVER_DESC "ViCam WebCam Driver" + +/* Define these values to match your device */ +#define USB_VICAM_VENDOR_ID 0x04c1 +#define USB_VICAM_PRODUCT_ID 0x009d +#define USB_COMPRO_VENDOR_ID 0x0602 +#define USB_COMPRO_PRODUCT_ID 0x1001 + +#define VICAM_BYTES_PER_PIXEL 3 +#define VICAM_MAX_READ_SIZE (512*242+128) +#define VICAM_MAX_FRAME_SIZE (VICAM_BYTES_PER_PIXEL*320*240) +#define VICAM_FRAMES 2 + +#define VICAM_HEADER_SIZE 64 + +/* rvmalloc / rvfree copied from usbvideo.c + * + * Not sure why these are not yet non-statics which I can reference through + * usbvideo.h the same as it is in 2.4.20. I bet this will get fixed sometime + * in the future. + * +*/ +static void *rvmalloc(unsigned long size) +{ + void *mem; + unsigned long adr; + + size = PAGE_ALIGN(size); + mem = vmalloc_32(size); + if (!mem) + return NULL; + + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr = (unsigned long) mem; + while (size > 0) { + SetPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + return mem; +} + +static void rvfree(void *mem, unsigned long size) +{ + unsigned long adr; + + if (!mem) + return; + + adr = (unsigned long) mem; + while ((long) size > 0) { + ClearPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + vfree(mem); +} + +struct vicam_camera { + u16 shutter_speed; // capture shutter speed + u16 gain; // capture gain + + u8 *raw_image; // raw data captured from the camera + u8 *framebuf; // processed data in RGB24 format + u8 *cntrlbuf; // area used to send control msgs + + struct video_device vdev; // v4l video device + struct usb_device *udev; // usb device + + /* guard against simultaneous accesses to the camera */ + struct mutex cam_lock; + + int is_initialized; + u8 open_count; + u8 bulkEndpoint; + int needsDummyRead; +}; + +static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id); +static void vicam_disconnect(struct usb_interface *intf); +static void read_frame(struct vicam_camera *cam, int framenum); +static void vicam_decode_color(const u8 *, u8 *); + +static int __send_control_msg(struct vicam_camera *cam, + u8 request, + u16 value, + u16 index, + unsigned char *cp, + u16 size) +{ + int status; + + /* cp must be memory that has been allocated by kmalloc */ + + status = usb_control_msg(cam->udev, + usb_sndctrlpipe(cam->udev, 0), + request, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, value, index, + cp, size, 1000); + + status = min(status, 0); + + if (status < 0) { + printk(KERN_INFO "Failed sending control message, error %d.\n", + status); + } + + return status; +} + +static int send_control_msg(struct vicam_camera *cam, + u8 request, + u16 value, + u16 index, + unsigned char *cp, + u16 size) +{ + int status = -ENODEV; + mutex_lock(&cam->cam_lock); + if (cam->udev) { + status = __send_control_msg(cam, request, value, + index, cp, size); + } + mutex_unlock(&cam->cam_lock); + return status; +} +static int +initialize_camera(struct vicam_camera *cam) +{ + int err; + const struct ihex_binrec *rec; + const struct firmware *uninitialized_var(fw); + + err = request_ihex_firmware(&fw, "vicam/firmware.fw", &cam->udev->dev); + if (err) { + printk(KERN_ERR "Failed to load \"vicam/firmware.fw\": %d\n", + err); + return err; + } + + for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) { + memcpy(cam->cntrlbuf, rec->data, be16_to_cpu(rec->len)); + + err = send_control_msg(cam, 0xff, 0, 0, + cam->cntrlbuf, be16_to_cpu(rec->len)); + if (err) + break; + } + + release_firmware(fw); + + return err; +} + +static int +set_camera_power(struct vicam_camera *cam, int state) +{ + int status; + + if ((status = send_control_msg(cam, 0x50, state, 0, NULL, 0)) < 0) + return status; + + if (state) { + send_control_msg(cam, 0x55, 1, 0, NULL, 0); + } + + return 0; +} + +static long +vicam_ioctl(struct file *file, unsigned int ioctlnr, unsigned long arg) +{ + void __user *user_arg = (void __user *)arg; + struct vicam_camera *cam = file->private_data; + long retval = 0; + + if (!cam) + return -ENODEV; + + switch (ioctlnr) { + /* query capabilities */ + case VIDIOCGCAP: + { + struct video_capability b; + + DBG("VIDIOCGCAP\n"); + memset(&b, 0, sizeof(b)); + strcpy(b.name, "ViCam-based Camera"); + b.type = VID_TYPE_CAPTURE; + b.channels = 1; + b.audios = 0; + b.maxwidth = 320; /* VIDEOSIZE_CIF */ + b.maxheight = 240; + b.minwidth = 320; /* VIDEOSIZE_48_48 */ + b.minheight = 240; + + if (copy_to_user(user_arg, &b, sizeof(b))) + retval = -EFAULT; + + break; + } + /* get/set video source - we are a camera and nothing else */ + case VIDIOCGCHAN: + { + struct video_channel v; + + DBG("VIDIOCGCHAN\n"); + if (copy_from_user(&v, user_arg, sizeof(v))) { + retval = -EFAULT; + break; + } + if (v.channel != 0) { + retval = -EINVAL; + break; + } + + v.channel = 0; + strcpy(v.name, "Camera"); + v.tuners = 0; + v.flags = 0; + v.type = VIDEO_TYPE_CAMERA; + v.norm = 0; + + if (copy_to_user(user_arg, &v, sizeof(v))) + retval = -EFAULT; + break; + } + + case VIDIOCSCHAN: + { + int v; + + if (copy_from_user(&v, user_arg, sizeof(v))) + retval = -EFAULT; + DBG("VIDIOCSCHAN %d\n", v); + + if (retval == 0 && v != 0) + retval = -EINVAL; + + break; + } + + /* image properties */ + case VIDIOCGPICT: + { + struct video_picture vp; + DBG("VIDIOCGPICT\n"); + memset(&vp, 0, sizeof (struct video_picture)); + vp.brightness = cam->gain << 8; + vp.depth = 24; + vp.palette = VIDEO_PALETTE_RGB24; + if (copy_to_user(user_arg, &vp, sizeof (struct video_picture))) + retval = -EFAULT; + break; + } + + case VIDIOCSPICT: + { + struct video_picture vp; + + if (copy_from_user(&vp, user_arg, sizeof(vp))) { + retval = -EFAULT; + break; + } + + DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth, + vp.palette); + + cam->gain = vp.brightness >> 8; + + if (vp.depth != 24 + || vp.palette != VIDEO_PALETTE_RGB24) + retval = -EINVAL; + + break; + } + + /* get/set capture window */ + case VIDIOCGWIN: + { + struct video_window vw; + vw.x = 0; + vw.y = 0; + vw.width = 320; + vw.height = 240; + vw.chromakey = 0; + vw.flags = 0; + vw.clips = NULL; + vw.clipcount = 0; + + DBG("VIDIOCGWIN\n"); + + if (copy_to_user(user_arg, (void *)&vw, sizeof(vw))) + retval = -EFAULT; + + // I'm not sure what the deal with a capture window is, it is very poorly described + // in the doc. So I won't support it now. + break; + } + + case VIDIOCSWIN: + { + + struct video_window vw; + + if (copy_from_user(&vw, user_arg, sizeof(vw))) { + retval = -EFAULT; + break; + } + + DBG("VIDIOCSWIN %d x %d\n", vw.width, vw.height); + + if ( vw.width != 320 || vw.height != 240 ) + retval = -EFAULT; + + break; + } + + /* mmap interface */ + case VIDIOCGMBUF: + { + struct video_mbuf vm; + int i; + + DBG("VIDIOCGMBUF\n"); + memset(&vm, 0, sizeof (vm)); + vm.size = + VICAM_MAX_FRAME_SIZE * VICAM_FRAMES; + vm.frames = VICAM_FRAMES; + for (i = 0; i < VICAM_FRAMES; i++) + vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i; + + if (copy_to_user(user_arg, (void *)&vm, sizeof(vm))) + retval = -EFAULT; + + break; + } + + case VIDIOCMCAPTURE: + { + struct video_mmap vm; + // int video_size; + + if (copy_from_user((void *)&vm, user_arg, sizeof(vm))) { + retval = -EFAULT; + break; + } + + DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format); + + if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 ) + retval = -EINVAL; + + // in theory right here we'd start the image capturing + // (fill in a bulk urb and submit it asynchronously) + // + // Instead we're going to do a total hack job for now and + // retrieve the frame in VIDIOCSYNC + + break; + } + + case VIDIOCSYNC: + { + int frame; + + if (copy_from_user((void *)&frame, user_arg, sizeof(int))) { + retval = -EFAULT; + break; + } + DBG("VIDIOCSYNC: %d\n", frame); + + read_frame(cam, frame); + vicam_decode_color(cam->raw_image, + cam->framebuf + + frame * VICAM_MAX_FRAME_SIZE ); + + break; + } + + /* pointless to implement overlay with this camera */ + case VIDIOCCAPTURE: + case VIDIOCGFBUF: + case VIDIOCSFBUF: + case VIDIOCKEY: + retval = -EINVAL; + break; + + /* tuner interface - we have none */ + case VIDIOCGTUNER: + case VIDIOCSTUNER: + case VIDIOCGFREQ: + case VIDIOCSFREQ: + retval = -EINVAL; + break; + + /* audio interface - we have none */ + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + retval = -EINVAL; + break; + default: + retval = -ENOIOCTLCMD; + break; + } + + return retval; +} + +static int +vicam_open(struct file *file) +{ + struct vicam_camera *cam = video_drvdata(file); + + DBG("open\n"); + + if (!cam) { + printk(KERN_ERR + "vicam video_device improperly initialized"); + return -EINVAL; + } + + /* cam_lock/open_count protects us from simultaneous opens + * ... for now. we probably shouldn't rely on this fact forever. + */ + + mutex_lock(&cam->cam_lock); + if (cam->open_count > 0) { + printk(KERN_INFO + "vicam_open called on already opened camera"); + mutex_unlock(&cam->cam_lock); + return -EBUSY; + } + + cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL); + if (!cam->raw_image) { + mutex_unlock(&cam->cam_lock); + return -ENOMEM; + } + + cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); + if (!cam->framebuf) { + kfree(cam->raw_image); + mutex_unlock(&cam->cam_lock); + return -ENOMEM; + } + + cam->cntrlbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!cam->cntrlbuf) { + kfree(cam->raw_image); + rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); + mutex_unlock(&cam->cam_lock); + return -ENOMEM; + } + + cam->needsDummyRead = 1; + cam->open_count++; + + file->private_data = cam; + mutex_unlock(&cam->cam_lock); + + + // First upload firmware, then turn the camera on + + if (!cam->is_initialized) { + initialize_camera(cam); + + cam->is_initialized = 1; + } + + set_camera_power(cam, 1); + + return 0; +} + +static int +vicam_close(struct file *file) +{ + struct vicam_camera *cam = file->private_data; + int open_count; + struct usb_device *udev; + + DBG("close\n"); + + /* it's not the end of the world if + * we fail to turn the camera off. + */ + + set_camera_power(cam, 0); + + kfree(cam->raw_image); + rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); + kfree(cam->cntrlbuf); + + mutex_lock(&cam->cam_lock); + + cam->open_count--; + open_count = cam->open_count; + udev = cam->udev; + + mutex_unlock(&cam->cam_lock); + + if (!open_count && !udev) { + kfree(cam); + } + + return 0; +} + +static void vicam_decode_color(const u8 *data, u8 *rgb) +{ + /* vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB + * Copyright (C) 2002 Monroe Williams (monroe@pobox.com) + */ + + int i, prevY, nextY; + + prevY = 512; + nextY = 512; + + data += VICAM_HEADER_SIZE; + + for( i = 0; i < 240; i++, data += 512 ) { + const int y = ( i * 242 ) / 240; + + int j, prevX, nextX; + int Y, Cr, Cb; + + if ( y == 242 - 1 ) { + nextY = -512; + } + + prevX = 1; + nextX = 1; + + for ( j = 0; j < 320; j++, rgb += 3 ) { + const int x = ( j * 512 ) / 320; + const u8 * const src = &data[x]; + + if ( x == 512 - 1 ) { + nextX = -1; + } + + Cr = ( src[prevX] - src[0] ) + + ( src[nextX] - src[0] ); + Cr /= 2; + + Cb = ( src[prevY] - src[prevX + prevY] ) + + ( src[prevY] - src[nextX + prevY] ) + + ( src[nextY] - src[prevX + nextY] ) + + ( src[nextY] - src[nextX + nextY] ); + Cb /= 4; + + Y = 1160 * ( src[0] + ( Cr / 2 ) - 16 ); + + if ( i & 1 ) { + int Ct = Cr; + Cr = Cb; + Cb = Ct; + } + + if ( ( x ^ i ) & 1 ) { + Cr = -Cr; + Cb = -Cb; + } + + rgb[0] = clamp( ( ( Y + ( 2017 * Cb ) ) + + 500 ) / 900, 0, 255 ); + rgb[1] = clamp( ( ( Y - ( 392 * Cb ) - + ( 813 * Cr ) ) + + 500 ) / 1000, 0, 255 ); + rgb[2] = clamp( ( ( Y + ( 1594 * Cr ) ) + + 500 ) / 1300, 0, 255 ); + + prevX = -1; + } + + prevY = -512; + } +} + +static void +read_frame(struct vicam_camera *cam, int framenum) +{ + unsigned char *request = cam->cntrlbuf; + int realShutter; + int n; + int actual_length; + + if (cam->needsDummyRead) { + cam->needsDummyRead = 0; + read_frame(cam, framenum); + } + + memset(request, 0, 16); + request[0] = cam->gain; // 0 = 0% gain, FF = 100% gain + + request[1] = 0; // 512x242 capture + + request[2] = 0x90; // the function of these two bytes + request[3] = 0x07; // is not yet understood + + if (cam->shutter_speed > 60) { + // Short exposure + realShutter = + ((-15631900 / cam->shutter_speed) + 260533) / 1000; + request[4] = realShutter & 0xFF; + request[5] = (realShutter >> 8) & 0xFF; + request[6] = 0x03; + request[7] = 0x01; + } else { + // Long exposure + realShutter = 15600 / cam->shutter_speed - 1; + request[4] = 0; + request[5] = 0; + request[6] = realShutter & 0xFF; + request[7] = realShutter >> 8; + } + + // Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0 + request[8] = 0; + // bytes 9-15 do not seem to affect exposure or image quality + + mutex_lock(&cam->cam_lock); + + if (!cam->udev) { + goto done; + } + + n = __send_control_msg(cam, 0x51, 0x80, 0, request, 16); + + if (n < 0) { + printk(KERN_ERR + " Problem sending frame capture control message"); + goto done; + } + + n = usb_bulk_msg(cam->udev, + usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint), + cam->raw_image, + 512 * 242 + 128, &actual_length, 10000); + + if (n < 0) { + printk(KERN_ERR "Problem during bulk read of frame data: %d\n", + n); + } + + done: + mutex_unlock(&cam->cam_lock); +} + +static ssize_t +vicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos ) +{ + struct vicam_camera *cam = file->private_data; + + DBG("read %d bytes.\n", (int) count); + + if (*ppos >= VICAM_MAX_FRAME_SIZE) { + *ppos = 0; + return 0; + } + + if (*ppos == 0) { + read_frame(cam, 0); + vicam_decode_color(cam->raw_image, + cam->framebuf + + 0 * VICAM_MAX_FRAME_SIZE); + } + + count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos); + + if (copy_to_user(buf, &cam->framebuf[*ppos], count)) { + count = -EFAULT; + } else { + *ppos += count; + } + + if (count == VICAM_MAX_FRAME_SIZE) { + *ppos = 0; + } + + return count; +} + + +static int +vicam_mmap(struct file *file, struct vm_area_struct *vma) +{ + // TODO: allocate the raw frame buffer if necessary + unsigned long page, pos; + unsigned long start = vma->vm_start; + unsigned long size = vma->vm_end-vma->vm_start; + struct vicam_camera *cam = file->private_data; + + if (!cam) + return -ENODEV; + + DBG("vicam_mmap: %ld\n", size); + + /* We let mmap allocate as much as it wants because Linux was adding 2048 bytes + * to the size the application requested for mmap and it was screwing apps up. + if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE) + return -EINVAL; + */ + + pos = (unsigned long)cam->framebuf; + while (size > 0) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) + return -EAGAIN; + + start += PAGE_SIZE; + pos += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + + return 0; +} + +static const struct v4l2_file_operations vicam_fops = { + .owner = THIS_MODULE, + .open = vicam_open, + .release = vicam_close, + .read = vicam_read, + .mmap = vicam_mmap, + .ioctl = vicam_ioctl, +}; + +static struct video_device vicam_template = { + .name = "ViCam-based USB Camera", + .fops = &vicam_fops, + .release = video_device_release_empty, +}; + +/* table of devices that work with this driver */ +static struct usb_device_id vicam_table[] = { + {USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)}, + {USB_DEVICE(USB_COMPRO_VENDOR_ID, USB_COMPRO_PRODUCT_ID)}, + {} /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, vicam_table); + +static struct usb_driver vicam_driver = { + .name = "vicam", + .probe = vicam_probe, + .disconnect = vicam_disconnect, + .id_table = vicam_table +}; + +/** + * vicam_probe + * @intf: the interface + * @id: the device id + * + * Called by the usb core when a new device is connected that it thinks + * this driver might be interested in. + */ +static int +vicam_probe( struct usb_interface *intf, const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + int bulkEndpoint = 0; + const struct usb_host_interface *interface; + const struct usb_endpoint_descriptor *endpoint; + struct vicam_camera *cam; + + printk(KERN_INFO "ViCam based webcam connected\n"); + + interface = intf->cur_altsetting; + + DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n", + interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints)); + endpoint = &interface->endpoint[0].desc; + + if (usb_endpoint_is_bulk_in(endpoint)) { + /* we found a bulk in endpoint */ + bulkEndpoint = endpoint->bEndpointAddress; + } else { + printk(KERN_ERR + "No bulk in endpoint was found ?! (this is bad)\n"); + } + + if ((cam = + kzalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) { + printk(KERN_WARNING + "could not allocate kernel memory for vicam_camera struct\n"); + return -ENOMEM; + } + + + cam->shutter_speed = 15; + + mutex_init(&cam->cam_lock); + + memcpy(&cam->vdev, &vicam_template, sizeof(vicam_template)); + video_set_drvdata(&cam->vdev, cam); + + cam->udev = dev; + cam->bulkEndpoint = bulkEndpoint; + + if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) < 0) { + kfree(cam); + printk(KERN_WARNING "video_register_device failed\n"); + return -EIO; + } + + printk(KERN_INFO "ViCam webcam driver now controlling device %s\n", + video_device_node_name(&cam->vdev)); + + usb_set_intfdata (intf, cam); + + return 0; +} + +static void +vicam_disconnect(struct usb_interface *intf) +{ + int open_count; + struct vicam_camera *cam = usb_get_intfdata (intf); + usb_set_intfdata (intf, NULL); + + /* we must unregister the device before taking its + * cam_lock. This is because the video open call + * holds the same lock as video unregister. if we + * unregister inside of the cam_lock and open also + * uses the cam_lock, we get deadlock. + */ + + video_unregister_device(&cam->vdev); + + /* stop the camera from being used */ + + mutex_lock(&cam->cam_lock); + + /* mark the camera as gone */ + + cam->udev = NULL; + + /* the only thing left to do is synchronize with + * our close/release function on who should release + * the camera memory. if there are any users using the + * camera, it's their job. if there are no users, + * it's ours. + */ + + open_count = cam->open_count; + + mutex_unlock(&cam->cam_lock); + + if (!open_count) { + kfree(cam); + } + + printk(KERN_DEBUG "ViCam-based WebCam disconnected\n"); +} + +/* + */ +static int __init +usb_vicam_init(void) +{ + int retval; + DBG(KERN_INFO "ViCam-based WebCam driver startup\n"); + retval = usb_register(&vicam_driver); + if (retval) + printk(KERN_WARNING "usb_register failed!\n"); + return retval; +} + +static void __exit +usb_vicam_exit(void) +{ + DBG(KERN_INFO + "ViCam-based WebCam driver shutdown\n"); + + usb_deregister(&vicam_driver); +} + +module_init(usb_vicam_init); +module_exit(usb_vicam_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE("vicam/firmware.fw"); -- cgit v0.10.2 From 71bb2876a3b2af8e6fd5ac20921ee0de9e07d809 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 25 Dec 2010 07:36:55 -0300 Subject: [media] se401: deprecate driver, move to staging The se401 driver is deprecated and is moved to staging. If no one will convert this driver to V4L2, then it will be removed in 2.6.39. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 3655b30..b3bf043 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -917,17 +917,6 @@ source "drivers/media/video/usbvision/Kconfig" source "drivers/media/video/et61x251/Kconfig" -config USB_SE401 - tristate "USB SE401 Camera support" - depends on VIDEO_V4L1 - ---help--- - Say Y here if you want to connect this type of camera to your - computer's USB port. See - for more information and for a list of supported cameras. - - To compile this driver as a module, choose M here: the - module will be called se401. - source "drivers/media/video/sn9c102/Kconfig" source "drivers/media/video/pwc/Kconfig" diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 2f2e3ac..fd684dd 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -122,7 +122,6 @@ obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o obj-$(CONFIG_USB_DABUSB) += dabusb.o -obj-$(CONFIG_USB_SE401) += se401.o obj-$(CONFIG_USB_ZR364XX) += zr364xx.o obj-$(CONFIG_USB_STKWEBCAM) += stkwebcam.o diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c deleted file mode 100644 index 41360d7..0000000 --- a/drivers/media/video/se401.c +++ /dev/null @@ -1,1492 +0,0 @@ -/* - * Endpoints (formerly known as AOX) se401 USB Camera Driver - * - * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org) - * - * Still somewhat based on the Linux ov511 driver. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - * Thanks to Endpoints Inc. (www.endpoints.com) for making documentation on - * their chipset available and supporting me while writing this driver. - * - Jeroen Vreeken - */ - -static const char version[] = "0.24"; - -#include -#include -#include -#include -#include -#include -#include "se401.h" - -static int flickerless; -static int video_nr = -1; - -static struct usb_device_id device_table[] = { - { USB_DEVICE(0x03e8, 0x0004) },/* Endpoints/Aox SE401 */ - { USB_DEVICE(0x0471, 0x030b) },/* Philips PCVC665K */ - { USB_DEVICE(0x047d, 0x5001) },/* Kensington 67014 */ - { USB_DEVICE(0x047d, 0x5002) },/* Kensington 6701(5/7) */ - { USB_DEVICE(0x047d, 0x5003) },/* Kensington 67016 */ - { } -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -MODULE_AUTHOR("Jeroen Vreeken "); -MODULE_DESCRIPTION("SE401 USB Camera Driver"); -MODULE_LICENSE("GPL"); -module_param(flickerless, int, 0); -MODULE_PARM_DESC(flickerless, - "Net frequency to adjust exposure time to (0/50/60)"); -module_param(video_nr, int, 0); - -static struct usb_driver se401_driver; - - -/********************************************************************** - * - * Memory management - * - **********************************************************************/ -static void *rvmalloc(unsigned long size) -{ - void *mem; - unsigned long adr; - - size = PAGE_ALIGN(size); - mem = vmalloc_32(size); - if (!mem) - return NULL; - - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long) mem; - while (size > 0) { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - return mem; -} - -static void rvfree(void *mem, unsigned long size) -{ - unsigned long adr; - - if (!mem) - return; - - adr = (unsigned long) mem; - while ((long) size > 0) { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - vfree(mem); -} - - - -/**************************************************************************** - * - * se401 register read/write functions - * - ***************************************************************************/ - -static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req, - unsigned short value, unsigned char *cp, int size) -{ - return usb_control_msg( - se401->dev, - set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0), - req, - (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - 0, - cp, - size, - 1000 - ); -} - -static int se401_set_feature(struct usb_se401 *se401, unsigned short selector, - unsigned short param) -{ - /* specs say that the selector (address) should go in the value field - and the param in index, but in the logs of the windows driver they do - this the other way around... - */ - return usb_control_msg( - se401->dev, - usb_sndctrlpipe(se401->dev, 0), - SE401_REQ_SET_EXT_FEATURE, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - param, - selector, - NULL, - 0, - 1000 - ); -} - -static unsigned short se401_get_feature(struct usb_se401 *se401, - unsigned short selector) -{ - /* For 'set' the selecetor should be in index, not sure if the spec is - wrong here to.... - */ - unsigned char cp[2]; - usb_control_msg( - se401->dev, - usb_rcvctrlpipe(se401->dev, 0), - SE401_REQ_GET_EXT_FEATURE, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, - selector, - cp, - 2, - 1000 - ); - return cp[0]+cp[1]*256; -} - -/**************************************************************************** - * - * Camera control - * - ***************************************************************************/ - - -static int se401_send_pict(struct usb_se401 *se401) -{ - /* integration time low */ - se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l); - /* integration time mid */ - se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m); - /* integration time mid */ - se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h); - /* reset level value */ - se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel); - /* red color gain */ - se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain); - /* green color gain */ - se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain); - /* blue color gain */ - se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain); - - return 0; -} - -static void se401_set_exposure(struct usb_se401 *se401, int brightness) -{ - int integration = brightness << 5; - - if (flickerless == 50) - integration = integration-integration % 106667; - if (flickerless == 60) - integration = integration-integration % 88889; - se401->brightness = integration >> 5; - se401->expose_h = (integration >> 16) & 0xff; - se401->expose_m = (integration >> 8) & 0xff; - se401->expose_l = integration & 0xff; -} - -static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p) -{ - p->brightness = se401->brightness; - if (se401->enhance) - p->whiteness = 32768; - else - p->whiteness = 0; - - p->colour = 65535; - p->contrast = 65535; - p->hue = se401->rgain << 10; - p->palette = se401->palette; - p->depth = 3; /* rgb24 */ - return 0; -} - - -static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p) -{ - if (p->palette != VIDEO_PALETTE_RGB24) - return 1; - se401->palette = p->palette; - if (p->hue != se401->hue) { - se401->rgain = p->hue >> 10; - se401->bgain = 0x40-(p->hue >> 10); - se401->hue = p->hue; - } - if (p->brightness != se401->brightness) - se401_set_exposure(se401, p->brightness); - - if (p->whiteness >= 32768) - se401->enhance = 1; - else - se401->enhance = 0; - se401_send_pict(se401); - se401_send_pict(se401); - return 0; -} - -/* - Hyundai have some really nice docs about this and other sensor related - stuff on their homepage: www.hei.co.kr -*/ -static void se401_auto_resetlevel(struct usb_se401 *se401) -{ - unsigned int ahrc, alrc; - int oldreset = se401->resetlevel; - - /* For some reason this normally read-only register doesn't get reset - to zero after reading them just once... - */ - se401_get_feature(se401, HV7131_REG_HIREFNOH); - se401_get_feature(se401, HV7131_REG_HIREFNOL); - se401_get_feature(se401, HV7131_REG_LOREFNOH); - se401_get_feature(se401, HV7131_REG_LOREFNOL); - ahrc = 256*se401_get_feature(se401, HV7131_REG_HIREFNOH) + - se401_get_feature(se401, HV7131_REG_HIREFNOL); - alrc = 256*se401_get_feature(se401, HV7131_REG_LOREFNOH) + - se401_get_feature(se401, HV7131_REG_LOREFNOL); - - /* Not an exact science, but it seems to work pretty well... */ - if (alrc > 10) { - while (alrc >= 10 && se401->resetlevel < 63) { - se401->resetlevel++; - alrc /= 2; - } - } else if (ahrc > 20) { - while (ahrc >= 20 && se401->resetlevel > 0) { - se401->resetlevel--; - ahrc /= 2; - } - } - if (se401->resetlevel != oldreset) - se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel); - - return; -} - -/* irq handler for snapshot button */ -static void se401_button_irq(struct urb *urb) -{ - struct usb_se401 *se401 = urb->context; - int status; - - if (!se401->dev) { - dev_info(&urb->dev->dev, "device vapourished\n"); - return; - } - - switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __func__, urb->status); - return; - default: - dbg("%s - nonzero urb status received: %d", - __func__, urb->status); - goto exit; - } - - if (urb->actual_length >= 2) - if (se401->button) - se401->buttonpressed = 1; -exit: - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) - err("%s - usb_submit_urb failed with result %d", - __func__, status); -} - -static void se401_video_irq(struct urb *urb) -{ - struct usb_se401 *se401 = urb->context; - int length = urb->actual_length; - - /* ohoh... */ - if (!se401->streaming) - return; - - if (!se401->dev) { - dev_info(&urb->dev->dev, "device vapourished\n"); - return; - } - - /* 0 sized packets happen if we are to fast, but sometimes the camera - keeps sending them forever... - */ - if (length && !urb->status) { - se401->nullpackets = 0; - switch (se401->scratch[se401->scratch_next].state) { - case BUFFER_READY: - case BUFFER_BUSY: - se401->dropped++; - break; - case BUFFER_UNUSED: - memcpy(se401->scratch[se401->scratch_next].data, - (unsigned char *)urb->transfer_buffer, length); - se401->scratch[se401->scratch_next].state - = BUFFER_READY; - se401->scratch[se401->scratch_next].offset - = se401->bayeroffset; - se401->scratch[se401->scratch_next].length = length; - if (waitqueue_active(&se401->wq)) - wake_up_interruptible(&se401->wq); - se401->scratch_overflow = 0; - se401->scratch_next++; - if (se401->scratch_next >= SE401_NUMSCRATCH) - se401->scratch_next = 0; - break; - } - se401->bayeroffset += length; - if (se401->bayeroffset >= se401->cheight * se401->cwidth) - se401->bayeroffset = 0; - } else { - se401->nullpackets++; - if (se401->nullpackets > SE401_MAX_NULLPACKETS) - if (waitqueue_active(&se401->wq)) - wake_up_interruptible(&se401->wq); - } - - /* Resubmit urb for new data */ - urb->status = 0; - urb->dev = se401->dev; - if (usb_submit_urb(urb, GFP_KERNEL)) - dev_info(&urb->dev->dev, "urb burned down\n"); - return; -} - -static void se401_send_size(struct usb_se401 *se401, int width, int height) -{ - int i = 0; - int mode = 0x03; /* No compression */ - int sendheight = height; - int sendwidth = width; - - /* JangGu compression can only be used with the camera supported sizes, - but bayer seems to work with any size that fits on the sensor. - We check if we can use compression with the current size with either - 4 or 16 times subcapturing, if not we use uncompressed bayer data - but this will result in cutouts of the maximum size.... - */ - while (i < se401->sizes && !(se401->width[i] == width && - se401->height[i] == height)) - i++; - while (i < se401->sizes) { - if (se401->width[i] == width * 2 && - se401->height[i] == height * 2) { - sendheight = se401->height[i]; - sendwidth = se401->width[i]; - mode = 0x40; - } - if (se401->width[i] == width * 4 && - se401->height[i] == height * 4) { - sendheight = se401->height[i]; - sendwidth = se401->width[i]; - mode = 0x42; - } - i++; - } - - se401_sndctrl(1, se401, SE401_REQ_SET_WIDTH, sendwidth, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0); - se401_set_feature(se401, SE401_OPERATINGMODE, mode); - - if (mode == 0x03) - se401->format = FMT_BAYER; - else - se401->format = FMT_JANGGU; -} - -/* - In this function se401_send_pict is called several times, - for some reason (depending on the state of the sensor and the phase of - the moon :) doing this only in either place doesn't always work... -*/ -static int se401_start_stream(struct usb_se401 *se401) -{ - struct urb *urb; - int err = 0, i; - se401->streaming = 1; - - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); - - /* Set picture settings */ - /* windowed + pix intg */ - se401_set_feature(se401, HV7131_REG_MODE_B, 0x05); - se401_send_pict(se401); - - se401_send_size(se401, se401->cwidth, se401->cheight); - - se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, - 0, NULL, 0); - - /* Do some memory allocation */ - for (i = 0; i < SE401_NUMFRAMES; i++) { - se401->frame[i].data = se401->fbuf + i * se401->maxframesize; - se401->frame[i].curpix = 0; - } - for (i = 0; i < SE401_NUMSBUF; i++) { - se401->sbuf[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL); - if (!se401->sbuf[i].data) { - for (i = i - 1; i >= 0; i--) { - kfree(se401->sbuf[i].data); - se401->sbuf[i].data = NULL; - } - return -ENOMEM; - } - } - - se401->bayeroffset = 0; - se401->scratch_next = 0; - se401->scratch_use = 0; - se401->scratch_overflow = 0; - for (i = 0; i < SE401_NUMSCRATCH; i++) { - se401->scratch[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL); - if (!se401->scratch[i].data) { - for (i = i - 1; i >= 0; i--) { - kfree(se401->scratch[i].data); - se401->scratch[i].data = NULL; - } - goto nomem_sbuf; - } - se401->scratch[i].state = BUFFER_UNUSED; - } - - for (i = 0; i < SE401_NUMSBUF; i++) { - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - for (i = i - 1; i >= 0; i--) { - usb_kill_urb(se401->urb[i]); - usb_free_urb(se401->urb[i]); - se401->urb[i] = NULL; - } - goto nomem_scratch; - } - - usb_fill_bulk_urb(urb, se401->dev, - usb_rcvbulkpipe(se401->dev, SE401_VIDEO_ENDPOINT), - se401->sbuf[i].data, SE401_PACKETSIZE, - se401_video_irq, - se401); - - se401->urb[i] = urb; - - err = usb_submit_urb(se401->urb[i], GFP_KERNEL); - if (err) - err("urb burned down"); - } - - se401->framecount = 0; - - return 0; - - nomem_scratch: - for (i = 0; i < SE401_NUMSCRATCH; i++) { - kfree(se401->scratch[i].data); - se401->scratch[i].data = NULL; - } - nomem_sbuf: - for (i = 0; i < SE401_NUMSBUF; i++) { - kfree(se401->sbuf[i].data); - se401->sbuf[i].data = NULL; - } - return -ENOMEM; -} - -static int se401_stop_stream(struct usb_se401 *se401) -{ - int i; - - if (!se401->streaming || !se401->dev) - return 1; - - se401->streaming = 0; - - se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0); - - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); - - for (i = 0; i < SE401_NUMSBUF; i++) - if (se401->urb[i]) { - usb_kill_urb(se401->urb[i]); - usb_free_urb(se401->urb[i]); - se401->urb[i] = NULL; - kfree(se401->sbuf[i].data); - } - for (i = 0; i < SE401_NUMSCRATCH; i++) { - kfree(se401->scratch[i].data); - se401->scratch[i].data = NULL; - } - - return 0; -} - -static int se401_set_size(struct usb_se401 *se401, int width, int height) -{ - int wasstreaming = se401->streaming; - /* Check to see if we need to change */ - if (se401->cwidth == width && se401->cheight == height) - return 0; - - /* Check for a valid mode */ - if (!width || !height) - return 1; - if ((width & 1) || (height & 1)) - return 1; - if (width > se401->width[se401->sizes-1]) - return 1; - if (height > se401->height[se401->sizes-1]) - return 1; - - /* Stop a current stream and start it again at the new size */ - if (wasstreaming) - se401_stop_stream(se401); - se401->cwidth = width; - se401->cheight = height; - if (wasstreaming) - se401_start_stream(se401); - return 0; -} - - -/**************************************************************************** - * - * Video Decoding - * - ***************************************************************************/ - -/* - This shouldn't really be done in a v4l driver.... - But it does make the image look a lot more usable. - Basically it lifts the dark pixels more than the light pixels. -*/ -static inline void enhance_picture(unsigned char *frame, int len) -{ - while (len--) { - *frame = (((*frame^255)*(*frame^255))/255)^255; - frame++; - } -} - -static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data) -{ - struct se401_frame *frame = &se401->frame[se401->curframe]; - int linelength = se401->cwidth * 3; - - if (frame->curlinepix >= linelength) { - frame->curlinepix = 0; - frame->curline += linelength; - } - - /* First three are absolute, all others relative. - * Format is rgb from right to left (mirrorred image), - * we flip it to get bgr from left to right. */ - if (frame->curlinepix < 3) - *(frame->curline-frame->curlinepix) = 1 + data * 4; - else - *(frame->curline-frame->curlinepix) = - *(frame->curline-frame->curlinepix + 3) + data * 4; - frame->curlinepix++; -} - -static inline void decode_JangGu_vlc(struct usb_se401 *se401, - unsigned char *data, int bit_exp, int packetlength) -{ - int pos = 0; - int vlc_cod = 0; - int vlc_size = 0; - int vlc_data = 0; - int bit_cur; - int bit; - data += 4; - while (pos < packetlength) { - bit_cur = 8; - while (bit_cur && bit_exp) { - bit = ((*data) >> (bit_cur-1))&1; - if (!vlc_cod) { - if (bit) { - vlc_size++; - } else { - if (!vlc_size) - decode_JangGu_integrate(se401, 0); - else { - vlc_cod = 2; - vlc_data = 0; - } - } - } else { - if (vlc_cod == 2) { - if (!bit) - vlc_data = -(1 << vlc_size) + 1; - vlc_cod--; - } - vlc_size--; - vlc_data += bit << vlc_size; - if (!vlc_size) { - decode_JangGu_integrate(se401, vlc_data); - vlc_cod = 0; - } - } - bit_cur--; - bit_exp--; - } - pos++; - data++; - } -} - -static inline void decode_JangGu(struct usb_se401 *se401, - struct se401_scratch *buffer) -{ - unsigned char *data = buffer->data; - int len = buffer->length; - int bit_exp = 0, pix_exp = 0, frameinfo = 0, packetlength = 0, size; - int datapos = 0; - - /* New image? */ - if (!se401->frame[se401->curframe].curpix) { - se401->frame[se401->curframe].curlinepix = 0; - se401->frame[se401->curframe].curline = - se401->frame[se401->curframe].data+ - se401->cwidth * 3 - 1; - if (se401->frame[se401->curframe].grabstate == FRAME_READY) - se401->frame[se401->curframe].grabstate = FRAME_GRABBING; - se401->vlcdatapos = 0; - } - while (datapos < len) { - size = 1024 - se401->vlcdatapos; - if (size+datapos > len) - size = len-datapos; - memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size); - se401->vlcdatapos += size; - packetlength = 0; - if (se401->vlcdatapos >= 4) { - bit_exp = se401->vlcdata[3] + (se401->vlcdata[2] << 8); - pix_exp = se401->vlcdata[1] + - ((se401->vlcdata[0] & 0x3f) << 8); - frameinfo = se401->vlcdata[0] & 0xc0; - packetlength = ((bit_exp + 47) >> 4) << 1; - if (packetlength > 1024) { - se401->vlcdatapos = 0; - datapos = len; - packetlength = 0; - se401->error++; - se401->frame[se401->curframe].curpix = 0; - } - } - if (packetlength && se401->vlcdatapos >= packetlength) { - decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, - packetlength); - se401->frame[se401->curframe].curpix += pix_exp * 3; - datapos += size-(se401->vlcdatapos-packetlength); - se401->vlcdatapos = 0; - if (se401->frame[se401->curframe].curpix >= se401->cwidth * se401->cheight * 3) { - if (se401->frame[se401->curframe].curpix == se401->cwidth * se401->cheight * 3) { - if (se401->frame[se401->curframe].grabstate == FRAME_GRABBING) { - se401->frame[se401->curframe].grabstate = FRAME_DONE; - se401->framecount++; - se401->readcount++; - } - if (se401->frame[(se401->curframe + 1) & (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) - se401->curframe = (se401->curframe + 1) & (SE401_NUMFRAMES - 1); - } else - se401->error++; - se401->frame[se401->curframe].curpix = 0; - datapos = len; - } - } else - datapos += size; - } -} - -static inline void decode_bayer(struct usb_se401 *se401, - struct se401_scratch *buffer) -{ - unsigned char *data = buffer->data; - int len = buffer->length; - int offset = buffer->offset; - int datasize = se401->cwidth * se401->cheight; - struct se401_frame *frame = &se401->frame[se401->curframe]; - unsigned char *framedata = frame->data, *curline, *nextline; - int width = se401->cwidth; - int blineoffset = 0, bline; - int linelength = width * 3, i; - - - if (frame->curpix == 0) { - if (frame->grabstate == FRAME_READY) - frame->grabstate = FRAME_GRABBING; - - frame->curline = framedata + linelength; - frame->curlinepix = 0; - } - - if (offset != frame->curpix) { - /* Regard frame as lost :( */ - frame->curpix = 0; - se401->error++; - return; - } - - /* Check if we have to much data */ - if (frame->curpix + len > datasize) - len = datasize-frame->curpix; - - if (se401->cheight % 4) - blineoffset = 1; - bline = frame->curpix / se401->cwidth+blineoffset; - - curline = frame->curline; - nextline = curline + linelength; - if (nextline >= framedata+datasize * 3) - nextline = curline; - while (len) { - if (frame->curlinepix >= width) { - frame->curlinepix -= width; - bline = frame->curpix / width + blineoffset; - curline += linelength*2; - nextline += linelength*2; - if (curline >= framedata+datasize * 3) { - frame->curlinepix++; - curline -= 3; - nextline -= 3; - len--; - data++; - frame->curpix++; - } - if (nextline >= framedata+datasize*3) - nextline = curline; - } - if (bline & 1) { - if (frame->curlinepix & 1) { - *(curline + 2) = *data; - *(curline - 1) = *data; - *(nextline + 2) = *data; - *(nextline - 1) = *data; - } else { - *(curline + 1) = - (*(curline + 1) + *data) / 2; - *(curline-2) = - (*(curline - 2) + *data) / 2; - *(nextline + 1) = *data; - *(nextline - 2) = *data; - } - } else { - if (frame->curlinepix & 1) { - *(curline + 1) = - (*(curline + 1) + *data) / 2; - *(curline - 2) = - (*(curline - 2) + *data) / 2; - *(nextline + 1) = *data; - *(nextline - 2) = *data; - } else { - *curline = *data; - *(curline - 3) = *data; - *nextline = *data; - *(nextline - 3) = *data; - } - } - frame->curlinepix++; - curline -= 3; - nextline -= 3; - len--; - data++; - frame->curpix++; - } - frame->curline = curline; - - if (frame->curpix >= datasize) { - /* Fix the top line */ - framedata += linelength; - for (i = 0; i < linelength; i++) { - framedata--; - *framedata = *(framedata + linelength); - } - /* Fix the left side (green is already present) */ - for (i = 0; i < se401->cheight; i++) { - *framedata = *(framedata + 3); - *(framedata + 1) = *(framedata + 4); - *(framedata + 2) = *(framedata + 5); - framedata += linelength; - } - frame->curpix = 0; - frame->grabstate = FRAME_DONE; - se401->framecount++; - se401->readcount++; - if (se401->frame[(se401->curframe + 1) & - (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) { - se401->curframe = (se401->curframe+1) & - (SE401_NUMFRAMES-1); - } - } -} - -static int se401_newframe(struct usb_se401 *se401, int framenr) -{ - DECLARE_WAITQUEUE(wait, current); - int errors = 0; - - while (se401->streaming && - (se401->frame[framenr].grabstate == FRAME_READY || - se401->frame[framenr].grabstate == FRAME_GRABBING)) { - if (!se401->frame[framenr].curpix) - errors++; - - wait_interruptible( - se401->scratch[se401->scratch_use].state != BUFFER_READY, - &se401->wq, &wait); - if (se401->nullpackets > SE401_MAX_NULLPACKETS) { - se401->nullpackets = 0; - dev_info(&se401->dev->dev, - "too many null length packets, restarting capture\n"); - se401_stop_stream(se401); - se401_start_stream(se401); - } else { - if (se401->scratch[se401->scratch_use].state != - BUFFER_READY) { - se401->frame[framenr].grabstate = FRAME_ERROR; - return -EIO; - } - se401->scratch[se401->scratch_use].state = BUFFER_BUSY; - if (se401->format == FMT_JANGGU) - decode_JangGu(se401, - &se401->scratch[se401->scratch_use]); - else - decode_bayer(se401, - &se401->scratch[se401->scratch_use]); - - se401->scratch[se401->scratch_use].state = - BUFFER_UNUSED; - se401->scratch_use++; - if (se401->scratch_use >= SE401_NUMSCRATCH) - se401->scratch_use = 0; - if (errors > SE401_MAX_ERRORS) { - errors = 0; - dev_info(&se401->dev->dev, - "too many errors, restarting capture\n"); - se401_stop_stream(se401); - se401_start_stream(se401); - } - } - } - - if (se401->frame[framenr].grabstate == FRAME_DONE) - if (se401->enhance) - enhance_picture(se401->frame[framenr].data, - se401->cheight * se401->cwidth * 3); - return 0; -} - -static void usb_se401_remove_disconnected(struct usb_se401 *se401) -{ - int i; - - se401->dev = NULL; - - for (i = 0; i < SE401_NUMSBUF; i++) - if (se401->urb[i]) { - usb_kill_urb(se401->urb[i]); - usb_free_urb(se401->urb[i]); - se401->urb[i] = NULL; - kfree(se401->sbuf[i].data); - } - - for (i = 0; i < SE401_NUMSCRATCH; i++) - kfree(se401->scratch[i].data); - - if (se401->inturb) { - usb_kill_urb(se401->inturb); - usb_free_urb(se401->inturb); - } - dev_info(&se401->dev->dev, "%s disconnected", se401->camera_name); - - /* Free the memory */ - kfree(se401->width); - kfree(se401->height); - kfree(se401); -} - - - -/**************************************************************************** - * - * Video4Linux - * - ***************************************************************************/ - - -static int se401_open(struct file *file) -{ - struct video_device *dev = video_devdata(file); - struct usb_se401 *se401 = (struct usb_se401 *)dev; - int err = 0; - - mutex_lock(&se401->lock); - if (se401->user) { - mutex_unlock(&se401->lock); - return -EBUSY; - } - se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES); - if (se401->fbuf) - file->private_data = dev; - else - err = -ENOMEM; - se401->user = !err; - mutex_unlock(&se401->lock); - - return err; -} - -static int se401_close(struct file *file) -{ - struct video_device *dev = file->private_data; - struct usb_se401 *se401 = (struct usb_se401 *)dev; - int i; - - rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES); - if (se401->removed) { - dev_info(&se401->dev->dev, "device unregistered\n"); - usb_se401_remove_disconnected(se401); - } else { - for (i = 0; i < SE401_NUMFRAMES; i++) - se401->frame[i].grabstate = FRAME_UNUSED; - if (se401->streaming) - se401_stop_stream(se401); - se401->user = 0; - } - file->private_data = NULL; - return 0; -} - -static long se401_do_ioctl(struct file *file, unsigned int cmd, void *arg) -{ - struct video_device *vdev = file->private_data; - struct usb_se401 *se401 = (struct usb_se401 *)vdev; - - if (!se401->dev) - return -EIO; - - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability *b = arg; - strcpy(b->name, se401->camera_name); - b->type = VID_TYPE_CAPTURE; - b->channels = 1; - b->audios = 0; - b->maxwidth = se401->width[se401->sizes-1]; - b->maxheight = se401->height[se401->sizes-1]; - b->minwidth = se401->width[0]; - b->minheight = se401->height[0]; - return 0; - } - case VIDIOCGCHAN: - { - struct video_channel *v = arg; - - if (v->channel != 0) - return -EINVAL; - v->flags = 0; - v->tuners = 0; - v->type = VIDEO_TYPE_CAMERA; - strcpy(v->name, "Camera"); - return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *v = arg; - - if (v->channel != 0) - return -EINVAL; - return 0; - } - case VIDIOCGPICT: - { - struct video_picture *p = arg; - - se401_get_pict(se401, p); - return 0; - } - case VIDIOCSPICT: - { - struct video_picture *p = arg; - - if (se401_set_pict(se401, p)) - return -EINVAL; - return 0; - } - case VIDIOCSWIN: - { - struct video_window *vw = arg; - - if (vw->flags) - return -EINVAL; - if (vw->clipcount) - return -EINVAL; - if (se401_set_size(se401, vw->width, vw->height)) - return -EINVAL; - return 0; - } - case VIDIOCGWIN: - { - struct video_window *vw = arg; - - vw->x = 0; /* FIXME */ - vw->y = 0; - vw->chromakey = 0; - vw->flags = 0; - vw->clipcount = 0; - vw->width = se401->cwidth; - vw->height = se401->cheight; - return 0; - } - case VIDIOCGMBUF: - { - struct video_mbuf *vm = arg; - int i; - - memset(vm, 0, sizeof(*vm)); - vm->size = SE401_NUMFRAMES * se401->maxframesize; - vm->frames = SE401_NUMFRAMES; - for (i = 0; i < SE401_NUMFRAMES; i++) - vm->offsets[i] = se401->maxframesize * i; - return 0; - } - case VIDIOCMCAPTURE: - { - struct video_mmap *vm = arg; - - if (vm->format != VIDEO_PALETTE_RGB24) - return -EINVAL; - if (vm->frame >= SE401_NUMFRAMES) - return -EINVAL; - if (se401->frame[vm->frame].grabstate != FRAME_UNUSED) - return -EBUSY; - - /* Is this according to the v4l spec??? */ - if (se401_set_size(se401, vm->width, vm->height)) - return -EINVAL; - se401->frame[vm->frame].grabstate = FRAME_READY; - - if (!se401->streaming) - se401_start_stream(se401); - - /* Set the picture properties */ - if (se401->framecount == 0) - se401_send_pict(se401); - /* Calibrate the reset level after a few frames. */ - if (se401->framecount % 20 == 1) - se401_auto_resetlevel(se401); - - return 0; - } - case VIDIOCSYNC: - { - int *frame = arg; - int ret = 0; - - if (*frame < 0 || *frame >= SE401_NUMFRAMES) - return -EINVAL; - - ret = se401_newframe(se401, *frame); - se401->frame[*frame].grabstate = FRAME_UNUSED; - return ret; - } - case VIDIOCGFBUF: - { - struct video_buffer *vb = arg; - - memset(vb, 0, sizeof(*vb)); - return 0; - } - case VIDIOCKEY: - return 0; - case VIDIOCCAPTURE: - return -EINVAL; - case VIDIOCSFBUF: - return -EINVAL; - case VIDIOCGTUNER: - case VIDIOCSTUNER: - return -EINVAL; - case VIDIOCGFREQ: - case VIDIOCSFREQ: - return -EINVAL; - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - return -EINVAL; - default: - return -ENOIOCTLCMD; - } /* end switch */ - - return 0; -} - -static long se401_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(file, cmd, arg, se401_do_ioctl); -} - -static ssize_t se401_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - int realcount = count, ret = 0; - struct video_device *dev = file->private_data; - struct usb_se401 *se401 = (struct usb_se401 *)dev; - - - if (se401->dev == NULL) - return -EIO; - if (realcount > se401->cwidth*se401->cheight*3) - realcount = se401->cwidth*se401->cheight*3; - - /* Shouldn't happen: */ - if (se401->frame[0].grabstate == FRAME_GRABBING) - return -EBUSY; - se401->frame[0].grabstate = FRAME_READY; - se401->frame[1].grabstate = FRAME_UNUSED; - se401->curframe = 0; - - if (!se401->streaming) - se401_start_stream(se401); - - /* Set the picture properties */ - if (se401->framecount == 0) - se401_send_pict(se401); - /* Calibrate the reset level after a few frames. */ - if (se401->framecount%20 == 1) - se401_auto_resetlevel(se401); - - ret = se401_newframe(se401, 0); - - se401->frame[0].grabstate = FRAME_UNUSED; - if (ret) - return ret; - if (copy_to_user(buf, se401->frame[0].data, realcount)) - return -EFAULT; - - return realcount; -} - -static int se401_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct video_device *dev = file->private_data; - struct usb_se401 *se401 = (struct usb_se401 *)dev; - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end-vma->vm_start; - unsigned long page, pos; - - mutex_lock(&se401->lock); - - if (se401->dev == NULL) { - mutex_unlock(&se401->lock); - return -EIO; - } - if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) - & ~(PAGE_SIZE - 1))) { - mutex_unlock(&se401->lock); - return -EINVAL; - } - pos = (unsigned long)se401->fbuf; - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { - mutex_unlock(&se401->lock); - return -EAGAIN; - } - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - mutex_unlock(&se401->lock); - - return 0; -} - -static const struct v4l2_file_operations se401_fops = { - .owner = THIS_MODULE, - .open = se401_open, - .release = se401_close, - .read = se401_read, - .mmap = se401_mmap, - .ioctl = se401_ioctl, -}; -static struct video_device se401_template = { - .name = "se401 USB camera", - .fops = &se401_fops, - .release = video_device_release_empty, -}; - - - -/***************************/ -static int se401_init(struct usb_se401 *se401, int button) -{ - int i = 0, rc; - unsigned char cp[0x40]; - char temp[200]; - int slen; - - /* led on */ - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); - - /* get camera descriptor */ - rc = se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, - cp, sizeof(cp)); - if (cp[1] != 0x41) { - err("Wrong descriptor type"); - return 1; - } - slen = snprintf(temp, 200, "ExtraFeatures: %d", cp[3]); - - se401->sizes = cp[4] + cp[5] * 256; - se401->width = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); - if (!se401->width) - return 1; - se401->height = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); - if (!se401->height) { - kfree(se401->width); - return 1; - } - for (i = 0; i < se401->sizes; i++) { - se401->width[i] = cp[6 + i * 4 + 0] + cp[6 + i*4 + 1] * 256; - se401->height[i] = cp[6 + i * 4 + 2] + cp[6 + i * 4 + 3] * 256; - } - slen += snprintf(temp + slen, 200 - slen, " Sizes:"); - for (i = 0; i < se401->sizes; i++) { - slen += snprintf(temp + slen, 200 - slen, - " %dx%d", se401->width[i], se401->height[i]); - } - dev_info(&se401->dev->dev, "%s\n", temp); - se401->maxframesize = se401->width[se401->sizes-1] * - se401->height[se401->sizes - 1] * 3; - - rc = se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp)); - se401->cwidth = cp[0]+cp[1]*256; - rc = se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp)); - se401->cheight = cp[0]+cp[1]*256; - - if (!(cp[2] & SE401_FORMAT_BAYER)) { - err("Bayer format not supported!"); - return 1; - } - /* set output mode (BAYER) */ - se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, - SE401_FORMAT_BAYER, NULL, 0); - - rc = se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp)); - se401->brightness = cp[0]+cp[1]*256; - /* some default values */ - se401->resetlevel = 0x2d; - se401->rgain = 0x20; - se401->ggain = 0x20; - se401->bgain = 0x20; - se401_set_exposure(se401, 20000); - se401->palette = VIDEO_PALETTE_RGB24; - se401->enhance = 1; - se401->dropped = 0; - se401->error = 0; - se401->framecount = 0; - se401->readcount = 0; - - /* Start interrupt transfers for snapshot button */ - if (button) { - se401->inturb = usb_alloc_urb(0, GFP_KERNEL); - if (!se401->inturb) { - dev_info(&se401->dev->dev, - "Allocation of inturb failed\n"); - return 1; - } - usb_fill_int_urb(se401->inturb, se401->dev, - usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT), - &se401->button, sizeof(se401->button), - se401_button_irq, - se401, - 8 - ); - if (usb_submit_urb(se401->inturb, GFP_KERNEL)) { - dev_info(&se401->dev->dev, "int urb burned down\n"); - return 1; - } - } else - se401->inturb = NULL; - - /* Flash the led */ - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); - se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0); - - return 0; -} - -static int se401_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_interface_descriptor *interface; - struct usb_se401 *se401; - char *camera_name = NULL; - int button = 1; - - /* We don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) - return -ENODEV; - - interface = &intf->cur_altsetting->desc; - - /* Is it an se401? */ - if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 && - le16_to_cpu(dev->descriptor.idProduct) == 0x0004) { - camera_name = "Endpoints/Aox SE401"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 && - le16_to_cpu(dev->descriptor.idProduct) == 0x030b) { - camera_name = "Philips PCVC665K"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && - le16_to_cpu(dev->descriptor.idProduct) == 0x5001) { - camera_name = "Kensington VideoCAM 67014"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && - le16_to_cpu(dev->descriptor.idProduct) == 0x5002) { - camera_name = "Kensington VideoCAM 6701(5/7)"; - } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && - le16_to_cpu(dev->descriptor.idProduct) == 0x5003) { - camera_name = "Kensington VideoCAM 67016"; - button = 0; - } else - return -ENODEV; - - /* Checking vendor/product should be enough, but what the hell */ - if (interface->bInterfaceClass != 0x00) - return -ENODEV; - if (interface->bInterfaceSubClass != 0x00) - return -ENODEV; - - /* We found one */ - dev_info(&intf->dev, "SE401 camera found: %s\n", camera_name); - - se401 = kzalloc(sizeof(*se401), GFP_KERNEL); - if (se401 == NULL) { - err("couldn't kmalloc se401 struct"); - return -ENOMEM; - } - - se401->dev = dev; - se401->iface = interface->bInterfaceNumber; - se401->camera_name = camera_name; - - dev_info(&intf->dev, "firmware version: %02x\n", - le16_to_cpu(dev->descriptor.bcdDevice) & 255); - - if (se401_init(se401, button)) { - kfree(se401); - return -EIO; - } - - memcpy(&se401->vdev, &se401_template, sizeof(se401_template)); - memcpy(se401->vdev.name, se401->camera_name, - strlen(se401->camera_name)); - init_waitqueue_head(&se401->wq); - mutex_init(&se401->lock); - wmb(); - - if (video_register_device(&se401->vdev, - VFL_TYPE_GRABBER, video_nr) < 0) { - kfree(se401); - err("video_register_device failed"); - return -EIO; - } - dev_info(&intf->dev, "registered new video device: %s\n", - video_device_node_name(&se401->vdev)); - - usb_set_intfdata(intf, se401); - return 0; -} - -static void se401_disconnect(struct usb_interface *intf) -{ - struct usb_se401 *se401 = usb_get_intfdata(intf); - - usb_set_intfdata(intf, NULL); - if (se401) { - video_unregister_device(&se401->vdev); - if (!se401->user) - usb_se401_remove_disconnected(se401); - else { - se401->frame[0].grabstate = FRAME_ERROR; - se401->frame[0].grabstate = FRAME_ERROR; - - se401->streaming = 0; - - wake_up_interruptible(&se401->wq); - se401->removed = 1; - } - } -} - -static struct usb_driver se401_driver = { - .name = "se401", - .id_table = device_table, - .probe = se401_probe, - .disconnect = se401_disconnect, -}; - - - -/**************************************************************************** - * - * Module routines - * - ***************************************************************************/ - -static int __init usb_se401_init(void) -{ - printk(KERN_INFO "SE401 usb camera driver version %s registering\n", - version); - if (flickerless) - if (flickerless != 50 && flickerless != 60) { - printk(KERN_ERR "Invallid flickerless value, use 0, 50 or 60.\n"); - return -1; - } - return usb_register(&se401_driver); -} - -static void __exit usb_se401_exit(void) -{ - usb_deregister(&se401_driver); - printk(KERN_INFO "SE401 driver deregistered\frame"); -} - -module_init(usb_se401_init); -module_exit(usb_se401_exit); diff --git a/drivers/media/video/se401.h b/drivers/media/video/se401.h deleted file mode 100644 index bf7d2e9..0000000 --- a/drivers/media/video/se401.h +++ /dev/null @@ -1,236 +0,0 @@ - -#ifndef __LINUX_se401_H -#define __LINUX_se401_H - -#include -#include -#include -#include -#include - -#define se401_DEBUG /* Turn on debug messages */ - -#ifdef se401_DEBUG -# define PDEBUG(level, fmt, args...) \ -if (debug >= level) \ - info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args) -#else -# define PDEBUG(level, fmt, args...) do {} while (0) -#endif - -/* An almost drop-in replacement for sleep_on_interruptible */ -#define wait_interruptible(test, queue, wait) \ -{ \ - add_wait_queue(queue, wait); \ - set_current_state(TASK_INTERRUPTIBLE); \ - if (test) \ - schedule(); \ - remove_wait_queue(queue, wait); \ - set_current_state(TASK_RUNNING); \ - if (signal_pending(current)) \ - break; \ -} - -#define SE401_REQ_GET_CAMERA_DESCRIPTOR 0x06 -#define SE401_REQ_START_CONTINUOUS_CAPTURE 0x41 -#define SE401_REQ_STOP_CONTINUOUS_CAPTURE 0x42 -#define SE401_REQ_CAPTURE_FRAME 0x43 -#define SE401_REQ_GET_BRT 0x44 -#define SE401_REQ_SET_BRT 0x45 -#define SE401_REQ_GET_WIDTH 0x4c -#define SE401_REQ_SET_WIDTH 0x4d -#define SE401_REQ_GET_HEIGHT 0x4e -#define SE401_REQ_SET_HEIGHT 0x4f -#define SE401_REQ_GET_OUTPUT_MODE 0x50 -#define SE401_REQ_SET_OUTPUT_MODE 0x51 -#define SE401_REQ_GET_EXT_FEATURE 0x52 -#define SE401_REQ_SET_EXT_FEATURE 0x53 -#define SE401_REQ_CAMERA_POWER 0x56 -#define SE401_REQ_LED_CONTROL 0x57 -#define SE401_REQ_BIOS 0xff - -#define SE401_BIOS_READ 0x07 - -#define SE401_FORMAT_BAYER 0x40 - -/* Hyundai hv7131b registers - 7121 and 7141 should be the same (haven't really checked...) */ -/* Mode registers: */ -#define HV7131_REG_MODE_A 0x00 -#define HV7131_REG_MODE_B 0x01 -#define HV7131_REG_MODE_C 0x02 -/* Frame registers: */ -#define HV7131_REG_FRSU 0x10 -#define HV7131_REG_FRSL 0x11 -#define HV7131_REG_FCSU 0x12 -#define HV7131_REG_FCSL 0x13 -#define HV7131_REG_FWHU 0x14 -#define HV7131_REG_FWHL 0x15 -#define HV7131_REG_FWWU 0x16 -#define HV7131_REG_FWWL 0x17 -/* Timing registers: */ -#define HV7131_REG_THBU 0x20 -#define HV7131_REG_THBL 0x21 -#define HV7131_REG_TVBU 0x22 -#define HV7131_REG_TVBL 0x23 -#define HV7131_REG_TITU 0x25 -#define HV7131_REG_TITM 0x26 -#define HV7131_REG_TITL 0x27 -#define HV7131_REG_TMCD 0x28 -/* Adjust Registers: */ -#define HV7131_REG_ARLV 0x30 -#define HV7131_REG_ARCG 0x31 -#define HV7131_REG_AGCG 0x32 -#define HV7131_REG_ABCG 0x33 -#define HV7131_REG_APBV 0x34 -#define HV7131_REG_ASLP 0x54 -/* Offset Registers: */ -#define HV7131_REG_OFSR 0x50 -#define HV7131_REG_OFSG 0x51 -#define HV7131_REG_OFSB 0x52 -/* REset level statistics registers: */ -#define HV7131_REG_LOREFNOH 0x57 -#define HV7131_REG_LOREFNOL 0x58 -#define HV7131_REG_HIREFNOH 0x59 -#define HV7131_REG_HIREFNOL 0x5a - -/* se401 registers */ -#define SE401_OPERATINGMODE 0x2000 - - -/* size of usb transfers */ -#define SE401_PACKETSIZE 4096 -/* number of queued bulk transfers to use, should be about 8 */ -#define SE401_NUMSBUF 1 -/* read the usb specs for this one :) */ -#define SE401_VIDEO_ENDPOINT 1 -#define SE401_BUTTON_ENDPOINT 2 -/* number of frames supported by the v4l part */ -#define SE401_NUMFRAMES 2 -/* scratch buffers for passing data to the decoders */ -#define SE401_NUMSCRATCH 32 -/* maximum amount of data in a JangGu packet */ -#define SE401_VLCDATALEN 1024 -/* number of nul sized packets to receive before kicking the camera */ -#define SE401_MAX_NULLPACKETS 4000 -/* number of decoding errors before kicking the camera */ -#define SE401_MAX_ERRORS 200 - -struct usb_device; - -struct se401_sbuf { - unsigned char *data; -}; - -enum { - FRAME_UNUSED, /* Unused (no MCAPTURE) */ - FRAME_READY, /* Ready to start grabbing */ - FRAME_GRABBING, /* In the process of being grabbed into */ - FRAME_DONE, /* Finished grabbing, but not been synced yet */ - FRAME_ERROR, /* Something bad happened while processing */ -}; - -enum { - FMT_BAYER, - FMT_JANGGU, -}; - -enum { - BUFFER_UNUSED, - BUFFER_READY, - BUFFER_BUSY, - BUFFER_DONE, -}; - -struct se401_scratch { - unsigned char *data; - volatile int state; - int offset; - int length; -}; - -struct se401_frame { - unsigned char *data; /* Frame buffer */ - - volatile int grabstate; /* State of grabbing */ - - unsigned char *curline; - int curlinepix; - int curpix; -}; - -struct usb_se401 { - struct video_device vdev; - - /* Device structure */ - struct usb_device *dev; - - unsigned char iface; - - char *camera_name; - - int change; - int brightness; - int hue; - int rgain; - int ggain; - int bgain; - int expose_h; - int expose_m; - int expose_l; - int resetlevel; - - int enhance; - - int format; - int sizes; - int *width; - int *height; - int cwidth; /* current width */ - int cheight; /* current height */ - int palette; - int maxframesize; - int cframesize; /* current framesize */ - - struct mutex lock; - int user; /* user count for exclusive use */ - int removed; /* device disconnected */ - - int streaming; /* Are we streaming video? */ - - char *fbuf; /* Videodev buffer area */ - - struct urb *urb[SE401_NUMSBUF]; - struct urb *inturb; - - int button; - int buttonpressed; - - int curframe; /* Current receiving frame */ - struct se401_frame frame[SE401_NUMFRAMES]; - int readcount; - int framecount; - int error; - int dropped; - - int scratch_next; - int scratch_use; - int scratch_overflow; - struct se401_scratch scratch[SE401_NUMSCRATCH]; - - /* Decoder specific data: */ - unsigned char vlcdata[SE401_VLCDATALEN]; - int vlcdatapos; - int bayeroffset; - - struct se401_sbuf sbuf[SE401_NUMSBUF]; - - wait_queue_head_t wq; /* Processes waiting */ - - int nullpackets; -}; - - - -#endif - diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index a402a56..d9e3b6d 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -55,6 +55,8 @@ source "drivers/staging/cpia/Kconfig" source "drivers/staging/stradis/Kconfig" +source "drivers/staging/se401/Kconfig" + source "drivers/staging/usbvideo/Kconfig" source "drivers/staging/usbip/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index d4eb714..8058a15 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_VIDEO_TM6000) += tm6000/ obj-$(CONFIG_VIDEO_CPIA) += cpia/ obj-$(CONFIG_VIDEO_STRADIS) += stradis/ obj-$(CONFIG_USB_VICAM) += usbvideo/ +obj-$(CONFIG_USB_SE401) += se401/ obj-$(CONFIG_LIRC_STAGING) += lirc/ obj-$(CONFIG_USB_IP_COMMON) += usbip/ obj-$(CONFIG_W35UND) += winbond/ diff --git a/drivers/staging/se401/Kconfig b/drivers/staging/se401/Kconfig new file mode 100644 index 0000000..586fc04 --- /dev/null +++ b/drivers/staging/se401/Kconfig @@ -0,0 +1,13 @@ +config USB_SE401 + tristate "USB SE401 Camera support (DEPRECATED)" + depends on VIDEO_V4L1 + ---help--- + Say Y here if you want to connect this type of camera to your + computer's USB port. See + for more information and for a list of supported cameras. + + This driver uses the deprecated V4L1 API and will be removed in + 2.6.39, unless someone converts it to the V4L2 API. + + To compile this driver as a module, choose M here: the + module will be called se401. diff --git a/drivers/staging/se401/Makefile b/drivers/staging/se401/Makefile new file mode 100644 index 0000000..b465d49 --- /dev/null +++ b/drivers/staging/se401/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_USB_SE401) += se401.o diff --git a/drivers/staging/se401/se401.c b/drivers/staging/se401/se401.c new file mode 100644 index 0000000..41360d7 --- /dev/null +++ b/drivers/staging/se401/se401.c @@ -0,0 +1,1492 @@ +/* + * Endpoints (formerly known as AOX) se401 USB Camera Driver + * + * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org) + * + * Still somewhat based on the Linux ov511 driver. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Thanks to Endpoints Inc. (www.endpoints.com) for making documentation on + * their chipset available and supporting me while writing this driver. + * - Jeroen Vreeken + */ + +static const char version[] = "0.24"; + +#include +#include +#include +#include +#include +#include +#include "se401.h" + +static int flickerless; +static int video_nr = -1; + +static struct usb_device_id device_table[] = { + { USB_DEVICE(0x03e8, 0x0004) },/* Endpoints/Aox SE401 */ + { USB_DEVICE(0x0471, 0x030b) },/* Philips PCVC665K */ + { USB_DEVICE(0x047d, 0x5001) },/* Kensington 67014 */ + { USB_DEVICE(0x047d, 0x5002) },/* Kensington 6701(5/7) */ + { USB_DEVICE(0x047d, 0x5003) },/* Kensington 67016 */ + { } +}; + +MODULE_DEVICE_TABLE(usb, device_table); + +MODULE_AUTHOR("Jeroen Vreeken "); +MODULE_DESCRIPTION("SE401 USB Camera Driver"); +MODULE_LICENSE("GPL"); +module_param(flickerless, int, 0); +MODULE_PARM_DESC(flickerless, + "Net frequency to adjust exposure time to (0/50/60)"); +module_param(video_nr, int, 0); + +static struct usb_driver se401_driver; + + +/********************************************************************** + * + * Memory management + * + **********************************************************************/ +static void *rvmalloc(unsigned long size) +{ + void *mem; + unsigned long adr; + + size = PAGE_ALIGN(size); + mem = vmalloc_32(size); + if (!mem) + return NULL; + + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr = (unsigned long) mem; + while (size > 0) { + SetPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + + return mem; +} + +static void rvfree(void *mem, unsigned long size) +{ + unsigned long adr; + + if (!mem) + return; + + adr = (unsigned long) mem; + while ((long) size > 0) { + ClearPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + vfree(mem); +} + + + +/**************************************************************************** + * + * se401 register read/write functions + * + ***************************************************************************/ + +static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req, + unsigned short value, unsigned char *cp, int size) +{ + return usb_control_msg( + se401->dev, + set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0), + req, + (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, + 0, + cp, + size, + 1000 + ); +} + +static int se401_set_feature(struct usb_se401 *se401, unsigned short selector, + unsigned short param) +{ + /* specs say that the selector (address) should go in the value field + and the param in index, but in the logs of the windows driver they do + this the other way around... + */ + return usb_control_msg( + se401->dev, + usb_sndctrlpipe(se401->dev, 0), + SE401_REQ_SET_EXT_FEATURE, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + param, + selector, + NULL, + 0, + 1000 + ); +} + +static unsigned short se401_get_feature(struct usb_se401 *se401, + unsigned short selector) +{ + /* For 'set' the selecetor should be in index, not sure if the spec is + wrong here to.... + */ + unsigned char cp[2]; + usb_control_msg( + se401->dev, + usb_rcvctrlpipe(se401->dev, 0), + SE401_REQ_GET_EXT_FEATURE, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, + selector, + cp, + 2, + 1000 + ); + return cp[0]+cp[1]*256; +} + +/**************************************************************************** + * + * Camera control + * + ***************************************************************************/ + + +static int se401_send_pict(struct usb_se401 *se401) +{ + /* integration time low */ + se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l); + /* integration time mid */ + se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m); + /* integration time mid */ + se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h); + /* reset level value */ + se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel); + /* red color gain */ + se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain); + /* green color gain */ + se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain); + /* blue color gain */ + se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain); + + return 0; +} + +static void se401_set_exposure(struct usb_se401 *se401, int brightness) +{ + int integration = brightness << 5; + + if (flickerless == 50) + integration = integration-integration % 106667; + if (flickerless == 60) + integration = integration-integration % 88889; + se401->brightness = integration >> 5; + se401->expose_h = (integration >> 16) & 0xff; + se401->expose_m = (integration >> 8) & 0xff; + se401->expose_l = integration & 0xff; +} + +static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p) +{ + p->brightness = se401->brightness; + if (se401->enhance) + p->whiteness = 32768; + else + p->whiteness = 0; + + p->colour = 65535; + p->contrast = 65535; + p->hue = se401->rgain << 10; + p->palette = se401->palette; + p->depth = 3; /* rgb24 */ + return 0; +} + + +static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p) +{ + if (p->palette != VIDEO_PALETTE_RGB24) + return 1; + se401->palette = p->palette; + if (p->hue != se401->hue) { + se401->rgain = p->hue >> 10; + se401->bgain = 0x40-(p->hue >> 10); + se401->hue = p->hue; + } + if (p->brightness != se401->brightness) + se401_set_exposure(se401, p->brightness); + + if (p->whiteness >= 32768) + se401->enhance = 1; + else + se401->enhance = 0; + se401_send_pict(se401); + se401_send_pict(se401); + return 0; +} + +/* + Hyundai have some really nice docs about this and other sensor related + stuff on their homepage: www.hei.co.kr +*/ +static void se401_auto_resetlevel(struct usb_se401 *se401) +{ + unsigned int ahrc, alrc; + int oldreset = se401->resetlevel; + + /* For some reason this normally read-only register doesn't get reset + to zero after reading them just once... + */ + se401_get_feature(se401, HV7131_REG_HIREFNOH); + se401_get_feature(se401, HV7131_REG_HIREFNOL); + se401_get_feature(se401, HV7131_REG_LOREFNOH); + se401_get_feature(se401, HV7131_REG_LOREFNOL); + ahrc = 256*se401_get_feature(se401, HV7131_REG_HIREFNOH) + + se401_get_feature(se401, HV7131_REG_HIREFNOL); + alrc = 256*se401_get_feature(se401, HV7131_REG_LOREFNOH) + + se401_get_feature(se401, HV7131_REG_LOREFNOL); + + /* Not an exact science, but it seems to work pretty well... */ + if (alrc > 10) { + while (alrc >= 10 && se401->resetlevel < 63) { + se401->resetlevel++; + alrc /= 2; + } + } else if (ahrc > 20) { + while (ahrc >= 20 && se401->resetlevel > 0) { + se401->resetlevel--; + ahrc /= 2; + } + } + if (se401->resetlevel != oldreset) + se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel); + + return; +} + +/* irq handler for snapshot button */ +static void se401_button_irq(struct urb *urb) +{ + struct usb_se401 *se401 = urb->context; + int status; + + if (!se401->dev) { + dev_info(&urb->dev->dev, "device vapourished\n"); + return; + } + + switch (urb->status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", + __func__, urb->status); + return; + default: + dbg("%s - nonzero urb status received: %d", + __func__, urb->status); + goto exit; + } + + if (urb->actual_length >= 2) + if (se401->button) + se401->buttonpressed = 1; +exit: + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status) + err("%s - usb_submit_urb failed with result %d", + __func__, status); +} + +static void se401_video_irq(struct urb *urb) +{ + struct usb_se401 *se401 = urb->context; + int length = urb->actual_length; + + /* ohoh... */ + if (!se401->streaming) + return; + + if (!se401->dev) { + dev_info(&urb->dev->dev, "device vapourished\n"); + return; + } + + /* 0 sized packets happen if we are to fast, but sometimes the camera + keeps sending them forever... + */ + if (length && !urb->status) { + se401->nullpackets = 0; + switch (se401->scratch[se401->scratch_next].state) { + case BUFFER_READY: + case BUFFER_BUSY: + se401->dropped++; + break; + case BUFFER_UNUSED: + memcpy(se401->scratch[se401->scratch_next].data, + (unsigned char *)urb->transfer_buffer, length); + se401->scratch[se401->scratch_next].state + = BUFFER_READY; + se401->scratch[se401->scratch_next].offset + = se401->bayeroffset; + se401->scratch[se401->scratch_next].length = length; + if (waitqueue_active(&se401->wq)) + wake_up_interruptible(&se401->wq); + se401->scratch_overflow = 0; + se401->scratch_next++; + if (se401->scratch_next >= SE401_NUMSCRATCH) + se401->scratch_next = 0; + break; + } + se401->bayeroffset += length; + if (se401->bayeroffset >= se401->cheight * se401->cwidth) + se401->bayeroffset = 0; + } else { + se401->nullpackets++; + if (se401->nullpackets > SE401_MAX_NULLPACKETS) + if (waitqueue_active(&se401->wq)) + wake_up_interruptible(&se401->wq); + } + + /* Resubmit urb for new data */ + urb->status = 0; + urb->dev = se401->dev; + if (usb_submit_urb(urb, GFP_KERNEL)) + dev_info(&urb->dev->dev, "urb burned down\n"); + return; +} + +static void se401_send_size(struct usb_se401 *se401, int width, int height) +{ + int i = 0; + int mode = 0x03; /* No compression */ + int sendheight = height; + int sendwidth = width; + + /* JangGu compression can only be used with the camera supported sizes, + but bayer seems to work with any size that fits on the sensor. + We check if we can use compression with the current size with either + 4 or 16 times subcapturing, if not we use uncompressed bayer data + but this will result in cutouts of the maximum size.... + */ + while (i < se401->sizes && !(se401->width[i] == width && + se401->height[i] == height)) + i++; + while (i < se401->sizes) { + if (se401->width[i] == width * 2 && + se401->height[i] == height * 2) { + sendheight = se401->height[i]; + sendwidth = se401->width[i]; + mode = 0x40; + } + if (se401->width[i] == width * 4 && + se401->height[i] == height * 4) { + sendheight = se401->height[i]; + sendwidth = se401->width[i]; + mode = 0x42; + } + i++; + } + + se401_sndctrl(1, se401, SE401_REQ_SET_WIDTH, sendwidth, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0); + se401_set_feature(se401, SE401_OPERATINGMODE, mode); + + if (mode == 0x03) + se401->format = FMT_BAYER; + else + se401->format = FMT_JANGGU; +} + +/* + In this function se401_send_pict is called several times, + for some reason (depending on the state of the sensor and the phase of + the moon :) doing this only in either place doesn't always work... +*/ +static int se401_start_stream(struct usb_se401 *se401) +{ + struct urb *urb; + int err = 0, i; + se401->streaming = 1; + + se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); + + /* Set picture settings */ + /* windowed + pix intg */ + se401_set_feature(se401, HV7131_REG_MODE_B, 0x05); + se401_send_pict(se401); + + se401_send_size(se401, se401->cwidth, se401->cheight); + + se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, + 0, NULL, 0); + + /* Do some memory allocation */ + for (i = 0; i < SE401_NUMFRAMES; i++) { + se401->frame[i].data = se401->fbuf + i * se401->maxframesize; + se401->frame[i].curpix = 0; + } + for (i = 0; i < SE401_NUMSBUF; i++) { + se401->sbuf[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL); + if (!se401->sbuf[i].data) { + for (i = i - 1; i >= 0; i--) { + kfree(se401->sbuf[i].data); + se401->sbuf[i].data = NULL; + } + return -ENOMEM; + } + } + + se401->bayeroffset = 0; + se401->scratch_next = 0; + se401->scratch_use = 0; + se401->scratch_overflow = 0; + for (i = 0; i < SE401_NUMSCRATCH; i++) { + se401->scratch[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL); + if (!se401->scratch[i].data) { + for (i = i - 1; i >= 0; i--) { + kfree(se401->scratch[i].data); + se401->scratch[i].data = NULL; + } + goto nomem_sbuf; + } + se401->scratch[i].state = BUFFER_UNUSED; + } + + for (i = 0; i < SE401_NUMSBUF; i++) { + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + for (i = i - 1; i >= 0; i--) { + usb_kill_urb(se401->urb[i]); + usb_free_urb(se401->urb[i]); + se401->urb[i] = NULL; + } + goto nomem_scratch; + } + + usb_fill_bulk_urb(urb, se401->dev, + usb_rcvbulkpipe(se401->dev, SE401_VIDEO_ENDPOINT), + se401->sbuf[i].data, SE401_PACKETSIZE, + se401_video_irq, + se401); + + se401->urb[i] = urb; + + err = usb_submit_urb(se401->urb[i], GFP_KERNEL); + if (err) + err("urb burned down"); + } + + se401->framecount = 0; + + return 0; + + nomem_scratch: + for (i = 0; i < SE401_NUMSCRATCH; i++) { + kfree(se401->scratch[i].data); + se401->scratch[i].data = NULL; + } + nomem_sbuf: + for (i = 0; i < SE401_NUMSBUF; i++) { + kfree(se401->sbuf[i].data); + se401->sbuf[i].data = NULL; + } + return -ENOMEM; +} + +static int se401_stop_stream(struct usb_se401 *se401) +{ + int i; + + if (!se401->streaming || !se401->dev) + return 1; + + se401->streaming = 0; + + se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0); + + se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); + + for (i = 0; i < SE401_NUMSBUF; i++) + if (se401->urb[i]) { + usb_kill_urb(se401->urb[i]); + usb_free_urb(se401->urb[i]); + se401->urb[i] = NULL; + kfree(se401->sbuf[i].data); + } + for (i = 0; i < SE401_NUMSCRATCH; i++) { + kfree(se401->scratch[i].data); + se401->scratch[i].data = NULL; + } + + return 0; +} + +static int se401_set_size(struct usb_se401 *se401, int width, int height) +{ + int wasstreaming = se401->streaming; + /* Check to see if we need to change */ + if (se401->cwidth == width && se401->cheight == height) + return 0; + + /* Check for a valid mode */ + if (!width || !height) + return 1; + if ((width & 1) || (height & 1)) + return 1; + if (width > se401->width[se401->sizes-1]) + return 1; + if (height > se401->height[se401->sizes-1]) + return 1; + + /* Stop a current stream and start it again at the new size */ + if (wasstreaming) + se401_stop_stream(se401); + se401->cwidth = width; + se401->cheight = height; + if (wasstreaming) + se401_start_stream(se401); + return 0; +} + + +/**************************************************************************** + * + * Video Decoding + * + ***************************************************************************/ + +/* + This shouldn't really be done in a v4l driver.... + But it does make the image look a lot more usable. + Basically it lifts the dark pixels more than the light pixels. +*/ +static inline void enhance_picture(unsigned char *frame, int len) +{ + while (len--) { + *frame = (((*frame^255)*(*frame^255))/255)^255; + frame++; + } +} + +static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data) +{ + struct se401_frame *frame = &se401->frame[se401->curframe]; + int linelength = se401->cwidth * 3; + + if (frame->curlinepix >= linelength) { + frame->curlinepix = 0; + frame->curline += linelength; + } + + /* First three are absolute, all others relative. + * Format is rgb from right to left (mirrorred image), + * we flip it to get bgr from left to right. */ + if (frame->curlinepix < 3) + *(frame->curline-frame->curlinepix) = 1 + data * 4; + else + *(frame->curline-frame->curlinepix) = + *(frame->curline-frame->curlinepix + 3) + data * 4; + frame->curlinepix++; +} + +static inline void decode_JangGu_vlc(struct usb_se401 *se401, + unsigned char *data, int bit_exp, int packetlength) +{ + int pos = 0; + int vlc_cod = 0; + int vlc_size = 0; + int vlc_data = 0; + int bit_cur; + int bit; + data += 4; + while (pos < packetlength) { + bit_cur = 8; + while (bit_cur && bit_exp) { + bit = ((*data) >> (bit_cur-1))&1; + if (!vlc_cod) { + if (bit) { + vlc_size++; + } else { + if (!vlc_size) + decode_JangGu_integrate(se401, 0); + else { + vlc_cod = 2; + vlc_data = 0; + } + } + } else { + if (vlc_cod == 2) { + if (!bit) + vlc_data = -(1 << vlc_size) + 1; + vlc_cod--; + } + vlc_size--; + vlc_data += bit << vlc_size; + if (!vlc_size) { + decode_JangGu_integrate(se401, vlc_data); + vlc_cod = 0; + } + } + bit_cur--; + bit_exp--; + } + pos++; + data++; + } +} + +static inline void decode_JangGu(struct usb_se401 *se401, + struct se401_scratch *buffer) +{ + unsigned char *data = buffer->data; + int len = buffer->length; + int bit_exp = 0, pix_exp = 0, frameinfo = 0, packetlength = 0, size; + int datapos = 0; + + /* New image? */ + if (!se401->frame[se401->curframe].curpix) { + se401->frame[se401->curframe].curlinepix = 0; + se401->frame[se401->curframe].curline = + se401->frame[se401->curframe].data+ + se401->cwidth * 3 - 1; + if (se401->frame[se401->curframe].grabstate == FRAME_READY) + se401->frame[se401->curframe].grabstate = FRAME_GRABBING; + se401->vlcdatapos = 0; + } + while (datapos < len) { + size = 1024 - se401->vlcdatapos; + if (size+datapos > len) + size = len-datapos; + memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size); + se401->vlcdatapos += size; + packetlength = 0; + if (se401->vlcdatapos >= 4) { + bit_exp = se401->vlcdata[3] + (se401->vlcdata[2] << 8); + pix_exp = se401->vlcdata[1] + + ((se401->vlcdata[0] & 0x3f) << 8); + frameinfo = se401->vlcdata[0] & 0xc0; + packetlength = ((bit_exp + 47) >> 4) << 1; + if (packetlength > 1024) { + se401->vlcdatapos = 0; + datapos = len; + packetlength = 0; + se401->error++; + se401->frame[se401->curframe].curpix = 0; + } + } + if (packetlength && se401->vlcdatapos >= packetlength) { + decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, + packetlength); + se401->frame[se401->curframe].curpix += pix_exp * 3; + datapos += size-(se401->vlcdatapos-packetlength); + se401->vlcdatapos = 0; + if (se401->frame[se401->curframe].curpix >= se401->cwidth * se401->cheight * 3) { + if (se401->frame[se401->curframe].curpix == se401->cwidth * se401->cheight * 3) { + if (se401->frame[se401->curframe].grabstate == FRAME_GRABBING) { + se401->frame[se401->curframe].grabstate = FRAME_DONE; + se401->framecount++; + se401->readcount++; + } + if (se401->frame[(se401->curframe + 1) & (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) + se401->curframe = (se401->curframe + 1) & (SE401_NUMFRAMES - 1); + } else + se401->error++; + se401->frame[se401->curframe].curpix = 0; + datapos = len; + } + } else + datapos += size; + } +} + +static inline void decode_bayer(struct usb_se401 *se401, + struct se401_scratch *buffer) +{ + unsigned char *data = buffer->data; + int len = buffer->length; + int offset = buffer->offset; + int datasize = se401->cwidth * se401->cheight; + struct se401_frame *frame = &se401->frame[se401->curframe]; + unsigned char *framedata = frame->data, *curline, *nextline; + int width = se401->cwidth; + int blineoffset = 0, bline; + int linelength = width * 3, i; + + + if (frame->curpix == 0) { + if (frame->grabstate == FRAME_READY) + frame->grabstate = FRAME_GRABBING; + + frame->curline = framedata + linelength; + frame->curlinepix = 0; + } + + if (offset != frame->curpix) { + /* Regard frame as lost :( */ + frame->curpix = 0; + se401->error++; + return; + } + + /* Check if we have to much data */ + if (frame->curpix + len > datasize) + len = datasize-frame->curpix; + + if (se401->cheight % 4) + blineoffset = 1; + bline = frame->curpix / se401->cwidth+blineoffset; + + curline = frame->curline; + nextline = curline + linelength; + if (nextline >= framedata+datasize * 3) + nextline = curline; + while (len) { + if (frame->curlinepix >= width) { + frame->curlinepix -= width; + bline = frame->curpix / width + blineoffset; + curline += linelength*2; + nextline += linelength*2; + if (curline >= framedata+datasize * 3) { + frame->curlinepix++; + curline -= 3; + nextline -= 3; + len--; + data++; + frame->curpix++; + } + if (nextline >= framedata+datasize*3) + nextline = curline; + } + if (bline & 1) { + if (frame->curlinepix & 1) { + *(curline + 2) = *data; + *(curline - 1) = *data; + *(nextline + 2) = *data; + *(nextline - 1) = *data; + } else { + *(curline + 1) = + (*(curline + 1) + *data) / 2; + *(curline-2) = + (*(curline - 2) + *data) / 2; + *(nextline + 1) = *data; + *(nextline - 2) = *data; + } + } else { + if (frame->curlinepix & 1) { + *(curline + 1) = + (*(curline + 1) + *data) / 2; + *(curline - 2) = + (*(curline - 2) + *data) / 2; + *(nextline + 1) = *data; + *(nextline - 2) = *data; + } else { + *curline = *data; + *(curline - 3) = *data; + *nextline = *data; + *(nextline - 3) = *data; + } + } + frame->curlinepix++; + curline -= 3; + nextline -= 3; + len--; + data++; + frame->curpix++; + } + frame->curline = curline; + + if (frame->curpix >= datasize) { + /* Fix the top line */ + framedata += linelength; + for (i = 0; i < linelength; i++) { + framedata--; + *framedata = *(framedata + linelength); + } + /* Fix the left side (green is already present) */ + for (i = 0; i < se401->cheight; i++) { + *framedata = *(framedata + 3); + *(framedata + 1) = *(framedata + 4); + *(framedata + 2) = *(framedata + 5); + framedata += linelength; + } + frame->curpix = 0; + frame->grabstate = FRAME_DONE; + se401->framecount++; + se401->readcount++; + if (se401->frame[(se401->curframe + 1) & + (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) { + se401->curframe = (se401->curframe+1) & + (SE401_NUMFRAMES-1); + } + } +} + +static int se401_newframe(struct usb_se401 *se401, int framenr) +{ + DECLARE_WAITQUEUE(wait, current); + int errors = 0; + + while (se401->streaming && + (se401->frame[framenr].grabstate == FRAME_READY || + se401->frame[framenr].grabstate == FRAME_GRABBING)) { + if (!se401->frame[framenr].curpix) + errors++; + + wait_interruptible( + se401->scratch[se401->scratch_use].state != BUFFER_READY, + &se401->wq, &wait); + if (se401->nullpackets > SE401_MAX_NULLPACKETS) { + se401->nullpackets = 0; + dev_info(&se401->dev->dev, + "too many null length packets, restarting capture\n"); + se401_stop_stream(se401); + se401_start_stream(se401); + } else { + if (se401->scratch[se401->scratch_use].state != + BUFFER_READY) { + se401->frame[framenr].grabstate = FRAME_ERROR; + return -EIO; + } + se401->scratch[se401->scratch_use].state = BUFFER_BUSY; + if (se401->format == FMT_JANGGU) + decode_JangGu(se401, + &se401->scratch[se401->scratch_use]); + else + decode_bayer(se401, + &se401->scratch[se401->scratch_use]); + + se401->scratch[se401->scratch_use].state = + BUFFER_UNUSED; + se401->scratch_use++; + if (se401->scratch_use >= SE401_NUMSCRATCH) + se401->scratch_use = 0; + if (errors > SE401_MAX_ERRORS) { + errors = 0; + dev_info(&se401->dev->dev, + "too many errors, restarting capture\n"); + se401_stop_stream(se401); + se401_start_stream(se401); + } + } + } + + if (se401->frame[framenr].grabstate == FRAME_DONE) + if (se401->enhance) + enhance_picture(se401->frame[framenr].data, + se401->cheight * se401->cwidth * 3); + return 0; +} + +static void usb_se401_remove_disconnected(struct usb_se401 *se401) +{ + int i; + + se401->dev = NULL; + + for (i = 0; i < SE401_NUMSBUF; i++) + if (se401->urb[i]) { + usb_kill_urb(se401->urb[i]); + usb_free_urb(se401->urb[i]); + se401->urb[i] = NULL; + kfree(se401->sbuf[i].data); + } + + for (i = 0; i < SE401_NUMSCRATCH; i++) + kfree(se401->scratch[i].data); + + if (se401->inturb) { + usb_kill_urb(se401->inturb); + usb_free_urb(se401->inturb); + } + dev_info(&se401->dev->dev, "%s disconnected", se401->camera_name); + + /* Free the memory */ + kfree(se401->width); + kfree(se401->height); + kfree(se401); +} + + + +/**************************************************************************** + * + * Video4Linux + * + ***************************************************************************/ + + +static int se401_open(struct file *file) +{ + struct video_device *dev = video_devdata(file); + struct usb_se401 *se401 = (struct usb_se401 *)dev; + int err = 0; + + mutex_lock(&se401->lock); + if (se401->user) { + mutex_unlock(&se401->lock); + return -EBUSY; + } + se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES); + if (se401->fbuf) + file->private_data = dev; + else + err = -ENOMEM; + se401->user = !err; + mutex_unlock(&se401->lock); + + return err; +} + +static int se401_close(struct file *file) +{ + struct video_device *dev = file->private_data; + struct usb_se401 *se401 = (struct usb_se401 *)dev; + int i; + + rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES); + if (se401->removed) { + dev_info(&se401->dev->dev, "device unregistered\n"); + usb_se401_remove_disconnected(se401); + } else { + for (i = 0; i < SE401_NUMFRAMES; i++) + se401->frame[i].grabstate = FRAME_UNUSED; + if (se401->streaming) + se401_stop_stream(se401); + se401->user = 0; + } + file->private_data = NULL; + return 0; +} + +static long se401_do_ioctl(struct file *file, unsigned int cmd, void *arg) +{ + struct video_device *vdev = file->private_data; + struct usb_se401 *se401 = (struct usb_se401 *)vdev; + + if (!se401->dev) + return -EIO; + + switch (cmd) { + case VIDIOCGCAP: + { + struct video_capability *b = arg; + strcpy(b->name, se401->camera_name); + b->type = VID_TYPE_CAPTURE; + b->channels = 1; + b->audios = 0; + b->maxwidth = se401->width[se401->sizes-1]; + b->maxheight = se401->height[se401->sizes-1]; + b->minwidth = se401->width[0]; + b->minheight = se401->height[0]; + return 0; + } + case VIDIOCGCHAN: + { + struct video_channel *v = arg; + + if (v->channel != 0) + return -EINVAL; + v->flags = 0; + v->tuners = 0; + v->type = VIDEO_TYPE_CAMERA; + strcpy(v->name, "Camera"); + return 0; + } + case VIDIOCSCHAN: + { + struct video_channel *v = arg; + + if (v->channel != 0) + return -EINVAL; + return 0; + } + case VIDIOCGPICT: + { + struct video_picture *p = arg; + + se401_get_pict(se401, p); + return 0; + } + case VIDIOCSPICT: + { + struct video_picture *p = arg; + + if (se401_set_pict(se401, p)) + return -EINVAL; + return 0; + } + case VIDIOCSWIN: + { + struct video_window *vw = arg; + + if (vw->flags) + return -EINVAL; + if (vw->clipcount) + return -EINVAL; + if (se401_set_size(se401, vw->width, vw->height)) + return -EINVAL; + return 0; + } + case VIDIOCGWIN: + { + struct video_window *vw = arg; + + vw->x = 0; /* FIXME */ + vw->y = 0; + vw->chromakey = 0; + vw->flags = 0; + vw->clipcount = 0; + vw->width = se401->cwidth; + vw->height = se401->cheight; + return 0; + } + case VIDIOCGMBUF: + { + struct video_mbuf *vm = arg; + int i; + + memset(vm, 0, sizeof(*vm)); + vm->size = SE401_NUMFRAMES * se401->maxframesize; + vm->frames = SE401_NUMFRAMES; + for (i = 0; i < SE401_NUMFRAMES; i++) + vm->offsets[i] = se401->maxframesize * i; + return 0; + } + case VIDIOCMCAPTURE: + { + struct video_mmap *vm = arg; + + if (vm->format != VIDEO_PALETTE_RGB24) + return -EINVAL; + if (vm->frame >= SE401_NUMFRAMES) + return -EINVAL; + if (se401->frame[vm->frame].grabstate != FRAME_UNUSED) + return -EBUSY; + + /* Is this according to the v4l spec??? */ + if (se401_set_size(se401, vm->width, vm->height)) + return -EINVAL; + se401->frame[vm->frame].grabstate = FRAME_READY; + + if (!se401->streaming) + se401_start_stream(se401); + + /* Set the picture properties */ + if (se401->framecount == 0) + se401_send_pict(se401); + /* Calibrate the reset level after a few frames. */ + if (se401->framecount % 20 == 1) + se401_auto_resetlevel(se401); + + return 0; + } + case VIDIOCSYNC: + { + int *frame = arg; + int ret = 0; + + if (*frame < 0 || *frame >= SE401_NUMFRAMES) + return -EINVAL; + + ret = se401_newframe(se401, *frame); + se401->frame[*frame].grabstate = FRAME_UNUSED; + return ret; + } + case VIDIOCGFBUF: + { + struct video_buffer *vb = arg; + + memset(vb, 0, sizeof(*vb)); + return 0; + } + case VIDIOCKEY: + return 0; + case VIDIOCCAPTURE: + return -EINVAL; + case VIDIOCSFBUF: + return -EINVAL; + case VIDIOCGTUNER: + case VIDIOCSTUNER: + return -EINVAL; + case VIDIOCGFREQ: + case VIDIOCSFREQ: + return -EINVAL; + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + return -EINVAL; + default: + return -ENOIOCTLCMD; + } /* end switch */ + + return 0; +} + +static long se401_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + return video_usercopy(file, cmd, arg, se401_do_ioctl); +} + +static ssize_t se401_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + int realcount = count, ret = 0; + struct video_device *dev = file->private_data; + struct usb_se401 *se401 = (struct usb_se401 *)dev; + + + if (se401->dev == NULL) + return -EIO; + if (realcount > se401->cwidth*se401->cheight*3) + realcount = se401->cwidth*se401->cheight*3; + + /* Shouldn't happen: */ + if (se401->frame[0].grabstate == FRAME_GRABBING) + return -EBUSY; + se401->frame[0].grabstate = FRAME_READY; + se401->frame[1].grabstate = FRAME_UNUSED; + se401->curframe = 0; + + if (!se401->streaming) + se401_start_stream(se401); + + /* Set the picture properties */ + if (se401->framecount == 0) + se401_send_pict(se401); + /* Calibrate the reset level after a few frames. */ + if (se401->framecount%20 == 1) + se401_auto_resetlevel(se401); + + ret = se401_newframe(se401, 0); + + se401->frame[0].grabstate = FRAME_UNUSED; + if (ret) + return ret; + if (copy_to_user(buf, se401->frame[0].data, realcount)) + return -EFAULT; + + return realcount; +} + +static int se401_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct video_device *dev = file->private_data; + struct usb_se401 *se401 = (struct usb_se401 *)dev; + unsigned long start = vma->vm_start; + unsigned long size = vma->vm_end-vma->vm_start; + unsigned long page, pos; + + mutex_lock(&se401->lock); + + if (se401->dev == NULL) { + mutex_unlock(&se401->lock); + return -EIO; + } + if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) + & ~(PAGE_SIZE - 1))) { + mutex_unlock(&se401->lock); + return -EINVAL; + } + pos = (unsigned long)se401->fbuf; + while (size > 0) { + page = vmalloc_to_pfn((void *)pos); + if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { + mutex_unlock(&se401->lock); + return -EAGAIN; + } + start += PAGE_SIZE; + pos += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + mutex_unlock(&se401->lock); + + return 0; +} + +static const struct v4l2_file_operations se401_fops = { + .owner = THIS_MODULE, + .open = se401_open, + .release = se401_close, + .read = se401_read, + .mmap = se401_mmap, + .ioctl = se401_ioctl, +}; +static struct video_device se401_template = { + .name = "se401 USB camera", + .fops = &se401_fops, + .release = video_device_release_empty, +}; + + + +/***************************/ +static int se401_init(struct usb_se401 *se401, int button) +{ + int i = 0, rc; + unsigned char cp[0x40]; + char temp[200]; + int slen; + + /* led on */ + se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); + + /* get camera descriptor */ + rc = se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, + cp, sizeof(cp)); + if (cp[1] != 0x41) { + err("Wrong descriptor type"); + return 1; + } + slen = snprintf(temp, 200, "ExtraFeatures: %d", cp[3]); + + se401->sizes = cp[4] + cp[5] * 256; + se401->width = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); + if (!se401->width) + return 1; + se401->height = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL); + if (!se401->height) { + kfree(se401->width); + return 1; + } + for (i = 0; i < se401->sizes; i++) { + se401->width[i] = cp[6 + i * 4 + 0] + cp[6 + i*4 + 1] * 256; + se401->height[i] = cp[6 + i * 4 + 2] + cp[6 + i * 4 + 3] * 256; + } + slen += snprintf(temp + slen, 200 - slen, " Sizes:"); + for (i = 0; i < se401->sizes; i++) { + slen += snprintf(temp + slen, 200 - slen, + " %dx%d", se401->width[i], se401->height[i]); + } + dev_info(&se401->dev->dev, "%s\n", temp); + se401->maxframesize = se401->width[se401->sizes-1] * + se401->height[se401->sizes - 1] * 3; + + rc = se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp)); + se401->cwidth = cp[0]+cp[1]*256; + rc = se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp)); + se401->cheight = cp[0]+cp[1]*256; + + if (!(cp[2] & SE401_FORMAT_BAYER)) { + err("Bayer format not supported!"); + return 1; + } + /* set output mode (BAYER) */ + se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, + SE401_FORMAT_BAYER, NULL, 0); + + rc = se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp)); + se401->brightness = cp[0]+cp[1]*256; + /* some default values */ + se401->resetlevel = 0x2d; + se401->rgain = 0x20; + se401->ggain = 0x20; + se401->bgain = 0x20; + se401_set_exposure(se401, 20000); + se401->palette = VIDEO_PALETTE_RGB24; + se401->enhance = 1; + se401->dropped = 0; + se401->error = 0; + se401->framecount = 0; + se401->readcount = 0; + + /* Start interrupt transfers for snapshot button */ + if (button) { + se401->inturb = usb_alloc_urb(0, GFP_KERNEL); + if (!se401->inturb) { + dev_info(&se401->dev->dev, + "Allocation of inturb failed\n"); + return 1; + } + usb_fill_int_urb(se401->inturb, se401->dev, + usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT), + &se401->button, sizeof(se401->button), + se401_button_irq, + se401, + 8 + ); + if (usb_submit_urb(se401->inturb, GFP_KERNEL)) { + dev_info(&se401->dev->dev, "int urb burned down\n"); + return 1; + } + } else + se401->inturb = NULL; + + /* Flash the led */ + se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); + se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0); + + return 0; +} + +static int se401_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct usb_interface_descriptor *interface; + struct usb_se401 *se401; + char *camera_name = NULL; + int button = 1; + + /* We don't handle multi-config cameras */ + if (dev->descriptor.bNumConfigurations != 1) + return -ENODEV; + + interface = &intf->cur_altsetting->desc; + + /* Is it an se401? */ + if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 && + le16_to_cpu(dev->descriptor.idProduct) == 0x0004) { + camera_name = "Endpoints/Aox SE401"; + } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 && + le16_to_cpu(dev->descriptor.idProduct) == 0x030b) { + camera_name = "Philips PCVC665K"; + } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && + le16_to_cpu(dev->descriptor.idProduct) == 0x5001) { + camera_name = "Kensington VideoCAM 67014"; + } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && + le16_to_cpu(dev->descriptor.idProduct) == 0x5002) { + camera_name = "Kensington VideoCAM 6701(5/7)"; + } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d && + le16_to_cpu(dev->descriptor.idProduct) == 0x5003) { + camera_name = "Kensington VideoCAM 67016"; + button = 0; + } else + return -ENODEV; + + /* Checking vendor/product should be enough, but what the hell */ + if (interface->bInterfaceClass != 0x00) + return -ENODEV; + if (interface->bInterfaceSubClass != 0x00) + return -ENODEV; + + /* We found one */ + dev_info(&intf->dev, "SE401 camera found: %s\n", camera_name); + + se401 = kzalloc(sizeof(*se401), GFP_KERNEL); + if (se401 == NULL) { + err("couldn't kmalloc se401 struct"); + return -ENOMEM; + } + + se401->dev = dev; + se401->iface = interface->bInterfaceNumber; + se401->camera_name = camera_name; + + dev_info(&intf->dev, "firmware version: %02x\n", + le16_to_cpu(dev->descriptor.bcdDevice) & 255); + + if (se401_init(se401, button)) { + kfree(se401); + return -EIO; + } + + memcpy(&se401->vdev, &se401_template, sizeof(se401_template)); + memcpy(se401->vdev.name, se401->camera_name, + strlen(se401->camera_name)); + init_waitqueue_head(&se401->wq); + mutex_init(&se401->lock); + wmb(); + + if (video_register_device(&se401->vdev, + VFL_TYPE_GRABBER, video_nr) < 0) { + kfree(se401); + err("video_register_device failed"); + return -EIO; + } + dev_info(&intf->dev, "registered new video device: %s\n", + video_device_node_name(&se401->vdev)); + + usb_set_intfdata(intf, se401); + return 0; +} + +static void se401_disconnect(struct usb_interface *intf) +{ + struct usb_se401 *se401 = usb_get_intfdata(intf); + + usb_set_intfdata(intf, NULL); + if (se401) { + video_unregister_device(&se401->vdev); + if (!se401->user) + usb_se401_remove_disconnected(se401); + else { + se401->frame[0].grabstate = FRAME_ERROR; + se401->frame[0].grabstate = FRAME_ERROR; + + se401->streaming = 0; + + wake_up_interruptible(&se401->wq); + se401->removed = 1; + } + } +} + +static struct usb_driver se401_driver = { + .name = "se401", + .id_table = device_table, + .probe = se401_probe, + .disconnect = se401_disconnect, +}; + + + +/**************************************************************************** + * + * Module routines + * + ***************************************************************************/ + +static int __init usb_se401_init(void) +{ + printk(KERN_INFO "SE401 usb camera driver version %s registering\n", + version); + if (flickerless) + if (flickerless != 50 && flickerless != 60) { + printk(KERN_ERR "Invallid flickerless value, use 0, 50 or 60.\n"); + return -1; + } + return usb_register(&se401_driver); +} + +static void __exit usb_se401_exit(void) +{ + usb_deregister(&se401_driver); + printk(KERN_INFO "SE401 driver deregistered\frame"); +} + +module_init(usb_se401_init); +module_exit(usb_se401_exit); diff --git a/drivers/staging/se401/se401.h b/drivers/staging/se401/se401.h new file mode 100644 index 0000000..bf7d2e9 --- /dev/null +++ b/drivers/staging/se401/se401.h @@ -0,0 +1,236 @@ + +#ifndef __LINUX_se401_H +#define __LINUX_se401_H + +#include +#include +#include +#include +#include + +#define se401_DEBUG /* Turn on debug messages */ + +#ifdef se401_DEBUG +# define PDEBUG(level, fmt, args...) \ +if (debug >= level) \ + info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args) +#else +# define PDEBUG(level, fmt, args...) do {} while (0) +#endif + +/* An almost drop-in replacement for sleep_on_interruptible */ +#define wait_interruptible(test, queue, wait) \ +{ \ + add_wait_queue(queue, wait); \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (test) \ + schedule(); \ + remove_wait_queue(queue, wait); \ + set_current_state(TASK_RUNNING); \ + if (signal_pending(current)) \ + break; \ +} + +#define SE401_REQ_GET_CAMERA_DESCRIPTOR 0x06 +#define SE401_REQ_START_CONTINUOUS_CAPTURE 0x41 +#define SE401_REQ_STOP_CONTINUOUS_CAPTURE 0x42 +#define SE401_REQ_CAPTURE_FRAME 0x43 +#define SE401_REQ_GET_BRT 0x44 +#define SE401_REQ_SET_BRT 0x45 +#define SE401_REQ_GET_WIDTH 0x4c +#define SE401_REQ_SET_WIDTH 0x4d +#define SE401_REQ_GET_HEIGHT 0x4e +#define SE401_REQ_SET_HEIGHT 0x4f +#define SE401_REQ_GET_OUTPUT_MODE 0x50 +#define SE401_REQ_SET_OUTPUT_MODE 0x51 +#define SE401_REQ_GET_EXT_FEATURE 0x52 +#define SE401_REQ_SET_EXT_FEATURE 0x53 +#define SE401_REQ_CAMERA_POWER 0x56 +#define SE401_REQ_LED_CONTROL 0x57 +#define SE401_REQ_BIOS 0xff + +#define SE401_BIOS_READ 0x07 + +#define SE401_FORMAT_BAYER 0x40 + +/* Hyundai hv7131b registers + 7121 and 7141 should be the same (haven't really checked...) */ +/* Mode registers: */ +#define HV7131_REG_MODE_A 0x00 +#define HV7131_REG_MODE_B 0x01 +#define HV7131_REG_MODE_C 0x02 +/* Frame registers: */ +#define HV7131_REG_FRSU 0x10 +#define HV7131_REG_FRSL 0x11 +#define HV7131_REG_FCSU 0x12 +#define HV7131_REG_FCSL 0x13 +#define HV7131_REG_FWHU 0x14 +#define HV7131_REG_FWHL 0x15 +#define HV7131_REG_FWWU 0x16 +#define HV7131_REG_FWWL 0x17 +/* Timing registers: */ +#define HV7131_REG_THBU 0x20 +#define HV7131_REG_THBL 0x21 +#define HV7131_REG_TVBU 0x22 +#define HV7131_REG_TVBL 0x23 +#define HV7131_REG_TITU 0x25 +#define HV7131_REG_TITM 0x26 +#define HV7131_REG_TITL 0x27 +#define HV7131_REG_TMCD 0x28 +/* Adjust Registers: */ +#define HV7131_REG_ARLV 0x30 +#define HV7131_REG_ARCG 0x31 +#define HV7131_REG_AGCG 0x32 +#define HV7131_REG_ABCG 0x33 +#define HV7131_REG_APBV 0x34 +#define HV7131_REG_ASLP 0x54 +/* Offset Registers: */ +#define HV7131_REG_OFSR 0x50 +#define HV7131_REG_OFSG 0x51 +#define HV7131_REG_OFSB 0x52 +/* REset level statistics registers: */ +#define HV7131_REG_LOREFNOH 0x57 +#define HV7131_REG_LOREFNOL 0x58 +#define HV7131_REG_HIREFNOH 0x59 +#define HV7131_REG_HIREFNOL 0x5a + +/* se401 registers */ +#define SE401_OPERATINGMODE 0x2000 + + +/* size of usb transfers */ +#define SE401_PACKETSIZE 4096 +/* number of queued bulk transfers to use, should be about 8 */ +#define SE401_NUMSBUF 1 +/* read the usb specs for this one :) */ +#define SE401_VIDEO_ENDPOINT 1 +#define SE401_BUTTON_ENDPOINT 2 +/* number of frames supported by the v4l part */ +#define SE401_NUMFRAMES 2 +/* scratch buffers for passing data to the decoders */ +#define SE401_NUMSCRATCH 32 +/* maximum amount of data in a JangGu packet */ +#define SE401_VLCDATALEN 1024 +/* number of nul sized packets to receive before kicking the camera */ +#define SE401_MAX_NULLPACKETS 4000 +/* number of decoding errors before kicking the camera */ +#define SE401_MAX_ERRORS 200 + +struct usb_device; + +struct se401_sbuf { + unsigned char *data; +}; + +enum { + FRAME_UNUSED, /* Unused (no MCAPTURE) */ + FRAME_READY, /* Ready to start grabbing */ + FRAME_GRABBING, /* In the process of being grabbed into */ + FRAME_DONE, /* Finished grabbing, but not been synced yet */ + FRAME_ERROR, /* Something bad happened while processing */ +}; + +enum { + FMT_BAYER, + FMT_JANGGU, +}; + +enum { + BUFFER_UNUSED, + BUFFER_READY, + BUFFER_BUSY, + BUFFER_DONE, +}; + +struct se401_scratch { + unsigned char *data; + volatile int state; + int offset; + int length; +}; + +struct se401_frame { + unsigned char *data; /* Frame buffer */ + + volatile int grabstate; /* State of grabbing */ + + unsigned char *curline; + int curlinepix; + int curpix; +}; + +struct usb_se401 { + struct video_device vdev; + + /* Device structure */ + struct usb_device *dev; + + unsigned char iface; + + char *camera_name; + + int change; + int brightness; + int hue; + int rgain; + int ggain; + int bgain; + int expose_h; + int expose_m; + int expose_l; + int resetlevel; + + int enhance; + + int format; + int sizes; + int *width; + int *height; + int cwidth; /* current width */ + int cheight; /* current height */ + int palette; + int maxframesize; + int cframesize; /* current framesize */ + + struct mutex lock; + int user; /* user count for exclusive use */ + int removed; /* device disconnected */ + + int streaming; /* Are we streaming video? */ + + char *fbuf; /* Videodev buffer area */ + + struct urb *urb[SE401_NUMSBUF]; + struct urb *inturb; + + int button; + int buttonpressed; + + int curframe; /* Current receiving frame */ + struct se401_frame frame[SE401_NUMFRAMES]; + int readcount; + int framecount; + int error; + int dropped; + + int scratch_next; + int scratch_use; + int scratch_overflow; + struct se401_scratch scratch[SE401_NUMSCRATCH]; + + /* Decoder specific data: */ + unsigned char vlcdata[SE401_VLCDATALEN]; + int vlcdatapos; + int bayeroffset; + + struct se401_sbuf sbuf[SE401_NUMSBUF]; + + wait_queue_head_t wq; /* Processes waiting */ + + int nullpackets; +}; + + + +#endif + -- cgit v0.10.2 From 39c3d488452ae206cfc8afda0db041ee55d01c3c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 25 Dec 2010 07:44:33 -0300 Subject: [media] cpia, stradis: remove deprecated V4L1 drivers Nobody stepped in to convert these drivers to V4L2, so they are now removed from the kernel. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/README.cpia b/Documentation/video4linux/README.cpia deleted file mode 100644 index 8a747fe..0000000 --- a/Documentation/video4linux/README.cpia +++ /dev/null @@ -1,191 +0,0 @@ -This is a driver for the CPiA PPC2 driven parallel connected -Camera. For example the Creative WebcamII is CPiA driven. - - ) [1]Peter Pregler, Linz 2000, published under the [2]GNU GPL - ---------------------------------------------------------------------------- - -USAGE: - -General: -======== - -1) Make sure you have created the video devices (/dev/video*): - -- if you have a recent MAKEDEV do a 'cd /dev;./MAKEDEV video' -- otherwise do a: - -cd /dev -mknod video0 c 81 0 -ln -s video0 video - -2) Compile the kernel (see below for the list of options to use), - configure your parport and reboot. - -3) If all worked well you should get messages similar - to the following (your versions may be different) on the console: - -V4L-Driver for Vision CPiA based cameras v0.7.4 -parport0: read2 timeout. -parport0: Multimedia device, VLSI Vision Ltd PPC2 -Parallel port driver for Vision CPiA based camera - CPIA Version: 1.20 (2.0) - CPIA PnP-ID: 0553:0002:0100 - VP-Version: 1.0 0100 - 1 camera(s) found - - -As modules: -=========== - -Make sure you have selected the following kernel options (you can -select all stuff as modules): - -The cpia-stuff is in the section 'Character devices -> Video For Linux'. - -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_FIFO=y -CONFIG_PARPORT_1284=y -CONFIG_VIDEO_DEV=m -CONFIG_VIDEO_CPIA=m -CONFIG_VIDEO_CPIA_PP=m - -For autoloading of all those modules you need to tell module-init-tools -some stuff. Add the following line to your module-init-tools config-file -(e.g. /etc/modprobe.conf or wherever your distribution does store that -stuff): - -options parport_pc io=0x378 irq=7 dma=3 -alias char-major-81 cpia_pp - -The first line tells the dma/irq channels to use. Those _must_ match -the settings of your BIOS. Do NOT simply use the values above. See -Documentation/parport.txt for more information about this. The second -line associates the video-device file with the driver. Of cause you -can also load the modules once upon boot (usually done in /etc/modules). - -Linked into the kernel: -======================= - -Make sure you have selected the following kernel options. Note that -you cannot compile the parport-stuff as modules and the cpia-driver -statically (the other way round is okay though). - -The cpia-stuff is in the section 'Character devices -> Video For Linux'. - -CONFIG_PARPORT=y -CONFIG_PARPORT_PC=y -CONFIG_PARPORT_PC_FIFO=y -CONFIG_PARPORT_1284=y -CONFIG_VIDEO_DEV=y -CONFIG_VIDEO_CPIA=y -CONFIG_VIDEO_CPIA_PP=y - -To use DMA/irq you will need to tell the kernel upon boot time the -hardware configuration of the parport. You can give the boot-parameter -at the LILO-prompt or specify it in lilo.conf. I use the following -append-line in lilo.conf: - - append="parport=0x378,7,3" - -See Documentation/parport.txt for more information about the -configuration of the parport and the values given above. Do not simply -use the values given above. - ---------------------------------------------------------------------------- -FEATURES: - -- mmap/read v4l-interface (but no overlay) -- image formats: CIF/QCIF, SIF/QSIF, various others used by isabel; - note: all sizes except CIF/QCIF are implemented by clipping, i.e. - pixels are not uploaded from the camera -- palettes: VIDEO_PALETTE_GRAY, VIDEO_PALETTE_RGB565, VIDEO_PALETTE_RGB555, - VIDEO_PALETTE_RGB24, VIDEO_PALETTE_RGB32, VIDEO_PALETTE_YUYV, - VIDEO_PALETTE_UYVY, VIDEO_PALETTE_YUV422 -- state information (color balance, exposure, ...) is preserved between - device opens -- complete control over camera via proc-interface (_all_ camera settings are - supported), there is also a python-gtk application available for this [3] -- works under SMP (but the driver is completely serialized and synchronous) - so you get no benefit from SMP, but at least it does not crash your box -- might work for non-Intel architecture, let us know about this - ---------------------------------------------------------------------------- -TESTED APPLICATIONS: - -- a simple test application based on Xt is available at [3] -- another test-application based on gqcam-0.4 (uses GTK) -- gqcam-0.6 should work -- xawtv-3.x (also the webcam software) -- xawtv-2.46 -- w3cam (cgi-interface and vidcat, e.g. you may try out 'vidcat |xv - -maxpect -root -quit +noresetroot -rmode 5 -') -- vic, the MBONE video conferencing tool (version 2.8ucl4-1) -- isabel 3R4beta (barely working, but AFAICT all the problems are on - their side) -- camserv-0.40 - -See [3] for pointers to v4l-applications. - ---------------------------------------------------------------------------- -KNOWN PROBLEMS: - -- some applications do not handle the image format correctly, you will - see strange horizontal stripes instead of a nice picture -> make sure - your application does use a supported image size or queries the driver - for the actually used size (reason behind this: the camera cannot - provide any image format, so if size NxM is requested the driver will - use a format to the closest fitting N1xM1, the application should now - query for this granted size, most applications do not). -- all the todo ;) -- if there is not enough light and the picture is too dark try to - adjust the SetSensorFPS setting, automatic frame rate adjustment - has its price -- do not try out isabel 3R4beta (built 135), you will be disappointed - ---------------------------------------------------------------------------- -TODO: - -- multiple camera support (struct camera or something) - This should work, - but hasn't been tested yet. -- architecture independence? -- SMP-safe asynchronous mmap interface -- nibble mode for old parport interfaces -- streaming capture, this should give a performance gain - ---------------------------------------------------------------------------- -IMPLEMENTATION NOTES: - -The camera can act in two modes, streaming or grabbing. Right now a -polling grab-scheme is used. Maybe interrupt driven streaming will be -used for a asynchronous mmap interface in the next major release of the -driver. This might give a better frame rate. - ---------------------------------------------------------------------------- -THANKS (in no particular order): - -- Scott J. Bertin for cleanups, the proc-filesystem - and much more -- Henry Bruce for providing developers information about - the CPiA chip, I wish all companies would treat Linux as seriously -- Karoly Erdei and RISC-Linz for being - my boss ;) resp. my employer and for providing me the hardware and - allow me to devote some working time to this project -- Manuel J. Petit de Gabriel for providing help - with Isabel (http://isabel.dit.upm.es/) -- Bas Huisman for writing the initial parport code -- Jarl Totland for setting up the mailing list - and maintaining the web-server[3] -- Chris Whiteford for fixes related to the - 1.02 firmware -- special kudos to all the tester whose machines crashed and/or - will crash. :) - ---------------------------------------------------------------------------- -REFERENCES - - 1. http://www.risc.uni-linz.ac.at/ - mailto:Peter_Pregler@email.com - 2. see the file COPYING in the top directory of the kernel tree - 3. http://webcam.sourceforge.net/ diff --git a/Documentation/video4linux/bttv/Cards b/Documentation/video4linux/bttv/Cards index 12217fc..db833ce 100644 --- a/Documentation/video4linux/bttv/Cards +++ b/Documentation/video4linux/bttv/Cards @@ -464,10 +464,6 @@ Siemens ------- Multimedia eXtension Board (MXB) (SAA7146, SAA7111) -Stradis -------- - SDM275,SDM250,SDM026,SDM025 (SAA7146, IBMMPEG2): MPEG2 decoder only - Powercolor ---------- MTV878 diff --git a/MAINTAINERS b/MAINTAINERS index 71e40f9..92203a3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5697,12 +5697,6 @@ M: Ion Badulescu S: Odd Fixes F: drivers/net/starfire* -STRADIS MPEG-2 DECODER DRIVER -M: Nathan Laredo -W: http://www.stradis.com/ -S: Maintained -F: drivers/media/video/stradis.c - SUN3/3X M: Sam Creasey W: http://sammy.net/sun3/ diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index d9e3b6d..7e7b27b 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -51,10 +51,6 @@ source "drivers/staging/cx25821/Kconfig" source "drivers/staging/tm6000/Kconfig" -source "drivers/staging/cpia/Kconfig" - -source "drivers/staging/stradis/Kconfig" - source "drivers/staging/se401/Kconfig" source "drivers/staging/usbvideo/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 8058a15..72e0c83 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -8,8 +8,6 @@ obj-$(CONFIG_SLICOSS) += slicoss/ obj-$(CONFIG_VIDEO_GO7007) += go7007/ obj-$(CONFIG_VIDEO_CX25821) += cx25821/ obj-$(CONFIG_VIDEO_TM6000) += tm6000/ -obj-$(CONFIG_VIDEO_CPIA) += cpia/ -obj-$(CONFIG_VIDEO_STRADIS) += stradis/ obj-$(CONFIG_USB_VICAM) += usbvideo/ obj-$(CONFIG_USB_SE401) += se401/ obj-$(CONFIG_LIRC_STAGING) += lirc/ diff --git a/drivers/staging/cpia/Kconfig b/drivers/staging/cpia/Kconfig deleted file mode 100644 index 205d247..0000000 --- a/drivers/staging/cpia/Kconfig +++ /dev/null @@ -1,39 +0,0 @@ -config VIDEO_CPIA - tristate "CPiA Video For Linux (DEPRECATED)" - depends on VIDEO_V4L1 - default n - ---help--- - This driver is DEPRECATED please use the gspca cpia1 module - instead. Note that you need atleast version 0.6.4 of libv4l for - the cpia1 gspca module. - - This is the video4linux driver for cameras based on Vision's CPiA - (Colour Processor Interface ASIC), such as the Creative Labs Video - Blaster Webcam II. If you have one of these cameras, say Y here - and select parallel port and/or USB lowlevel support below, - otherwise say N. This will not work with the Creative Webcam III. - - Please read for more - information. - - This driver is also available as a module (cpia). - -config VIDEO_CPIA_PP - tristate "CPiA Parallel Port Lowlevel Support" - depends on PARPORT_1284 && VIDEO_CPIA && PARPORT - help - This is the lowlevel parallel port support for cameras based on - Vision's CPiA (Colour Processor Interface ASIC), such as the - Creative Webcam II. If you have the parallel port version of one - of these cameras, say Y here, otherwise say N. It is also available - as a module (cpia_pp). - -config VIDEO_CPIA_USB - tristate "CPiA USB Lowlevel Support" - depends on VIDEO_CPIA && USB - help - This is the lowlevel USB support for cameras based on Vision's CPiA - (Colour Processor Interface ASIC), such as the Creative Webcam II. - If you have the USB version of one of these cameras, say Y here, - otherwise say N. This will not work with the Creative Webcam III. - It is also available as a module (cpia_usb). diff --git a/drivers/staging/cpia/Makefile b/drivers/staging/cpia/Makefile deleted file mode 100644 index 89e52f1..0000000 --- a/drivers/staging/cpia/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-$(CONFIG_VIDEO_CPIA) += cpia.o -obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o -obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o - -EXTRA_CFLAGS += -Idrivers/media/video diff --git a/drivers/staging/cpia/TODO b/drivers/staging/cpia/TODO deleted file mode 100644 index ccb1c07..0000000 --- a/drivers/staging/cpia/TODO +++ /dev/null @@ -1,8 +0,0 @@ -This is an obsolete driver for some cpia-based webcams that use the parallel port. -We couldn't find anyone with this hardware in order to port it to use V4L2. - -Also, parallel-port webcams are obsolete nowadays. - -If nobody take care on it, the driver will be removed for 2.6.38. - -Please send patches to linux-media@vger.kernel.org diff --git a/drivers/staging/cpia/cpia.c b/drivers/staging/cpia/cpia.c deleted file mode 100644 index 0e740b8..0000000 --- a/drivers/staging/cpia/cpia.c +++ /dev/null @@ -1,4028 +0,0 @@ -/* - * cpia CPiA driver - * - * Supports CPiA based Video Camera's. - * - * (C) Copyright 1999-2000 Peter Pregler - * (C) Copyright 1999-2000 Scott J. Bertin - * (C) Copyright 1999-2000 Johannes Erdfelt - * (C) Copyright 2000 STMicroelectronics - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */ -/* #define _CPIA_DEBUG_ 1 */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cpia.h" - -static int video_nr = -1; - -#ifdef MODULE -module_param(video_nr, int, 0); -MODULE_AUTHOR("Scott J. Bertin & Peter Pregler & Johannes Erdfelt "); -MODULE_DESCRIPTION("V4L-driver for Vision CPiA based cameras"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("video"); -#endif - -static unsigned short colorspace_conv; -module_param(colorspace_conv, ushort, 0444); -MODULE_PARM_DESC(colorspace_conv, - " Colorspace conversion:" - "\n 0 = disable, 1 = enable" - "\n Default value is 0" - ); - -#define ABOUT "V4L-Driver for Vision CPiA based cameras" - -#define CPIA_MODULE_CPIA (0<<5) -#define CPIA_MODULE_SYSTEM (1<<5) -#define CPIA_MODULE_VP_CTRL (5<<5) -#define CPIA_MODULE_CAPTURE (6<<5) -#define CPIA_MODULE_DEBUG (7<<5) - -#define INPUT (DATA_IN << 8) -#define OUTPUT (DATA_OUT << 8) - -#define CPIA_COMMAND_GetCPIAVersion (INPUT | CPIA_MODULE_CPIA | 1) -#define CPIA_COMMAND_GetPnPID (INPUT | CPIA_MODULE_CPIA | 2) -#define CPIA_COMMAND_GetCameraStatus (INPUT | CPIA_MODULE_CPIA | 3) -#define CPIA_COMMAND_GotoHiPower (OUTPUT | CPIA_MODULE_CPIA | 4) -#define CPIA_COMMAND_GotoLoPower (OUTPUT | CPIA_MODULE_CPIA | 5) -#define CPIA_COMMAND_GotoSuspend (OUTPUT | CPIA_MODULE_CPIA | 7) -#define CPIA_COMMAND_GotoPassThrough (OUTPUT | CPIA_MODULE_CPIA | 8) -#define CPIA_COMMAND_ModifyCameraStatus (OUTPUT | CPIA_MODULE_CPIA | 10) - -#define CPIA_COMMAND_ReadVCRegs (INPUT | CPIA_MODULE_SYSTEM | 1) -#define CPIA_COMMAND_WriteVCReg (OUTPUT | CPIA_MODULE_SYSTEM | 2) -#define CPIA_COMMAND_ReadMCPorts (INPUT | CPIA_MODULE_SYSTEM | 3) -#define CPIA_COMMAND_WriteMCPort (OUTPUT | CPIA_MODULE_SYSTEM | 4) -#define CPIA_COMMAND_SetBaudRate (OUTPUT | CPIA_MODULE_SYSTEM | 5) -#define CPIA_COMMAND_SetECPTiming (OUTPUT | CPIA_MODULE_SYSTEM | 6) -#define CPIA_COMMAND_ReadIDATA (INPUT | CPIA_MODULE_SYSTEM | 7) -#define CPIA_COMMAND_WriteIDATA (OUTPUT | CPIA_MODULE_SYSTEM | 8) -#define CPIA_COMMAND_GenericCall (OUTPUT | CPIA_MODULE_SYSTEM | 9) -#define CPIA_COMMAND_I2CStart (OUTPUT | CPIA_MODULE_SYSTEM | 10) -#define CPIA_COMMAND_I2CStop (OUTPUT | CPIA_MODULE_SYSTEM | 11) -#define CPIA_COMMAND_I2CWrite (OUTPUT | CPIA_MODULE_SYSTEM | 12) -#define CPIA_COMMAND_I2CRead (INPUT | CPIA_MODULE_SYSTEM | 13) - -#define CPIA_COMMAND_GetVPVersion (INPUT | CPIA_MODULE_VP_CTRL | 1) -#define CPIA_COMMAND_ResetFrameCounter (INPUT | CPIA_MODULE_VP_CTRL | 2) -#define CPIA_COMMAND_SetColourParams (OUTPUT | CPIA_MODULE_VP_CTRL | 3) -#define CPIA_COMMAND_SetExposure (OUTPUT | CPIA_MODULE_VP_CTRL | 4) -#define CPIA_COMMAND_SetColourBalance (OUTPUT | CPIA_MODULE_VP_CTRL | 6) -#define CPIA_COMMAND_SetSensorFPS (OUTPUT | CPIA_MODULE_VP_CTRL | 7) -#define CPIA_COMMAND_SetVPDefaults (OUTPUT | CPIA_MODULE_VP_CTRL | 8) -#define CPIA_COMMAND_SetApcor (OUTPUT | CPIA_MODULE_VP_CTRL | 9) -#define CPIA_COMMAND_SetFlickerCtrl (OUTPUT | CPIA_MODULE_VP_CTRL | 10) -#define CPIA_COMMAND_SetVLOffset (OUTPUT | CPIA_MODULE_VP_CTRL | 11) -#define CPIA_COMMAND_GetColourParams (INPUT | CPIA_MODULE_VP_CTRL | 16) -#define CPIA_COMMAND_GetColourBalance (INPUT | CPIA_MODULE_VP_CTRL | 17) -#define CPIA_COMMAND_GetExposure (INPUT | CPIA_MODULE_VP_CTRL | 18) -#define CPIA_COMMAND_SetSensorMatrix (OUTPUT | CPIA_MODULE_VP_CTRL | 19) -#define CPIA_COMMAND_ColourBars (OUTPUT | CPIA_MODULE_VP_CTRL | 25) -#define CPIA_COMMAND_ReadVPRegs (INPUT | CPIA_MODULE_VP_CTRL | 30) -#define CPIA_COMMAND_WriteVPReg (OUTPUT | CPIA_MODULE_VP_CTRL | 31) - -#define CPIA_COMMAND_GrabFrame (OUTPUT | CPIA_MODULE_CAPTURE | 1) -#define CPIA_COMMAND_UploadFrame (OUTPUT | CPIA_MODULE_CAPTURE | 2) -#define CPIA_COMMAND_SetGrabMode (OUTPUT | CPIA_MODULE_CAPTURE | 3) -#define CPIA_COMMAND_InitStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 4) -#define CPIA_COMMAND_FiniStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 5) -#define CPIA_COMMAND_StartStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 6) -#define CPIA_COMMAND_EndStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 7) -#define CPIA_COMMAND_SetFormat (OUTPUT | CPIA_MODULE_CAPTURE | 8) -#define CPIA_COMMAND_SetROI (OUTPUT | CPIA_MODULE_CAPTURE | 9) -#define CPIA_COMMAND_SetCompression (OUTPUT | CPIA_MODULE_CAPTURE | 10) -#define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11) -#define CPIA_COMMAND_SetYUVThresh (OUTPUT | CPIA_MODULE_CAPTURE | 12) -#define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13) -#define CPIA_COMMAND_DiscardFrame (OUTPUT | CPIA_MODULE_CAPTURE | 14) -#define CPIA_COMMAND_GrabReset (OUTPUT | CPIA_MODULE_CAPTURE | 15) - -#define CPIA_COMMAND_OutputRS232 (OUTPUT | CPIA_MODULE_DEBUG | 1) -#define CPIA_COMMAND_AbortProcess (OUTPUT | CPIA_MODULE_DEBUG | 4) -#define CPIA_COMMAND_SetDramPage (OUTPUT | CPIA_MODULE_DEBUG | 5) -#define CPIA_COMMAND_StartDramUpload (OUTPUT | CPIA_MODULE_DEBUG | 6) -#define CPIA_COMMAND_StartDummyDtream (OUTPUT | CPIA_MODULE_DEBUG | 8) -#define CPIA_COMMAND_AbortStream (OUTPUT | CPIA_MODULE_DEBUG | 9) -#define CPIA_COMMAND_DownloadDRAM (OUTPUT | CPIA_MODULE_DEBUG | 10) -#define CPIA_COMMAND_Null (OUTPUT | CPIA_MODULE_DEBUG | 11) - -enum { - FRAME_READY, /* Ready to grab into */ - FRAME_GRABBING, /* In the process of being grabbed into */ - FRAME_DONE, /* Finished grabbing, but not been synced yet */ - FRAME_UNUSED, /* Unused (no MCAPTURE) */ -}; - -#define COMMAND_NONE 0x0000 -#define COMMAND_SETCOMPRESSION 0x0001 -#define COMMAND_SETCOMPRESSIONTARGET 0x0002 -#define COMMAND_SETCOLOURPARAMS 0x0004 -#define COMMAND_SETFORMAT 0x0008 -#define COMMAND_PAUSE 0x0010 -#define COMMAND_RESUME 0x0020 -#define COMMAND_SETYUVTHRESH 0x0040 -#define COMMAND_SETECPTIMING 0x0080 -#define COMMAND_SETCOMPRESSIONPARAMS 0x0100 -#define COMMAND_SETEXPOSURE 0x0200 -#define COMMAND_SETCOLOURBALANCE 0x0400 -#define COMMAND_SETSENSORFPS 0x0800 -#define COMMAND_SETAPCOR 0x1000 -#define COMMAND_SETFLICKERCTRL 0x2000 -#define COMMAND_SETVLOFFSET 0x4000 -#define COMMAND_SETLIGHTS 0x8000 - -#define ROUND_UP_EXP_FOR_FLICKER 15 - -/* Constants for automatic frame rate adjustment */ -#define MAX_EXP 302 -#define MAX_EXP_102 255 -#define LOW_EXP 140 -#define VERY_LOW_EXP 70 -#define TC 94 -#define EXP_ACC_DARK 50 -#define EXP_ACC_LIGHT 90 -#define HIGH_COMP_102 160 -#define MAX_COMP 239 -#define DARK_TIME 3 -#define LIGHT_TIME 3 - -/* Maximum number of 10ms loops to wait for the stream to become ready */ -#define READY_TIMEOUT 100 - -/* Developer's Guide Table 5 p 3-34 - * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/ -static u8 flicker_jumps[2][2][4] = -{ { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } }, - { { 64, 32, 16, 8 }, { 76, 38, 19, 9} } -}; - -/* forward declaration of local function */ -static void reset_camera_struct(struct cam_data *cam); -static int find_over_exposure(int brightness); -static void set_flicker(struct cam_params *params, volatile u32 *command_flags, - int on); - - -/********************************************************************** - * - * Memory management - * - **********************************************************************/ -static void *rvmalloc(unsigned long size) -{ - void *mem; - unsigned long adr; - - size = PAGE_ALIGN(size); - mem = vmalloc_32(size); - if (!mem) - return NULL; - - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long) mem; - while (size > 0) { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - return mem; -} - -static void rvfree(void *mem, unsigned long size) -{ - unsigned long adr; - - if (!mem) - return; - - adr = (unsigned long) mem; - while ((long) size > 0) { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - vfree(mem); -} - -/********************************************************************** - * - * /proc interface - * - **********************************************************************/ -#ifdef CONFIG_PROC_FS -static struct proc_dir_entry *cpia_proc_root=NULL; - -static int cpia_proc_show(struct seq_file *m, void *v) -{ - struct cam_data *cam = m->private; - int tmp; - char tmpstr[29]; - - seq_printf(m, "read-only\n-----------------------\n"); - seq_printf(m, "V4L Driver version: %d.%d.%d\n", - CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER); - seq_printf(m, "CPIA Version: %d.%02d (%d.%d)\n", - cam->params.version.firmwareVersion, - cam->params.version.firmwareRevision, - cam->params.version.vcVersion, - cam->params.version.vcRevision); - seq_printf(m, "CPIA PnP-ID: %04x:%04x:%04x\n", - cam->params.pnpID.vendor, cam->params.pnpID.product, - cam->params.pnpID.deviceRevision); - seq_printf(m, "VP-Version: %d.%d %04x\n", - cam->params.vpVersion.vpVersion, - cam->params.vpVersion.vpRevision, - cam->params.vpVersion.cameraHeadID); - - seq_printf(m, "system_state: %#04x\n", - cam->params.status.systemState); - seq_printf(m, "grab_state: %#04x\n", - cam->params.status.grabState); - seq_printf(m, "stream_state: %#04x\n", - cam->params.status.streamState); - seq_printf(m, "fatal_error: %#04x\n", - cam->params.status.fatalError); - seq_printf(m, "cmd_error: %#04x\n", - cam->params.status.cmdError); - seq_printf(m, "debug_flags: %#04x\n", - cam->params.status.debugFlags); - seq_printf(m, "vp_status: %#04x\n", - cam->params.status.vpStatus); - seq_printf(m, "error_code: %#04x\n", - cam->params.status.errorCode); - /* QX3 specific entries */ - if (cam->params.qx3.qx3_detected) { - seq_printf(m, "button: %4d\n", - cam->params.qx3.button); - seq_printf(m, "cradled: %4d\n", - cam->params.qx3.cradled); - } - seq_printf(m, "video_size: %s\n", - cam->params.format.videoSize == VIDEOSIZE_CIF ? - "CIF " : "QCIF"); - seq_printf(m, "roi: (%3d, %3d) to (%3d, %3d)\n", - cam->params.roi.colStart*8, - cam->params.roi.rowStart*4, - cam->params.roi.colEnd*8, - cam->params.roi.rowEnd*4); - seq_printf(m, "actual_fps: %3d\n", cam->fps); - seq_printf(m, "transfer_rate: %4dkB/s\n", - cam->transfer_rate); - - seq_printf(m, "\nread-write\n"); - seq_printf(m, "----------------------- current min" - " max default comment\n"); - seq_printf(m, "brightness: %8d %8d %8d %8d\n", - cam->params.colourParams.brightness, 0, 100, 50); - if (cam->params.version.firmwareVersion == 1 && - cam->params.version.firmwareRevision == 2) - /* 1-02 firmware limits contrast to 80 */ - tmp = 80; - else - tmp = 96; - - seq_printf(m, "contrast: %8d %8d %8d %8d" - " steps of 8\n", - cam->params.colourParams.contrast, 0, tmp, 48); - seq_printf(m, "saturation: %8d %8d %8d %8d\n", - cam->params.colourParams.saturation, 0, 100, 50); - tmp = (25000+5000*cam->params.sensorFps.baserate)/ - (1<params.sensorFps.divisor); - seq_printf(m, "sensor_fps: %4d.%03d %8d %8d %8d\n", - tmp/1000, tmp%1000, 3, 30, 15); - seq_printf(m, "stream_start_line: %8d %8d %8d %8d\n", - 2*cam->params.streamStartLine, 0, - cam->params.format.videoSize == VIDEOSIZE_CIF ? 288:144, - cam->params.format.videoSize == VIDEOSIZE_CIF ? 240:120); - seq_printf(m, "sub_sample: %8s %8s %8s %8s\n", - cam->params.format.subSample == SUBSAMPLE_420 ? - "420" : "422", "420", "422", "422"); - seq_printf(m, "yuv_order: %8s %8s %8s %8s\n", - cam->params.format.yuvOrder == YUVORDER_YUYV ? - "YUYV" : "UYVY", "YUYV" , "UYVY", "YUYV"); - seq_printf(m, "ecp_timing: %8s %8s %8s %8s\n", - cam->params.ecpTiming ? "slow" : "normal", "slow", - "normal", "normal"); - - if (cam->params.colourBalance.balanceMode == 2) { - sprintf(tmpstr, "auto"); - } else { - sprintf(tmpstr, "manual"); - } - seq_printf(m, "color_balance_mode: %8s %8s %8s" - " %8s\n", tmpstr, "manual", "auto", "auto"); - seq_printf(m, "red_gain: %8d %8d %8d %8d\n", - cam->params.colourBalance.redGain, 0, 212, 32); - seq_printf(m, "green_gain: %8d %8d %8d %8d\n", - cam->params.colourBalance.greenGain, 0, 212, 6); - seq_printf(m, "blue_gain: %8d %8d %8d %8d\n", - cam->params.colourBalance.blueGain, 0, 212, 92); - - if (cam->params.version.firmwareVersion == 1 && - cam->params.version.firmwareRevision == 2) - /* 1-02 firmware limits gain to 2 */ - sprintf(tmpstr, "%8d %8d %8d", 1, 2, 2); - else - sprintf(tmpstr, "%8d %8d %8d", 1, 8, 2); - - if (cam->params.exposure.gainMode == 0) - seq_printf(m, "max_gain: unknown %28s" - " powers of 2\n", tmpstr); - else - seq_printf(m, "max_gain: %8d %28s" - " 1,2,4 or 8 \n", - 1<<(cam->params.exposure.gainMode-1), tmpstr); - - switch(cam->params.exposure.expMode) { - case 1: - case 3: - sprintf(tmpstr, "manual"); - break; - case 2: - sprintf(tmpstr, "auto"); - break; - default: - sprintf(tmpstr, "unknown"); - break; - } - seq_printf(m, "exposure_mode: %8s %8s %8s" - " %8s\n", tmpstr, "manual", "auto", "auto"); - seq_printf(m, "centre_weight: %8s %8s %8s %8s\n", - (2-cam->params.exposure.centreWeight) ? "on" : "off", - "off", "on", "on"); - seq_printf(m, "gain: %8d %8d max_gain %8d 1,2,4,8 possible\n", - 1<params.exposure.gain, 1, 1); - if (cam->params.version.firmwareVersion == 1 && - cam->params.version.firmwareRevision == 2) - /* 1-02 firmware limits fineExp/2 to 127 */ - tmp = 254; - else - tmp = 510; - - seq_printf(m, "fine_exp: %8d %8d %8d %8d\n", - cam->params.exposure.fineExp*2, 0, tmp, 0); - if (cam->params.version.firmwareVersion == 1 && - cam->params.version.firmwareRevision == 2) - /* 1-02 firmware limits coarseExpHi to 0 */ - tmp = MAX_EXP_102; - else - tmp = MAX_EXP; - - seq_printf(m, "coarse_exp: %8d %8d %8d" - " %8d\n", cam->params.exposure.coarseExpLo+ - 256*cam->params.exposure.coarseExpHi, 0, tmp, 185); - seq_printf(m, "red_comp: %8d %8d %8d %8d\n", - cam->params.exposure.redComp, COMP_RED, 255, COMP_RED); - seq_printf(m, "green1_comp: %8d %8d %8d %8d\n", - cam->params.exposure.green1Comp, COMP_GREEN1, 255, - COMP_GREEN1); - seq_printf(m, "green2_comp: %8d %8d %8d %8d\n", - cam->params.exposure.green2Comp, COMP_GREEN2, 255, - COMP_GREEN2); - seq_printf(m, "blue_comp: %8d %8d %8d %8d\n", - cam->params.exposure.blueComp, COMP_BLUE, 255, COMP_BLUE); - - seq_printf(m, "apcor_gain1: %#8x %#8x %#8x %#8x\n", - cam->params.apcor.gain1, 0, 0xff, 0x1c); - seq_printf(m, "apcor_gain2: %#8x %#8x %#8x %#8x\n", - cam->params.apcor.gain2, 0, 0xff, 0x1a); - seq_printf(m, "apcor_gain4: %#8x %#8x %#8x %#8x\n", - cam->params.apcor.gain4, 0, 0xff, 0x2d); - seq_printf(m, "apcor_gain8: %#8x %#8x %#8x %#8x\n", - cam->params.apcor.gain8, 0, 0xff, 0x2a); - seq_printf(m, "vl_offset_gain1: %8d %8d %8d %8d\n", - cam->params.vlOffset.gain1, 0, 255, 24); - seq_printf(m, "vl_offset_gain2: %8d %8d %8d %8d\n", - cam->params.vlOffset.gain2, 0, 255, 28); - seq_printf(m, "vl_offset_gain4: %8d %8d %8d %8d\n", - cam->params.vlOffset.gain4, 0, 255, 30); - seq_printf(m, "vl_offset_gain8: %8d %8d %8d %8d\n", - cam->params.vlOffset.gain8, 0, 255, 30); - seq_printf(m, "flicker_control: %8s %8s %8s %8s\n", - cam->params.flickerControl.flickerMode ? "on" : "off", - "off", "on", "off"); - seq_printf(m, "mains_frequency: %8d %8d %8d %8d" - " only 50/60\n", - cam->mainsFreq ? 60 : 50, 50, 60, 50); - if(cam->params.flickerControl.allowableOverExposure < 0) - seq_printf(m, "allowable_overexposure: %4dauto auto %8d auto\n", - -cam->params.flickerControl.allowableOverExposure, - 255); - else - seq_printf(m, "allowable_overexposure: %8d auto %8d auto\n", - cam->params.flickerControl.allowableOverExposure, - 255); - seq_printf(m, "compression_mode: "); - switch(cam->params.compression.mode) { - case CPIA_COMPRESSION_NONE: - seq_printf(m, "%8s", "none"); - break; - case CPIA_COMPRESSION_AUTO: - seq_printf(m, "%8s", "auto"); - break; - case CPIA_COMPRESSION_MANUAL: - seq_printf(m, "%8s", "manual"); - break; - default: - seq_printf(m, "%8s", "unknown"); - break; - } - seq_printf(m, " none,auto,manual auto\n"); - seq_printf(m, "decimation_enable: %8s %8s %8s %8s\n", - cam->params.compression.decimation == - DECIMATION_ENAB ? "on":"off", "off", "on", - "off"); - seq_printf(m, "compression_target: %9s %9s %9s %9s\n", - cam->params.compressionTarget.frTargeting == - CPIA_COMPRESSION_TARGET_FRAMERATE ? - "framerate":"quality", - "framerate", "quality", "quality"); - seq_printf(m, "target_framerate: %8d %8d %8d %8d\n", - cam->params.compressionTarget.targetFR, 1, 30, 15); - seq_printf(m, "target_quality: %8d %8d %8d %8d\n", - cam->params.compressionTarget.targetQ, 1, 64, 5); - seq_printf(m, "y_threshold: %8d %8d %8d %8d\n", - cam->params.yuvThreshold.yThreshold, 0, 31, 6); - seq_printf(m, "uv_threshold: %8d %8d %8d %8d\n", - cam->params.yuvThreshold.uvThreshold, 0, 31, 6); - seq_printf(m, "hysteresis: %8d %8d %8d %8d\n", - cam->params.compressionParams.hysteresis, 0, 255, 3); - seq_printf(m, "threshold_max: %8d %8d %8d %8d\n", - cam->params.compressionParams.threshMax, 0, 255, 11); - seq_printf(m, "small_step: %8d %8d %8d %8d\n", - cam->params.compressionParams.smallStep, 0, 255, 1); - seq_printf(m, "large_step: %8d %8d %8d %8d\n", - cam->params.compressionParams.largeStep, 0, 255, 3); - seq_printf(m, "decimation_hysteresis: %8d %8d %8d %8d\n", - cam->params.compressionParams.decimationHysteresis, - 0, 255, 2); - seq_printf(m, "fr_diff_step_thresh: %8d %8d %8d %8d\n", - cam->params.compressionParams.frDiffStepThresh, - 0, 255, 5); - seq_printf(m, "q_diff_step_thresh: %8d %8d %8d %8d\n", - cam->params.compressionParams.qDiffStepThresh, - 0, 255, 3); - seq_printf(m, "decimation_thresh_mod: %8d %8d %8d %8d\n", - cam->params.compressionParams.decimationThreshMod, - 0, 255, 2); - /* QX3 specific entries */ - if (cam->params.qx3.qx3_detected) { - seq_printf(m, "toplight: %8s %8s %8s %8s\n", - cam->params.qx3.toplight ? "on" : "off", - "off", "on", "off"); - seq_printf(m, "bottomlight: %8s %8s %8s %8s\n", - cam->params.qx3.bottomlight ? "on" : "off", - "off", "on", "off"); - } - - return 0; -} - -static int cpia_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, cpia_proc_show, PDE(inode)->data); -} - -static int match(char *checkstr, char **buffer, size_t *count, - int *find_colon, int *err) -{ - int ret, colon_found = 1; - int len = strlen(checkstr); - ret = (len <= *count && strncmp(*buffer, checkstr, len) == 0); - if (ret) { - *buffer += len; - *count -= len; - if (*find_colon) { - colon_found = 0; - while (*count && (**buffer == ' ' || **buffer == '\t' || - (!colon_found && **buffer == ':'))) { - if (**buffer == ':') - colon_found = 1; - --*count; - ++*buffer; - } - if (!*count || !colon_found) - *err = -EINVAL; - *find_colon = 0; - } - } - return ret; -} - -static unsigned long int value(char **buffer, size_t *count, int *err) -{ - char *p; - unsigned long int ret; - ret = simple_strtoul(*buffer, &p, 0); - if (p == *buffer) - *err = -EINVAL; - else { - *count -= p - *buffer; - *buffer = p; - } - return ret; -} - -static ssize_t cpia_proc_write(struct file *file, const char __user *buf, - size_t count, loff_t *pos) -{ - struct cam_data *cam = PDE(file->f_path.dentry->d_inode)->data; - struct cam_params new_params; - char *page, *buffer; - int retval, find_colon; - int size = count; - unsigned long val = 0; - u32 command_flags = 0; - u8 new_mains; - - /* - * This code to copy from buf to page is shamelessly copied - * from the comx driver - */ - if (count > PAGE_SIZE) { - printk(KERN_ERR "count is %zu > %d!!!\n", count, (int)PAGE_SIZE); - return -ENOSPC; - } - - if (!(page = (char *)__get_free_page(GFP_KERNEL))) return -ENOMEM; - - if(copy_from_user(page, buf, count)) - { - retval = -EFAULT; - goto out; - } - - if (page[count-1] == '\n') - page[count-1] = '\0'; - else if (count < PAGE_SIZE) - page[count] = '\0'; - else if (page[count]) { - retval = -EINVAL; - goto out; - } - - buffer = page; - - if (mutex_lock_interruptible(&cam->param_lock)) - return -ERESTARTSYS; - - /* - * Skip over leading whitespace - */ - while (count && isspace(*buffer)) { - --count; - ++buffer; - } - - memcpy(&new_params, &cam->params, sizeof(struct cam_params)); - new_mains = cam->mainsFreq; - -#define MATCH(x) (match(x, &buffer, &count, &find_colon, &retval)) -#define VALUE (value(&buffer,&count, &retval)) -#define FIRMWARE_VERSION(x,y) (new_params.version.firmwareVersion == (x) && \ - new_params.version.firmwareRevision == (y)) - - retval = 0; - while (count && !retval) { - find_colon = 1; - if (MATCH("brightness")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 100) - new_params.colourParams.brightness = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOLOURPARAMS; - if(new_params.flickerControl.allowableOverExposure < 0) - new_params.flickerControl.allowableOverExposure = - -find_over_exposure(new_params.colourParams.brightness); - if(new_params.flickerControl.flickerMode != 0) - command_flags |= COMMAND_SETFLICKERCTRL; - - } else if (MATCH("contrast")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 100) { - /* contrast is in steps of 8, so round*/ - val = ((val + 3) / 8) * 8; - /* 1-02 firmware limits contrast to 80*/ - if (FIRMWARE_VERSION(1,2) && val > 80) - val = 80; - - new_params.colourParams.contrast = val; - } else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOLOURPARAMS; - } else if (MATCH("saturation")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 100) - new_params.colourParams.saturation = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOLOURPARAMS; - } else if (MATCH("sensor_fps")) { - if (!retval) - val = VALUE; - - if (!retval) { - /* find values so that sensorFPS is minimized, - * but >= val */ - if (val > 30) - retval = -EINVAL; - else if (val > 25) { - new_params.sensorFps.divisor = 0; - new_params.sensorFps.baserate = 1; - } else if (val > 15) { - new_params.sensorFps.divisor = 0; - new_params.sensorFps.baserate = 0; - } else if (val > 12) { - new_params.sensorFps.divisor = 1; - new_params.sensorFps.baserate = 1; - } else if (val > 7) { - new_params.sensorFps.divisor = 1; - new_params.sensorFps.baserate = 0; - } else if (val > 6) { - new_params.sensorFps.divisor = 2; - new_params.sensorFps.baserate = 1; - } else if (val > 3) { - new_params.sensorFps.divisor = 2; - new_params.sensorFps.baserate = 0; - } else { - new_params.sensorFps.divisor = 3; - /* Either base rate would work here */ - new_params.sensorFps.baserate = 1; - } - new_params.flickerControl.coarseJump = - flicker_jumps[new_mains] - [new_params.sensorFps.baserate] - [new_params.sensorFps.divisor]; - if (new_params.flickerControl.flickerMode) - command_flags |= COMMAND_SETFLICKERCTRL; - } - command_flags |= COMMAND_SETSENSORFPS; - cam->exposure_status = EXPOSURE_NORMAL; - } else if (MATCH("stream_start_line")) { - if (!retval) - val = VALUE; - - if (!retval) { - int max_line = 288; - - if (new_params.format.videoSize == VIDEOSIZE_QCIF) - max_line = 144; - if (val <= max_line) - new_params.streamStartLine = val/2; - else - retval = -EINVAL; - } - } else if (MATCH("sub_sample")) { - if (!retval && MATCH("420")) - new_params.format.subSample = SUBSAMPLE_420; - else if (!retval && MATCH("422")) - new_params.format.subSample = SUBSAMPLE_422; - else - retval = -EINVAL; - - command_flags |= COMMAND_SETFORMAT; - } else if (MATCH("yuv_order")) { - if (!retval && MATCH("YUYV")) - new_params.format.yuvOrder = YUVORDER_YUYV; - else if (!retval && MATCH("UYVY")) - new_params.format.yuvOrder = YUVORDER_UYVY; - else - retval = -EINVAL; - - command_flags |= COMMAND_SETFORMAT; - } else if (MATCH("ecp_timing")) { - if (!retval && MATCH("normal")) - new_params.ecpTiming = 0; - else if (!retval && MATCH("slow")) - new_params.ecpTiming = 1; - else - retval = -EINVAL; - - command_flags |= COMMAND_SETECPTIMING; - } else if (MATCH("color_balance_mode")) { - if (!retval && MATCH("manual")) - new_params.colourBalance.balanceMode = 3; - else if (!retval && MATCH("auto")) - new_params.colourBalance.balanceMode = 2; - else - retval = -EINVAL; - - command_flags |= COMMAND_SETCOLOURBALANCE; - } else if (MATCH("red_gain")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 212) { - new_params.colourBalance.redGain = val; - new_params.colourBalance.balanceMode = 1; - } else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOLOURBALANCE; - } else if (MATCH("green_gain")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 212) { - new_params.colourBalance.greenGain = val; - new_params.colourBalance.balanceMode = 1; - } else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOLOURBALANCE; - } else if (MATCH("blue_gain")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 212) { - new_params.colourBalance.blueGain = val; - new_params.colourBalance.balanceMode = 1; - } else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOLOURBALANCE; - } else if (MATCH("max_gain")) { - if (!retval) - val = VALUE; - - if (!retval) { - /* 1-02 firmware limits gain to 2 */ - if (FIRMWARE_VERSION(1,2) && val > 2) - val = 2; - switch(val) { - case 1: - new_params.exposure.gainMode = 1; - break; - case 2: - new_params.exposure.gainMode = 2; - break; - case 4: - new_params.exposure.gainMode = 3; - break; - case 8: - new_params.exposure.gainMode = 4; - break; - default: - retval = -EINVAL; - break; - } - } - command_flags |= COMMAND_SETEXPOSURE; - } else if (MATCH("exposure_mode")) { - if (!retval && MATCH("auto")) - new_params.exposure.expMode = 2; - else if (!retval && MATCH("manual")) { - if (new_params.exposure.expMode == 2) - new_params.exposure.expMode = 3; - if(new_params.flickerControl.flickerMode != 0) - command_flags |= COMMAND_SETFLICKERCTRL; - new_params.flickerControl.flickerMode = 0; - } else - retval = -EINVAL; - - command_flags |= COMMAND_SETEXPOSURE; - } else if (MATCH("centre_weight")) { - if (!retval && MATCH("on")) - new_params.exposure.centreWeight = 1; - else if (!retval && MATCH("off")) - new_params.exposure.centreWeight = 2; - else - retval = -EINVAL; - - command_flags |= COMMAND_SETEXPOSURE; - } else if (MATCH("gain")) { - if (!retval) - val = VALUE; - - if (!retval) { - switch(val) { - case 1: - new_params.exposure.gain = 0; - break; - case 2: - new_params.exposure.gain = 1; - break; - case 4: - new_params.exposure.gain = 2; - break; - case 8: - new_params.exposure.gain = 3; - break; - default: - retval = -EINVAL; - break; - } - new_params.exposure.expMode = 1; - if(new_params.flickerControl.flickerMode != 0) - command_flags |= COMMAND_SETFLICKERCTRL; - new_params.flickerControl.flickerMode = 0; - command_flags |= COMMAND_SETEXPOSURE; - if (new_params.exposure.gain > - new_params.exposure.gainMode-1) - retval = -EINVAL; - } - } else if (MATCH("fine_exp")) { - if (!retval) - val = VALUE/2; - - if (!retval) { - if (val < 256) { - /* 1-02 firmware limits fineExp/2 to 127*/ - if (FIRMWARE_VERSION(1,2) && val > 127) - val = 127; - new_params.exposure.fineExp = val; - new_params.exposure.expMode = 1; - command_flags |= COMMAND_SETEXPOSURE; - if(new_params.flickerControl.flickerMode != 0) - command_flags |= COMMAND_SETFLICKERCTRL; - new_params.flickerControl.flickerMode = 0; - command_flags |= COMMAND_SETFLICKERCTRL; - } else - retval = -EINVAL; - } - } else if (MATCH("coarse_exp")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= MAX_EXP) { - if (FIRMWARE_VERSION(1,2) && - val > MAX_EXP_102) - val = MAX_EXP_102; - new_params.exposure.coarseExpLo = - val & 0xff; - new_params.exposure.coarseExpHi = - val >> 8; - new_params.exposure.expMode = 1; - command_flags |= COMMAND_SETEXPOSURE; - if(new_params.flickerControl.flickerMode != 0) - command_flags |= COMMAND_SETFLICKERCTRL; - new_params.flickerControl.flickerMode = 0; - command_flags |= COMMAND_SETFLICKERCTRL; - } else - retval = -EINVAL; - } - } else if (MATCH("red_comp")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val >= COMP_RED && val <= 255) { - new_params.exposure.redComp = val; - new_params.exposure.compMode = 1; - command_flags |= COMMAND_SETEXPOSURE; - } else - retval = -EINVAL; - } - } else if (MATCH("green1_comp")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val >= COMP_GREEN1 && val <= 255) { - new_params.exposure.green1Comp = val; - new_params.exposure.compMode = 1; - command_flags |= COMMAND_SETEXPOSURE; - } else - retval = -EINVAL; - } - } else if (MATCH("green2_comp")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val >= COMP_GREEN2 && val <= 255) { - new_params.exposure.green2Comp = val; - new_params.exposure.compMode = 1; - command_flags |= COMMAND_SETEXPOSURE; - } else - retval = -EINVAL; - } - } else if (MATCH("blue_comp")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val >= COMP_BLUE && val <= 255) { - new_params.exposure.blueComp = val; - new_params.exposure.compMode = 1; - command_flags |= COMMAND_SETEXPOSURE; - } else - retval = -EINVAL; - } - } else if (MATCH("apcor_gain1")) { - if (!retval) - val = VALUE; - - if (!retval) { - command_flags |= COMMAND_SETAPCOR; - if (val <= 0xff) - new_params.apcor.gain1 = val; - else - retval = -EINVAL; - } - } else if (MATCH("apcor_gain2")) { - if (!retval) - val = VALUE; - - if (!retval) { - command_flags |= COMMAND_SETAPCOR; - if (val <= 0xff) - new_params.apcor.gain2 = val; - else - retval = -EINVAL; - } - } else if (MATCH("apcor_gain4")) { - if (!retval) - val = VALUE; - - if (!retval) { - command_flags |= COMMAND_SETAPCOR; - if (val <= 0xff) - new_params.apcor.gain4 = val; - else - retval = -EINVAL; - } - } else if (MATCH("apcor_gain8")) { - if (!retval) - val = VALUE; - - if (!retval) { - command_flags |= COMMAND_SETAPCOR; - if (val <= 0xff) - new_params.apcor.gain8 = val; - else - retval = -EINVAL; - } - } else if (MATCH("vl_offset_gain1")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.vlOffset.gain1 = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETVLOFFSET; - } else if (MATCH("vl_offset_gain2")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.vlOffset.gain2 = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETVLOFFSET; - } else if (MATCH("vl_offset_gain4")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.vlOffset.gain4 = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETVLOFFSET; - } else if (MATCH("vl_offset_gain8")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.vlOffset.gain8 = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETVLOFFSET; - } else if (MATCH("flicker_control")) { - if (!retval && MATCH("on")) { - set_flicker(&new_params, &command_flags, 1); - } else if (!retval && MATCH("off")) { - set_flicker(&new_params, &command_flags, 0); - } else - retval = -EINVAL; - - command_flags |= COMMAND_SETFLICKERCTRL; - } else if (MATCH("mains_frequency")) { - if (!retval && MATCH("50")) { - new_mains = 0; - new_params.flickerControl.coarseJump = - flicker_jumps[new_mains] - [new_params.sensorFps.baserate] - [new_params.sensorFps.divisor]; - if (new_params.flickerControl.flickerMode) - command_flags |= COMMAND_SETFLICKERCTRL; - } else if (!retval && MATCH("60")) { - new_mains = 1; - new_params.flickerControl.coarseJump = - flicker_jumps[new_mains] - [new_params.sensorFps.baserate] - [new_params.sensorFps.divisor]; - if (new_params.flickerControl.flickerMode) - command_flags |= COMMAND_SETFLICKERCTRL; - } else - retval = -EINVAL; - } else if (MATCH("allowable_overexposure")) { - if (!retval && MATCH("auto")) { - new_params.flickerControl.allowableOverExposure = - -find_over_exposure(new_params.colourParams.brightness); - if(new_params.flickerControl.flickerMode != 0) - command_flags |= COMMAND_SETFLICKERCTRL; - } else { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) { - new_params.flickerControl. - allowableOverExposure = val; - if(new_params.flickerControl.flickerMode != 0) - command_flags |= COMMAND_SETFLICKERCTRL; - } else - retval = -EINVAL; - } - } - } else if (MATCH("compression_mode")) { - if (!retval && MATCH("none")) - new_params.compression.mode = - CPIA_COMPRESSION_NONE; - else if (!retval && MATCH("auto")) - new_params.compression.mode = - CPIA_COMPRESSION_AUTO; - else if (!retval && MATCH("manual")) - new_params.compression.mode = - CPIA_COMPRESSION_MANUAL; - else - retval = -EINVAL; - - command_flags |= COMMAND_SETCOMPRESSION; - } else if (MATCH("decimation_enable")) { - if (!retval && MATCH("off")) - new_params.compression.decimation = 0; - else if (!retval && MATCH("on")) - new_params.compression.decimation = 1; - else - retval = -EINVAL; - - command_flags |= COMMAND_SETCOMPRESSION; - } else if (MATCH("compression_target")) { - if (!retval && MATCH("quality")) - new_params.compressionTarget.frTargeting = - CPIA_COMPRESSION_TARGET_QUALITY; - else if (!retval && MATCH("framerate")) - new_params.compressionTarget.frTargeting = - CPIA_COMPRESSION_TARGET_FRAMERATE; - else - retval = -EINVAL; - - command_flags |= COMMAND_SETCOMPRESSIONTARGET; - } else if (MATCH("target_framerate")) { - if (!retval) - val = VALUE; - - if (!retval) { - if(val > 0 && val <= 30) - new_params.compressionTarget.targetFR = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOMPRESSIONTARGET; - } else if (MATCH("target_quality")) { - if (!retval) - val = VALUE; - - if (!retval) { - if(val > 0 && val <= 64) - new_params.compressionTarget.targetQ = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOMPRESSIONTARGET; - } else if (MATCH("y_threshold")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val < 32) - new_params.yuvThreshold.yThreshold = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETYUVTHRESH; - } else if (MATCH("uv_threshold")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val < 32) - new_params.yuvThreshold.uvThreshold = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETYUVTHRESH; - } else if (MATCH("hysteresis")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.compressionParams.hysteresis = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOMPRESSIONPARAMS; - } else if (MATCH("threshold_max")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.compressionParams.threshMax = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOMPRESSIONPARAMS; - } else if (MATCH("small_step")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.compressionParams.smallStep = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOMPRESSIONPARAMS; - } else if (MATCH("large_step")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.compressionParams.largeStep = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOMPRESSIONPARAMS; - } else if (MATCH("decimation_hysteresis")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.compressionParams.decimationHysteresis = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOMPRESSIONPARAMS; - } else if (MATCH("fr_diff_step_thresh")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.compressionParams.frDiffStepThresh = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOMPRESSIONPARAMS; - } else if (MATCH("q_diff_step_thresh")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.compressionParams.qDiffStepThresh = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOMPRESSIONPARAMS; - } else if (MATCH("decimation_thresh_mod")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - new_params.compressionParams.decimationThreshMod = val; - else - retval = -EINVAL; - } - command_flags |= COMMAND_SETCOMPRESSIONPARAMS; - } else if (MATCH("toplight")) { - if (!retval && MATCH("on")) - new_params.qx3.toplight = 1; - else if (!retval && MATCH("off")) - new_params.qx3.toplight = 0; - else - retval = -EINVAL; - command_flags |= COMMAND_SETLIGHTS; - } else if (MATCH("bottomlight")) { - if (!retval && MATCH("on")) - new_params.qx3.bottomlight = 1; - else if (!retval && MATCH("off")) - new_params.qx3.bottomlight = 0; - else - retval = -EINVAL; - command_flags |= COMMAND_SETLIGHTS; - } else { - DBG("No match found\n"); - retval = -EINVAL; - } - - if (!retval) { - while (count && isspace(*buffer) && *buffer != '\n') { - --count; - ++buffer; - } - if (count) { - if (*buffer == '\0' && count != 1) - retval = -EINVAL; - else if (*buffer != '\n' && *buffer != ';' && - *buffer != '\0') - retval = -EINVAL; - else { - --count; - ++buffer; - } - } - } - } -#undef MATCH -#undef VALUE -#undef FIRMWARE_VERSION - if (!retval) { - if (command_flags & COMMAND_SETCOLOURPARAMS) { - /* Adjust cam->vp to reflect these changes */ - cam->vp.brightness = - new_params.colourParams.brightness*65535/100; - cam->vp.contrast = - new_params.colourParams.contrast*65535/100; - cam->vp.colour = - new_params.colourParams.saturation*65535/100; - } - if((command_flags & COMMAND_SETEXPOSURE) && - new_params.exposure.expMode == 2) - cam->exposure_status = EXPOSURE_NORMAL; - - memcpy(&cam->params, &new_params, sizeof(struct cam_params)); - cam->mainsFreq = new_mains; - cam->cmd_queue |= command_flags; - retval = size; - } else - DBG("error: %d\n", retval); - - mutex_unlock(&cam->param_lock); - -out: - free_page((unsigned long)page); - return retval; -} - -static const struct file_operations cpia_proc_fops = { - .owner = THIS_MODULE, - .open = cpia_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = cpia_proc_write, -}; - -static void create_proc_cpia_cam(struct cam_data *cam) -{ - struct proc_dir_entry *ent; - - if (!cpia_proc_root || !cam) - return; - - ent = proc_create_data(video_device_node_name(&cam->vdev), - S_IRUGO|S_IWUSR, cpia_proc_root, - &cpia_proc_fops, cam); - if (!ent) - return; - - /* - size of the proc entry is 3736 bytes for the standard webcam; - the extra features of the QX3 microscope add 189 bytes. - (we have not yet probed the camera to see which type it is). - */ - ent->size = 3736 + 189; - cam->proc_entry = ent; -} - -static void destroy_proc_cpia_cam(struct cam_data *cam) -{ - if (!cam || !cam->proc_entry) - return; - - remove_proc_entry(video_device_node_name(&cam->vdev), cpia_proc_root); - cam->proc_entry = NULL; -} - -static void proc_cpia_create(void) -{ - cpia_proc_root = proc_mkdir("cpia", NULL); - - if (!cpia_proc_root) - LOG("Unable to initialise /proc/cpia\n"); -} - -static void __exit proc_cpia_destroy(void) -{ - remove_proc_entry("cpia", NULL); -} -#endif /* CONFIG_PROC_FS */ - -/* ----------------------- debug functions ---------------------- */ - -#define printstatus(cam) \ - DBG("%02x %02x %02x %02x %02x %02x %02x %02x\n",\ - cam->params.status.systemState, cam->params.status.grabState, \ - cam->params.status.streamState, cam->params.status.fatalError, \ - cam->params.status.cmdError, cam->params.status.debugFlags, \ - cam->params.status.vpStatus, cam->params.status.errorCode); - -/* ----------------------- v4l helpers -------------------------- */ - -/* supported frame palettes and depths */ -static inline int valid_mode(u16 palette, u16 depth) -{ - if ((palette == VIDEO_PALETTE_YUV422 && depth == 16) || - (palette == VIDEO_PALETTE_YUYV && depth == 16)) - return 1; - - if (colorspace_conv) - return (palette == VIDEO_PALETTE_GREY && depth == 8) || - (palette == VIDEO_PALETTE_RGB555 && depth == 16) || - (palette == VIDEO_PALETTE_RGB565 && depth == 16) || - (palette == VIDEO_PALETTE_RGB24 && depth == 24) || - (palette == VIDEO_PALETTE_RGB32 && depth == 32) || - (palette == VIDEO_PALETTE_UYVY && depth == 16); - - return 0; -} - -static int match_videosize( int width, int height ) -{ - /* return the best match, where 'best' is as always - * the largest that is not bigger than what is requested. */ - if (width>=352 && height>=288) - return VIDEOSIZE_352_288; /* CIF */ - - if (width>=320 && height>=240) - return VIDEOSIZE_320_240; /* SIF */ - - if (width>=288 && height>=216) - return VIDEOSIZE_288_216; - - if (width>=256 && height>=192) - return VIDEOSIZE_256_192; - - if (width>=224 && height>=168) - return VIDEOSIZE_224_168; - - if (width>=192 && height>=144) - return VIDEOSIZE_192_144; - - if (width>=176 && height>=144) - return VIDEOSIZE_176_144; /* QCIF */ - - if (width>=160 && height>=120) - return VIDEOSIZE_160_120; /* QSIF */ - - if (width>=128 && height>=96) - return VIDEOSIZE_128_96; - - if (width>=88 && height>=72) - return VIDEOSIZE_88_72; - - if (width>=64 && height>=48) - return VIDEOSIZE_64_48; - - if (width>=48 && height>=48) - return VIDEOSIZE_48_48; - - return -1; -} - -/* these are the capture sizes we support */ -static void set_vw_size(struct cam_data *cam) -{ - /* the col/row/start/end values are the result of simple math */ - /* study the SetROI-command in cpia developers guide p 2-22 */ - /* streamStartLine is set to the recommended value in the cpia */ - /* developers guide p 3-37 */ - switch(cam->video_size) { - case VIDEOSIZE_CIF: - cam->vw.width = 352; - cam->vw.height = 288; - cam->params.format.videoSize=VIDEOSIZE_CIF; - cam->params.roi.colStart=0; - cam->params.roi.rowStart=0; - cam->params.streamStartLine = 120; - break; - case VIDEOSIZE_SIF: - cam->vw.width = 320; - cam->vw.height = 240; - cam->params.format.videoSize=VIDEOSIZE_CIF; - cam->params.roi.colStart=2; - cam->params.roi.rowStart=6; - cam->params.streamStartLine = 120; - break; - case VIDEOSIZE_288_216: - cam->vw.width = 288; - cam->vw.height = 216; - cam->params.format.videoSize=VIDEOSIZE_CIF; - cam->params.roi.colStart=4; - cam->params.roi.rowStart=9; - cam->params.streamStartLine = 120; - break; - case VIDEOSIZE_256_192: - cam->vw.width = 256; - cam->vw.height = 192; - cam->params.format.videoSize=VIDEOSIZE_CIF; - cam->params.roi.colStart=6; - cam->params.roi.rowStart=12; - cam->params.streamStartLine = 120; - break; - case VIDEOSIZE_224_168: - cam->vw.width = 224; - cam->vw.height = 168; - cam->params.format.videoSize=VIDEOSIZE_CIF; - cam->params.roi.colStart=8; - cam->params.roi.rowStart=15; - cam->params.streamStartLine = 120; - break; - case VIDEOSIZE_192_144: - cam->vw.width = 192; - cam->vw.height = 144; - cam->params.format.videoSize=VIDEOSIZE_CIF; - cam->params.roi.colStart=10; - cam->params.roi.rowStart=18; - cam->params.streamStartLine = 120; - break; - case VIDEOSIZE_QCIF: - cam->vw.width = 176; - cam->vw.height = 144; - cam->params.format.videoSize=VIDEOSIZE_QCIF; - cam->params.roi.colStart=0; - cam->params.roi.rowStart=0; - cam->params.streamStartLine = 60; - break; - case VIDEOSIZE_QSIF: - cam->vw.width = 160; - cam->vw.height = 120; - cam->params.format.videoSize=VIDEOSIZE_QCIF; - cam->params.roi.colStart=1; - cam->params.roi.rowStart=3; - cam->params.streamStartLine = 60; - break; - case VIDEOSIZE_128_96: - cam->vw.width = 128; - cam->vw.height = 96; - cam->params.format.videoSize=VIDEOSIZE_QCIF; - cam->params.roi.colStart=3; - cam->params.roi.rowStart=6; - cam->params.streamStartLine = 60; - break; - case VIDEOSIZE_88_72: - cam->vw.width = 88; - cam->vw.height = 72; - cam->params.format.videoSize=VIDEOSIZE_QCIF; - cam->params.roi.colStart=5; - cam->params.roi.rowStart=9; - cam->params.streamStartLine = 60; - break; - case VIDEOSIZE_64_48: - cam->vw.width = 64; - cam->vw.height = 48; - cam->params.format.videoSize=VIDEOSIZE_QCIF; - cam->params.roi.colStart=7; - cam->params.roi.rowStart=12; - cam->params.streamStartLine = 60; - break; - case VIDEOSIZE_48_48: - cam->vw.width = 48; - cam->vw.height = 48; - cam->params.format.videoSize=VIDEOSIZE_QCIF; - cam->params.roi.colStart=8; - cam->params.roi.rowStart=6; - cam->params.streamStartLine = 60; - break; - default: - LOG("bad videosize value: %d\n", cam->video_size); - return; - } - - if(cam->vc.width == 0) - cam->vc.width = cam->vw.width; - if(cam->vc.height == 0) - cam->vc.height = cam->vw.height; - - cam->params.roi.colStart += cam->vc.x >> 3; - cam->params.roi.colEnd = cam->params.roi.colStart + - (cam->vc.width >> 3); - cam->params.roi.rowStart += cam->vc.y >> 2; - cam->params.roi.rowEnd = cam->params.roi.rowStart + - (cam->vc.height >> 2); - - return; -} - -static int allocate_frame_buf(struct cam_data *cam) -{ - int i; - - cam->frame_buf = rvmalloc(FRAME_NUM * CPIA_MAX_FRAME_SIZE); - if (!cam->frame_buf) - return -ENOBUFS; - - for (i = 0; i < FRAME_NUM; i++) - cam->frame[i].data = cam->frame_buf + i * CPIA_MAX_FRAME_SIZE; - - return 0; -} - -static int free_frame_buf(struct cam_data *cam) -{ - int i; - - rvfree(cam->frame_buf, FRAME_NUM*CPIA_MAX_FRAME_SIZE); - cam->frame_buf = NULL; - for (i=0; i < FRAME_NUM; i++) - cam->frame[i].data = NULL; - - return 0; -} - - -static inline void free_frames(struct cpia_frame frame[FRAME_NUM]) -{ - int i; - - for (i=0; i < FRAME_NUM; i++) - frame[i].state = FRAME_UNUSED; - return; -} - -/********************************************************************** - * - * General functions - * - **********************************************************************/ -/* send an arbitrary command to the camera */ -static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d) -{ - int retval, datasize; - u8 cmd[8], data[8]; - - switch(command) { - case CPIA_COMMAND_GetCPIAVersion: - case CPIA_COMMAND_GetPnPID: - case CPIA_COMMAND_GetCameraStatus: - case CPIA_COMMAND_GetVPVersion: - datasize=8; - break; - case CPIA_COMMAND_GetColourParams: - case CPIA_COMMAND_GetColourBalance: - case CPIA_COMMAND_GetExposure: - mutex_lock(&cam->param_lock); - datasize=8; - break; - case CPIA_COMMAND_ReadMCPorts: - case CPIA_COMMAND_ReadVCRegs: - datasize = 4; - break; - default: - datasize=0; - break; - } - - cmd[0] = command>>8; - cmd[1] = command&0xff; - cmd[2] = a; - cmd[3] = b; - cmd[4] = c; - cmd[5] = d; - cmd[6] = datasize; - cmd[7] = 0; - - retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data); - if (retval) { - DBG("%x - failed, retval=%d\n", command, retval); - if (command == CPIA_COMMAND_GetColourParams || - command == CPIA_COMMAND_GetColourBalance || - command == CPIA_COMMAND_GetExposure) - mutex_unlock(&cam->param_lock); - } else { - switch(command) { - case CPIA_COMMAND_GetCPIAVersion: - cam->params.version.firmwareVersion = data[0]; - cam->params.version.firmwareRevision = data[1]; - cam->params.version.vcVersion = data[2]; - cam->params.version.vcRevision = data[3]; - break; - case CPIA_COMMAND_GetPnPID: - cam->params.pnpID.vendor = data[0]+(((u16)data[1])<<8); - cam->params.pnpID.product = data[2]+(((u16)data[3])<<8); - cam->params.pnpID.deviceRevision = - data[4]+(((u16)data[5])<<8); - break; - case CPIA_COMMAND_GetCameraStatus: - cam->params.status.systemState = data[0]; - cam->params.status.grabState = data[1]; - cam->params.status.streamState = data[2]; - cam->params.status.fatalError = data[3]; - cam->params.status.cmdError = data[4]; - cam->params.status.debugFlags = data[5]; - cam->params.status.vpStatus = data[6]; - cam->params.status.errorCode = data[7]; - break; - case CPIA_COMMAND_GetVPVersion: - cam->params.vpVersion.vpVersion = data[0]; - cam->params.vpVersion.vpRevision = data[1]; - cam->params.vpVersion.cameraHeadID = - data[2]+(((u16)data[3])<<8); - break; - case CPIA_COMMAND_GetColourParams: - cam->params.colourParams.brightness = data[0]; - cam->params.colourParams.contrast = data[1]; - cam->params.colourParams.saturation = data[2]; - mutex_unlock(&cam->param_lock); - break; - case CPIA_COMMAND_GetColourBalance: - cam->params.colourBalance.redGain = data[0]; - cam->params.colourBalance.greenGain = data[1]; - cam->params.colourBalance.blueGain = data[2]; - mutex_unlock(&cam->param_lock); - break; - case CPIA_COMMAND_GetExposure: - cam->params.exposure.gain = data[0]; - cam->params.exposure.fineExp = data[1]; - cam->params.exposure.coarseExpLo = data[2]; - cam->params.exposure.coarseExpHi = data[3]; - cam->params.exposure.redComp = data[4]; - cam->params.exposure.green1Comp = data[5]; - cam->params.exposure.green2Comp = data[6]; - cam->params.exposure.blueComp = data[7]; - mutex_unlock(&cam->param_lock); - break; - - case CPIA_COMMAND_ReadMCPorts: - if (!cam->params.qx3.qx3_detected) - break; - /* test button press */ - cam->params.qx3.button = ((data[1] & 0x02) == 0); - if (cam->params.qx3.button) { - /* button pressed - unlock the latch */ - do_command(cam,CPIA_COMMAND_WriteMCPort,3,0xDF,0xDF,0); - do_command(cam,CPIA_COMMAND_WriteMCPort,3,0xFF,0xFF,0); - } - - /* test whether microscope is cradled */ - cam->params.qx3.cradled = ((data[2] & 0x40) == 0); - break; - - default: - break; - } - } - return retval; -} - -/* send a command to the camera with an additional data transaction */ -static int do_command_extended(struct cam_data *cam, u16 command, - u8 a, u8 b, u8 c, u8 d, - u8 e, u8 f, u8 g, u8 h, - u8 i, u8 j, u8 k, u8 l) -{ - int retval; - u8 cmd[8], data[8]; - - cmd[0] = command>>8; - cmd[1] = command&0xff; - cmd[2] = a; - cmd[3] = b; - cmd[4] = c; - cmd[5] = d; - cmd[6] = 8; - cmd[7] = 0; - data[0] = e; - data[1] = f; - data[2] = g; - data[3] = h; - data[4] = i; - data[5] = j; - data[6] = k; - data[7] = l; - - retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data); - if (retval) - DBG("%x - failed\n", command); - - return retval; -} - -/********************************************************************** - * - * Colorspace conversion - * - **********************************************************************/ -#define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16) - -static int convert420(unsigned char *yuv, unsigned char *rgb, int out_fmt, - int linesize, int mmap_kludge) -{ - int y, u, v, r, g, b, y1; - - /* Odd lines use the same u and v as the previous line. - * Because of compression, it is necessary to get this - * information from the decoded image. */ - switch(out_fmt) { - case VIDEO_PALETTE_RGB555: - y = (*yuv++ - 16) * 76310; - y1 = (*yuv - 16) * 76310; - r = ((*(rgb+1-linesize)) & 0x7c) << 1; - g = ((*(rgb-linesize)) & 0xe0) >> 4 | - ((*(rgb+1-linesize)) & 0x03) << 6; - b = ((*(rgb-linesize)) & 0x1f) << 3; - u = (-53294 * r - 104635 * g + 157929 * b) / 5756495; - v = (157968 * r - 132278 * g - 25690 * b) / 5366159; - r = 104635 * v; - g = -25690 * u - 53294 * v; - b = 132278 * u; - *rgb++ = ((LIMIT(g+y) & 0xf8) << 2) | (LIMIT(b+y) >> 3); - *rgb++ = ((LIMIT(r+y) & 0xf8) >> 1) | (LIMIT(g+y) >> 6); - *rgb++ = ((LIMIT(g+y1) & 0xf8) << 2) | (LIMIT(b+y1) >> 3); - *rgb = ((LIMIT(r+y1) & 0xf8) >> 1) | (LIMIT(g+y1) >> 6); - return 4; - case VIDEO_PALETTE_RGB565: - y = (*yuv++ - 16) * 76310; - y1 = (*yuv - 16) * 76310; - r = (*(rgb+1-linesize)) & 0xf8; - g = ((*(rgb-linesize)) & 0xe0) >> 3 | - ((*(rgb+1-linesize)) & 0x07) << 5; - b = ((*(rgb-linesize)) & 0x1f) << 3; - u = (-53294 * r - 104635 * g + 157929 * b) / 5756495; - v = (157968 * r - 132278 * g - 25690 * b) / 5366159; - r = 104635 * v; - g = -25690 * u - 53294 * v; - b = 132278 * u; - *rgb++ = ((LIMIT(g+y) & 0xfc) << 3) | (LIMIT(b+y) >> 3); - *rgb++ = (LIMIT(r+y) & 0xf8) | (LIMIT(g+y) >> 5); - *rgb++ = ((LIMIT(g+y1) & 0xfc) << 3) | (LIMIT(b+y1) >> 3); - *rgb = (LIMIT(r+y1) & 0xf8) | (LIMIT(g+y1) >> 5); - return 4; - break; - case VIDEO_PALETTE_RGB24: - case VIDEO_PALETTE_RGB32: - y = (*yuv++ - 16) * 76310; - y1 = (*yuv - 16) * 76310; - if (mmap_kludge) { - r = *(rgb+2-linesize); - g = *(rgb+1-linesize); - b = *(rgb-linesize); - } else { - r = *(rgb-linesize); - g = *(rgb+1-linesize); - b = *(rgb+2-linesize); - } - u = (-53294 * r - 104635 * g + 157929 * b) / 5756495; - v = (157968 * r - 132278 * g - 25690 * b) / 5366159; - r = 104635 * v; - g = -25690 * u + -53294 * v; - b = 132278 * u; - if (mmap_kludge) { - *rgb++ = LIMIT(b+y); - *rgb++ = LIMIT(g+y); - *rgb++ = LIMIT(r+y); - if(out_fmt == VIDEO_PALETTE_RGB32) - rgb++; - *rgb++ = LIMIT(b+y1); - *rgb++ = LIMIT(g+y1); - *rgb = LIMIT(r+y1); - } else { - *rgb++ = LIMIT(r+y); - *rgb++ = LIMIT(g+y); - *rgb++ = LIMIT(b+y); - if(out_fmt == VIDEO_PALETTE_RGB32) - rgb++; - *rgb++ = LIMIT(r+y1); - *rgb++ = LIMIT(g+y1); - *rgb = LIMIT(b+y1); - } - if(out_fmt == VIDEO_PALETTE_RGB32) - return 8; - return 6; - case VIDEO_PALETTE_YUV422: - case VIDEO_PALETTE_YUYV: - y = *yuv++; - u = *(rgb+1-linesize); - y1 = *yuv; - v = *(rgb+3-linesize); - *rgb++ = y; - *rgb++ = u; - *rgb++ = y1; - *rgb = v; - return 4; - case VIDEO_PALETTE_UYVY: - u = *(rgb-linesize); - y = *yuv++; - v = *(rgb+2-linesize); - y1 = *yuv; - *rgb++ = u; - *rgb++ = y; - *rgb++ = v; - *rgb = y1; - return 4; - case VIDEO_PALETTE_GREY: - *rgb++ = *yuv++; - *rgb = *yuv; - return 2; - default: - DBG("Empty: %d\n", out_fmt); - return 0; - } -} - - -static int yuvconvert(unsigned char *yuv, unsigned char *rgb, int out_fmt, - int in_uyvy, int mmap_kludge) -{ - int y, u, v, r, g, b, y1; - - switch(out_fmt) { - case VIDEO_PALETTE_RGB555: - case VIDEO_PALETTE_RGB565: - case VIDEO_PALETTE_RGB24: - case VIDEO_PALETTE_RGB32: - if (in_uyvy) { - u = *yuv++ - 128; - y = (*yuv++ - 16) * 76310; - v = *yuv++ - 128; - y1 = (*yuv - 16) * 76310; - } else { - y = (*yuv++ - 16) * 76310; - u = *yuv++ - 128; - y1 = (*yuv++ - 16) * 76310; - v = *yuv - 128; - } - r = 104635 * v; - g = -25690 * u + -53294 * v; - b = 132278 * u; - break; - default: - y = *yuv++; - u = *yuv++; - y1 = *yuv++; - v = *yuv; - /* Just to avoid compiler warnings */ - r = 0; - g = 0; - b = 0; - break; - } - switch(out_fmt) { - case VIDEO_PALETTE_RGB555: - *rgb++ = ((LIMIT(g+y) & 0xf8) << 2) | (LIMIT(b+y) >> 3); - *rgb++ = ((LIMIT(r+y) & 0xf8) >> 1) | (LIMIT(g+y) >> 6); - *rgb++ = ((LIMIT(g+y1) & 0xf8) << 2) | (LIMIT(b+y1) >> 3); - *rgb = ((LIMIT(r+y1) & 0xf8) >> 1) | (LIMIT(g+y1) >> 6); - return 4; - case VIDEO_PALETTE_RGB565: - *rgb++ = ((LIMIT(g+y) & 0xfc) << 3) | (LIMIT(b+y) >> 3); - *rgb++ = (LIMIT(r+y) & 0xf8) | (LIMIT(g+y) >> 5); - *rgb++ = ((LIMIT(g+y1) & 0xfc) << 3) | (LIMIT(b+y1) >> 3); - *rgb = (LIMIT(r+y1) & 0xf8) | (LIMIT(g+y1) >> 5); - return 4; - case VIDEO_PALETTE_RGB24: - if (mmap_kludge) { - *rgb++ = LIMIT(b+y); - *rgb++ = LIMIT(g+y); - *rgb++ = LIMIT(r+y); - *rgb++ = LIMIT(b+y1); - *rgb++ = LIMIT(g+y1); - *rgb = LIMIT(r+y1); - } else { - *rgb++ = LIMIT(r+y); - *rgb++ = LIMIT(g+y); - *rgb++ = LIMIT(b+y); - *rgb++ = LIMIT(r+y1); - *rgb++ = LIMIT(g+y1); - *rgb = LIMIT(b+y1); - } - return 6; - case VIDEO_PALETTE_RGB32: - if (mmap_kludge) { - *rgb++ = LIMIT(b+y); - *rgb++ = LIMIT(g+y); - *rgb++ = LIMIT(r+y); - rgb++; - *rgb++ = LIMIT(b+y1); - *rgb++ = LIMIT(g+y1); - *rgb = LIMIT(r+y1); - } else { - *rgb++ = LIMIT(r+y); - *rgb++ = LIMIT(g+y); - *rgb++ = LIMIT(b+y); - rgb++; - *rgb++ = LIMIT(r+y1); - *rgb++ = LIMIT(g+y1); - *rgb = LIMIT(b+y1); - } - return 8; - case VIDEO_PALETTE_GREY: - *rgb++ = y; - *rgb = y1; - return 2; - case VIDEO_PALETTE_YUV422: - case VIDEO_PALETTE_YUYV: - *rgb++ = y; - *rgb++ = u; - *rgb++ = y1; - *rgb = v; - return 4; - case VIDEO_PALETTE_UYVY: - *rgb++ = u; - *rgb++ = y; - *rgb++ = v; - *rgb = y1; - return 4; - default: - DBG("Empty: %d\n", out_fmt); - return 0; - } -} - -static int skipcount(int count, int fmt) -{ - switch(fmt) { - case VIDEO_PALETTE_GREY: - return count; - case VIDEO_PALETTE_RGB555: - case VIDEO_PALETTE_RGB565: - case VIDEO_PALETTE_YUV422: - case VIDEO_PALETTE_YUYV: - case VIDEO_PALETTE_UYVY: - return 2*count; - case VIDEO_PALETTE_RGB24: - return 3*count; - case VIDEO_PALETTE_RGB32: - return 4*count; - default: - return 0; - } -} - -static int parse_picture(struct cam_data *cam, int size) -{ - u8 *obuf, *ibuf, *end_obuf; - int ll, in_uyvy, compressed, decimation, even_line, origsize, out_fmt; - int rows, cols, linesize, subsample_422; - - /* make sure params don't change while we are decoding */ - mutex_lock(&cam->param_lock); - - obuf = cam->decompressed_frame.data; - end_obuf = obuf+CPIA_MAX_FRAME_SIZE; - ibuf = cam->raw_image; - origsize = size; - out_fmt = cam->vp.palette; - - if ((ibuf[0] != MAGIC_0) || (ibuf[1] != MAGIC_1)) { - LOG("header not found\n"); - mutex_unlock(&cam->param_lock); - return -1; - } - - if ((ibuf[16] != VIDEOSIZE_QCIF) && (ibuf[16] != VIDEOSIZE_CIF)) { - LOG("wrong video size\n"); - mutex_unlock(&cam->param_lock); - return -1; - } - - if (ibuf[17] != SUBSAMPLE_420 && ibuf[17] != SUBSAMPLE_422) { - LOG("illegal subtype %d\n",ibuf[17]); - mutex_unlock(&cam->param_lock); - return -1; - } - subsample_422 = ibuf[17] == SUBSAMPLE_422; - - if (ibuf[18] != YUVORDER_YUYV && ibuf[18] != YUVORDER_UYVY) { - LOG("illegal yuvorder %d\n",ibuf[18]); - mutex_unlock(&cam->param_lock); - return -1; - } - in_uyvy = ibuf[18] == YUVORDER_UYVY; - - if ((ibuf[24] != cam->params.roi.colStart) || - (ibuf[25] != cam->params.roi.colEnd) || - (ibuf[26] != cam->params.roi.rowStart) || - (ibuf[27] != cam->params.roi.rowEnd)) { - LOG("ROI mismatch\n"); - mutex_unlock(&cam->param_lock); - return -1; - } - cols = 8*(ibuf[25] - ibuf[24]); - rows = 4*(ibuf[27] - ibuf[26]); - - - if ((ibuf[28] != NOT_COMPRESSED) && (ibuf[28] != COMPRESSED)) { - LOG("illegal compression %d\n",ibuf[28]); - mutex_unlock(&cam->param_lock); - return -1; - } - compressed = (ibuf[28] == COMPRESSED); - - if (ibuf[29] != NO_DECIMATION && ibuf[29] != DECIMATION_ENAB) { - LOG("illegal decimation %d\n",ibuf[29]); - mutex_unlock(&cam->param_lock); - return -1; - } - decimation = (ibuf[29] == DECIMATION_ENAB); - - cam->params.yuvThreshold.yThreshold = ibuf[30]; - cam->params.yuvThreshold.uvThreshold = ibuf[31]; - cam->params.status.systemState = ibuf[32]; - cam->params.status.grabState = ibuf[33]; - cam->params.status.streamState = ibuf[34]; - cam->params.status.fatalError = ibuf[35]; - cam->params.status.cmdError = ibuf[36]; - cam->params.status.debugFlags = ibuf[37]; - cam->params.status.vpStatus = ibuf[38]; - cam->params.status.errorCode = ibuf[39]; - cam->fps = ibuf[41]; - mutex_unlock(&cam->param_lock); - - linesize = skipcount(cols, out_fmt); - ibuf += FRAME_HEADER_SIZE; - size -= FRAME_HEADER_SIZE; - ll = ibuf[0] | (ibuf[1] << 8); - ibuf += 2; - even_line = 1; - - while (size > 0) { - size -= (ll+2); - if (size < 0) { - LOG("Insufficient data in buffer\n"); - return -1; - } - - while (ll > 1) { - if (!compressed || (compressed && !(*ibuf & 1))) { - if(subsample_422 || even_line) { - obuf += yuvconvert(ibuf, obuf, out_fmt, - in_uyvy, cam->mmap_kludge); - ibuf += 4; - ll -= 4; - } else { - /* SUBSAMPLE_420 on an odd line */ - obuf += convert420(ibuf, obuf, - out_fmt, linesize, - cam->mmap_kludge); - ibuf += 2; - ll -= 2; - } - } else { - /*skip compressed interval from previous frame*/ - obuf += skipcount(*ibuf >> 1, out_fmt); - if (obuf > end_obuf) { - LOG("Insufficient buffer size\n"); - return -1; - } - ++ibuf; - ll--; - } - } - if (ll == 1) { - if (*ibuf != EOL) { - DBG("EOL not found giving up after %d/%d" - " bytes\n", origsize-size, origsize); - return -1; - } - - ++ibuf; /* skip over EOL */ - - if ((size > 3) && (ibuf[0] == EOI) && (ibuf[1] == EOI) && - (ibuf[2] == EOI) && (ibuf[3] == EOI)) { - size -= 4; - break; - } - - if(decimation) { - /* skip the odd lines for now */ - obuf += linesize; - } - - if (size > 1) { - ll = ibuf[0] | (ibuf[1] << 8); - ibuf += 2; /* skip over line length */ - } - if(!decimation) - even_line = !even_line; - } else { - LOG("line length was not 1 but %d after %d/%d bytes\n", - ll, origsize-size, origsize); - return -1; - } - } - - if(decimation) { - /* interpolate odd rows */ - int i, j; - u8 *prev, *next; - prev = cam->decompressed_frame.data; - obuf = prev+linesize; - next = obuf+linesize; - for(i=1; idecompressed_frame.count = obuf-cam->decompressed_frame.data; - - return cam->decompressed_frame.count; -} - -/* InitStreamCap wrapper to select correct start line */ -static inline int init_stream_cap(struct cam_data *cam) -{ - return do_command(cam, CPIA_COMMAND_InitStreamCap, - 0, cam->params.streamStartLine, 0, 0); -} - - -/* find_over_exposure - * Finds a suitable value of OverExposure for use with SetFlickerCtrl - * Some calculation is required because this value changes with the brightness - * set with SetColourParameters - * - * Parameters: Brightness - last brightness value set with SetColourParameters - * - * Returns: OverExposure value to use with SetFlickerCtrl - */ -#define FLICKER_MAX_EXPOSURE 250 -#define FLICKER_ALLOWABLE_OVER_EXPOSURE 146 -#define FLICKER_BRIGHTNESS_CONSTANT 59 -static int find_over_exposure(int brightness) -{ - int MaxAllowableOverExposure, OverExposure; - - MaxAllowableOverExposure = FLICKER_MAX_EXPOSURE - brightness - - FLICKER_BRIGHTNESS_CONSTANT; - - if (MaxAllowableOverExposure < FLICKER_ALLOWABLE_OVER_EXPOSURE) { - OverExposure = MaxAllowableOverExposure; - } else { - OverExposure = FLICKER_ALLOWABLE_OVER_EXPOSURE; - } - - return OverExposure; -} -#undef FLICKER_MAX_EXPOSURE -#undef FLICKER_ALLOWABLE_OVER_EXPOSURE -#undef FLICKER_BRIGHTNESS_CONSTANT - -/* update various camera modes and settings */ -static void dispatch_commands(struct cam_data *cam) -{ - mutex_lock(&cam->param_lock); - if (cam->cmd_queue==COMMAND_NONE) { - mutex_unlock(&cam->param_lock); - return; - } - DEB_BYTE(cam->cmd_queue); - DEB_BYTE(cam->cmd_queue>>8); - if (cam->cmd_queue & COMMAND_SETFORMAT) { - do_command(cam, CPIA_COMMAND_SetFormat, - cam->params.format.videoSize, - cam->params.format.subSample, - cam->params.format.yuvOrder, 0); - do_command(cam, CPIA_COMMAND_SetROI, - cam->params.roi.colStart, cam->params.roi.colEnd, - cam->params.roi.rowStart, cam->params.roi.rowEnd); - cam->first_frame = 1; - } - - if (cam->cmd_queue & COMMAND_SETCOLOURPARAMS) - do_command(cam, CPIA_COMMAND_SetColourParams, - cam->params.colourParams.brightness, - cam->params.colourParams.contrast, - cam->params.colourParams.saturation, 0); - - if (cam->cmd_queue & COMMAND_SETAPCOR) - do_command(cam, CPIA_COMMAND_SetApcor, - cam->params.apcor.gain1, - cam->params.apcor.gain2, - cam->params.apcor.gain4, - cam->params.apcor.gain8); - - if (cam->cmd_queue & COMMAND_SETVLOFFSET) - do_command(cam, CPIA_COMMAND_SetVLOffset, - cam->params.vlOffset.gain1, - cam->params.vlOffset.gain2, - cam->params.vlOffset.gain4, - cam->params.vlOffset.gain8); - - if (cam->cmd_queue & COMMAND_SETEXPOSURE) { - do_command_extended(cam, CPIA_COMMAND_SetExposure, - cam->params.exposure.gainMode, - 1, - cam->params.exposure.compMode, - cam->params.exposure.centreWeight, - cam->params.exposure.gain, - cam->params.exposure.fineExp, - cam->params.exposure.coarseExpLo, - cam->params.exposure.coarseExpHi, - cam->params.exposure.redComp, - cam->params.exposure.green1Comp, - cam->params.exposure.green2Comp, - cam->params.exposure.blueComp); - if(cam->params.exposure.expMode != 1) { - do_command_extended(cam, CPIA_COMMAND_SetExposure, - 0, - cam->params.exposure.expMode, - 0, 0, - cam->params.exposure.gain, - cam->params.exposure.fineExp, - cam->params.exposure.coarseExpLo, - cam->params.exposure.coarseExpHi, - 0, 0, 0, 0); - } - } - - if (cam->cmd_queue & COMMAND_SETCOLOURBALANCE) { - if (cam->params.colourBalance.balanceMode == 1) { - do_command(cam, CPIA_COMMAND_SetColourBalance, - 1, - cam->params.colourBalance.redGain, - cam->params.colourBalance.greenGain, - cam->params.colourBalance.blueGain); - do_command(cam, CPIA_COMMAND_SetColourBalance, - 3, 0, 0, 0); - } - if (cam->params.colourBalance.balanceMode == 2) { - do_command(cam, CPIA_COMMAND_SetColourBalance, - 2, 0, 0, 0); - } - if (cam->params.colourBalance.balanceMode == 3) { - do_command(cam, CPIA_COMMAND_SetColourBalance, - 3, 0, 0, 0); - } - } - - if (cam->cmd_queue & COMMAND_SETCOMPRESSIONTARGET) - do_command(cam, CPIA_COMMAND_SetCompressionTarget, - cam->params.compressionTarget.frTargeting, - cam->params.compressionTarget.targetFR, - cam->params.compressionTarget.targetQ, 0); - - if (cam->cmd_queue & COMMAND_SETYUVTHRESH) - do_command(cam, CPIA_COMMAND_SetYUVThresh, - cam->params.yuvThreshold.yThreshold, - cam->params.yuvThreshold.uvThreshold, 0, 0); - - if (cam->cmd_queue & COMMAND_SETCOMPRESSIONPARAMS) - do_command_extended(cam, CPIA_COMMAND_SetCompressionParams, - 0, 0, 0, 0, - cam->params.compressionParams.hysteresis, - cam->params.compressionParams.threshMax, - cam->params.compressionParams.smallStep, - cam->params.compressionParams.largeStep, - cam->params.compressionParams.decimationHysteresis, - cam->params.compressionParams.frDiffStepThresh, - cam->params.compressionParams.qDiffStepThresh, - cam->params.compressionParams.decimationThreshMod); - - if (cam->cmd_queue & COMMAND_SETCOMPRESSION) - do_command(cam, CPIA_COMMAND_SetCompression, - cam->params.compression.mode, - cam->params.compression.decimation, 0, 0); - - if (cam->cmd_queue & COMMAND_SETSENSORFPS) - do_command(cam, CPIA_COMMAND_SetSensorFPS, - cam->params.sensorFps.divisor, - cam->params.sensorFps.baserate, 0, 0); - - if (cam->cmd_queue & COMMAND_SETFLICKERCTRL) - do_command(cam, CPIA_COMMAND_SetFlickerCtrl, - cam->params.flickerControl.flickerMode, - cam->params.flickerControl.coarseJump, - abs(cam->params.flickerControl.allowableOverExposure), - 0); - - if (cam->cmd_queue & COMMAND_SETECPTIMING) - do_command(cam, CPIA_COMMAND_SetECPTiming, - cam->params.ecpTiming, 0, 0, 0); - - if (cam->cmd_queue & COMMAND_PAUSE) - do_command(cam, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0); - - if (cam->cmd_queue & COMMAND_RESUME) - init_stream_cap(cam); - - if (cam->cmd_queue & COMMAND_SETLIGHTS && cam->params.qx3.qx3_detected) - { - int p1 = (cam->params.qx3.bottomlight == 0) << 1; - int p2 = (cam->params.qx3.toplight == 0) << 3; - do_command(cam, CPIA_COMMAND_WriteVCReg, 0x90, 0x8F, 0x50, 0); - do_command(cam, CPIA_COMMAND_WriteMCPort, 2, 0, (p1|p2|0xE0), 0); - } - - cam->cmd_queue = COMMAND_NONE; - mutex_unlock(&cam->param_lock); - return; -} - - - -static void set_flicker(struct cam_params *params, volatile u32 *command_flags, - int on) -{ - /* Everything in here is from the Windows driver */ -#define FIRMWARE_VERSION(x,y) (params->version.firmwareVersion == (x) && \ - params->version.firmwareRevision == (y)) -/* define for compgain calculation */ -#if 0 -#define COMPGAIN(base, curexp, newexp) \ - (u8) ((((float) base - 128.0) * ((float) curexp / (float) newexp)) + 128.5) -#define EXP_FROM_COMP(basecomp, curcomp, curexp) \ - (u16)((float)curexp * (float)(u8)(curcomp + 128) / (float)(u8)(basecomp - 128)) -#else - /* equivalent functions without floating point math */ -#define COMPGAIN(base, curexp, newexp) \ - (u8)(128 + (((u32)(2*(base-128)*curexp + newexp)) / (2* newexp)) ) -#define EXP_FROM_COMP(basecomp, curcomp, curexp) \ - (u16)(((u32)(curexp * (u8)(curcomp + 128)) / (u8)(basecomp - 128))) -#endif - - - int currentexp = params->exposure.coarseExpLo + - params->exposure.coarseExpHi*256; - int startexp; - if (on) { - int cj = params->flickerControl.coarseJump; - params->flickerControl.flickerMode = 1; - params->flickerControl.disabled = 0; - if(params->exposure.expMode != 2) - *command_flags |= COMMAND_SETEXPOSURE; - params->exposure.expMode = 2; - currentexp = currentexp << params->exposure.gain; - params->exposure.gain = 0; - /* round down current exposure to nearest value */ - startexp = (currentexp + ROUND_UP_EXP_FOR_FLICKER) / cj; - if(startexp < 1) - startexp = 1; - startexp = (startexp * cj) - 1; - if(FIRMWARE_VERSION(1,2)) - while(startexp > MAX_EXP_102) - startexp -= cj; - else - while(startexp > MAX_EXP) - startexp -= cj; - params->exposure.coarseExpLo = startexp & 0xff; - params->exposure.coarseExpHi = startexp >> 8; - if (currentexp > startexp) { - if (currentexp > (2 * startexp)) - currentexp = 2 * startexp; - params->exposure.redComp = COMPGAIN (COMP_RED, currentexp, startexp); - params->exposure.green1Comp = COMPGAIN (COMP_GREEN1, currentexp, startexp); - params->exposure.green2Comp = COMPGAIN (COMP_GREEN2, currentexp, startexp); - params->exposure.blueComp = COMPGAIN (COMP_BLUE, currentexp, startexp); - } else { - params->exposure.redComp = COMP_RED; - params->exposure.green1Comp = COMP_GREEN1; - params->exposure.green2Comp = COMP_GREEN2; - params->exposure.blueComp = COMP_BLUE; - } - if(FIRMWARE_VERSION(1,2)) - params->exposure.compMode = 0; - else - params->exposure.compMode = 1; - - params->apcor.gain1 = 0x18; - params->apcor.gain2 = 0x18; - params->apcor.gain4 = 0x16; - params->apcor.gain8 = 0x14; - *command_flags |= COMMAND_SETAPCOR; - } else { - params->flickerControl.flickerMode = 0; - params->flickerControl.disabled = 1; - /* Coarse = average of equivalent coarse for each comp channel */ - startexp = EXP_FROM_COMP(COMP_RED, params->exposure.redComp, currentexp); - startexp += EXP_FROM_COMP(COMP_GREEN1, params->exposure.green1Comp, currentexp); - startexp += EXP_FROM_COMP(COMP_GREEN2, params->exposure.green2Comp, currentexp); - startexp += EXP_FROM_COMP(COMP_BLUE, params->exposure.blueComp, currentexp); - startexp = startexp >> 2; - while(startexp > MAX_EXP && - params->exposure.gain < params->exposure.gainMode-1) { - startexp = startexp >> 1; - ++params->exposure.gain; - } - if(FIRMWARE_VERSION(1,2) && startexp > MAX_EXP_102) - startexp = MAX_EXP_102; - if(startexp > MAX_EXP) - startexp = MAX_EXP; - params->exposure.coarseExpLo = startexp&0xff; - params->exposure.coarseExpHi = startexp >> 8; - params->exposure.redComp = COMP_RED; - params->exposure.green1Comp = COMP_GREEN1; - params->exposure.green2Comp = COMP_GREEN2; - params->exposure.blueComp = COMP_BLUE; - params->exposure.compMode = 1; - *command_flags |= COMMAND_SETEXPOSURE; - params->apcor.gain1 = 0x18; - params->apcor.gain2 = 0x16; - params->apcor.gain4 = 0x24; - params->apcor.gain8 = 0x34; - *command_flags |= COMMAND_SETAPCOR; - } - params->vlOffset.gain1 = 20; - params->vlOffset.gain2 = 24; - params->vlOffset.gain4 = 26; - params->vlOffset.gain8 = 26; - *command_flags |= COMMAND_SETVLOFFSET; -#undef FIRMWARE_VERSION -#undef EXP_FROM_COMP -#undef COMPGAIN -} - -#define FIRMWARE_VERSION(x,y) (cam->params.version.firmwareVersion == (x) && \ - cam->params.version.firmwareRevision == (y)) -/* monitor the exposure and adjust the sensor frame rate if needed */ -static void monitor_exposure(struct cam_data *cam) -{ - u8 exp_acc, bcomp, gain, coarseL, cmd[8], data[8]; - int retval, light_exp, dark_exp, very_dark_exp; - int old_exposure, new_exposure, framerate; - - /* get necessary stats and register settings from camera */ - /* do_command can't handle this, so do it ourselves */ - cmd[0] = CPIA_COMMAND_ReadVPRegs>>8; - cmd[1] = CPIA_COMMAND_ReadVPRegs&0xff; - cmd[2] = 30; - cmd[3] = 4; - cmd[4] = 9; - cmd[5] = 8; - cmd[6] = 8; - cmd[7] = 0; - retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data); - if (retval) { - LOG("ReadVPRegs(30,4,9,8) - failed, retval=%d\n", - retval); - return; - } - exp_acc = data[0]; - bcomp = data[1]; - gain = data[2]; - coarseL = data[3]; - - mutex_lock(&cam->param_lock); - light_exp = cam->params.colourParams.brightness + - TC - 50 + EXP_ACC_LIGHT; - if(light_exp > 255) - light_exp = 255; - dark_exp = cam->params.colourParams.brightness + - TC - 50 - EXP_ACC_DARK; - if(dark_exp < 0) - dark_exp = 0; - very_dark_exp = dark_exp/2; - - old_exposure = cam->params.exposure.coarseExpHi * 256 + - cam->params.exposure.coarseExpLo; - - if(!cam->params.flickerControl.disabled) { - /* Flicker control on */ - int max_comp = FIRMWARE_VERSION(1,2) ? MAX_COMP : HIGH_COMP_102; - bcomp += 128; /* decode */ - if(bcomp >= max_comp && exp_acc < dark_exp) { - /* dark */ - if(exp_acc < very_dark_exp) { - /* very dark */ - if(cam->exposure_status == EXPOSURE_VERY_DARK) - ++cam->exposure_count; - else { - cam->exposure_status = EXPOSURE_VERY_DARK; - cam->exposure_count = 1; - } - } else { - /* just dark */ - if(cam->exposure_status == EXPOSURE_DARK) - ++cam->exposure_count; - else { - cam->exposure_status = EXPOSURE_DARK; - cam->exposure_count = 1; - } - } - } else if(old_exposure <= LOW_EXP || exp_acc > light_exp) { - /* light */ - if(old_exposure <= VERY_LOW_EXP) { - /* very light */ - if(cam->exposure_status == EXPOSURE_VERY_LIGHT) - ++cam->exposure_count; - else { - cam->exposure_status = EXPOSURE_VERY_LIGHT; - cam->exposure_count = 1; - } - } else { - /* just light */ - if(cam->exposure_status == EXPOSURE_LIGHT) - ++cam->exposure_count; - else { - cam->exposure_status = EXPOSURE_LIGHT; - cam->exposure_count = 1; - } - } - } else { - /* not dark or light */ - cam->exposure_status = EXPOSURE_NORMAL; - } - } else { - /* Flicker control off */ - if(old_exposure >= MAX_EXP && exp_acc < dark_exp) { - /* dark */ - if(exp_acc < very_dark_exp) { - /* very dark */ - if(cam->exposure_status == EXPOSURE_VERY_DARK) - ++cam->exposure_count; - else { - cam->exposure_status = EXPOSURE_VERY_DARK; - cam->exposure_count = 1; - } - } else { - /* just dark */ - if(cam->exposure_status == EXPOSURE_DARK) - ++cam->exposure_count; - else { - cam->exposure_status = EXPOSURE_DARK; - cam->exposure_count = 1; - } - } - } else if(old_exposure <= LOW_EXP || exp_acc > light_exp) { - /* light */ - if(old_exposure <= VERY_LOW_EXP) { - /* very light */ - if(cam->exposure_status == EXPOSURE_VERY_LIGHT) - ++cam->exposure_count; - else { - cam->exposure_status = EXPOSURE_VERY_LIGHT; - cam->exposure_count = 1; - } - } else { - /* just light */ - if(cam->exposure_status == EXPOSURE_LIGHT) - ++cam->exposure_count; - else { - cam->exposure_status = EXPOSURE_LIGHT; - cam->exposure_count = 1; - } - } - } else { - /* not dark or light */ - cam->exposure_status = EXPOSURE_NORMAL; - } - } - - framerate = cam->fps; - if(framerate > 30 || framerate < 1) - framerate = 1; - - if(!cam->params.flickerControl.disabled) { - /* Flicker control on */ - if((cam->exposure_status == EXPOSURE_VERY_DARK || - cam->exposure_status == EXPOSURE_DARK) && - cam->exposure_count >= DARK_TIME*framerate && - cam->params.sensorFps.divisor < 3) { - - /* dark for too long */ - ++cam->params.sensorFps.divisor; - cam->cmd_queue |= COMMAND_SETSENSORFPS; - - cam->params.flickerControl.coarseJump = - flicker_jumps[cam->mainsFreq] - [cam->params.sensorFps.baserate] - [cam->params.sensorFps.divisor]; - cam->cmd_queue |= COMMAND_SETFLICKERCTRL; - - new_exposure = cam->params.flickerControl.coarseJump-1; - while(new_exposure < old_exposure/2) - new_exposure += cam->params.flickerControl.coarseJump; - cam->params.exposure.coarseExpLo = new_exposure & 0xff; - cam->params.exposure.coarseExpHi = new_exposure >> 8; - cam->cmd_queue |= COMMAND_SETEXPOSURE; - cam->exposure_status = EXPOSURE_NORMAL; - LOG("Automatically decreasing sensor_fps\n"); - - } else if((cam->exposure_status == EXPOSURE_VERY_LIGHT || - cam->exposure_status == EXPOSURE_LIGHT) && - cam->exposure_count >= LIGHT_TIME*framerate && - cam->params.sensorFps.divisor > 0) { - - /* light for too long */ - int max_exp = FIRMWARE_VERSION(1,2) ? MAX_EXP_102 : MAX_EXP ; - - --cam->params.sensorFps.divisor; - cam->cmd_queue |= COMMAND_SETSENSORFPS; - - cam->params.flickerControl.coarseJump = - flicker_jumps[cam->mainsFreq] - [cam->params.sensorFps.baserate] - [cam->params.sensorFps.divisor]; - cam->cmd_queue |= COMMAND_SETFLICKERCTRL; - - new_exposure = cam->params.flickerControl.coarseJump-1; - while(new_exposure < 2*old_exposure && - new_exposure+ - cam->params.flickerControl.coarseJump < max_exp) - new_exposure += cam->params.flickerControl.coarseJump; - cam->params.exposure.coarseExpLo = new_exposure & 0xff; - cam->params.exposure.coarseExpHi = new_exposure >> 8; - cam->cmd_queue |= COMMAND_SETEXPOSURE; - cam->exposure_status = EXPOSURE_NORMAL; - LOG("Automatically increasing sensor_fps\n"); - } - } else { - /* Flicker control off */ - if((cam->exposure_status == EXPOSURE_VERY_DARK || - cam->exposure_status == EXPOSURE_DARK) && - cam->exposure_count >= DARK_TIME*framerate && - cam->params.sensorFps.divisor < 3) { - - /* dark for too long */ - ++cam->params.sensorFps.divisor; - cam->cmd_queue |= COMMAND_SETSENSORFPS; - - if(cam->params.exposure.gain > 0) { - --cam->params.exposure.gain; - cam->cmd_queue |= COMMAND_SETEXPOSURE; - } - cam->exposure_status = EXPOSURE_NORMAL; - LOG("Automatically decreasing sensor_fps\n"); - - } else if((cam->exposure_status == EXPOSURE_VERY_LIGHT || - cam->exposure_status == EXPOSURE_LIGHT) && - cam->exposure_count >= LIGHT_TIME*framerate && - cam->params.sensorFps.divisor > 0) { - - /* light for too long */ - --cam->params.sensorFps.divisor; - cam->cmd_queue |= COMMAND_SETSENSORFPS; - - if(cam->params.exposure.gain < - cam->params.exposure.gainMode-1) { - ++cam->params.exposure.gain; - cam->cmd_queue |= COMMAND_SETEXPOSURE; - } - cam->exposure_status = EXPOSURE_NORMAL; - LOG("Automatically increasing sensor_fps\n"); - } - } - mutex_unlock(&cam->param_lock); -} - -/*-----------------------------------------------------------------*/ -/* if flicker is switched off, this function switches it back on.It checks, - however, that conditions are suitable before restarting it. - This should only be called for firmware version 1.2. - - It also adjust the colour balance when an exposure step is detected - as - long as flicker is running -*/ -static void restart_flicker(struct cam_data *cam) -{ - int cam_exposure, old_exp; - if(!FIRMWARE_VERSION(1,2)) - return; - mutex_lock(&cam->param_lock); - if(cam->params.flickerControl.flickerMode == 0 || - cam->raw_image[39] == 0) { - mutex_unlock(&cam->param_lock); - return; - } - cam_exposure = cam->raw_image[39]*2; - old_exp = cam->params.exposure.coarseExpLo + - cam->params.exposure.coarseExpHi*256; - /* - see how far away camera exposure is from a valid - flicker exposure value - */ - cam_exposure %= cam->params.flickerControl.coarseJump; - if(!cam->params.flickerControl.disabled && - cam_exposure <= cam->params.flickerControl.coarseJump - 3) { - /* Flicker control auto-disabled */ - cam->params.flickerControl.disabled = 1; - } - - if(cam->params.flickerControl.disabled && - cam->params.flickerControl.flickerMode && - old_exp > cam->params.flickerControl.coarseJump + - ROUND_UP_EXP_FOR_FLICKER) { - /* exposure is now high enough to switch - flicker control back on */ - set_flicker(&cam->params, &cam->cmd_queue, 1); - if((cam->cmd_queue & COMMAND_SETEXPOSURE) && - cam->params.exposure.expMode == 2) - cam->exposure_status = EXPOSURE_NORMAL; - - } - mutex_unlock(&cam->param_lock); -} -#undef FIRMWARE_VERSION - -static int clear_stall(struct cam_data *cam) -{ - /* FIXME: Does this actually work? */ - LOG("Clearing stall\n"); - - cam->ops->streamRead(cam->lowlevel_data, cam->raw_image, 0); - do_command(cam, CPIA_COMMAND_GetCameraStatus,0,0,0,0); - return cam->params.status.streamState != STREAM_PAUSED; -} - -/* kernel thread function to read image from camera */ -static int fetch_frame(void *data) -{ - int image_size, retry; - struct cam_data *cam = (struct cam_data *)data; - unsigned long oldjif, rate, diff; - - /* Allow up to two bad images in a row to be read and - * ignored before an error is reported */ - for (retry = 0; retry < 3; ++retry) { - if (retry) - DBG("retry=%d\n", retry); - - if (!cam->ops) - continue; - - /* load first frame always uncompressed */ - if (cam->first_frame && - cam->params.compression.mode != CPIA_COMPRESSION_NONE) { - do_command(cam, CPIA_COMMAND_SetCompression, - CPIA_COMPRESSION_NONE, - NO_DECIMATION, 0, 0); - /* Trial & error - Discarding a frame prevents the - first frame from having an error in the data. */ - do_command(cam, CPIA_COMMAND_DiscardFrame, 0, 0, 0, 0); - } - - /* init camera upload */ - if (do_command(cam, CPIA_COMMAND_GrabFrame, 0, - cam->params.streamStartLine, 0, 0)) - continue; - - if (cam->ops->wait_for_stream_ready) { - /* loop until image ready */ - int count = 0; - do_command(cam, CPIA_COMMAND_GetCameraStatus,0,0,0,0); - while (cam->params.status.streamState != STREAM_READY) { - if(++count > READY_TIMEOUT) - break; - if(cam->params.status.streamState == - STREAM_PAUSED) { - /* Bad news */ - if(!clear_stall(cam)) - return -EIO; - } - - cond_resched(); - - /* sleep for 10 ms, hopefully ;) */ - msleep_interruptible(10); - if (signal_pending(current)) - return -EINTR; - - do_command(cam, CPIA_COMMAND_GetCameraStatus, - 0, 0, 0, 0); - } - if(cam->params.status.streamState != STREAM_READY) { - continue; - } - } - - cond_resched(); - - /* grab image from camera */ - oldjif = jiffies; - image_size = cam->ops->streamRead(cam->lowlevel_data, - cam->raw_image, 0); - if (image_size <= 0) { - DBG("streamRead failed: %d\n", image_size); - continue; - } - - rate = image_size * HZ / 1024; - diff = jiffies-oldjif; - cam->transfer_rate = diff==0 ? rate : rate/diff; - /* diff==0 ? unlikely but possible */ - - /* Switch flicker control back on if it got turned off */ - restart_flicker(cam); - - /* If AEC is enabled, monitor the exposure and - adjust the sensor frame rate if needed */ - if(cam->params.exposure.expMode == 2) - monitor_exposure(cam); - - /* camera idle now so dispatch queued commands */ - dispatch_commands(cam); - - /* Update our knowledge of the camera state */ - do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0); - do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); - do_command(cam, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0); - - /* decompress and convert image to by copying it from - * raw_image to decompressed_frame - */ - - cond_resched(); - - cam->image_size = parse_picture(cam, image_size); - if (cam->image_size <= 0) { - DBG("parse_picture failed %d\n", cam->image_size); - if(cam->params.compression.mode != - CPIA_COMPRESSION_NONE) { - /* Compression may not work right if we - had a bad frame, get the next one - uncompressed. */ - cam->first_frame = 1; - do_command(cam, CPIA_COMMAND_SetGrabMode, - CPIA_GRAB_SINGLE, 0, 0, 0); - /* FIXME: Trial & error - need up to 70ms for - the grab mode change to complete ? */ - msleep_interruptible(70); - if (signal_pending(current)) - return -EINTR; - } - } else - break; - } - - if (retry < 3) { - /* FIXME: this only works for double buffering */ - if (cam->frame[cam->curframe].state == FRAME_READY) { - memcpy(cam->frame[cam->curframe].data, - cam->decompressed_frame.data, - cam->decompressed_frame.count); - cam->frame[cam->curframe].state = FRAME_DONE; - } else - cam->decompressed_frame.state = FRAME_DONE; - - if (cam->first_frame) { - cam->first_frame = 0; - do_command(cam, CPIA_COMMAND_SetCompression, - cam->params.compression.mode, - cam->params.compression.decimation, 0, 0); - - /* Switch from single-grab to continuous grab */ - do_command(cam, CPIA_COMMAND_SetGrabMode, - CPIA_GRAB_CONTINUOUS, 0, 0, 0); - } - return 0; - } - return -EIO; -} - -static int capture_frame(struct cam_data *cam, struct video_mmap *vm) -{ - if (!cam->frame_buf) { - /* we do lazy allocation */ - int err; - if ((err = allocate_frame_buf(cam))) - return err; - } - - cam->curframe = vm->frame; - cam->frame[cam->curframe].state = FRAME_READY; - return fetch_frame(cam); -} - -static int goto_high_power(struct cam_data *cam) -{ - if (do_command(cam, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0)) - return -EIO; - msleep_interruptible(40); /* windows driver does it too */ - if(signal_pending(current)) - return -EINTR; - if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0)) - return -EIO; - if (cam->params.status.systemState == HI_POWER_STATE) { - DBG("camera now in HIGH power state\n"); - return 0; - } - printstatus(cam); - return -EIO; -} - -static int goto_low_power(struct cam_data *cam) -{ - if (do_command(cam, CPIA_COMMAND_GotoLoPower, 0, 0, 0, 0)) - return -1; - if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0)) - return -1; - if (cam->params.status.systemState == LO_POWER_STATE) { - DBG("camera now in LOW power state\n"); - return 0; - } - printstatus(cam); - return -1; -} - -static void save_camera_state(struct cam_data *cam) -{ - if(!(cam->cmd_queue & COMMAND_SETCOLOURBALANCE)) - do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0); - if(!(cam->cmd_queue & COMMAND_SETEXPOSURE)) - do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); - - DBG("%d/%d/%d/%d/%d/%d/%d/%d\n", - cam->params.exposure.gain, - cam->params.exposure.fineExp, - cam->params.exposure.coarseExpLo, - cam->params.exposure.coarseExpHi, - cam->params.exposure.redComp, - cam->params.exposure.green1Comp, - cam->params.exposure.green2Comp, - cam->params.exposure.blueComp); - DBG("%d/%d/%d\n", - cam->params.colourBalance.redGain, - cam->params.colourBalance.greenGain, - cam->params.colourBalance.blueGain); -} - -static int set_camera_state(struct cam_data *cam) -{ - cam->cmd_queue = COMMAND_SETCOMPRESSION | - COMMAND_SETCOMPRESSIONTARGET | - COMMAND_SETCOLOURPARAMS | - COMMAND_SETFORMAT | - COMMAND_SETYUVTHRESH | - COMMAND_SETECPTIMING | - COMMAND_SETCOMPRESSIONPARAMS | - COMMAND_SETEXPOSURE | - COMMAND_SETCOLOURBALANCE | - COMMAND_SETSENSORFPS | - COMMAND_SETAPCOR | - COMMAND_SETFLICKERCTRL | - COMMAND_SETVLOFFSET; - - do_command(cam, CPIA_COMMAND_SetGrabMode, CPIA_GRAB_SINGLE,0,0,0); - dispatch_commands(cam); - - /* Wait 6 frames for the sensor to get all settings and - AEC/ACB to settle */ - msleep_interruptible(6*(cam->params.sensorFps.baserate ? 33 : 40) * - (1 << cam->params.sensorFps.divisor) + 10); - - if(signal_pending(current)) - return -EINTR; - - save_camera_state(cam); - - return 0; -} - -static void get_version_information(struct cam_data *cam) -{ - /* GetCPIAVersion */ - do_command(cam, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0); - - /* GetPnPID */ - do_command(cam, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0); -} - -/* initialize camera */ -static int reset_camera(struct cam_data *cam) -{ - int err; - /* Start the camera in low power mode */ - if (goto_low_power(cam)) { - if (cam->params.status.systemState != WARM_BOOT_STATE) - return -ENODEV; - - /* FIXME: this is just dirty trial and error */ - err = goto_high_power(cam); - if(err) - return err; - do_command(cam, CPIA_COMMAND_DiscardFrame, 0, 0, 0, 0); - if (goto_low_power(cam)) - return -ENODEV; - } - - /* procedure described in developer's guide p3-28 */ - - /* Check the firmware version. */ - cam->params.version.firmwareVersion = 0; - get_version_information(cam); - if (cam->params.version.firmwareVersion != 1) - return -ENODEV; - - /* A bug in firmware 1-02 limits gainMode to 2 */ - if(cam->params.version.firmwareRevision <= 2 && - cam->params.exposure.gainMode > 2) { - cam->params.exposure.gainMode = 2; - } - - /* set QX3 detected flag */ - cam->params.qx3.qx3_detected = (cam->params.pnpID.vendor == 0x0813 && - cam->params.pnpID.product == 0x0001); - - /* The fatal error checking should be done after - * the camera powers up (developer's guide p 3-38) */ - - /* Set streamState before transition to high power to avoid bug - * in firmware 1-02 */ - do_command(cam, CPIA_COMMAND_ModifyCameraStatus, STREAMSTATE, 0, - STREAM_NOT_READY, 0); - - /* GotoHiPower */ - err = goto_high_power(cam); - if (err) - return err; - - /* Check the camera status */ - if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0)) - return -EIO; - - if (cam->params.status.fatalError) { - DBG("fatal_error: %#04x\n", - cam->params.status.fatalError); - DBG("vp_status: %#04x\n", - cam->params.status.vpStatus); - if (cam->params.status.fatalError & ~(COM_FLAG|CPIA_FLAG)) { - /* Fatal error in camera */ - return -EIO; - } else if (cam->params.status.fatalError & (COM_FLAG|CPIA_FLAG)) { - /* Firmware 1-02 may do this for parallel port cameras, - * just clear the flags (developer's guide p 3-38) */ - do_command(cam, CPIA_COMMAND_ModifyCameraStatus, - FATALERROR, ~(COM_FLAG|CPIA_FLAG), 0, 0); - } - } - - /* Check the camera status again */ - if (cam->params.status.fatalError) { - if (cam->params.status.fatalError) - return -EIO; - } - - /* VPVersion can't be retrieved before the camera is in HiPower, - * so get it here instead of in get_version_information. */ - do_command(cam, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0); - - /* set camera to a known state */ - return set_camera_state(cam); -} - -static void put_cam(struct cpia_camera_ops* ops) -{ - module_put(ops->owner); -} - -/* ------------------------- V4L interface --------------------- */ -static int cpia_open(struct file *file) -{ - struct video_device *dev = video_devdata(file); - struct cam_data *cam = video_get_drvdata(dev); - int err; - - if (!cam) { - DBG("Internal error, cam_data not found!\n"); - return -ENODEV; - } - - if (cam->open_count > 0) { - DBG("Camera already open\n"); - return -EBUSY; - } - - if (!try_module_get(cam->ops->owner)) - return -ENODEV; - - mutex_lock(&cam->busy_lock); - err = -ENOMEM; - if (!cam->raw_image) { - cam->raw_image = rvmalloc(CPIA_MAX_IMAGE_SIZE); - if (!cam->raw_image) - goto oops; - } - - if (!cam->decompressed_frame.data) { - cam->decompressed_frame.data = rvmalloc(CPIA_MAX_FRAME_SIZE); - if (!cam->decompressed_frame.data) - goto oops; - } - - /* open cpia */ - err = -ENODEV; - if (cam->ops->open(cam->lowlevel_data)) - goto oops; - - /* reset the camera */ - if ((err = reset_camera(cam)) != 0) { - cam->ops->close(cam->lowlevel_data); - goto oops; - } - - /* Set ownership of /proc/cpia/videoX to current user */ - if(cam->proc_entry) - cam->proc_entry->uid = current_euid(); - - /* set mark for loading first frame uncompressed */ - cam->first_frame = 1; - - /* init it to something */ - cam->mmap_kludge = 0; - - ++cam->open_count; - file->private_data = dev; - mutex_unlock(&cam->busy_lock); - return 0; - - oops: - if (cam->decompressed_frame.data) { - rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE); - cam->decompressed_frame.data = NULL; - } - if (cam->raw_image) { - rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE); - cam->raw_image = NULL; - } - mutex_unlock(&cam->busy_lock); - put_cam(cam->ops); - return err; -} - -static int cpia_close(struct file *file) -{ - struct video_device *dev = file->private_data; - struct cam_data *cam = video_get_drvdata(dev); - - if (cam->ops) { - /* Return ownership of /proc/cpia/videoX to root */ - if(cam->proc_entry) - cam->proc_entry->uid = 0; - - /* save camera state for later open (developers guide ch 3.5.3) */ - save_camera_state(cam); - - /* GotoLoPower */ - goto_low_power(cam); - - /* Update the camera status */ - do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); - - /* cleanup internal state stuff */ - free_frames(cam->frame); - - /* close cpia */ - cam->ops->close(cam->lowlevel_data); - - put_cam(cam->ops); - } - - if (--cam->open_count == 0) { - /* clean up capture-buffers */ - if (cam->raw_image) { - rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE); - cam->raw_image = NULL; - } - - if (cam->decompressed_frame.data) { - rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE); - cam->decompressed_frame.data = NULL; - } - - if (cam->frame_buf) - free_frame_buf(cam); - - if (!cam->ops) - kfree(cam); - } - file->private_data = NULL; - - return 0; -} - -static ssize_t cpia_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct video_device *dev = file->private_data; - struct cam_data *cam = video_get_drvdata(dev); - int err; - - /* make this _really_ smp and multithread-safe */ - if (mutex_lock_interruptible(&cam->busy_lock)) - return -EINTR; - - if (!buf) { - DBG("buf NULL\n"); - mutex_unlock(&cam->busy_lock); - return -EINVAL; - } - - if (!count) { - DBG("count 0\n"); - mutex_unlock(&cam->busy_lock); - return 0; - } - - if (!cam->ops) { - DBG("ops NULL\n"); - mutex_unlock(&cam->busy_lock); - return -ENODEV; - } - - /* upload frame */ - cam->decompressed_frame.state = FRAME_READY; - cam->mmap_kludge=0; - if((err = fetch_frame(cam)) != 0) { - DBG("ERROR from fetch_frame: %d\n", err); - mutex_unlock(&cam->busy_lock); - return err; - } - cam->decompressed_frame.state = FRAME_UNUSED; - - /* copy data to user space */ - if (cam->decompressed_frame.count > count) { - DBG("count wrong: %d, %lu\n", cam->decompressed_frame.count, - (unsigned long) count); - mutex_unlock(&cam->busy_lock); - return -EFAULT; - } - if (copy_to_user(buf, cam->decompressed_frame.data, - cam->decompressed_frame.count)) { - DBG("copy_to_user failed\n"); - mutex_unlock(&cam->busy_lock); - return -EFAULT; - } - - mutex_unlock(&cam->busy_lock); - return cam->decompressed_frame.count; -} - -static long cpia_do_ioctl(struct file *file, unsigned int cmd, void *arg) -{ - struct video_device *dev = file->private_data; - struct cam_data *cam = video_get_drvdata(dev); - int retval = 0; - - if (!cam || !cam->ops) - return -ENODEV; - - /* make this _really_ smp-safe */ - if (mutex_lock_interruptible(&cam->busy_lock)) - return -EINTR; - - /* DBG("cpia_ioctl: %u\n", cmd); */ - - switch (cmd) { - /* query capabilities */ - case VIDIOCGCAP: - { - struct video_capability *b = arg; - - DBG("VIDIOCGCAP\n"); - strcpy(b->name, "CPiA Camera"); - b->type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE; - b->channels = 1; - b->audios = 0; - b->maxwidth = 352; /* VIDEOSIZE_CIF */ - b->maxheight = 288; - b->minwidth = 48; /* VIDEOSIZE_48_48 */ - b->minheight = 48; - break; - } - - /* get/set video source - we are a camera and nothing else */ - case VIDIOCGCHAN: - { - struct video_channel *v = arg; - - DBG("VIDIOCGCHAN\n"); - if (v->channel != 0) { - retval = -EINVAL; - break; - } - - v->channel = 0; - strcpy(v->name, "Camera"); - v->tuners = 0; - v->flags = 0; - v->type = VIDEO_TYPE_CAMERA; - v->norm = 0; - break; - } - - case VIDIOCSCHAN: - { - struct video_channel *v = arg; - - DBG("VIDIOCSCHAN\n"); - if (v->channel != 0) - retval = -EINVAL; - break; - } - - /* image properties */ - case VIDIOCGPICT: - { - struct video_picture *pic = arg; - DBG("VIDIOCGPICT\n"); - *pic = cam->vp; - break; - } - - case VIDIOCSPICT: - { - struct video_picture *vp = arg; - - DBG("VIDIOCSPICT\n"); - - /* check validity */ - DBG("palette: %d\n", vp->palette); - DBG("depth: %d\n", vp->depth); - if (!valid_mode(vp->palette, vp->depth)) { - retval = -EINVAL; - break; - } - - mutex_lock(&cam->param_lock); - /* brightness, colour, contrast need no check 0-65535 */ - cam->vp = *vp; - /* update cam->params.colourParams */ - cam->params.colourParams.brightness = vp->brightness*100/65535; - cam->params.colourParams.contrast = vp->contrast*100/65535; - cam->params.colourParams.saturation = vp->colour*100/65535; - /* contrast is in steps of 8, so round */ - cam->params.colourParams.contrast = - ((cam->params.colourParams.contrast + 3) / 8) * 8; - if (cam->params.version.firmwareVersion == 1 && - cam->params.version.firmwareRevision == 2 && - cam->params.colourParams.contrast > 80) { - /* 1-02 firmware limits contrast to 80 */ - cam->params.colourParams.contrast = 80; - } - - /* Adjust flicker control if necessary */ - if(cam->params.flickerControl.allowableOverExposure < 0) - cam->params.flickerControl.allowableOverExposure = - -find_over_exposure(cam->params.colourParams.brightness); - if(cam->params.flickerControl.flickerMode != 0) - cam->cmd_queue |= COMMAND_SETFLICKERCTRL; - - - /* queue command to update camera */ - cam->cmd_queue |= COMMAND_SETCOLOURPARAMS; - mutex_unlock(&cam->param_lock); - DBG("VIDIOCSPICT: %d / %d // %d / %d / %d / %d\n", - vp->depth, vp->palette, vp->brightness, vp->hue, vp->colour, - vp->contrast); - break; - } - - /* get/set capture window */ - case VIDIOCGWIN: - { - struct video_window *vw = arg; - DBG("VIDIOCGWIN\n"); - - *vw = cam->vw; - break; - } - - case VIDIOCSWIN: - { - /* copy_from_user, check validity, copy to internal structure */ - struct video_window *vw = arg; - DBG("VIDIOCSWIN\n"); - - if (vw->clipcount != 0) { /* clipping not supported */ - retval = -EINVAL; - break; - } - if (vw->clips != NULL) { /* clipping not supported */ - retval = -EINVAL; - break; - } - - /* we set the video window to something smaller or equal to what - * is requested by the user??? - */ - mutex_lock(&cam->param_lock); - if (vw->width != cam->vw.width || vw->height != cam->vw.height) { - int video_size = match_videosize(vw->width, vw->height); - - if (video_size < 0) { - retval = -EINVAL; - mutex_unlock(&cam->param_lock); - break; - } - cam->video_size = video_size; - - /* video size is changing, reset the subcapture area */ - memset(&cam->vc, 0, sizeof(cam->vc)); - - set_vw_size(cam); - DBG("%d / %d\n", cam->vw.width, cam->vw.height); - cam->cmd_queue |= COMMAND_SETFORMAT; - } - - mutex_unlock(&cam->param_lock); - - /* setformat ignored by camera during streaming, - * so stop/dispatch/start */ - if (cam->cmd_queue & COMMAND_SETFORMAT) { - DBG("\n"); - dispatch_commands(cam); - } - DBG("%d/%d:%d\n", cam->video_size, - cam->vw.width, cam->vw.height); - break; - } - - /* mmap interface */ - case VIDIOCGMBUF: - { - struct video_mbuf *vm = arg; - int i; - - DBG("VIDIOCGMBUF\n"); - memset(vm, 0, sizeof(*vm)); - vm->size = CPIA_MAX_FRAME_SIZE*FRAME_NUM; - vm->frames = FRAME_NUM; - for (i = 0; i < FRAME_NUM; i++) - vm->offsets[i] = CPIA_MAX_FRAME_SIZE * i; - break; - } - - case VIDIOCMCAPTURE: - { - struct video_mmap *vm = arg; - int video_size; - - DBG("VIDIOCMCAPTURE: %d / %d / %dx%d\n", vm->format, vm->frame, - vm->width, vm->height); - if (vm->frame<0||vm->frame>=FRAME_NUM) { - retval = -EINVAL; - break; - } - - /* set video format */ - cam->vp.palette = vm->format; - switch(vm->format) { - case VIDEO_PALETTE_GREY: - cam->vp.depth=8; - break; - case VIDEO_PALETTE_RGB555: - case VIDEO_PALETTE_RGB565: - case VIDEO_PALETTE_YUV422: - case VIDEO_PALETTE_YUYV: - case VIDEO_PALETTE_UYVY: - cam->vp.depth = 16; - break; - case VIDEO_PALETTE_RGB24: - cam->vp.depth = 24; - break; - case VIDEO_PALETTE_RGB32: - cam->vp.depth = 32; - break; - default: - retval = -EINVAL; - break; - } - if (retval) - break; - - /* set video size */ - video_size = match_videosize(vm->width, vm->height); - if (video_size < 0) { - retval = -EINVAL; - break; - } - if (video_size != cam->video_size) { - cam->video_size = video_size; - - /* video size is changing, reset the subcapture area */ - memset(&cam->vc, 0, sizeof(cam->vc)); - - set_vw_size(cam); - cam->cmd_queue |= COMMAND_SETFORMAT; - dispatch_commands(cam); - } - /* according to v4l-spec we must start streaming here */ - cam->mmap_kludge = 1; - retval = capture_frame(cam, vm); - - break; - } - - case VIDIOCSYNC: - { - int *frame = arg; - - //DBG("VIDIOCSYNC: %d\n", *frame); - - if (*frame<0 || *frame >= FRAME_NUM) { - retval = -EINVAL; - break; - } - - switch (cam->frame[*frame].state) { - case FRAME_UNUSED: - case FRAME_READY: - case FRAME_GRABBING: - DBG("sync to unused frame %d\n", *frame); - retval = -EINVAL; - break; - - case FRAME_DONE: - cam->frame[*frame].state = FRAME_UNUSED; - //DBG("VIDIOCSYNC: %d synced\n", *frame); - break; - } - if (retval == -EINTR) { - /* FIXME - xawtv does not handle this nice */ - retval = 0; - } - break; - } - - case VIDIOCGCAPTURE: - { - struct video_capture *vc = arg; - - DBG("VIDIOCGCAPTURE\n"); - - *vc = cam->vc; - - break; - } - - case VIDIOCSCAPTURE: - { - struct video_capture *vc = arg; - - DBG("VIDIOCSCAPTURE\n"); - - if (vc->decimation != 0) { /* How should this be used? */ - retval = -EINVAL; - break; - } - if (vc->flags != 0) { /* Even/odd grab not supported */ - retval = -EINVAL; - break; - } - - /* Clip to the resolution we can set for the ROI - (every 8 columns and 4 rows) */ - vc->x = vc->x & ~(__u32)7; - vc->y = vc->y & ~(__u32)3; - vc->width = vc->width & ~(__u32)7; - vc->height = vc->height & ~(__u32)3; - - if(vc->width == 0 || vc->height == 0 || - vc->x + vc->width > cam->vw.width || - vc->y + vc->height > cam->vw.height) { - retval = -EINVAL; - break; - } - - DBG("%d,%d/%dx%d\n", vc->x,vc->y,vc->width, vc->height); - - mutex_lock(&cam->param_lock); - - cam->vc.x = vc->x; - cam->vc.y = vc->y; - cam->vc.width = vc->width; - cam->vc.height = vc->height; - - set_vw_size(cam); - cam->cmd_queue |= COMMAND_SETFORMAT; - - mutex_unlock(&cam->param_lock); - - /* setformat ignored by camera during streaming, - * so stop/dispatch/start */ - dispatch_commands(cam); - break; - } - - case VIDIOCGUNIT: - { - struct video_unit *vu = arg; - - DBG("VIDIOCGUNIT\n"); - - vu->video = cam->vdev.minor; - vu->vbi = VIDEO_NO_UNIT; - vu->radio = VIDEO_NO_UNIT; - vu->audio = VIDEO_NO_UNIT; - vu->teletext = VIDEO_NO_UNIT; - - break; - } - - - /* pointless to implement overlay with this camera */ - case VIDIOCCAPTURE: - case VIDIOCGFBUF: - case VIDIOCSFBUF: - case VIDIOCKEY: - /* tuner interface - we have none */ - case VIDIOCGTUNER: - case VIDIOCSTUNER: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - /* audio interface - we have none */ - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - retval = -EINVAL; - break; - default: - retval = -ENOIOCTLCMD; - break; - } - - mutex_unlock(&cam->busy_lock); - return retval; -} - -static long cpia_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(file, cmd, arg, cpia_do_ioctl); -} - - -/* FIXME */ -static int cpia_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct video_device *dev = file->private_data; - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end - vma->vm_start; - unsigned long page, pos; - struct cam_data *cam = video_get_drvdata(dev); - int retval; - - if (!cam || !cam->ops) - return -ENODEV; - - DBG("cpia_mmap: %ld\n", size); - - if (size > FRAME_NUM*CPIA_MAX_FRAME_SIZE) - return -EINVAL; - - /* make this _really_ smp-safe */ - if (mutex_lock_interruptible(&cam->busy_lock)) - return -EINTR; - - if (!cam->frame_buf) { /* we do lazy allocation */ - if ((retval = allocate_frame_buf(cam))) { - mutex_unlock(&cam->busy_lock); - return retval; - } - } - - pos = (unsigned long)(cam->frame_buf); - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { - mutex_unlock(&cam->busy_lock); - return -EAGAIN; - } - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - - DBG("cpia_mmap: %ld\n", size); - mutex_unlock(&cam->busy_lock); - - return 0; -} - -static const struct v4l2_file_operations cpia_fops = { - .owner = THIS_MODULE, - .open = cpia_open, - .release = cpia_close, - .read = cpia_read, - .mmap = cpia_mmap, - .ioctl = cpia_ioctl, -}; - -static struct video_device cpia_template = { - .name = "CPiA Camera", - .fops = &cpia_fops, - .release = video_device_release_empty, -}; - -/* initialise cam_data structure */ -static void reset_camera_struct(struct cam_data *cam) -{ - /* The following parameter values are the defaults from - * "Software Developer's Guide for CPiA Cameras". Any changes - * to the defaults are noted in comments. */ - cam->params.colourParams.brightness = 50; - cam->params.colourParams.contrast = 48; - cam->params.colourParams.saturation = 50; - cam->params.exposure.gainMode = 4; - cam->params.exposure.expMode = 2; /* AEC */ - cam->params.exposure.compMode = 1; - cam->params.exposure.centreWeight = 1; - cam->params.exposure.gain = 0; - cam->params.exposure.fineExp = 0; - cam->params.exposure.coarseExpLo = 185; - cam->params.exposure.coarseExpHi = 0; - cam->params.exposure.redComp = COMP_RED; - cam->params.exposure.green1Comp = COMP_GREEN1; - cam->params.exposure.green2Comp = COMP_GREEN2; - cam->params.exposure.blueComp = COMP_BLUE; - cam->params.colourBalance.balanceMode = 2; /* ACB */ - cam->params.colourBalance.redGain = 32; - cam->params.colourBalance.greenGain = 6; - cam->params.colourBalance.blueGain = 92; - cam->params.apcor.gain1 = 0x18; - cam->params.apcor.gain2 = 0x16; - cam->params.apcor.gain4 = 0x24; - cam->params.apcor.gain8 = 0x34; - cam->params.flickerControl.flickerMode = 0; - cam->params.flickerControl.disabled = 1; - - cam->params.flickerControl.coarseJump = - flicker_jumps[cam->mainsFreq] - [cam->params.sensorFps.baserate] - [cam->params.sensorFps.divisor]; - cam->params.flickerControl.allowableOverExposure = - -find_over_exposure(cam->params.colourParams.brightness); - cam->params.vlOffset.gain1 = 20; - cam->params.vlOffset.gain2 = 24; - cam->params.vlOffset.gain4 = 26; - cam->params.vlOffset.gain8 = 26; - cam->params.compressionParams.hysteresis = 3; - cam->params.compressionParams.threshMax = 11; - cam->params.compressionParams.smallStep = 1; - cam->params.compressionParams.largeStep = 3; - cam->params.compressionParams.decimationHysteresis = 2; - cam->params.compressionParams.frDiffStepThresh = 5; - cam->params.compressionParams.qDiffStepThresh = 3; - cam->params.compressionParams.decimationThreshMod = 2; - /* End of default values from Software Developer's Guide */ - - cam->transfer_rate = 0; - cam->exposure_status = EXPOSURE_NORMAL; - - /* Set Sensor FPS to 15fps. This seems better than 30fps - * for indoor lighting. */ - cam->params.sensorFps.divisor = 1; - cam->params.sensorFps.baserate = 1; - - cam->params.yuvThreshold.yThreshold = 6; /* From windows driver */ - cam->params.yuvThreshold.uvThreshold = 6; /* From windows driver */ - - cam->params.format.subSample = SUBSAMPLE_422; - cam->params.format.yuvOrder = YUVORDER_YUYV; - - cam->params.compression.mode = CPIA_COMPRESSION_AUTO; - cam->params.compressionTarget.frTargeting = - CPIA_COMPRESSION_TARGET_QUALITY; - cam->params.compressionTarget.targetFR = 15; /* From windows driver */ - cam->params.compressionTarget.targetQ = 5; /* From windows driver */ - - cam->params.qx3.qx3_detected = 0; - cam->params.qx3.toplight = 0; - cam->params.qx3.bottomlight = 0; - cam->params.qx3.button = 0; - cam->params.qx3.cradled = 0; - - cam->video_size = VIDEOSIZE_CIF; - - cam->vp.colour = 32768; /* 50% */ - cam->vp.hue = 32768; /* 50% */ - cam->vp.brightness = 32768; /* 50% */ - cam->vp.contrast = 32768; /* 50% */ - cam->vp.whiteness = 0; /* not used -> grayscale only */ - cam->vp.depth = 24; /* to be set by user */ - cam->vp.palette = VIDEO_PALETTE_RGB24; /* to be set by user */ - - cam->vc.x = 0; - cam->vc.y = 0; - cam->vc.width = 0; - cam->vc.height = 0; - - cam->vw.x = 0; - cam->vw.y = 0; - set_vw_size(cam); - cam->vw.chromakey = 0; - cam->vw.flags = 0; - cam->vw.clipcount = 0; - cam->vw.clips = NULL; - - cam->cmd_queue = COMMAND_NONE; - cam->first_frame = 1; - - return; -} - -/* initialize cam_data structure */ -static void init_camera_struct(struct cam_data *cam, - struct cpia_camera_ops *ops ) -{ - int i; - - /* Default everything to 0 */ - memset(cam, 0, sizeof(struct cam_data)); - - cam->ops = ops; - mutex_init(&cam->param_lock); - mutex_init(&cam->busy_lock); - - reset_camera_struct(cam); - - cam->proc_entry = NULL; - - memcpy(&cam->vdev, &cpia_template, sizeof(cpia_template)); - video_set_drvdata(&cam->vdev, cam); - - cam->curframe = 0; - for (i = 0; i < FRAME_NUM; i++) { - cam->frame[i].width = 0; - cam->frame[i].height = 0; - cam->frame[i].state = FRAME_UNUSED; - cam->frame[i].data = NULL; - } - cam->decompressed_frame.width = 0; - cam->decompressed_frame.height = 0; - cam->decompressed_frame.state = FRAME_UNUSED; - cam->decompressed_frame.data = NULL; -} - -struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowlevel) -{ - struct cam_data *camera; - - if ((camera = kmalloc(sizeof(struct cam_data), GFP_KERNEL)) == NULL) - return NULL; - - - init_camera_struct( camera, ops ); - camera->lowlevel_data = lowlevel; - - /* register v4l device */ - if (video_register_device(&camera->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { - kfree(camera); - printk(KERN_DEBUG "video_register_device failed\n"); - return NULL; - } - - /* get version information from camera: open/reset/close */ - - /* open cpia */ - if (camera->ops->open(camera->lowlevel_data)) - return camera; - - /* reset the camera */ - if (reset_camera(camera) != 0) { - camera->ops->close(camera->lowlevel_data); - return camera; - } - - /* close cpia */ - camera->ops->close(camera->lowlevel_data); - -#ifdef CONFIG_PROC_FS - create_proc_cpia_cam(camera); -#endif - - printk(KERN_INFO " CPiA Version: %d.%02d (%d.%d)\n", - camera->params.version.firmwareVersion, - camera->params.version.firmwareRevision, - camera->params.version.vcVersion, - camera->params.version.vcRevision); - printk(KERN_INFO " CPiA PnP-ID: %04x:%04x:%04x\n", - camera->params.pnpID.vendor, - camera->params.pnpID.product, - camera->params.pnpID.deviceRevision); - printk(KERN_INFO " VP-Version: %d.%d %04x\n", - camera->params.vpVersion.vpVersion, - camera->params.vpVersion.vpRevision, - camera->params.vpVersion.cameraHeadID); - - return camera; -} - -void cpia_unregister_camera(struct cam_data *cam) -{ - DBG("unregistering video\n"); - video_unregister_device(&cam->vdev); - if (cam->open_count) { - put_cam(cam->ops); - DBG("camera open -- setting ops to NULL\n"); - cam->ops = NULL; - } - -#ifdef CONFIG_PROC_FS - DBG("destroying /proc/cpia/%s\n", video_device_node_name(&cam->vdev)); - destroy_proc_cpia_cam(cam); -#endif - if (!cam->open_count) { - DBG("freeing camera\n"); - kfree(cam); - } -} - -static int __init cpia_init(void) -{ - printk(KERN_INFO "%s v%d.%d.%d\n", ABOUT, - CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER); - - printk(KERN_WARNING "Since in-kernel colorspace conversion is not " - "allowed, it is disabled by default now. Users should fix the " - "applications in case they don't work without conversion " - "reenabled by setting the 'colorspace_conv' module " - "parameter to 1\n"); - -#ifdef CONFIG_PROC_FS - proc_cpia_create(); -#endif - - return 0; -} - -static void __exit cpia_exit(void) -{ -#ifdef CONFIG_PROC_FS - proc_cpia_destroy(); -#endif -} - -module_init(cpia_init); -module_exit(cpia_exit); - -/* Exported symbols for modules. */ - -EXPORT_SYMBOL(cpia_register_camera); -EXPORT_SYMBOL(cpia_unregister_camera); diff --git a/drivers/staging/cpia/cpia.h b/drivers/staging/cpia/cpia.h deleted file mode 100644 index 8f0cfee..0000000 --- a/drivers/staging/cpia/cpia.h +++ /dev/null @@ -1,432 +0,0 @@ -#ifndef cpia_h -#define cpia_h - -/* - * CPiA Parallel Port Video4Linux driver - * - * Supports CPiA based parallel port Video Camera's. - * - * (C) Copyright 1999 Bas Huisman, - * Peter Pregler, - * Scott J. Bertin, - * VLSI Vision Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#define CPIA_MAJ_VER 1 -#define CPIA_MIN_VER 2 -#define CPIA_PATCH_VER 3 - -#define CPIA_PP_MAJ_VER CPIA_MAJ_VER -#define CPIA_PP_MIN_VER CPIA_MIN_VER -#define CPIA_PP_PATCH_VER CPIA_PATCH_VER - -#define CPIA_USB_MAJ_VER CPIA_MAJ_VER -#define CPIA_USB_MIN_VER CPIA_MIN_VER -#define CPIA_USB_PATCH_VER CPIA_PATCH_VER - -#define CPIA_MAX_FRAME_SIZE_UNALIGNED (352 * 288 * 4) /* CIF at RGB32 */ -#define CPIA_MAX_FRAME_SIZE ((CPIA_MAX_FRAME_SIZE_UNALIGNED + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) /* align above to PAGE_SIZE */ - -#ifdef __KERNEL__ - -#include -#include -#include -#include -#include -#include - -struct cpia_camera_ops -{ - /* open sets privdata to point to structure for this camera. - * Returns negative value on error, otherwise 0. - */ - int (*open)(void *privdata); - - /* Registers callback function cb to be called with cbdata - * when an image is ready. If cb is NULL, only single image grabs - * should be used. cb should immediately call streamRead to read - * the data or data may be lost. Returns negative value on error, - * otherwise 0. - */ - int (*registerCallback)(void *privdata, void (*cb)(void *cbdata), - void *cbdata); - - /* transferCmd sends commands to the camera. command MUST point to - * an 8 byte buffer in kernel space. data can be NULL if no extra - * data is needed. The size of the data is given by the last 2 - * bytes of command. data must also point to memory in kernel space. - * Returns negative value on error, otherwise 0. - */ - int (*transferCmd)(void *privdata, u8 *command, u8 *data); - - /* streamStart initiates stream capture mode. - * Returns negative value on error, otherwise 0. - */ - int (*streamStart)(void *privdata); - - /* streamStop terminates stream capture mode. - * Returns negative value on error, otherwise 0. - */ - int (*streamStop)(void *privdata); - - /* streamRead reads a frame from the camera. buffer points to a - * buffer large enough to hold a complete frame in kernel space. - * noblock indicates if this should be a non blocking read. - * Returns the number of bytes read, or negative value on error. - */ - int (*streamRead)(void *privdata, u8 *buffer, int noblock); - - /* close disables the device until open() is called again. - * Returns negative value on error, otherwise 0. - */ - int (*close)(void *privdata); - - /* If wait_for_stream_ready is non-zero, wait until the streamState - * is STREAM_READY before calling streamRead. - */ - int wait_for_stream_ready; - - /* - * Used to maintain lowlevel module usage counts - */ - struct module *owner; -}; - -struct cpia_frame { - u8 *data; - int count; - int width; - int height; - volatile int state; -}; - -struct cam_params { - struct { - u8 firmwareVersion; - u8 firmwareRevision; - u8 vcVersion; - u8 vcRevision; - } version; - struct { - u16 vendor; - u16 product; - u16 deviceRevision; - } pnpID; - struct { - u8 vpVersion; - u8 vpRevision; - u16 cameraHeadID; - } vpVersion; - struct { - u8 systemState; - u8 grabState; - u8 streamState; - u8 fatalError; - u8 cmdError; - u8 debugFlags; - u8 vpStatus; - u8 errorCode; - } status; - struct { - u8 brightness; - u8 contrast; - u8 saturation; - } colourParams; - struct { - u8 gainMode; - u8 expMode; - u8 compMode; - u8 centreWeight; - u8 gain; - u8 fineExp; - u8 coarseExpLo; - u8 coarseExpHi; - u8 redComp; - u8 green1Comp; - u8 green2Comp; - u8 blueComp; - } exposure; - struct { - u8 balanceMode; - u8 redGain; - u8 greenGain; - u8 blueGain; - } colourBalance; - struct { - u8 divisor; - u8 baserate; - } sensorFps; - struct { - u8 gain1; - u8 gain2; - u8 gain4; - u8 gain8; - } apcor; - struct { - u8 disabled; - u8 flickerMode; - u8 coarseJump; - int allowableOverExposure; - } flickerControl; - struct { - u8 gain1; - u8 gain2; - u8 gain4; - u8 gain8; - } vlOffset; - struct { - u8 mode; - u8 decimation; - } compression; - struct { - u8 frTargeting; - u8 targetFR; - u8 targetQ; - } compressionTarget; - struct { - u8 yThreshold; - u8 uvThreshold; - } yuvThreshold; - struct { - u8 hysteresis; - u8 threshMax; - u8 smallStep; - u8 largeStep; - u8 decimationHysteresis; - u8 frDiffStepThresh; - u8 qDiffStepThresh; - u8 decimationThreshMod; - } compressionParams; - struct { - u8 videoSize; /* CIF/QCIF */ - u8 subSample; - u8 yuvOrder; - } format; - struct { /* Intel QX3 specific data */ - u8 qx3_detected; /* a QX3 is present */ - u8 toplight; /* top light lit , R/W */ - u8 bottomlight; /* bottom light lit, R/W */ - u8 button; /* snapshot button pressed (R/O) */ - u8 cradled; /* microscope is in cradle (R/O) */ - } qx3; - struct { - u8 colStart; /* skip first 8*colStart pixels */ - u8 colEnd; /* finish at 8*colEnd pixels */ - u8 rowStart; /* skip first 4*rowStart lines */ - u8 rowEnd; /* finish at 4*rowEnd lines */ - } roi; - u8 ecpTiming; - u8 streamStartLine; -}; - -enum v4l_camstates { - CPIA_V4L_IDLE = 0, - CPIA_V4L_ERROR, - CPIA_V4L_COMMAND, - CPIA_V4L_GRABBING, - CPIA_V4L_STREAMING, - CPIA_V4L_STREAMING_PAUSED, -}; - -#define FRAME_NUM 2 /* double buffering for now */ - -struct cam_data { - struct list_head cam_data_list; - - struct mutex busy_lock; /* guard against SMP multithreading */ - struct cpia_camera_ops *ops; /* lowlevel driver operations */ - void *lowlevel_data; /* private data for lowlevel driver */ - u8 *raw_image; /* buffer for raw image data */ - struct cpia_frame decompressed_frame; - /* buffer to hold decompressed frame */ - int image_size; /* sizeof last decompressed image */ - int open_count; /* # of process that have camera open */ - - /* camera status */ - int fps; /* actual fps reported by the camera */ - int transfer_rate; /* transfer rate from camera in kB/s */ - u8 mainsFreq; /* for flicker control */ - - /* proc interface */ - struct mutex param_lock; /* params lock for this camera */ - struct cam_params params; /* camera settings */ - struct proc_dir_entry *proc_entry; /* /proc/cpia/videoX */ - - /* v4l */ - int video_size; /* VIDEO_SIZE_ */ - volatile enum v4l_camstates camstate; /* v4l layer status */ - struct video_device vdev; /* v4l videodev */ - struct video_picture vp; /* v4l camera settings */ - struct video_window vw; /* v4l capture area */ - struct video_capture vc; /* v4l subcapture area */ - - /* mmap interface */ - int curframe; /* the current frame to grab into */ - u8 *frame_buf; /* frame buffer data */ - struct cpia_frame frame[FRAME_NUM]; - /* FRAME_NUM-buffering, so we need a array */ - - int first_frame; - int mmap_kludge; /* 'wrong' byte order for mmap */ - volatile u32 cmd_queue; /* queued commands */ - int exposure_status; /* EXPOSURE_* */ - int exposure_count; /* number of frames at this status */ -}; - -/* cpia_register_camera is called by low level driver for each camera. - * A unique camera number is returned, or a negative value on error */ -struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowlevel); - -/* cpia_unregister_camera is called by low level driver when a camera - * is removed. This must not fail. */ -void cpia_unregister_camera(struct cam_data *cam); - -/* raw CIF + 64 byte header + (2 bytes line_length + EOL) per line + 4*EOI + - * one byte 16bit DMA alignment - */ -#define CPIA_MAX_IMAGE_SIZE ((352*288*2)+64+(288*3)+5) - -/* constant value's */ -#define MAGIC_0 0x19 -#define MAGIC_1 0x68 -#define DATA_IN 0xC0 -#define DATA_OUT 0x40 -#define VIDEOSIZE_QCIF 0 /* 176x144 */ -#define VIDEOSIZE_CIF 1 /* 352x288 */ -#define VIDEOSIZE_SIF 2 /* 320x240 */ -#define VIDEOSIZE_QSIF 3 /* 160x120 */ -#define VIDEOSIZE_48_48 4 /* where no one has gone before, iconsize! */ -#define VIDEOSIZE_64_48 5 -#define VIDEOSIZE_128_96 6 -#define VIDEOSIZE_160_120 VIDEOSIZE_QSIF -#define VIDEOSIZE_176_144 VIDEOSIZE_QCIF -#define VIDEOSIZE_192_144 7 -#define VIDEOSIZE_224_168 8 -#define VIDEOSIZE_256_192 9 -#define VIDEOSIZE_288_216 10 -#define VIDEOSIZE_320_240 VIDEOSIZE_SIF -#define VIDEOSIZE_352_288 VIDEOSIZE_CIF -#define VIDEOSIZE_88_72 11 /* quarter CIF */ -#define SUBSAMPLE_420 0 -#define SUBSAMPLE_422 1 -#define YUVORDER_YUYV 0 -#define YUVORDER_UYVY 1 -#define NOT_COMPRESSED 0 -#define COMPRESSED 1 -#define NO_DECIMATION 0 -#define DECIMATION_ENAB 1 -#define EOI 0xff /* End Of Image */ -#define EOL 0xfd /* End Of Line */ -#define FRAME_HEADER_SIZE 64 - -/* Image grab modes */ -#define CPIA_GRAB_SINGLE 0 -#define CPIA_GRAB_CONTINUOUS 1 - -/* Compression parameters */ -#define CPIA_COMPRESSION_NONE 0 -#define CPIA_COMPRESSION_AUTO 1 -#define CPIA_COMPRESSION_MANUAL 2 -#define CPIA_COMPRESSION_TARGET_QUALITY 0 -#define CPIA_COMPRESSION_TARGET_FRAMERATE 1 - -/* Return offsets for GetCameraState */ -#define SYSTEMSTATE 0 -#define GRABSTATE 1 -#define STREAMSTATE 2 -#define FATALERROR 3 -#define CMDERROR 4 -#define DEBUGFLAGS 5 -#define VPSTATUS 6 -#define ERRORCODE 7 - -/* SystemState */ -#define UNINITIALISED_STATE 0 -#define PASS_THROUGH_STATE 1 -#define LO_POWER_STATE 2 -#define HI_POWER_STATE 3 -#define WARM_BOOT_STATE 4 - -/* GrabState */ -#define GRAB_IDLE 0 -#define GRAB_ACTIVE 1 -#define GRAB_DONE 2 - -/* StreamState */ -#define STREAM_NOT_READY 0 -#define STREAM_READY 1 -#define STREAM_OPEN 2 -#define STREAM_PAUSED 3 -#define STREAM_FINISHED 4 - -/* Fatal Error, CmdError, and DebugFlags */ -#define CPIA_FLAG 1 -#define SYSTEM_FLAG 2 -#define INT_CTRL_FLAG 4 -#define PROCESS_FLAG 8 -#define COM_FLAG 16 -#define VP_CTRL_FLAG 32 -#define CAPTURE_FLAG 64 -#define DEBUG_FLAG 128 - -/* VPStatus */ -#define VP_STATE_OK 0x00 - -#define VP_STATE_FAILED_VIDEOINIT 0x01 -#define VP_STATE_FAILED_AECACBINIT 0x02 -#define VP_STATE_AEC_MAX 0x04 -#define VP_STATE_ACB_BMAX 0x08 - -#define VP_STATE_ACB_RMIN 0x10 -#define VP_STATE_ACB_GMIN 0x20 -#define VP_STATE_ACB_RMAX 0x40 -#define VP_STATE_ACB_GMAX 0x80 - -/* default (minimum) compensation values */ -#define COMP_RED 220 -#define COMP_GREEN1 214 -#define COMP_GREEN2 COMP_GREEN1 -#define COMP_BLUE 230 - -/* exposure status */ -#define EXPOSURE_VERY_LIGHT 0 -#define EXPOSURE_LIGHT 1 -#define EXPOSURE_NORMAL 2 -#define EXPOSURE_DARK 3 -#define EXPOSURE_VERY_DARK 4 - -/* ErrorCode */ -#define ERROR_FLICKER_BELOW_MIN_EXP 0x01 /*flicker exposure got below minimum exposure */ -#define ALOG(fmt,args...) printk(fmt, ##args) -#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __func__ , __LINE__ , ##args) - -#ifdef _CPIA_DEBUG_ -#define ADBG(fmt,args...) printk(fmt, jiffies, ##args) -#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __func__, __LINE__ , ##args) -#else -#define DBG(fmn,args...) do {} while(0) -#endif - -#define DEB_BYTE(p)\ - DBG("%1d %1d %1d %1d %1d %1d %1d %1d \n",\ - (p)&0x80?1:0, (p)&0x40?1:0, (p)&0x20?1:0, (p)&0x10?1:0,\ - (p)&0x08?1:0, (p)&0x04?1:0, (p)&0x02?1:0, (p)&0x01?1:0); - -#endif /* __KERNEL__ */ - -#endif /* cpia_h */ diff --git a/drivers/staging/cpia/cpia_pp.c b/drivers/staging/cpia/cpia_pp.c deleted file mode 100644 index f5604c1..0000000 --- a/drivers/staging/cpia/cpia_pp.c +++ /dev/null @@ -1,869 +0,0 @@ -/* - * cpia_pp CPiA Parallel Port driver - * - * Supports CPiA based parallel port Video Camera's. - * - * (C) Copyright 1999 Bas Huisman - * (C) Copyright 1999-2000 Scott J. Bertin , - * (C) Copyright 1999-2000 Peter Pregler - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */ -/* #define _CPIA_DEBUG_ 1 */ - - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -/* #define _CPIA_DEBUG_ define for verbose debug output */ -#include "cpia.h" - -static int cpia_pp_open(void *privdata); -static int cpia_pp_registerCallback(void *privdata, void (*cb) (void *cbdata), - void *cbdata); -static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data); -static int cpia_pp_streamStart(void *privdata); -static int cpia_pp_streamStop(void *privdata); -static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock); -static int cpia_pp_close(void *privdata); - - -#define ABOUT "Parallel port driver for Vision CPiA based cameras" - -#define PACKET_LENGTH 8 - -/* Magic numbers for defining port-device mappings */ -#define PPCPIA_PARPORT_UNSPEC -4 -#define PPCPIA_PARPORT_AUTO -3 -#define PPCPIA_PARPORT_OFF -2 -#define PPCPIA_PARPORT_NONE -1 - -static int parport_nr[PARPORT_MAX] = {[0 ... PARPORT_MAX - 1] = PPCPIA_PARPORT_UNSPEC}; -static char *parport[PARPORT_MAX] = {NULL,}; - -MODULE_AUTHOR("B. Huisman & Peter Pregler "); -MODULE_DESCRIPTION("Parallel port driver for Vision CPiA based cameras"); -MODULE_LICENSE("GPL"); - -module_param_array(parport, charp, NULL, 0); -MODULE_PARM_DESC(parport, "'auto' or a list of parallel port numbers. Just like lp."); - -struct pp_cam_entry { - struct pardevice *pdev; - struct parport *port; - struct work_struct cb_task; - void (*cb_func)(void *cbdata); - void *cb_data; - int open_count; - wait_queue_head_t wq_stream; - /* image state flags */ - int image_ready; /* we got an interrupt */ - int image_complete; /* we have seen 4 EOI */ - - int streaming; /* we are in streaming mode */ - int stream_irq; -}; - -static struct cpia_camera_ops cpia_pp_ops = -{ - cpia_pp_open, - cpia_pp_registerCallback, - cpia_pp_transferCmd, - cpia_pp_streamStart, - cpia_pp_streamStop, - cpia_pp_streamRead, - cpia_pp_close, - 1, - THIS_MODULE -}; - -static LIST_HEAD(cam_list); -static spinlock_t cam_list_lock_pp; - -/* FIXME */ -static void cpia_parport_enable_irq( struct parport *port ) { - parport_enable_irq(port); - mdelay(10); - return; -} - -static void cpia_parport_disable_irq( struct parport *port ) { - parport_disable_irq(port); - mdelay(10); - return; -} - -/* Special CPiA PPC modes: These are invoked by using the 1284 Extensibility - * Link Flag during negotiation */ -#define UPLOAD_FLAG 0x08 -#define NIBBLE_TRANSFER 0x01 -#define ECP_TRANSFER 0x03 - -#define PARPORT_CHUNK_SIZE PAGE_SIZE - - -static void cpia_pp_run_callback(struct work_struct *work) -{ - void (*cb_func)(void *cbdata); - void *cb_data; - struct pp_cam_entry *cam; - - cam = container_of(work, struct pp_cam_entry, cb_task); - cb_func = cam->cb_func; - cb_data = cam->cb_data; - - cb_func(cb_data); -} - -/**************************************************************************** - * - * CPiA-specific low-level parport functions for nibble uploads - * - ***************************************************************************/ -/* CPiA nonstandard "Nibble" mode (no nDataAvail signal after each byte). */ -/* The standard kernel parport_ieee1284_read_nibble() fails with the CPiA... */ - -static size_t cpia_read_nibble (struct parport *port, - void *buffer, size_t len, - int flags) -{ - /* adapted verbatim, with one change, from - parport_ieee1284_read_nibble() in drivers/parport/ieee1284-ops.c */ - - unsigned char *buf = buffer; - int i; - unsigned char byte = 0; - - len *= 2; /* in nibbles */ - for (i=0; i < len; i++) { - unsigned char nibble; - - /* The CPiA firmware suppresses the use of nDataAvail (nFault LO) - * after every second nibble to signal that more - * data is available. (the total number of Bytes that - * should be sent is known; if too few are received, an error - * will be recorded after a timeout). - * This is incompatible with parport_ieee1284_read_nibble(), - * which expects to find nFault LO after every second nibble. - */ - - /* Solution: modify cpia_read_nibble to only check for - * nDataAvail before the first nibble is sent. - */ - - /* Does the error line indicate end of data? */ - if (((i /*& 1*/) == 0) && - (parport_read_status(port) & PARPORT_STATUS_ERROR)) { - DBG("%s: No more nibble data (%d bytes)\n", - port->name, i/2); - goto end_of_data; - } - - /* Event 7: Set nAutoFd low. */ - parport_frob_control (port, - PARPORT_CONTROL_AUTOFD, - PARPORT_CONTROL_AUTOFD); - - /* Event 9: nAck goes low. */ - port->ieee1284.phase = IEEE1284_PH_REV_DATA; - if (parport_wait_peripheral (port, - PARPORT_STATUS_ACK, 0)) { - /* Timeout -- no more data? */ - DBG("%s: Nibble timeout at event 9 (%d bytes)\n", - port->name, i/2); - parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0); - break; - } - - - /* Read a nibble. */ - nibble = parport_read_status (port) >> 3; - nibble &= ~8; - if ((nibble & 0x10) == 0) - nibble |= 8; - nibble &= 0xf; - - /* Event 10: Set nAutoFd high. */ - parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0); - - /* Event 11: nAck goes high. */ - if (parport_wait_peripheral (port, - PARPORT_STATUS_ACK, - PARPORT_STATUS_ACK)) { - /* Timeout -- no more data? */ - DBG("%s: Nibble timeout at event 11\n", - port->name); - break; - } - - if (i & 1) { - /* Second nibble */ - byte |= nibble << 4; - *buf++ = byte; - } else - byte = nibble; - } - - if (i == len) { - /* Read the last nibble without checking data avail. */ - if (parport_read_status (port) & PARPORT_STATUS_ERROR) { - end_of_data: - /* Go to reverse idle phase. */ - parport_frob_control (port, - PARPORT_CONTROL_AUTOFD, - PARPORT_CONTROL_AUTOFD); - port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE; - } - else - port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL; - } - - return i/2; -} - -/* CPiA nonstandard "Nibble Stream" mode (2 nibbles per cycle, instead of 1) - * (See CPiA Data sheet p. 31) - * - * "Nibble Stream" mode used by CPiA for uploads to non-ECP ports is a - * nonstandard variant of nibble mode which allows the same (mediocre) - * data flow of 8 bits per cycle as software-enabled ECP by TRISTATE-capable - * parallel ports, but works also for non-TRISTATE-capable ports. - * (Standard nibble mode only send 4 bits per cycle) - * - */ - -static size_t cpia_read_nibble_stream(struct parport *port, - void *buffer, size_t len, - int flags) -{ - int i; - unsigned char *buf = buffer; - int endseen = 0; - - for (i=0; i < len; i++) { - unsigned char nibble[2], byte = 0; - int j; - - /* Image Data is complete when 4 consecutive EOI bytes (0xff) are seen */ - if (endseen > 3 ) - break; - - /* Event 7: Set nAutoFd low. */ - parport_frob_control (port, - PARPORT_CONTROL_AUTOFD, - PARPORT_CONTROL_AUTOFD); - - /* Event 9: nAck goes low. */ - port->ieee1284.phase = IEEE1284_PH_REV_DATA; - if (parport_wait_peripheral (port, - PARPORT_STATUS_ACK, 0)) { - /* Timeout -- no more data? */ - DBG("%s: Nibble timeout at event 9 (%d bytes)\n", - port->name, i/2); - parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0); - break; - } - - /* Read lower nibble */ - nibble[0] = parport_read_status (port) >>3; - - /* Event 10: Set nAutoFd high. */ - parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0); - - /* Event 11: nAck goes high. */ - if (parport_wait_peripheral (port, - PARPORT_STATUS_ACK, - PARPORT_STATUS_ACK)) { - /* Timeout -- no more data? */ - DBG("%s: Nibble timeout at event 11\n", - port->name); - break; - } - - /* Read upper nibble */ - nibble[1] = parport_read_status (port) >>3; - - /* reassemble the byte */ - for (j = 0; j < 2 ; j++ ) { - nibble[j] &= ~8; - if ((nibble[j] & 0x10) == 0) - nibble[j] |= 8; - nibble[j] &= 0xf; - } - byte = (nibble[0] |(nibble[1] << 4)); - *buf++ = byte; - - if(byte == EOI) - endseen++; - else - endseen = 0; - } - return i; -} - -/**************************************************************************** - * - * EndTransferMode - * - ***************************************************************************/ -static void EndTransferMode(struct pp_cam_entry *cam) -{ - parport_negotiate(cam->port, IEEE1284_MODE_COMPAT); -} - -/**************************************************************************** - * - * ForwardSetup - * - ***************************************************************************/ -static int ForwardSetup(struct pp_cam_entry *cam) -{ - int retry; - - /* The CPiA uses ECP protocol for Downloads from the Host to the camera. - * This will be software-emulated if ECP hardware is not present - */ - - /* the usual camera maximum response time is 10ms, but after receiving - * some commands, it needs up to 40ms. (Data Sheet p. 32)*/ - - for(retry = 0; retry < 4; ++retry) { - if(!parport_negotiate(cam->port, IEEE1284_MODE_ECP)) { - break; - } - mdelay(10); - } - if(retry == 4) { - DBG("Unable to negotiate IEEE1284 ECP Download mode\n"); - return -1; - } - return 0; -} -/**************************************************************************** - * - * ReverseSetup - * - ***************************************************************************/ -static int ReverseSetup(struct pp_cam_entry *cam, int extensibility) -{ - int retry; - int upload_mode, mode = IEEE1284_MODE_ECP; - int transfer_mode = ECP_TRANSFER; - - if (!(cam->port->modes & PARPORT_MODE_ECP) && - !(cam->port->modes & PARPORT_MODE_TRISTATE)) { - mode = IEEE1284_MODE_NIBBLE; - transfer_mode = NIBBLE_TRANSFER; - } - - upload_mode = mode; - if(extensibility) mode = UPLOAD_FLAG|transfer_mode|IEEE1284_EXT_LINK; - - /* the usual camera maximum response time is 10ms, but after - * receiving some commands, it needs up to 40ms. */ - - for(retry = 0; retry < 4; ++retry) { - if(!parport_negotiate(cam->port, mode)) { - break; - } - mdelay(10); - } - if(retry == 4) { - if(extensibility) - DBG("Unable to negotiate upload extensibility mode\n"); - else - DBG("Unable to negotiate upload mode\n"); - return -1; - } - if(extensibility) cam->port->ieee1284.mode = upload_mode; - return 0; -} - -/**************************************************************************** - * - * WritePacket - * - ***************************************************************************/ -static int WritePacket(struct pp_cam_entry *cam, const u8 *packet, size_t size) -{ - int retval=0; - int size_written; - - if (packet == NULL) { - return -EINVAL; - } - if (ForwardSetup(cam)) { - DBG("Write failed in setup\n"); - return -EIO; - } - size_written = parport_write(cam->port, packet, size); - if(size_written != size) { - DBG("Write failed, wrote %d/%d\n", size_written, size); - retval = -EIO; - } - EndTransferMode(cam); - return retval; -} - -/**************************************************************************** - * - * ReadPacket - * - ***************************************************************************/ -static int ReadPacket(struct pp_cam_entry *cam, u8 *packet, size_t size) -{ - int retval=0; - - if (packet == NULL) { - return -EINVAL; - } - if (ReverseSetup(cam, 0)) { - return -EIO; - } - - /* support for CPiA variant nibble reads */ - if(cam->port->ieee1284.mode == IEEE1284_MODE_NIBBLE) { - if(cpia_read_nibble(cam->port, packet, size, 0) != size) - retval = -EIO; - } else { - if(parport_read(cam->port, packet, size) != size) - retval = -EIO; - } - EndTransferMode(cam); - return retval; -} - -/**************************************************************************** - * - * cpia_pp_streamStart - * - ***************************************************************************/ -static int cpia_pp_streamStart(void *privdata) -{ - struct pp_cam_entry *cam = privdata; - DBG("\n"); - cam->streaming=1; - cam->image_ready=0; - //if (ReverseSetup(cam,1)) return -EIO; - if(cam->stream_irq) cpia_parport_enable_irq(cam->port); - return 0; -} - -/**************************************************************************** - * - * cpia_pp_streamStop - * - ***************************************************************************/ -static int cpia_pp_streamStop(void *privdata) -{ - struct pp_cam_entry *cam = privdata; - - DBG("\n"); - cam->streaming=0; - cpia_parport_disable_irq(cam->port); - //EndTransferMode(cam); - - return 0; -} - -/**************************************************************************** - * - * cpia_pp_streamRead - * - ***************************************************************************/ -static int cpia_pp_read(struct parport *port, u8 *buffer, int len) -{ - int bytes_read; - - /* support for CPiA variant "nibble stream" reads */ - if(port->ieee1284.mode == IEEE1284_MODE_NIBBLE) - bytes_read = cpia_read_nibble_stream(port,buffer,len,0); - else { - int new_bytes; - for(bytes_read=0; bytes_readstreaming) DBG("%d / %d\n", cam->image_ready, noblock); - if( cam->stream_irq ) { - DBG("%d\n", cam->image_ready); - cam->image_ready--; - } - cam->image_complete=0; - if (0/*cam->streaming*/) { - if(!cam->image_ready) { - if(noblock) return -EWOULDBLOCK; - interruptible_sleep_on(&cam->wq_stream); - if( signal_pending(current) ) return -EINTR; - DBG("%d\n", cam->image_ready); - } - } else { - if (ReverseSetup(cam, 1)) { - DBG("unable to ReverseSetup\n"); - return -EIO; - } - } - endseen = 0; - block_size = PARPORT_CHUNK_SIZE; - while( !cam->image_complete ) { - cond_resched(); - - new_bytes = cpia_pp_read(cam->port, buffer, block_size ); - if( new_bytes <= 0 ) { - break; - } - i=-1; - while(++iimage_complete=1; - break; - } - if( CPIA_MAX_IMAGE_SIZE-read_bytes <= PARPORT_CHUNK_SIZE ) { - block_size=CPIA_MAX_IMAGE_SIZE-read_bytes; - } - } - EndTransferMode(cam); - return cam->image_complete ? read_bytes : -EIO; -} -/**************************************************************************** - * - * cpia_pp_transferCmd - * - ***************************************************************************/ -static int cpia_pp_transferCmd(void *privdata, u8 *command, u8 *data) -{ - int err; - int retval=0; - int databytes; - struct pp_cam_entry *cam = privdata; - - if(cam == NULL) { - DBG("Internal driver error: cam is NULL\n"); - return -EINVAL; - } - if(command == NULL) { - DBG("Internal driver error: command is NULL\n"); - return -EINVAL; - } - databytes = (((int)command[7])<<8) | command[6]; - if ((err = WritePacket(cam, command, PACKET_LENGTH)) < 0) { - DBG("Error writing command\n"); - return err; - } - if(command[0] == DATA_IN) { - u8 buffer[8]; - if(data == NULL) { - DBG("Internal driver error: data is NULL\n"); - return -EINVAL; - } - if((err = ReadPacket(cam, buffer, 8)) < 0) { - DBG("Error reading command result\n"); - return err; - } - memcpy(data, buffer, databytes); - } else if(command[0] == DATA_OUT) { - if(databytes > 0) { - if(data == NULL) { - DBG("Internal driver error: data is NULL\n"); - retval = -EINVAL; - } else { - if((err=WritePacket(cam, data, databytes)) < 0){ - DBG("Error writing command data\n"); - return err; - } - } - } - } else { - DBG("Unexpected first byte of command: %x\n", command[0]); - retval = -EINVAL; - } - return retval; -} - -/**************************************************************************** - * - * cpia_pp_open - * - ***************************************************************************/ -static int cpia_pp_open(void *privdata) -{ - struct pp_cam_entry *cam = (struct pp_cam_entry *)privdata; - - if (cam == NULL) - return -EINVAL; - - if(cam->open_count == 0) { - if (parport_claim(cam->pdev)) { - DBG("failed to claim the port\n"); - return -EBUSY; - } - parport_negotiate(cam->port, IEEE1284_MODE_COMPAT); - parport_data_forward(cam->port); - parport_write_control(cam->port, PARPORT_CONTROL_SELECT); - udelay(50); - parport_write_control(cam->port, - PARPORT_CONTROL_SELECT - | PARPORT_CONTROL_INIT); - } - - ++cam->open_count; - - return 0; -} - -/**************************************************************************** - * - * cpia_pp_registerCallback - * - ***************************************************************************/ -static int cpia_pp_registerCallback(void *privdata, void (*cb)(void *cbdata), void *cbdata) -{ - struct pp_cam_entry *cam = privdata; - int retval = 0; - - if(cam->port->irq != PARPORT_IRQ_NONE) { - cam->cb_func = cb; - cam->cb_data = cbdata; - INIT_WORK(&cam->cb_task, cpia_pp_run_callback); - } else { - retval = -1; - } - return retval; -} - -/**************************************************************************** - * - * cpia_pp_close - * - ***************************************************************************/ -static int cpia_pp_close(void *privdata) -{ - struct pp_cam_entry *cam = privdata; - if (--cam->open_count == 0) { - parport_release(cam->pdev); - } - return 0; -} - -/**************************************************************************** - * - * cpia_pp_register - * - ***************************************************************************/ -static int cpia_pp_register(struct parport *port) -{ - struct pardevice *pdev = NULL; - struct pp_cam_entry *cam; - struct cam_data *cpia; - - if (!(port->modes & PARPORT_MODE_PCSPP)) { - LOG("port is not supported by CPiA driver\n"); - return -ENXIO; - } - - cam = kzalloc(sizeof(struct pp_cam_entry), GFP_KERNEL); - if (cam == NULL) { - LOG("failed to allocate camera structure\n"); - return -ENOMEM; - } - - pdev = parport_register_device(port, "cpia_pp", NULL, NULL, - NULL, 0, cam); - - if (!pdev) { - LOG("failed to parport_register_device\n"); - kfree(cam); - return -ENXIO; - } - - cam->pdev = pdev; - cam->port = port; - init_waitqueue_head(&cam->wq_stream); - - cam->streaming = 0; - cam->stream_irq = 0; - - if((cpia = cpia_register_camera(&cpia_pp_ops, cam)) == NULL) { - LOG("failed to cpia_register_camera\n"); - parport_unregister_device(pdev); - kfree(cam); - return -ENXIO; - } - spin_lock( &cam_list_lock_pp ); - list_add( &cpia->cam_data_list, &cam_list ); - spin_unlock( &cam_list_lock_pp ); - - return 0; -} - -static void cpia_pp_detach (struct parport *port) -{ - struct list_head *tmp; - struct cam_data *cpia = NULL; - struct pp_cam_entry *cam; - - spin_lock( &cam_list_lock_pp ); - list_for_each (tmp, &cam_list) { - cpia = list_entry(tmp, struct cam_data, cam_data_list); - cam = (struct pp_cam_entry *) cpia->lowlevel_data; - if (cam && cam->port->number == port->number) { - list_del(&cpia->cam_data_list); - break; - } - cpia = NULL; - } - spin_unlock( &cam_list_lock_pp ); - - if (!cpia) { - DBG("cpia_pp_detach failed to find cam_data in cam_list\n"); - return; - } - - cam = (struct pp_cam_entry *) cpia->lowlevel_data; - cpia_unregister_camera(cpia); - if(cam->open_count > 0) - cpia_pp_close(cam); - parport_unregister_device(cam->pdev); - cpia->lowlevel_data = NULL; - kfree(cam); -} - -static void cpia_pp_attach (struct parport *port) -{ - unsigned int i; - - switch (parport_nr[0]) - { - case PPCPIA_PARPORT_UNSPEC: - case PPCPIA_PARPORT_AUTO: - if (port->probe_info[0].class != PARPORT_CLASS_MEDIA || - port->probe_info[0].cmdset == NULL || - strncmp(port->probe_info[0].cmdset, "CPIA_1", 6) != 0) - return; - - cpia_pp_register(port); - - break; - - default: - for (i = 0; i < PARPORT_MAX; ++i) { - if (port->number == parport_nr[i]) { - cpia_pp_register(port); - break; - } - } - break; - } -} - -static struct parport_driver cpia_pp_driver = { - .name = "cpia_pp", - .attach = cpia_pp_attach, - .detach = cpia_pp_detach, -}; - -static int __init cpia_pp_init(void) -{ - printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, - CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER); - - if(parport_nr[0] == PPCPIA_PARPORT_OFF) { - printk(" disabled\n"); - return 0; - } - - spin_lock_init( &cam_list_lock_pp ); - - if (parport_register_driver (&cpia_pp_driver)) { - LOG ("unable to register with parport\n"); - return -EIO; - } - return 0; -} - -static int __init cpia_init(void) -{ - if (parport[0]) { - /* The user gave some parameters. Let's see what they were. */ - if (!strncmp(parport[0], "auto", 4)) { - parport_nr[0] = PPCPIA_PARPORT_AUTO; - } else { - int n; - for (n = 0; n < PARPORT_MAX && parport[n]; n++) { - if (!strncmp(parport[n], "none", 4)) { - parport_nr[n] = PPCPIA_PARPORT_NONE; - } else { - char *ep; - unsigned long r = simple_strtoul(parport[n], &ep, 0); - if (ep != parport[n]) { - parport_nr[n] = r; - } else { - LOG("bad port specifier `%s'\n", parport[n]); - return -ENODEV; - } - } - } - } - } - return cpia_pp_init(); -} - -static void __exit cpia_cleanup(void) -{ - parport_unregister_driver(&cpia_pp_driver); - return; -} - -module_init(cpia_init); -module_exit(cpia_cleanup); diff --git a/drivers/staging/cpia/cpia_usb.c b/drivers/staging/cpia/cpia_usb.c deleted file mode 100644 index 58d193f..0000000 --- a/drivers/staging/cpia/cpia_usb.c +++ /dev/null @@ -1,640 +0,0 @@ -/* - * cpia_usb CPiA USB driver - * - * Supports CPiA based parallel port Video Camera's. - * - * Copyright (C) 1999 Jochen Scharrlach - * Copyright (C) 1999, 2000 Johannes Erdfelt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */ -/* #define _CPIA_DEBUG_ 1 */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cpia.h" - -#define USB_REQ_CPIA_GRAB_FRAME 0xC1 -#define USB_REQ_CPIA_UPLOAD_FRAME 0xC2 -#define WAIT_FOR_NEXT_FRAME 0 -#define FORCE_FRAME_UPLOAD 1 - -#define FRAMES_PER_DESC 10 -#define FRAME_SIZE_PER_DESC 960 /* Shouldn't be hardcoded */ -#define CPIA_NUMSBUF 2 -#define STREAM_BUF_SIZE (PAGE_SIZE * 4) -#define SCRATCH_BUF_SIZE (STREAM_BUF_SIZE * 2) - -struct cpia_sbuf { - char *data; - struct urb *urb; -}; - -#define FRAMEBUF_LEN (CPIA_MAX_FRAME_SIZE+100) -enum framebuf_status { - FRAME_EMPTY, - FRAME_READING, - FRAME_READY, - FRAME_ERROR, -}; - -struct framebuf { - int length; - enum framebuf_status status; - u8 data[FRAMEBUF_LEN]; - struct framebuf *next; -}; - -struct usb_cpia { - /* Device structure */ - struct usb_device *dev; - - unsigned char iface; - wait_queue_head_t wq_stream; - - int cursbuf; /* Current receiving sbuf */ - struct cpia_sbuf sbuf[CPIA_NUMSBUF]; /* Double buffering */ - - int streaming; - int open; - int present; - struct framebuf *buffers[3]; - struct framebuf *curbuff, *workbuff; -}; - -static int cpia_usb_open(void *privdata); -static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata), - void *cbdata); -static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data); -static int cpia_usb_streamStart(void *privdata); -static int cpia_usb_streamStop(void *privdata); -static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock); -static int cpia_usb_close(void *privdata); - -#define ABOUT "USB driver for Vision CPiA based cameras" - -static struct cpia_camera_ops cpia_usb_ops = { - cpia_usb_open, - cpia_usb_registerCallback, - cpia_usb_transferCmd, - cpia_usb_streamStart, - cpia_usb_streamStop, - cpia_usb_streamRead, - cpia_usb_close, - 0, - THIS_MODULE -}; - -static LIST_HEAD(cam_list); -static spinlock_t cam_list_lock_usb; - -static void cpia_usb_complete(struct urb *urb) -{ - int i; - char *cdata; - struct usb_cpia *ucpia; - - if (!urb || !urb->context) - return; - - ucpia = (struct usb_cpia *) urb->context; - - if (!ucpia->dev || !ucpia->streaming || !ucpia->present || !ucpia->open) - return; - - if (ucpia->workbuff->status == FRAME_EMPTY) { - ucpia->workbuff->status = FRAME_READING; - ucpia->workbuff->length = 0; - } - - for (i = 0; i < urb->number_of_packets; i++) { - int n = urb->iso_frame_desc[i].actual_length; - int st = urb->iso_frame_desc[i].status; - - cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - - if (st) - printk(KERN_DEBUG "cpia data error: [%d] len=%d, status=%X\n", i, n, st); - - if (FRAMEBUF_LEN < ucpia->workbuff->length + n) { - printk(KERN_DEBUG "cpia: scratch buf overflow!scr_len: %d, n: %d\n", ucpia->workbuff->length, n); - return; - } - - if (n) { - if ((ucpia->workbuff->length > 0) || - (0x19 == cdata[0] && 0x68 == cdata[1])) { - memcpy(ucpia->workbuff->data + ucpia->workbuff->length, cdata, n); - ucpia->workbuff->length += n; - } else - DBG("Ignoring packet!\n"); - } else { - if (ucpia->workbuff->length > 4 && - 0xff == ucpia->workbuff->data[ucpia->workbuff->length-1] && - 0xff == ucpia->workbuff->data[ucpia->workbuff->length-2] && - 0xff == ucpia->workbuff->data[ucpia->workbuff->length-3] && - 0xff == ucpia->workbuff->data[ucpia->workbuff->length-4]) { - ucpia->workbuff->status = FRAME_READY; - ucpia->curbuff = ucpia->workbuff; - ucpia->workbuff = ucpia->workbuff->next; - ucpia->workbuff->status = FRAME_EMPTY; - ucpia->workbuff->length = 0; - - if (waitqueue_active(&ucpia->wq_stream)) - wake_up_interruptible(&ucpia->wq_stream); - } - } - } - - /* resubmit */ - urb->dev = ucpia->dev; - if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0) - printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __func__, i); -} - -static int cpia_usb_open(void *privdata) -{ - struct usb_cpia *ucpia = (struct usb_cpia *) privdata; - struct urb *urb; - int ret, retval = 0, fx, err; - - if (!ucpia) - return -EINVAL; - - ucpia->sbuf[0].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL); - if (!ucpia->sbuf[0].data) - return -EINVAL; - - ucpia->sbuf[1].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL); - if (!ucpia->sbuf[1].data) { - retval = -EINVAL; - goto error_0; - } - - ret = usb_set_interface(ucpia->dev, ucpia->iface, 3); - if (ret < 0) { - printk(KERN_ERR "cpia_usb_open: usb_set_interface error (ret = %d)\n", ret); - retval = -EBUSY; - goto error_1; - } - - ucpia->buffers[0]->status = FRAME_EMPTY; - ucpia->buffers[0]->length = 0; - ucpia->buffers[1]->status = FRAME_EMPTY; - ucpia->buffers[1]->length = 0; - ucpia->buffers[2]->status = FRAME_EMPTY; - ucpia->buffers[2]->length = 0; - ucpia->curbuff = ucpia->buffers[0]; - ucpia->workbuff = ucpia->buffers[1]; - - /* We double buffer the Iso lists, and also know the polling - * interval is every frame (1 == (1 << (bInterval -1))). - */ - urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); - if (!urb) { - printk(KERN_ERR "cpia_init_isoc: usb_alloc_urb 0\n"); - retval = -ENOMEM; - goto error_1; - } - - ucpia->sbuf[0].urb = urb; - urb->dev = ucpia->dev; - urb->context = ucpia; - urb->pipe = usb_rcvisocpipe(ucpia->dev, 1); - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = ucpia->sbuf[0].data; - urb->complete = cpia_usb_complete; - urb->number_of_packets = FRAMES_PER_DESC; - urb->interval = 1; - urb->transfer_buffer_length = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC; - for (fx = 0; fx < FRAMES_PER_DESC; fx++) { - urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx; - urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC; - } - - urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); - if (!urb) { - printk(KERN_ERR "cpia_init_isoc: usb_alloc_urb 1\n"); - retval = -ENOMEM; - goto error_urb0; - } - - ucpia->sbuf[1].urb = urb; - urb->dev = ucpia->dev; - urb->context = ucpia; - urb->pipe = usb_rcvisocpipe(ucpia->dev, 1); - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = ucpia->sbuf[1].data; - urb->complete = cpia_usb_complete; - urb->number_of_packets = FRAMES_PER_DESC; - urb->interval = 1; - urb->transfer_buffer_length = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC; - for (fx = 0; fx < FRAMES_PER_DESC; fx++) { - urb->iso_frame_desc[fx].offset = FRAME_SIZE_PER_DESC * fx; - urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC; - } - - /* queue the ISO urbs, and resubmit in the completion handler */ - err = usb_submit_urb(ucpia->sbuf[0].urb, GFP_KERNEL); - if (err) { - printk(KERN_ERR "cpia_init_isoc: usb_submit_urb 0 ret %d\n", - err); - goto error_urb1; - } - err = usb_submit_urb(ucpia->sbuf[1].urb, GFP_KERNEL); - if (err) { - printk(KERN_ERR "cpia_init_isoc: usb_submit_urb 1 ret %d\n", - err); - goto error_urb1; - } - - ucpia->streaming = 1; - ucpia->open = 1; - - return 0; - -error_urb1: /* free urb 1 */ - usb_free_urb(ucpia->sbuf[1].urb); - ucpia->sbuf[1].urb = NULL; -error_urb0: /* free urb 0 */ - usb_free_urb(ucpia->sbuf[0].urb); - ucpia->sbuf[0].urb = NULL; -error_1: - kfree (ucpia->sbuf[1].data); - ucpia->sbuf[1].data = NULL; -error_0: - kfree (ucpia->sbuf[0].data); - ucpia->sbuf[0].data = NULL; - - return retval; -} - -// -// convenience functions -// - -/**************************************************************************** - * - * WritePacket - * - ***************************************************************************/ -static int WritePacket(struct usb_device *udev, const u8 *packet, u8 *buf, size_t size) -{ - if (!packet) - return -EINVAL; - - return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - packet[1] + (packet[0] << 8), - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - packet[2] + (packet[3] << 8), - packet[4] + (packet[5] << 8), buf, size, 1000); -} - -/**************************************************************************** - * - * ReadPacket - * - ***************************************************************************/ -static int ReadPacket(struct usb_device *udev, u8 *packet, u8 *buf, size_t size) -{ - if (!packet || size <= 0) - return -EINVAL; - - return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - packet[1] + (packet[0] << 8), - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - packet[2] + (packet[3] << 8), - packet[4] + (packet[5] << 8), buf, size, 1000); -} - -static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data) -{ - int err = 0; - int databytes; - struct usb_cpia *ucpia = (struct usb_cpia *)privdata; - struct usb_device *udev = ucpia->dev; - - if (!udev) { - DBG("Internal driver error: udev is NULL\n"); - return -EINVAL; - } - - if (!command) { - DBG("Internal driver error: command is NULL\n"); - return -EINVAL; - } - - databytes = (((int)command[7])<<8) | command[6]; - - if (command[0] == DATA_IN) { - u8 buffer[8]; - - if (!data) { - DBG("Internal driver error: data is NULL\n"); - return -EINVAL; - } - - err = ReadPacket(udev, command, buffer, 8); - if (err < 0) - return err; - - memcpy(data, buffer, databytes); - } else if(command[0] == DATA_OUT) - WritePacket(udev, command, data, databytes); - else { - DBG("Unexpected first byte of command: %x\n", command[0]); - err = -EINVAL; - } - - return 0; -} - -static int cpia_usb_registerCallback(void *privdata, void (*cb) (void *cbdata), - void *cbdata) -{ - return -ENODEV; -} - -static int cpia_usb_streamStart(void *privdata) -{ - return -ENODEV; -} - -static int cpia_usb_streamStop(void *privdata) -{ - return -ENODEV; -} - -static int cpia_usb_streamRead(void *privdata, u8 *frame, int noblock) -{ - struct usb_cpia *ucpia = (struct usb_cpia *) privdata; - struct framebuf *mybuff; - - if (!ucpia || !ucpia->present) - return -1; - - if (ucpia->curbuff->status != FRAME_READY) - interruptible_sleep_on(&ucpia->wq_stream); - else - DBG("Frame already waiting!\n"); - - mybuff = ucpia->curbuff; - - if (!mybuff) - return -1; - - if (mybuff->status != FRAME_READY || mybuff->length < 4) { - DBG("Something went wrong!\n"); - return -1; - } - - memcpy(frame, mybuff->data, mybuff->length); - mybuff->status = FRAME_EMPTY; - -/* DBG("read done, %d bytes, Header: %x/%x, Footer: %x%x%x%x\n", */ -/* mybuff->length, frame[0], frame[1], */ -/* frame[mybuff->length-4], frame[mybuff->length-3], */ -/* frame[mybuff->length-2], frame[mybuff->length-1]); */ - - return mybuff->length; -} - -static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try) -{ - if (!ucpia->streaming) - return; - - ucpia->streaming = 0; - - /* Set packet size to 0 */ - if (try) { - int ret; - - ret = usb_set_interface(ucpia->dev, ucpia->iface, 0); - if (ret < 0) { - printk(KERN_ERR "usb_set_interface error (ret = %d)\n", ret); - return; - } - } - - /* Unschedule all of the iso td's */ - if (ucpia->sbuf[1].urb) { - usb_kill_urb(ucpia->sbuf[1].urb); - usb_free_urb(ucpia->sbuf[1].urb); - ucpia->sbuf[1].urb = NULL; - } - - kfree(ucpia->sbuf[1].data); - ucpia->sbuf[1].data = NULL; - - if (ucpia->sbuf[0].urb) { - usb_kill_urb(ucpia->sbuf[0].urb); - usb_free_urb(ucpia->sbuf[0].urb); - ucpia->sbuf[0].urb = NULL; - } - - kfree(ucpia->sbuf[0].data); - ucpia->sbuf[0].data = NULL; -} - -static int cpia_usb_close(void *privdata) -{ - struct usb_cpia *ucpia = (struct usb_cpia *) privdata; - - if(!ucpia) - return -ENODEV; - - ucpia->open = 0; - - /* ucpia->present = 0 protects against trying to reset the - * alt setting if camera is physically disconnected while open */ - cpia_usb_free_resources(ucpia, ucpia->present); - - return 0; -} - -/* Probing and initializing */ - -static int cpia_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct usb_host_interface *interface; - struct usb_cpia *ucpia; - struct cam_data *cam; - int ret; - - /* A multi-config CPiA camera? */ - if (udev->descriptor.bNumConfigurations != 1) - return -ENODEV; - - interface = intf->cur_altsetting; - - printk(KERN_INFO "USB CPiA camera found\n"); - - ucpia = kzalloc(sizeof(*ucpia), GFP_KERNEL); - if (!ucpia) { - printk(KERN_ERR "couldn't kmalloc cpia struct\n"); - return -ENOMEM; - } - - ucpia->dev = udev; - ucpia->iface = interface->desc.bInterfaceNumber; - init_waitqueue_head(&ucpia->wq_stream); - - ucpia->buffers[0] = vmalloc(sizeof(*ucpia->buffers[0])); - if (!ucpia->buffers[0]) { - printk(KERN_ERR "couldn't vmalloc frame buffer 0\n"); - goto fail_alloc_0; - } - - ucpia->buffers[1] = vmalloc(sizeof(*ucpia->buffers[1])); - if (!ucpia->buffers[1]) { - printk(KERN_ERR "couldn't vmalloc frame buffer 1\n"); - goto fail_alloc_1; - } - - ucpia->buffers[2] = vmalloc(sizeof(*ucpia->buffers[2])); - if (!ucpia->buffers[2]) { - printk(KERN_ERR "couldn't vmalloc frame buffer 2\n"); - goto fail_alloc_2; - } - - ucpia->buffers[0]->next = ucpia->buffers[1]; - ucpia->buffers[1]->next = ucpia->buffers[2]; - ucpia->buffers[2]->next = ucpia->buffers[0]; - - ret = usb_set_interface(udev, ucpia->iface, 0); - if (ret < 0) { - printk(KERN_ERR "cpia_probe: usb_set_interface error (ret = %d)\n", ret); - /* goto fail_all; */ - } - - /* Before register_camera, important */ - ucpia->present = 1; - - cam = cpia_register_camera(&cpia_usb_ops, ucpia); - if (!cam) { - LOG("failed to cpia_register_camera\n"); - goto fail_all; - } - - spin_lock( &cam_list_lock_usb ); - list_add( &cam->cam_data_list, &cam_list ); - spin_unlock( &cam_list_lock_usb ); - - usb_set_intfdata(intf, cam); - return 0; - -fail_all: - vfree(ucpia->buffers[2]); - ucpia->buffers[2] = NULL; -fail_alloc_2: - vfree(ucpia->buffers[1]); - ucpia->buffers[1] = NULL; -fail_alloc_1: - vfree(ucpia->buffers[0]); - ucpia->buffers[0] = NULL; -fail_alloc_0: - kfree(ucpia); - return -EIO; -} - -static void cpia_disconnect(struct usb_interface *intf); - -static struct usb_device_id cpia_id_table [] = { - { USB_DEVICE(0x0553, 0x0002) }, - { USB_DEVICE(0x0813, 0x0001) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, cpia_id_table); -MODULE_LICENSE("GPL"); - - -static struct usb_driver cpia_driver = { - .name = "cpia", - .probe = cpia_probe, - .disconnect = cpia_disconnect, - .id_table = cpia_id_table, -}; - -static void cpia_disconnect(struct usb_interface *intf) -{ - struct cam_data *cam = usb_get_intfdata(intf); - struct usb_cpia *ucpia; - - usb_set_intfdata(intf, NULL); - if (!cam) - return; - - ucpia = (struct usb_cpia *) cam->lowlevel_data; - spin_lock( &cam_list_lock_usb ); - list_del(&cam->cam_data_list); - spin_unlock( &cam_list_lock_usb ); - - ucpia->present = 0; - - cpia_unregister_camera(cam); - if(ucpia->open) - cpia_usb_close(cam->lowlevel_data); - - ucpia->curbuff->status = FRAME_ERROR; - - if (waitqueue_active(&ucpia->wq_stream)) - wake_up_interruptible(&ucpia->wq_stream); - - ucpia->curbuff = ucpia->workbuff = NULL; - - vfree(ucpia->buffers[2]); - ucpia->buffers[2] = NULL; - - vfree(ucpia->buffers[1]); - ucpia->buffers[1] = NULL; - - vfree(ucpia->buffers[0]); - ucpia->buffers[0] = NULL; - - cam->lowlevel_data = NULL; - kfree(ucpia); -} - -static int __init usb_cpia_init(void) -{ - printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, - CPIA_USB_MAJ_VER,CPIA_USB_MIN_VER,CPIA_USB_PATCH_VER); - - spin_lock_init(&cam_list_lock_usb); - return usb_register(&cpia_driver); -} - -static void __exit usb_cpia_cleanup(void) -{ - usb_deregister(&cpia_driver); -} - - -module_init (usb_cpia_init); -module_exit (usb_cpia_cleanup); - diff --git a/drivers/staging/stradis/Kconfig b/drivers/staging/stradis/Kconfig deleted file mode 100644 index 02f0fc5..0000000 --- a/drivers/staging/stradis/Kconfig +++ /dev/null @@ -1,7 +0,0 @@ -config VIDEO_STRADIS - tristate "Stradis 4:2:2 MPEG-2 video driver (DEPRECATED)" - depends on EXPERIMENTAL && PCI && VIDEO_V4L1 && VIRT_TO_BUS && BKL - help - Say Y here to enable support for the Stradis 4:2:2 MPEG-2 video - driver for PCI. There is a product page at - . diff --git a/drivers/staging/stradis/Makefile b/drivers/staging/stradis/Makefile deleted file mode 100644 index 0f1feab..0000000 --- a/drivers/staging/stradis/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_VIDEO_STRADIS) += stradis.o - -EXTRA_CFLAGS += -Idrivers/media/video diff --git a/drivers/staging/stradis/TODO b/drivers/staging/stradis/TODO deleted file mode 100644 index f48150f..0000000 --- a/drivers/staging/stradis/TODO +++ /dev/null @@ -1,6 +0,0 @@ -This is an obsolete driver for ancient stradis hardware. -We couldn't find anyone with this hardware in order to port it to use V4L2. - -If nobody take care on it, the driver will be removed for 2.6.38. - -Please send patches to linux-media@vger.kernel.org diff --git a/drivers/staging/stradis/stradis.c b/drivers/staging/stradis/stradis.c deleted file mode 100644 index 807dd7e..0000000 --- a/drivers/staging/stradis/stradis.c +++ /dev/null @@ -1,2222 +0,0 @@ -/* - * stradis.c - stradis 4:2:2 mpeg decoder driver - * - * Stradis 4:2:2 MPEG-2 Decoder Driver - * Copyright (C) 1999 Nathan Laredo - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "saa7146.h" -#include "saa7146reg.h" -#include "ibmmpeg2.h" -#include "saa7121.h" -#include "cs8420.h" - -#define DEBUG(x) /* debug driver */ -#undef IDEBUG /* debug irq handler */ -#undef MDEBUG /* debug memory management */ - -#define SAA7146_MAX 6 - -static struct saa7146 saa7146s[SAA7146_MAX]; - -static int saa_num; /* number of SAA7146s in use */ - -static int video_nr = -1; -module_param(video_nr, int, 0); -MODULE_LICENSE("GPL"); - -#define nDebNormal 0x00480000 -#define nDebNoInc 0x00480000 -#define nDebVideo 0xd0480000 -#define nDebAudio 0xd0400000 -#define nDebDMA 0x02c80000 - -#define oDebNormal 0x13c80000 -#define oDebNoInc 0x13c80000 -#define oDebVideo 0xd1080000 -#define oDebAudio 0xd1080000 -#define oDebDMA 0x03080000 - -#define NewCard (saa->boardcfg[3]) -#define ChipControl (saa->boardcfg[1]) -#define NTSCFirstActive (saa->boardcfg[4]) -#define PALFirstActive (saa->boardcfg[5]) -#define NTSCLastActive (saa->boardcfg[54]) -#define PALLastActive (saa->boardcfg[55]) -#define Have2MB (saa->boardcfg[18] & 0x40) -#define HaveCS8420 (saa->boardcfg[18] & 0x04) -#define IBMMPEGCD20 (saa->boardcfg[18] & 0x20) -#define HaveCS3310 (saa->boardcfg[18] & 0x01) -#define CS3310MaxLvl ((saa->boardcfg[30] << 8) | saa->boardcfg[31]) -#define HaveCS4341 (saa->boardcfg[40] == 2) -#define SDIType (saa->boardcfg[27]) -#define CurrentMode (saa->boardcfg[2]) - -#define debNormal (NewCard ? nDebNormal : oDebNormal) -#define debNoInc (NewCard ? nDebNoInc : oDebNoInc) -#define debVideo (NewCard ? nDebVideo : oDebVideo) -#define debAudio (NewCard ? nDebAudio : oDebAudio) -#define debDMA (NewCard ? nDebDMA : oDebDMA) - -#ifdef USE_RESCUE_EEPROM_SDM275 -static unsigned char rescue_eeprom[64] = { - 0x00, 0x01, 0x04, 0x13, 0x26, 0x0f, 0x10, 0x00, 0x00, 0x00, 0x43, 0x63, - 0x22, 0x01, 0x29, 0x15, 0x73, 0x00, 0x1f, 'd', 'e', 'c', 'x', 'l', - 'd', 'v', 'a', 0x02, 0x00, 0x01, 0x00, 0xcc, 0xa4, 0x63, 0x09, 0xe2, - 0x10, 0x00, 0x0a, 0x00, 0x02, 0x02, 'd', 'e', 'c', 'x', 'l', 'a', - 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, -}; -#endif - -/* ----------------------------------------------------------------------- */ -/* Hardware I2C functions */ -static void I2CWipe(struct saa7146 *saa) -{ - int i; - /* set i2c to ~=100kHz, abort transfer, clear busy */ - saawrite(0x600 | SAA7146_I2C_ABORT, SAA7146_I2C_STATUS); - saawrite((SAA7146_MC2_UPLD_I2C << 16) | - SAA7146_MC2_UPLD_I2C, SAA7146_MC2); - /* wait for i2c registers to be programmed */ - for (i = 0; i < 1000 && - !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) - schedule(); - saawrite(0x600, SAA7146_I2C_STATUS); - saawrite((SAA7146_MC2_UPLD_I2C << 16) | - SAA7146_MC2_UPLD_I2C, SAA7146_MC2); - /* wait for i2c registers to be programmed */ - for (i = 0; i < 1000 && - !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) - schedule(); - saawrite(0x600, SAA7146_I2C_STATUS); - saawrite((SAA7146_MC2_UPLD_I2C << 16) | - SAA7146_MC2_UPLD_I2C, SAA7146_MC2); - /* wait for i2c registers to be programmed */ - for (i = 0; i < 1000 && - !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) - schedule(); -} - -/* read I2C */ -static int I2CRead(struct saa7146 *saa, unsigned char addr, - unsigned char subaddr, int dosub) -{ - int i; - - if (saaread(SAA7146_I2C_STATUS) & 0x3c) - I2CWipe(saa); - for (i = 0; - i < 1000 && (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); - i++) - schedule(); - if (i == 1000) - I2CWipe(saa); - if (dosub) - saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 8) | - ((subaddr & 0xff) << 16) | 0xed, SAA7146_I2C_TRANSFER); - else - saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 16) | - 0xf1, SAA7146_I2C_TRANSFER); - saawrite((SAA7146_MC2_UPLD_I2C << 16) | - SAA7146_MC2_UPLD_I2C, SAA7146_MC2); - /* wait for i2c registers to be programmed */ - for (i = 0; i < 1000 && - !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) - schedule(); - /* wait for valid data */ - for (i = 0; i < 1000 && - (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++) - schedule(); - if (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_ERR) - return -1; - if (i == 1000) - printk("i2c setup read timeout\n"); - saawrite(0x41, SAA7146_I2C_TRANSFER); - saawrite((SAA7146_MC2_UPLD_I2C << 16) | - SAA7146_MC2_UPLD_I2C, SAA7146_MC2); - /* wait for i2c registers to be programmed */ - for (i = 0; i < 1000 && - !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) - schedule(); - /* wait for valid data */ - for (i = 0; i < 1000 && - (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_BUSY); i++) - schedule(); - if (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_ERR) - return -1; - if (i == 1000) - printk("i2c read timeout\n"); - return ((saaread(SAA7146_I2C_TRANSFER) >> 24) & 0xff); -} - -/* set both to write both bytes, reset it to write only b1 */ - -static int I2CWrite(struct saa7146 *saa, unsigned char addr, unsigned char b1, - unsigned char b2, int both) -{ - int i; - u32 data; - - if (saaread(SAA7146_I2C_STATUS) & 0x3c) - I2CWipe(saa); - for (i = 0; i < 1000 && - (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++) - schedule(); - if (i == 1000) - I2CWipe(saa); - data = ((addr & 0xfe) << 24) | ((b1 & 0xff) << 16); - if (both) - data |= ((b2 & 0xff) << 8) | 0xe5; - else - data |= 0xd1; - saawrite(data, SAA7146_I2C_TRANSFER); - saawrite((SAA7146_MC2_UPLD_I2C << 16) | SAA7146_MC2_UPLD_I2C, - SAA7146_MC2); - return 0; -} - -static void attach_inform(struct saa7146 *saa, int id) -{ - int i; - - DEBUG(printk(KERN_DEBUG "stradis%d: i2c: device found=%02x\n", saa->nr, - id)); - if (id == 0xa0) { /* we have rev2 or later board, fill in info */ - for (i = 0; i < 64; i++) - saa->boardcfg[i] = I2CRead(saa, 0xa0, i, 1); -#ifdef USE_RESCUE_EEPROM_SDM275 - if (saa->boardcfg[0] != 0) { - printk("stradis%d: WARNING: EEPROM STORED VALUES HAVE " - "BEEN IGNORED\n", saa->nr); - for (i = 0; i < 64; i++) - saa->boardcfg[i] = rescue_eeprom[i]; - } -#endif - printk("stradis%d: config =", saa->nr); - for (i = 0; i < 51; i++) { - printk(" %02x", saa->boardcfg[i]); - } - printk("\n"); - } -} - -static void I2CBusScan(struct saa7146 *saa) -{ - int i; - for (i = 0; i < 0xff; i += 2) - if ((I2CRead(saa, i, 0, 0)) >= 0) - attach_inform(saa, i); -} - -static int debiwait_maxwait; - -static int wait_for_debi_done(struct saa7146 *saa) -{ - int i; - - /* wait for registers to be programmed */ - for (i = 0; i < 100000 && - !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_DEBI); i++) - saaread(SAA7146_MC2); - /* wait for transfer to complete */ - for (i = 0; i < 500000 && - (saaread(SAA7146_PSR) & SAA7146_PSR_DEBI_S); i++) - saaread(SAA7146_MC2); - - if (i > debiwait_maxwait) - printk("wait-for-debi-done maxwait: %d\n", - debiwait_maxwait = i); - - if (i == 500000) - return -1; - - return 0; -} - -static int debiwrite(struct saa7146 *saa, u32 config, int addr, - u32 val, int count) -{ - u32 cmd; - if (count <= 0 || count > 32764) - return -1; - if (wait_for_debi_done(saa) < 0) - return -1; - saawrite(config, SAA7146_DEBI_CONFIG); - if (count <= 4) /* immediate transfer */ - saawrite(val, SAA7146_DEBI_AD); - else /* block transfer */ - saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD); - saawrite((cmd = (count << 17) | (addr & 0xffff)), SAA7146_DEBI_COMMAND); - saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI, - SAA7146_MC2); - return 0; -} - -static u32 debiread(struct saa7146 *saa, u32 config, int addr, int count) -{ - u32 result = 0; - - if (count > 32764 || count <= 0) - return 0; - if (wait_for_debi_done(saa) < 0) - return 0; - saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD); - saawrite((count << 17) | 0x10000 | (addr & 0xffff), - SAA7146_DEBI_COMMAND); - saawrite(config, SAA7146_DEBI_CONFIG); - saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI, - SAA7146_MC2); - if (count > 4) /* not an immediate transfer */ - return count; - wait_for_debi_done(saa); - result = saaread(SAA7146_DEBI_AD); - if (count == 1) - result &= 0xff; - if (count == 2) - result &= 0xffff; - if (count == 3) - result &= 0xffffff; - return result; -} - -static void do_irq_send_data(struct saa7146 *saa) -{ - int split, audbytes, vidbytes; - - saawrite(SAA7146_PSR_PIN1, SAA7146_IER); - /* if special feature mode in effect, disable audio sending */ - if (saa->playmode != VID_PLAY_NORMAL) - saa->audtail = saa->audhead = 0; - if (saa->audhead <= saa->audtail) - audbytes = saa->audtail - saa->audhead; - else - audbytes = 65536 - (saa->audhead - saa->audtail); - if (saa->vidhead <= saa->vidtail) - vidbytes = saa->vidtail - saa->vidhead; - else - vidbytes = 524288 - (saa->vidhead - saa->vidtail); - if (audbytes == 0 && vidbytes == 0 && saa->osdtail == saa->osdhead) { - saawrite(0, SAA7146_IER); - return; - } - /* if at least 1 block audio waiting and audio fifo isn't full */ - if (audbytes >= 2048 && (debiread(saa, debNormal, IBM_MP2_AUD_FIFO, 2) - & 0xff) < 60) { - if (saa->audhead > saa->audtail) - split = 65536 - saa->audhead; - else - split = 0; - audbytes = 2048; - if (split > 0 && split < 2048) { - memcpy(saa->dmadebi, saa->audbuf + saa->audhead, split); - saa->audhead = 0; - audbytes -= split; - } else - split = 0; - memcpy(saa->dmadebi + split, saa->audbuf + saa->audhead, - audbytes); - saa->audhead += audbytes; - saa->audhead &= 0xffff; - debiwrite(saa, debAudio, (NewCard ? IBM_MP2_AUD_FIFO : - IBM_MP2_AUD_FIFOW), 0, 2048); - wake_up_interruptible(&saa->audq); - /* if at least 1 block video waiting and video fifo isn't full */ - } else if (vidbytes >= 30720 && (debiread(saa, debNormal, - IBM_MP2_FIFO, 2)) < 16384) { - if (saa->vidhead > saa->vidtail) - split = 524288 - saa->vidhead; - else - split = 0; - vidbytes = 30720; - if (split > 0 && split < 30720) { - memcpy(saa->dmadebi, saa->vidbuf + saa->vidhead, split); - saa->vidhead = 0; - vidbytes -= split; - } else - split = 0; - memcpy(saa->dmadebi + split, saa->vidbuf + saa->vidhead, - vidbytes); - saa->vidhead += vidbytes; - saa->vidhead &= 0x7ffff; - debiwrite(saa, debVideo, (NewCard ? IBM_MP2_FIFO : - IBM_MP2_FIFOW), 0, 30720); - wake_up_interruptible(&saa->vidq); - } - saawrite(SAA7146_PSR_DEBI_S | SAA7146_PSR_PIN1, SAA7146_IER); -} - -static void send_osd_data(struct saa7146 *saa) -{ - int size = saa->osdtail - saa->osdhead; - if (size > 30720) - size = 30720; - /* ensure some multiple of 8 bytes is transferred */ - size = 8 * ((size + 8) >> 3); - if (size) { - debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR, - (saa->osdhead >> 3), 2); - memcpy(saa->dmadebi, &saa->osdbuf[saa->osdhead], size); - saa->osdhead += size; - /* block transfer of next 8 bytes to ~32k bytes */ - debiwrite(saa, debNormal, IBM_MP2_OSD_DATA, 0, size); - } - if (saa->osdhead >= saa->osdtail) { - saa->osdhead = saa->osdtail = 0; - debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2); - } -} - -static irqreturn_t saa7146_irq(int irq, void *dev_id) -{ - struct saa7146 *saa = dev_id; - u32 stat, astat; - int count; - int handled = 0; - - count = 0; - while (1) { - /* get/clear interrupt status bits */ - stat = saaread(SAA7146_ISR); - astat = stat & saaread(SAA7146_IER); - if (!astat) - break; - handled = 1; - saawrite(astat, SAA7146_ISR); - if (astat & SAA7146_PSR_DEBI_S) { - do_irq_send_data(saa); - } - if (astat & SAA7146_PSR_PIN1) { - int istat; - /* the following read will trigger DEBI_S */ - istat = debiread(saa, debNormal, IBM_MP2_HOST_INT, 2); - if (istat & 1) { - saawrite(0, SAA7146_IER); - send_osd_data(saa); - saawrite(SAA7146_PSR_DEBI_S | - SAA7146_PSR_PIN1, SAA7146_IER); - } - if (istat & 0x20) { /* Video Start */ - saa->vidinfo.frame_count++; - } - if (istat & 0x400) { /* Picture Start */ - /* update temporal reference */ - } - if (istat & 0x200) { /* Picture Resolution Change */ - /* read new resolution */ - } - if (istat & 0x100) { /* New User Data found */ - /* read new user data */ - } - if (istat & 0x1000) { /* new GOP/SMPTE */ - /* read new SMPTE */ - } - if (istat & 0x8000) { /* Sequence Start Code */ - /* reset frame counter, load sizes */ - saa->vidinfo.frame_count = 0; - saa->vidinfo.h_size = 704; - saa->vidinfo.v_size = 480; -#if 0 - if (saa->endmarkhead != saa->endmarktail) { - saa->audhead = - saa->endmark[saa->endmarkhead]; - saa->endmarkhead++; - if (saa->endmarkhead >= MAX_MARKS) - saa->endmarkhead = 0; - } -#endif - } - if (istat & 0x4000) { /* Sequence Error Code */ - if (saa->endmarkhead != saa->endmarktail) { - saa->audhead = - saa->endmark[saa->endmarkhead]; - saa->endmarkhead++; - if (saa->endmarkhead >= MAX_MARKS) - saa->endmarkhead = 0; - } - } - } -#ifdef IDEBUG - if (astat & SAA7146_PSR_PPEF) { - IDEBUG(printk("stradis%d irq: PPEF\n", saa->nr)); - } - if (astat & SAA7146_PSR_PABO) { - IDEBUG(printk("stradis%d irq: PABO\n", saa->nr)); - } - if (astat & SAA7146_PSR_PPED) { - IDEBUG(printk("stradis%d irq: PPED\n", saa->nr)); - } - if (astat & SAA7146_PSR_RPS_I1) { - IDEBUG(printk("stradis%d irq: RPS_I1\n", saa->nr)); - } - if (astat & SAA7146_PSR_RPS_I0) { - IDEBUG(printk("stradis%d irq: RPS_I0\n", saa->nr)); - } - if (astat & SAA7146_PSR_RPS_LATE1) { - IDEBUG(printk("stradis%d irq: RPS_LATE1\n", saa->nr)); - } - if (astat & SAA7146_PSR_RPS_LATE0) { - IDEBUG(printk("stradis%d irq: RPS_LATE0\n", saa->nr)); - } - if (astat & SAA7146_PSR_RPS_E1) { - IDEBUG(printk("stradis%d irq: RPS_E1\n", saa->nr)); - } - if (astat & SAA7146_PSR_RPS_E0) { - IDEBUG(printk("stradis%d irq: RPS_E0\n", saa->nr)); - } - if (astat & SAA7146_PSR_RPS_TO1) { - IDEBUG(printk("stradis%d irq: RPS_TO1\n", saa->nr)); - } - if (astat & SAA7146_PSR_RPS_TO0) { - IDEBUG(printk("stradis%d irq: RPS_TO0\n", saa->nr)); - } - if (astat & SAA7146_PSR_UPLD) { - IDEBUG(printk("stradis%d irq: UPLD\n", saa->nr)); - } - if (astat & SAA7146_PSR_DEBI_E) { - IDEBUG(printk("stradis%d irq: DEBI_E\n", saa->nr)); - } - if (astat & SAA7146_PSR_I2C_S) { - IDEBUG(printk("stradis%d irq: I2C_S\n", saa->nr)); - } - if (astat & SAA7146_PSR_I2C_E) { - IDEBUG(printk("stradis%d irq: I2C_E\n", saa->nr)); - } - if (astat & SAA7146_PSR_A2_IN) { - IDEBUG(printk("stradis%d irq: A2_IN\n", saa->nr)); - } - if (astat & SAA7146_PSR_A2_OUT) { - IDEBUG(printk("stradis%d irq: A2_OUT\n", saa->nr)); - } - if (astat & SAA7146_PSR_A1_IN) { - IDEBUG(printk("stradis%d irq: A1_IN\n", saa->nr)); - } - if (astat & SAA7146_PSR_A1_OUT) { - IDEBUG(printk("stradis%d irq: A1_OUT\n", saa->nr)); - } - if (astat & SAA7146_PSR_AFOU) { - IDEBUG(printk("stradis%d irq: AFOU\n", saa->nr)); - } - if (astat & SAA7146_PSR_V_PE) { - IDEBUG(printk("stradis%d irq: V_PE\n", saa->nr)); - } - if (astat & SAA7146_PSR_VFOU) { - IDEBUG(printk("stradis%d irq: VFOU\n", saa->nr)); - } - if (astat & SAA7146_PSR_FIDA) { - IDEBUG(printk("stradis%d irq: FIDA\n", saa->nr)); - } - if (astat & SAA7146_PSR_FIDB) { - IDEBUG(printk("stradis%d irq: FIDB\n", saa->nr)); - } - if (astat & SAA7146_PSR_PIN3) { - IDEBUG(printk("stradis%d irq: PIN3\n", saa->nr)); - } - if (astat & SAA7146_PSR_PIN2) { - IDEBUG(printk("stradis%d irq: PIN2\n", saa->nr)); - } - if (astat & SAA7146_PSR_PIN0) { - IDEBUG(printk("stradis%d irq: PIN0\n", saa->nr)); - } - if (astat & SAA7146_PSR_ECS) { - IDEBUG(printk("stradis%d irq: ECS\n", saa->nr)); - } - if (astat & SAA7146_PSR_EC3S) { - IDEBUG(printk("stradis%d irq: EC3S\n", saa->nr)); - } - if (astat & SAA7146_PSR_EC0S) { - IDEBUG(printk("stradis%d irq: EC0S\n", saa->nr)); - } -#endif - count++; - if (count > 15) - printk(KERN_WARNING "stradis%d: irq loop %d\n", - saa->nr, count); - if (count > 20) { - saawrite(0, SAA7146_IER); - printk(KERN_ERR - "stradis%d: IRQ loop cleared\n", saa->nr); - } - } - return IRQ_RETVAL(handled); -} - -static int ibm_send_command(struct saa7146 *saa, - int command, int data, int chain) -{ - int i; - - if (chain) - debiwrite(saa, debNormal, IBM_MP2_COMMAND, (command << 1)| 1,2); - else - debiwrite(saa, debNormal, IBM_MP2_COMMAND, command << 1, 2); - debiwrite(saa, debNormal, IBM_MP2_CMD_DATA, data, 2); - debiwrite(saa, debNormal, IBM_MP2_CMD_STAT, 1, 2); - for (i = 0; i < 100 && - (debiread(saa, debNormal, IBM_MP2_CMD_STAT, 2) & 1); i++) - schedule(); - if (i == 100) - return -1; - return 0; -} - -static void cs4341_setlevel(struct saa7146 *saa, int left, int right) -{ - I2CWrite(saa, 0x22, 0x03, left > 94 ? 94 : left, 2); - I2CWrite(saa, 0x22, 0x04, right > 94 ? 94 : right, 2); -} - -static void initialize_cs4341(struct saa7146 *saa) -{ - int i; - for (i = 0; i < 200; i++) { - /* auto mute off, power on, no de-emphasis */ - /* I2S data up to 24-bit 64xFs internal SCLK */ - I2CWrite(saa, 0x22, 0x01, 0x11, 2); - /* ATAPI mixer settings */ - I2CWrite(saa, 0x22, 0x02, 0x49, 2); - /* attenuation left 3db */ - I2CWrite(saa, 0x22, 0x03, 0x00, 2); - /* attenuation right 3db */ - I2CWrite(saa, 0x22, 0x04, 0x00, 2); - I2CWrite(saa, 0x22, 0x01, 0x10, 2); - if (I2CRead(saa, 0x22, 0x02, 1) == 0x49) - break; - schedule(); - } - printk("stradis%d: CS4341 initialized (%d)\n", saa->nr, i); - return; -} - -static void initialize_cs8420(struct saa7146 *saa, int pro) -{ - int i; - u8 *sequence; - if (pro) - sequence = mode8420pro; - else - sequence = mode8420con; - for (i = 0; i < INIT8420LEN; i++) - I2CWrite(saa, 0x20, init8420[i * 2], init8420[i * 2 + 1], 2); - for (i = 0; i < MODE8420LEN; i++) - I2CWrite(saa, 0x20, sequence[i * 2], sequence[i * 2 + 1], 2); - printk("stradis%d: CS8420 initialized\n", saa->nr); -} - -static void initialize_saa7121(struct saa7146 *saa, int dopal) -{ - int i, mod; - u8 *sequence; - if (dopal) - sequence = init7121pal; - else - sequence = init7121ntsc; - mod = saaread(SAA7146_PSR) & 0x08; - /* initialize PAL/NTSC video encoder */ - for (i = 0; i < INIT7121LEN; i++) { - if (NewCard) { /* handle new card encoder differences */ - if (sequence[i * 2] == 0x3a) - I2CWrite(saa, 0x88, 0x3a, 0x13, 2); - else if (sequence[i * 2] == 0x6b) - I2CWrite(saa, 0x88, 0x6b, 0x20, 2); - else if (sequence[i * 2] == 0x6c) - I2CWrite(saa, 0x88, 0x6c, - dopal ? 0x09 : 0xf5, 2); - else if (sequence[i * 2] == 0x6d) - I2CWrite(saa, 0x88, 0x6d, - dopal ? 0x20 : 0x00, 2); - else if (sequence[i * 2] == 0x7a) - I2CWrite(saa, 0x88, 0x7a, - dopal ? (PALFirstActive - 1) : - (NTSCFirstActive - 4), 2); - else if (sequence[i * 2] == 0x7b) - I2CWrite(saa, 0x88, 0x7b, - dopal ? PALLastActive : - NTSCLastActive, 2); - else - I2CWrite(saa, 0x88, sequence[i * 2], - sequence[i * 2 + 1], 2); - } else { - if (sequence[i * 2] == 0x6b && mod) - I2CWrite(saa, 0x88, 0x6b, - (sequence[i * 2 + 1] ^ 0x09), 2); - else if (sequence[i * 2] == 0x7a) - I2CWrite(saa, 0x88, 0x7a, - dopal ? (PALFirstActive - 1) : - (NTSCFirstActive - 4), 2); - else if (sequence[i * 2] == 0x7b) - I2CWrite(saa, 0x88, 0x7b, - dopal ? PALLastActive : - NTSCLastActive, 2); - else - I2CWrite(saa, 0x88, sequence[i * 2], - sequence[i * 2 + 1], 2); - } - } -} - -static void set_genlock_offset(struct saa7146 *saa, int noffset) -{ - int nCode; - int PixelsPerLine = 858; - if (CurrentMode == VIDEO_MODE_PAL) - PixelsPerLine = 864; - if (noffset > 500) - noffset = 500; - else if (noffset < -500) - noffset = -500; - nCode = noffset + 0x100; - if (nCode == 1) - nCode = 0x401; - else if (nCode < 1) - nCode = 0x400 + PixelsPerLine + nCode; - debiwrite(saa, debNormal, XILINX_GLDELAY, nCode, 2); -} - -static void set_out_format(struct saa7146 *saa, int mode) -{ - initialize_saa7121(saa, (mode == VIDEO_MODE_NTSC ? 0 : 1)); - saa->boardcfg[2] = mode; - /* do not adjust analog video parameters here, use saa7121 init */ - /* you will affect the SDI output on the new card */ - if (mode == VIDEO_MODE_PAL) { /* PAL */ - debiwrite(saa, debNormal, XILINX_CTL0, 0x0808, 2); - mdelay(50); - saawrite(0x012002c0, SAA7146_NUM_LINE_BYTE1); - if (NewCard) { - debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, 0xe100, 2); - mdelay(50); - } - debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, - NewCard ? 0xe500 : 0x6500, 2); - debiwrite(saa, debNormal, IBM_MP2_DISP_DLY, - (1 << 8) | - (NewCard ? PALFirstActive : PALFirstActive - 6), 2); - } else { /* NTSC */ - debiwrite(saa, debNormal, XILINX_CTL0, 0x0800, 2); - mdelay(50); - saawrite(0x00f002c0, SAA7146_NUM_LINE_BYTE1); - debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, - NewCard ? 0xe100 : 0x6100, 2); - debiwrite(saa, debNormal, IBM_MP2_DISP_DLY, - (1 << 8) | - (NewCard ? NTSCFirstActive : NTSCFirstActive - 6), 2); - } -} - -/* Intialize bitmangler to map from a byte value to the mangled word that - * must be output to program the Xilinx part through the DEBI port. - * Xilinx Data Bit->DEBI Bit: 0->15 1->7 2->6 3->12 4->11 5->2 6->1 7->0 - * transfer FPGA code, init IBM chip, transfer IBM microcode - * rev2 card mangles: 0->7 1->6 2->5 3->4 4->3 5->2 6->1 7->0 - */ -static u16 bitmangler[256]; - -static int initialize_fpga(struct video_code *bitdata) -{ - int i, num, startindex, failure = 0, loadtwo, loadfile = 0; - u16 *dmabuf; - u8 *newdma; - struct saa7146 *saa; - - /* verify fpga code */ - for (startindex = 0; startindex < bitdata->datasize; startindex++) - if (bitdata->data[startindex] == 255) - break; - if (startindex == bitdata->datasize) { - printk(KERN_INFO "stradis: bad fpga code\n"); - return -1; - } - /* initialize all detected cards */ - for (num = 0; num < saa_num; num++) { - saa = &saa7146s[num]; - if (saa->boardcfg[0] > 20) - continue; /* card was programmed */ - loadtwo = (saa->boardcfg[18] & 0x10); - if (!NewCard) /* we have an old board */ - for (i = 0; i < 256; i++) - bitmangler[i] = ((i & 0x01) << 15) | - ((i & 0x02) << 6) | ((i & 0x04) << 4) | - ((i & 0x08) << 9) | ((i & 0x10) << 7) | - ((i & 0x20) >> 3) | ((i & 0x40) >> 5) | - ((i & 0x80) >> 7); - else /* else we have a new board */ - for (i = 0; i < 256; i++) - bitmangler[i] = ((i & 0x01) << 7) | - ((i & 0x02) << 5) | ((i & 0x04) << 3) | - ((i & 0x08) << 1) | ((i & 0x10) >> 1) | - ((i & 0x20) >> 3) | ((i & 0x40) >> 5) | - ((i & 0x80) >> 7); - - dmabuf = (u16 *) saa->dmadebi; - newdma = (u8 *) saa->dmadebi; - if (NewCard) { /* SDM2xxx */ - if (!strncmp(bitdata->loadwhat, "decoder2", 8)) - continue; /* fpga not for this card */ - if (!strncmp(&saa->boardcfg[42], bitdata->loadwhat, 8)) - loadfile = 1; - else if (loadtwo && !strncmp(&saa->boardcfg[19], - bitdata->loadwhat, 8)) - loadfile = 2; - else if (!saa->boardcfg[42] && !strncmp("decxl", - bitdata->loadwhat, 8)) - loadfile = 1; /* special */ - else - continue; /* fpga not for this card */ - if (loadfile != 1 && loadfile != 2) - continue; /* skip to next card */ - if (saa->boardcfg[0] && loadfile == 1) - continue; /* skip to next card */ - if (saa->boardcfg[0] != 1 && loadfile == 2) - continue; /* skip to next card */ - saa->boardcfg[0]++; /* mark fpga handled */ - printk("stradis%d: loading %s\n", saa->nr, - bitdata->loadwhat); - if (loadtwo && loadfile == 2) - goto send_fpga_stuff; - /* turn on the Audio interface to set PROG low */ - saawrite(0x00400040, SAA7146_GPIO_CTRL); - saaread(SAA7146_PSR); /* ensure posted write */ - /* wait for everyone to reset */ - mdelay(10); - saawrite(0x00400000, SAA7146_GPIO_CTRL); - } else { /* original card */ - if (strncmp(bitdata->loadwhat, "decoder2", 8)) - continue; /* fpga not for this card */ - /* Pull the Xilinx PROG signal WS3 low */ - saawrite(0x02000200, SAA7146_MC1); - /* Turn on the Audio interface so can set PROG low */ - saawrite(0x000000c0, SAA7146_ACON1); - /* Pull the Xilinx INIT signal (GPIO2) low */ - saawrite(0x00400000, SAA7146_GPIO_CTRL); - /* Make sure everybody resets */ - saaread(SAA7146_PSR); /* ensure posted write */ - mdelay(10); - /* Release the Xilinx PROG signal */ - saawrite(0x00000000, SAA7146_ACON1); - /* Turn off the Audio interface */ - saawrite(0x02000000, SAA7146_MC1); - } - /* Release Xilinx INIT signal (WS2) */ - saawrite(0x00000000, SAA7146_GPIO_CTRL); - /* Wait for the INIT to go High */ - for (i = 0; - i < 10000 && !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2); - i++) - schedule(); - if (i == 1000) { - printk(KERN_INFO "stradis%d: no fpga INIT\n", saa->nr); - return -1; - } -send_fpga_stuff: - if (NewCard) { - for (i = startindex; i < bitdata->datasize; i++) - newdma[i - startindex] = - bitmangler[bitdata->data[i]]; - debiwrite(saa, 0x01420000, 0, 0, - ((bitdata->datasize - startindex) + 5)); - if (loadtwo && loadfile == 1) { - printk("stradis%d: awaiting 2nd FPGA bitfile\n", - saa->nr); - continue; /* skip to next card */ - } - } else { - for (i = startindex; i < bitdata->datasize; i++) - dmabuf[i - startindex] = - bitmangler[bitdata->data[i]]; - debiwrite(saa, 0x014a0000, 0, 0, - ((bitdata->datasize - startindex) + 5) * 2); - } - for (i = 0; - i < 1000 && !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2); - i++) - schedule(); - if (i == 1000) { - printk(KERN_INFO "stradis%d: FPGA load failed\n", - saa->nr); - failure++; - continue; - } - if (!NewCard) { - /* Pull the Xilinx INIT signal (GPIO2) low */ - saawrite(0x00400000, SAA7146_GPIO_CTRL); - saaread(SAA7146_PSR); /* ensure posted write */ - mdelay(2); - saawrite(0x00000000, SAA7146_GPIO_CTRL); - mdelay(2); - } - printk(KERN_INFO "stradis%d: FPGA Loaded\n", saa->nr); - saa->boardcfg[0] = 26; /* mark fpga programmed */ - /* set VXCO to its lowest frequency */ - debiwrite(saa, debNormal, XILINX_PWM, 0, 2); - if (NewCard) { - /* mute CS3310 */ - if (HaveCS3310) - debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, - 0, 2); - /* set VXCO to PWM mode, release reset, blank on */ - debiwrite(saa, debNormal, XILINX_CTL0, 0xffc4, 2); - mdelay(10); - /* unmute CS3310 */ - if (HaveCS3310) - debiwrite(saa, debNormal, XILINX_CTL0, - 0x2020, 2); - } - /* set source Black */ - debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2); - saa->boardcfg[4] = 22; /* set NTSC First Active Line */ - saa->boardcfg[5] = 23; /* set PAL First Active Line */ - saa->boardcfg[54] = 2; /* set NTSC Last Active Line - 256 */ - saa->boardcfg[55] = 54; /* set PAL Last Active Line - 256 */ - set_out_format(saa, VIDEO_MODE_NTSC); - mdelay(50); - /* begin IBM chip init */ - debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2); - saaread(SAA7146_PSR); /* wait for reset */ - mdelay(5); - debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2); - debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2); - debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0x10, 2); - debiwrite(saa, debNormal, IBM_MP2_CMD_ADDR, 0, 2); - debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2); - if (NewCard) { - mdelay(5); - /* set i2s rate converter to 48KHz */ - debiwrite(saa, debNormal, 0x80c0, 6, 2); - /* we must init CS8420 first since rev b pulls i2s */ - /* master clock low and CS4341 needs i2s master to */ - /* run the i2c port. */ - if (HaveCS8420) - /* 0=consumer, 1=pro */ - initialize_cs8420(saa, 0); - - mdelay(5); - if (HaveCS4341) - initialize_cs4341(saa); - } - debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2); - debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2); - debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2); - debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2); - if (NewCard) - set_genlock_offset(saa, 0); - debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2); -#if 0 - /* enable genlock */ - debiwrite(saa, debNormal, XILINX_CTL0, 0x8000, 2); -#else - /* disable genlock */ - debiwrite(saa, debNormal, XILINX_CTL0, 0x8080, 2); -#endif - } - - return failure; -} - -static int do_ibm_reset(struct saa7146 *saa) -{ - /* failure if decoder not previously programmed */ - if (saa->boardcfg[0] < 37) - return -EIO; - /* mute CS3310 */ - if (HaveCS3310) - debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, 0, 2); - /* disable interrupts */ - saawrite(0, SAA7146_IER); - saa->audhead = saa->audtail = 0; - saa->vidhead = saa->vidtail = 0; - /* tristate debi bus, disable debi transfers */ - saawrite(0x00880000, SAA7146_MC1); - /* ensure posted write */ - saaread(SAA7146_MC1); - mdelay(50); - /* re-enable debi transfers */ - saawrite(0x00880088, SAA7146_MC1); - /* set source Black */ - debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2); - /* begin IBM chip init */ - set_out_format(saa, CurrentMode); - debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2); - saaread(SAA7146_PSR); /* wait for reset */ - mdelay(5); - debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2); - debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2); - debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2); - debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2); - if (NewCard) { - mdelay(5); - /* set i2s rate converter to 48KHz */ - debiwrite(saa, debNormal, 0x80c0, 6, 2); - /* we must init CS8420 first since rev b pulls i2s */ - /* master clock low and CS4341 needs i2s master to */ - /* run the i2c port. */ - if (HaveCS8420) - /* 0=consumer, 1=pro */ - initialize_cs8420(saa, 1); - - mdelay(5); - if (HaveCS4341) - initialize_cs4341(saa); - } - debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2); - debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2); - debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2); - debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2); - if (NewCard) - set_genlock_offset(saa, 0); - debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2); - debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2); - debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2); - if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER, - (ChipControl == 0x43 ? 0xe800 : 0xe000), 1)) { - printk(KERN_ERR "stradis%d: IBM config failed\n", saa->nr); - } - if (HaveCS3310) { - int i = CS3310MaxLvl; - debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, ((i << 8)| i),2); - } - /* start video decoder */ - debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2); - /* 256k vid, 3520 bytes aud */ - debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037, 2); - debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2); - ibm_send_command(saa, IBM_MP2_PLAY, 0, 0); - /* enable buffer threshold irq */ - debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2); - /* clear pending interrupts */ - debiread(saa, debNormal, IBM_MP2_HOST_INT, 2); - debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2); - - return 0; -} - -/* load the decoder microcode */ -static int initialize_ibmmpeg2(struct video_code *microcode) -{ - int i, num; - struct saa7146 *saa; - - for (num = 0; num < saa_num; num++) { - saa = &saa7146s[num]; - /* check that FPGA is loaded */ - debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0xa55a, 2); - i = debiread(saa, debNormal, IBM_MP2_OSD_SIZE, 2); - if (i != 0xa55a) { - printk(KERN_INFO "stradis%d: %04x != 0xa55a\n", - saa->nr, i); -#if 0 - return -1; -#endif - } - if (!strncmp(microcode->loadwhat, "decoder.vid", 11)) { - if (saa->boardcfg[0] > 27) - continue; /* skip to next card */ - /* load video control store */ - saa->boardcfg[1] = 0x13; /* no-sync default */ - debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2); - debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2); - for (i = 0; i < microcode->datasize / 2; i++) - debiwrite(saa, debNormal, IBM_MP2_PROC_IDATA, - (microcode->data[i * 2] << 8) | - microcode->data[i * 2 + 1], 2); - debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2); - debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2); - debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, - ChipControl, 2); - saa->boardcfg[0] = 28; - } - if (!strncmp(microcode->loadwhat, "decoder.aud", 11)) { - if (saa->boardcfg[0] > 35) - continue; /* skip to next card */ - /* load audio control store */ - debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2); - debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2); - for (i = 0; i < microcode->datasize; i++) - debiwrite(saa, debNormal, IBM_MP2_AUD_IDATA, - microcode->data[i], 1); - debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2); - debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2); - debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2); - debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2); - if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER, - 0xe000, 1)) { - printk(KERN_ERR "stradis%d: IBM config " - "failed\n", saa->nr); - return -1; - } - /* set PWM to center value */ - if (NewCard) { - debiwrite(saa, debNormal, XILINX_PWM, - saa->boardcfg[14] + - (saa->boardcfg[13] << 8), 2); - } else - debiwrite(saa, debNormal, XILINX_PWM, 0x46, 2); - - if (HaveCS3310) { - i = CS3310MaxLvl; - debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, - (i << 8) | i, 2); - } - printk(KERN_INFO "stradis%d: IBM MPEGCD%d Inited\n", - saa->nr, 18 + (debiread(saa, debNormal, - IBM_MP2_CHIP_CONTROL, 2) >> 12)); - /* start video decoder */ - debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, - ChipControl, 2); - debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037, - 2); /* 256k vid, 3520 bytes aud */ - debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2); - ibm_send_command(saa, IBM_MP2_PLAY, 0, 0); - /* enable buffer threshold irq */ - debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2); - debiread(saa, debNormal, IBM_MP2_HOST_INT, 2); - /* enable gpio irq */ - saawrite(0x00002000, SAA7146_GPIO_CTRL); - /* enable decoder output to HPS */ - debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2); - saa->boardcfg[0] = 37; - } - } - - return 0; -} - -static u32 palette2fmt[] = { /* some of these YUV translations are wrong */ - 0xffffffff, 0x86000000, 0x87000000, 0x80000000, 0x8100000, 0x82000000, - 0x83000000, 0x00000000, 0x03000000, 0x03000000, 0x0a00000, 0x03000000, - 0x06000000, 0x00000000, 0x03000000, 0x0a000000, 0x0300000 -}; -static int bpp2fmt[4] = { - VIDEO_PALETTE_HI240, VIDEO_PALETTE_RGB565, VIDEO_PALETTE_RGB24, - VIDEO_PALETTE_RGB32 -}; - -/* I wish I could find a formula to calculate these... */ -static u32 h_prescale[64] = { - 0x10000000, 0x18040202, 0x18080000, 0x380c0606, 0x38100204, 0x38140808, - 0x38180000, 0x381c0000, 0x3820161c, 0x38242a3b, 0x38281230, 0x382c4460, - 0x38301040, 0x38340080, 0x38380000, 0x383c0000, 0x3840fefe, 0x3844ee9f, - 0x3848ee9f, 0x384cee9f, 0x3850ee9f, 0x38542a3b, 0x38581230, 0x385c0000, - 0x38600000, 0x38640000, 0x38680000, 0x386c0000, 0x38700000, 0x38740000, - 0x38780000, 0x387c0000, 0x30800000, 0x38840000, 0x38880000, 0x388c0000, - 0x38900000, 0x38940000, 0x38980000, 0x389c0000, 0x38a00000, 0x38a40000, - 0x38a80000, 0x38ac0000, 0x38b00000, 0x38b40000, 0x38b80000, 0x38bc0000, - 0x38c00000, 0x38c40000, 0x38c80000, 0x38cc0000, 0x38d00000, 0x38d40000, - 0x38d80000, 0x38dc0000, 0x38e00000, 0x38e40000, 0x38e80000, 0x38ec0000, - 0x38f00000, 0x38f40000, 0x38f80000, 0x38fc0000, -}; -static u32 v_gain[64] = { - 0x016000ff, 0x016100ff, 0x016100ff, 0x016200ff, 0x016200ff, 0x016200ff, - 0x016200ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff, - 0x016300ff, 0x016300ff, 0x016300ff, 0x016400ff, 0x016400ff, 0x016400ff, - 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, - 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, - 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, - 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, - 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, - 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, - 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, - 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, -}; - -static void saa7146_set_winsize(struct saa7146 *saa) -{ - u32 format; - int offset, yacl, ysci; - saa->win.color_fmt = format = - (saa->win.depth == 15) ? palette2fmt[VIDEO_PALETTE_RGB555] : - palette2fmt[bpp2fmt[(saa->win.bpp - 1) & 3]]; - offset = saa->win.x * saa->win.bpp + saa->win.y * saa->win.bpl; - saawrite(saa->win.vidadr + offset, SAA7146_BASE_EVEN1); - saawrite(saa->win.vidadr + offset + saa->win.bpl, SAA7146_BASE_ODD1); - saawrite(saa->win.bpl * 2, SAA7146_PITCH1); - saawrite(saa->win.vidadr + saa->win.bpl * saa->win.sheight, - SAA7146_PROT_ADDR1); - saawrite(0, SAA7146_PAGE1); - saawrite(format | 0x60, SAA7146_CLIP_FORMAT_CTRL); - offset = (704 / (saa->win.width - 1)) & 0x3f; - saawrite(h_prescale[offset], SAA7146_HPS_H_PRESCALE); - offset = (720896 / saa->win.width) / (offset + 1); - saawrite((offset << 12) | 0x0c, SAA7146_HPS_H_SCALE); - if (CurrentMode == VIDEO_MODE_NTSC) { - yacl = /*(480 / saa->win.height - 1) & 0x3f */ 0; - ysci = 1024 - (saa->win.height * 1024 / 480); - } else { - yacl = /*(576 / saa->win.height - 1) & 0x3f */ 0; - ysci = 1024 - (saa->win.height * 1024 / 576); - } - saawrite((1 << 31) | (ysci << 21) | (yacl << 15), SAA7146_HPS_V_SCALE); - saawrite(v_gain[yacl], SAA7146_HPS_V_GAIN); - saawrite(((SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_HPS_V | - SAA7146_MC2_UPLD_HPS_H) << 16) | (SAA7146_MC2_UPLD_DMA1 | - SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_HPS_H), SAA7146_MC2); -} - -/* clip_draw_rectangle(cm,x,y,w,h) -- handle clipping an area - * bitmap is fixed width, 128 bytes (1024 pixels represented) - * arranged most-sigificant-bit-left in 32-bit words - * based on saa7146 clipping hardware, it swaps bytes if LE - * much of this makes up for egcs brain damage -- so if you - * are wondering "why did he do this?" it is because the C - * was adjusted to generate the optimal asm output without - * writing non-portable __asm__ directives. - */ - -static void clip_draw_rectangle(u32 *clipmap, int x, int y, int w, int h) -{ - register int startword, endword; - register u32 bitsleft, bitsright; - u32 *temp; - if (x < 0) { - w += x; - x = 0; - } - if (y < 0) { - h += y; - y = 0; - } - if (w <= 0 || h <= 0 || x > 1023 || y > 639) - return; /* throw away bad clips */ - if (x + w > 1024) - w = 1024 - x; - if (y + h > 640) - h = 640 - y; - startword = (x >> 5); - endword = ((x + w) >> 5); - bitsleft = (0xffffffff >> (x & 31)); - bitsright = (0xffffffff << (~((x + w) - (endword << 5)))); - temp = &clipmap[(y << 5) + startword]; - w = endword - startword; - if (!w) { - bitsleft |= bitsright; - for (y = 0; y < h; y++) { - *temp |= bitsleft; - temp += 32; - } - } else { - for (y = 0; y < h; y++) { - *temp++ |= bitsleft; - for (x = 1; x < w; x++) - *temp++ = 0xffffffff; - *temp |= bitsright; - temp += (32 - w); - } - } -} - -static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr) -{ - int i, width, height; - u32 *clipmap; - - clipmap = saa->dmavid2; - if ((width = saa->win.width) > 1023) - width = 1023; /* sanity check */ - if ((height = saa->win.height) > 640) - height = 639; /* sanity check */ - if (ncr > 0) { /* rectangles pased */ - /* convert rectangular clips to a bitmap */ - memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */ - for (i = 0; i < ncr; i++) - clip_draw_rectangle(clipmap, cr[i].x, cr[i].y, - cr[i].width, cr[i].height); - } - /* clip against viewing window AND screen - so we do not have to rely on the user program - */ - clip_draw_rectangle(clipmap, (saa->win.x + width > saa->win.swidth) ? - (saa->win.swidth - saa->win.x) : width, 0, 1024, 768); - clip_draw_rectangle(clipmap, 0, - (saa->win.y + height > saa->win.sheight) ? - (saa->win.sheight - saa->win.y) : height, 1024, 768); - if (saa->win.x < 0) - clip_draw_rectangle(clipmap, 0, 0, -saa->win.x, 768); - if (saa->win.y < 0) - clip_draw_rectangle(clipmap, 0, 0, 1024, -saa->win.y); -} - -static long saa_ioctl(struct file *file, - unsigned int cmd, unsigned long argl) -{ - struct saa7146 *saa = file->private_data; - void __user *arg = (void __user *)argl; - - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability b; - memset(&b, 0, sizeof(b)); - strcpy(b.name, saa->video_dev.name); - b.type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY | - VID_TYPE_CLIPPING | VID_TYPE_FRAMERAM | - VID_TYPE_SCALES; - b.channels = 1; - b.audios = 1; - b.maxwidth = 768; - b.maxheight = 576; - b.minwidth = 32; - b.minheight = 32; - if (copy_to_user(arg, &b, sizeof(b))) - return -EFAULT; - return 0; - } - case VIDIOCGPICT: - { - struct video_picture p = saa->picture; - if (saa->win.depth == 8) - p.palette = VIDEO_PALETTE_HI240; - if (saa->win.depth == 15) - p.palette = VIDEO_PALETTE_RGB555; - if (saa->win.depth == 16) - p.palette = VIDEO_PALETTE_RGB565; - if (saa->win.depth == 24) - p.palette = VIDEO_PALETTE_RGB24; - if (saa->win.depth == 32) - p.palette = VIDEO_PALETTE_RGB32; - if (copy_to_user(arg, &p, sizeof(p))) - return -EFAULT; - return 0; - } - case VIDIOCSPICT: - { - struct video_picture p; - u32 format; - if (copy_from_user(&p, arg, sizeof(p))) - return -EFAULT; - if (p.palette < ARRAY_SIZE(palette2fmt)) { - format = palette2fmt[p.palette]; - saa->win.color_fmt = format; - saawrite(format | 0x60, - SAA7146_CLIP_FORMAT_CTRL); - } - saawrite(((p.brightness & 0xff00) << 16) | - ((p.contrast & 0xfe00) << 7) | - ((p.colour & 0xfe00) >> 9), SAA7146_BCS_CTRL); - saa->picture = p; - /* upload changed registers */ - saawrite(((SAA7146_MC2_UPLD_HPS_H | - SAA7146_MC2_UPLD_HPS_V) << 16) | - SAA7146_MC2_UPLD_HPS_H | - SAA7146_MC2_UPLD_HPS_V, SAA7146_MC2); - return 0; - } - case VIDIOCSWIN: - { - struct video_window vw; - struct video_clip *vcp = NULL; - - if (copy_from_user(&vw, arg, sizeof(vw))) - return -EFAULT; - - /* stop capture */ - if (vw.flags || vw.width < 16 || vw.height < 16) { - saawrite((SAA7146_MC1_TR_E_1 << 16), - SAA7146_MC1); - return -EINVAL; - } - /* 32-bit align start and adjust width */ - if (saa->win.bpp < 4) { - int i = vw.x; - vw.x = (vw.x + 3) & ~3; - i = vw.x - i; - vw.width -= i; - } - saa->win.x = vw.x; - saa->win.y = vw.y; - saa->win.width = vw.width; - if (saa->win.width > 768) - saa->win.width = 768; - saa->win.height = vw.height; - if (CurrentMode == VIDEO_MODE_NTSC) { - if (saa->win.height > 480) - saa->win.height = 480; - } else { - if (saa->win.height > 576) - saa->win.height = 576; - } - - /* stop capture */ - saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1); - saa7146_set_winsize(saa); - - /* - * Do any clips. - */ - if (vw.clipcount < 0) { - if (copy_from_user(saa->dmavid2, vw.clips, - VIDEO_CLIPMAP_SIZE)) - return -EFAULT; - } else if (vw.clipcount > 16384) { - return -EINVAL; - } else if (vw.clipcount > 0) { - vcp = vmalloc(sizeof(struct video_clip) * - vw.clipcount); - if (vcp == NULL) - return -ENOMEM; - if (copy_from_user(vcp, vw.clips, - sizeof(struct video_clip) * - vw.clipcount)) { - vfree(vcp); - return -EFAULT; - } - } else /* nothing clipped */ - memset(saa->dmavid2, 0, VIDEO_CLIPMAP_SIZE); - - make_clip_tab(saa, vcp, vw.clipcount); - if (vw.clipcount > 0) - vfree(vcp); - - /* start capture & clip dma if we have an address */ - if ((saa->cap & 3) && saa->win.vidadr != 0) - saawrite(((SAA7146_MC1_TR_E_1 | - SAA7146_MC1_TR_E_2) << 16) | 0xffff, - SAA7146_MC1); - return 0; - } - case VIDIOCGWIN: - { - struct video_window vw; - memset(&vw, 0, sizeof(vw)); - vw.x = saa->win.x; - vw.y = saa->win.y; - vw.width = saa->win.width; - vw.height = saa->win.height; - vw.chromakey = 0; - vw.flags = 0; - if (copy_to_user(arg, &vw, sizeof(vw))) - return -EFAULT; - return 0; - } - case VIDIOCCAPTURE: - { - int v; - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if (v == 0) { - saa->cap &= ~1; - saawrite((SAA7146_MC1_TR_E_1 << 16), - SAA7146_MC1); - } else { - if (saa->win.vidadr == 0 || saa->win.width == 0 - || saa->win.height == 0) - return -EINVAL; - saa->cap |= 1; - saawrite((SAA7146_MC1_TR_E_1 << 16) | 0xffff, - SAA7146_MC1); - } - return 0; - } - case VIDIOCGFBUF: - { - struct video_buffer v; - memset(&v, 0, sizeof(v)); - v.base = (void *)saa->win.vidadr; - v.height = saa->win.sheight; - v.width = saa->win.swidth; - v.depth = saa->win.depth; - v.bytesperline = saa->win.bpl; - if (copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; - return 0; - - } - case VIDIOCSFBUF: - { - struct video_buffer v; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if (v.depth != 8 && v.depth != 15 && v.depth != 16 && - v.depth != 24 && v.depth != 32 && v.width > 16 && - v.height > 16 && v.bytesperline > 16) - return -EINVAL; - if (v.base) - saa->win.vidadr = (unsigned long)v.base; - saa->win.sheight = v.height; - saa->win.swidth = v.width; - saa->win.bpp = ((v.depth + 7) & 0x38) / 8; - saa->win.depth = v.depth; - saa->win.bpl = v.bytesperline; - - DEBUG(printk("Display at %p is %d by %d, bytedepth %d, " - "bpl %d\n", v.base, v.width, v.height, - saa->win.bpp, saa->win.bpl)); - saa7146_set_winsize(saa); - return 0; - } - case VIDIOCKEY: - { - /* Will be handled higher up .. */ - return 0; - } - - case VIDIOCGAUDIO: - { - struct video_audio v; - memset(&v, 0, sizeof(v)); - v = saa->audio_dev; - v.flags &= ~(VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE); - v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME; - strcpy(v.name, "MPEG"); - v.mode = VIDEO_SOUND_STEREO; - if (copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio v; - int i; - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - i = (~(v.volume >> 8)) & 0xff; - if (!HaveCS4341) { - if (v.flags & VIDEO_AUDIO_MUTE) - debiwrite(saa, debNormal, - IBM_MP2_FRNT_ATTEN, 0xffff, 2); - if (!(v.flags & VIDEO_AUDIO_MUTE)) - debiwrite(saa, debNormal, - IBM_MP2_FRNT_ATTEN, 0x0000, 2); - if (v.flags & VIDEO_AUDIO_VOLUME) - debiwrite(saa, debNormal, - IBM_MP2_FRNT_ATTEN, - (i << 8) | i, 2); - } else { - if (v.flags & VIDEO_AUDIO_MUTE) - cs4341_setlevel(saa, 0xff, 0xff); - if (!(v.flags & VIDEO_AUDIO_MUTE)) - cs4341_setlevel(saa, 0, 0); - if (v.flags & VIDEO_AUDIO_VOLUME) - cs4341_setlevel(saa, i, i); - } - saa->audio_dev = v; - return 0; - } - - case VIDIOCGUNIT: - { - struct video_unit vu; - memset(&vu, 0, sizeof(vu)); - vu.video = saa->video_dev.minor; - vu.vbi = VIDEO_NO_UNIT; - vu.radio = VIDEO_NO_UNIT; - vu.audio = VIDEO_NO_UNIT; - vu.teletext = VIDEO_NO_UNIT; - if (copy_to_user(arg, &vu, sizeof(vu))) - return -EFAULT; - return 0; - } - case VIDIOCSPLAYMODE: - { - struct video_play_mode pmode; - if (copy_from_user((void *)&pmode, arg, - sizeof(struct video_play_mode))) - return -EFAULT; - switch (pmode.mode) { - case VID_PLAY_VID_OUT_MODE: - if (pmode.p1 != VIDEO_MODE_NTSC && - pmode.p1 != VIDEO_MODE_PAL) - return -EINVAL; - set_out_format(saa, pmode.p1); - return 0; - case VID_PLAY_GENLOCK: - debiwrite(saa, debNormal, XILINX_CTL0, - pmode.p1 ? 0x8000 : 0x8080, 2); - if (NewCard) - set_genlock_offset(saa, pmode.p2); - return 0; - case VID_PLAY_NORMAL: - debiwrite(saa, debNormal, - IBM_MP2_CHIP_CONTROL, ChipControl, 2); - ibm_send_command(saa, IBM_MP2_PLAY, 0, 0); - saa->playmode = pmode.mode; - return 0; - case VID_PLAY_PAUSE: - /* IBM removed the PAUSE command */ - /* they say use SINGLE_FRAME now */ - case VID_PLAY_SINGLE_FRAME: - ibm_send_command(saa, IBM_MP2_SINGLE_FRAME,0,0); - if (saa->playmode == pmode.mode) { - debiwrite(saa, debNormal, - IBM_MP2_CHIP_CONTROL, - ChipControl, 2); - } - saa->playmode = pmode.mode; - return 0; - case VID_PLAY_FAST_FORWARD: - ibm_send_command(saa, IBM_MP2_FAST_FORWARD,0,0); - saa->playmode = pmode.mode; - return 0; - case VID_PLAY_SLOW_MOTION: - ibm_send_command(saa, IBM_MP2_SLOW_MOTION, - pmode.p1, 0); - saa->playmode = pmode.mode; - return 0; - case VID_PLAY_IMMEDIATE_NORMAL: - /* ensure transfers resume */ - debiwrite(saa, debNormal, - IBM_MP2_CHIP_CONTROL, ChipControl, 2); - ibm_send_command(saa, IBM_MP2_IMED_NORM_PLAY, - 0, 0); - saa->playmode = VID_PLAY_NORMAL; - return 0; - case VID_PLAY_SWITCH_CHANNELS: - saa->audhead = saa->audtail = 0; - saa->vidhead = saa->vidtail = 0; - ibm_send_command(saa, IBM_MP2_FREEZE_FRAME,0,1); - ibm_send_command(saa, IBM_MP2_RESET_AUD_RATE, - 0, 1); - debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, - 0, 2); - ibm_send_command(saa, IBM_MP2_CHANNEL_SWITCH, - 0, 1); - debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, - ChipControl, 2); - ibm_send_command(saa, IBM_MP2_PLAY, 0, 0); - saa->playmode = VID_PLAY_NORMAL; - return 0; - case VID_PLAY_FREEZE_FRAME: - ibm_send_command(saa, IBM_MP2_FREEZE_FRAME,0,0); - saa->playmode = pmode.mode; - return 0; - case VID_PLAY_STILL_MODE: - ibm_send_command(saa, IBM_MP2_SET_STILL_MODE, - 0, 0); - saa->playmode = pmode.mode; - return 0; - case VID_PLAY_MASTER_MODE: - if (pmode.p1 == VID_PLAY_MASTER_NONE) - saa->boardcfg[1] = 0x13; - else if (pmode.p1 == VID_PLAY_MASTER_VIDEO) - saa->boardcfg[1] = 0x23; - else if (pmode.p1 == VID_PLAY_MASTER_AUDIO) - saa->boardcfg[1] = 0x43; - else - return -EINVAL; - debiwrite(saa, debNormal, - IBM_MP2_CHIP_CONTROL, ChipControl, 2); - return 0; - case VID_PLAY_ACTIVE_SCANLINES: - if (CurrentMode == VIDEO_MODE_PAL) { - if (pmode.p1 < 1 || pmode.p2 > 625) - return -EINVAL; - saa->boardcfg[5] = pmode.p1; - saa->boardcfg[55] = (pmode.p1 + - (pmode.p2 / 2) - 1) & 0xff; - } else { - if (pmode.p1 < 4 || pmode.p2 > 525) - return -EINVAL; - saa->boardcfg[4] = pmode.p1; - saa->boardcfg[54] = (pmode.p1 + - (pmode.p2 / 2) - 4) & 0xff; - } - set_out_format(saa, CurrentMode); - case VID_PLAY_RESET: - return do_ibm_reset(saa); - case VID_PLAY_END_MARK: - if (saa->endmarktail < saa->endmarkhead) { - if (saa->endmarkhead - - saa->endmarktail < 2) - return -ENOSPC; - } else if (saa->endmarkhead <=saa->endmarktail){ - if (saa->endmarktail - saa->endmarkhead - > (MAX_MARKS - 2)) - return -ENOSPC; - } else - return -ENOSPC; - saa->endmark[saa->endmarktail] = saa->audtail; - saa->endmarktail++; - if (saa->endmarktail >= MAX_MARKS) - saa->endmarktail = 0; - } - return -EINVAL; - } - case VIDIOCSWRITEMODE: - { - int mode; - if (copy_from_user((void *)&mode, arg, sizeof(int))) - return -EFAULT; - if (mode == VID_WRITE_MPEG_AUD || - mode == VID_WRITE_MPEG_VID || - mode == VID_WRITE_CC || - mode == VID_WRITE_TTX || - mode == VID_WRITE_OSD) { - saa->writemode = mode; - return 0; - } - return -EINVAL; - } - case VIDIOCSMICROCODE: - { - struct video_code ucode; - __u8 *udata; - int i; - if (copy_from_user(&ucode, arg, sizeof(ucode))) - return -EFAULT; - if (ucode.datasize > 65536 || ucode.datasize < 1024 || - strncmp(ucode.loadwhat, "dec", 3)) - return -EINVAL; - if ((udata = vmalloc(ucode.datasize)) == NULL) - return -ENOMEM; - if (copy_from_user(udata, ucode.data, ucode.datasize)) { - vfree(udata); - return -EFAULT; - } - ucode.data = udata; - if (!strncmp(ucode.loadwhat, "decoder.aud", 11) || - !strncmp(ucode.loadwhat, "decoder.vid", 11)) - i = initialize_ibmmpeg2(&ucode); - else - i = initialize_fpga(&ucode); - vfree(udata); - if (i) - return -EINVAL; - return 0; - - } - case VIDIOCGCHAN: /* this makes xawtv happy */ - { - struct video_channel v; - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - v.flags = VIDEO_VC_AUDIO; - v.tuners = 0; - v.type = VID_TYPE_MPEG_DECODER; - v.norm = CurrentMode; - strcpy(v.name, "MPEG2"); - if (copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSCHAN: /* this makes xawtv happy */ - { - struct video_channel v; - if (copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - /* do nothing */ - return 0; - } - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static int saa_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct saa7146 *saa = file->private_data; - printk(KERN_DEBUG "stradis%d: saa_mmap called\n", saa->nr); - return -EINVAL; -} - -static ssize_t saa_read(struct file *file, char __user * buf, - size_t count, loff_t * ppos) -{ - return -EINVAL; -} - -static ssize_t saa_write(struct file *file, const char __user * buf, - size_t count, loff_t * ppos) -{ - struct saa7146 *saa = file->private_data; - unsigned long todo = count; - int blocksize, split; - unsigned long flags; - - while (todo > 0) { - if (saa->writemode == VID_WRITE_MPEG_AUD) { - spin_lock_irqsave(&saa->lock, flags); - if (saa->audhead <= saa->audtail) - blocksize = 65536 - - (saa->audtail - saa->audhead); - else - blocksize = saa->audhead - saa->audtail; - spin_unlock_irqrestore(&saa->lock, flags); - if (blocksize < 16384) { - saawrite(SAA7146_PSR_DEBI_S | - SAA7146_PSR_PIN1, SAA7146_IER); - saawrite(SAA7146_PSR_PIN1, SAA7146_PSR); - /* wait for buffer space to open */ - interruptible_sleep_on(&saa->audq); - } - spin_lock_irqsave(&saa->lock, flags); - if (saa->audhead <= saa->audtail) { - blocksize = 65536 - - (saa->audtail - saa->audhead); - split = 65536 - saa->audtail; - } else { - blocksize = saa->audhead - saa->audtail; - split = 65536; - } - spin_unlock_irqrestore(&saa->lock, flags); - blocksize--; - if (blocksize > todo) - blocksize = todo; - /* double check that we really have space */ - if (!blocksize) - return -ENOSPC; - if (split < blocksize) { - if (copy_from_user(saa->audbuf + - saa->audtail, buf, split)) - return -EFAULT; - buf += split; - todo -= split; - blocksize -= split; - saa->audtail = 0; - } - if (copy_from_user(saa->audbuf + saa->audtail, buf, - blocksize)) - return -EFAULT; - saa->audtail += blocksize; - todo -= blocksize; - buf += blocksize; - saa->audtail &= 0xffff; - } else if (saa->writemode == VID_WRITE_MPEG_VID) { - spin_lock_irqsave(&saa->lock, flags); - if (saa->vidhead <= saa->vidtail) - blocksize = 524288 - - (saa->vidtail - saa->vidhead); - else - blocksize = saa->vidhead - saa->vidtail; - spin_unlock_irqrestore(&saa->lock, flags); - if (blocksize < 65536) { - saawrite(SAA7146_PSR_DEBI_S | - SAA7146_PSR_PIN1, SAA7146_IER); - saawrite(SAA7146_PSR_PIN1, SAA7146_PSR); - /* wait for buffer space to open */ - interruptible_sleep_on(&saa->vidq); - } - spin_lock_irqsave(&saa->lock, flags); - if (saa->vidhead <= saa->vidtail) { - blocksize = 524288 - - (saa->vidtail - saa->vidhead); - split = 524288 - saa->vidtail; - } else { - blocksize = saa->vidhead - saa->vidtail; - split = 524288; - } - spin_unlock_irqrestore(&saa->lock, flags); - blocksize--; - if (blocksize > todo) - blocksize = todo; - /* double check that we really have space */ - if (!blocksize) - return -ENOSPC; - if (split < blocksize) { - if (copy_from_user(saa->vidbuf + - saa->vidtail, buf, split)) - return -EFAULT; - buf += split; - todo -= split; - blocksize -= split; - saa->vidtail = 0; - } - if (copy_from_user(saa->vidbuf + saa->vidtail, buf, - blocksize)) - return -EFAULT; - saa->vidtail += blocksize; - todo -= blocksize; - buf += blocksize; - saa->vidtail &= 0x7ffff; - } else if (saa->writemode == VID_WRITE_OSD) { - if (count > 131072) - return -ENOSPC; - if (copy_from_user(saa->osdbuf, buf, count)) - return -EFAULT; - buf += count; - saa->osdhead = 0; - saa->osdtail = count; - debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR, 0, 2); - debiwrite(saa, debNormal, IBM_MP2_OSD_LINK_ADDR, 0, 2); - debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00d, 2); - debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, - debiread(saa, debNormal, - IBM_MP2_DISP_MODE, 2) | 1, 2); - /* trigger osd data transfer */ - saawrite(SAA7146_PSR_DEBI_S | - SAA7146_PSR_PIN1, SAA7146_IER); - saawrite(SAA7146_PSR_PIN1, SAA7146_PSR); - } - } - return count; -} - -static int saa_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev); - - lock_kernel(); - file->private_data = saa; - - saa->user++; - if (saa->user > 1) { - saa->user--; - unlock_kernel(); - return 0; /* device open already, don't reset */ - } - saa->writemode = VID_WRITE_MPEG_VID; /* default to video */ - unlock_kernel(); - return 0; -} - -static int saa_release(struct file *file) -{ - struct saa7146 *saa = file->private_data; - saa->user--; - - if (saa->user > 0) /* still someone using device */ - return 0; - saawrite(0x007f0000, SAA7146_MC1); /* stop all overlay dma */ - return 0; -} - -static const struct v4l2_file_operations saa_fops = { - .owner = THIS_MODULE, - .open = saa_open, - .release = saa_release, - .ioctl = saa_ioctl, - .read = saa_read, - .write = saa_write, - .mmap = saa_mmap, -}; - -/* template for video_device-structure */ -static struct video_device saa_template = { - .name = "SAA7146A", - .fops = &saa_fops, - .release = video_device_release_empty, -}; - -static int __devinit configure_saa7146(struct pci_dev *pdev, int num) -{ - int retval; - struct saa7146 *saa = pci_get_drvdata(pdev); - - saa->endmarkhead = saa->endmarktail = 0; - saa->win.x = saa->win.y = 0; - saa->win.width = saa->win.cropwidth = 720; - saa->win.height = saa->win.cropheight = 480; - saa->win.cropx = saa->win.cropy = 0; - saa->win.bpp = 2; - saa->win.depth = 16; - saa->win.color_fmt = palette2fmt[VIDEO_PALETTE_RGB565]; - saa->win.bpl = 1024 * saa->win.bpp; - saa->win.swidth = 1024; - saa->win.sheight = 768; - saa->picture.brightness = 32768; - saa->picture.contrast = 38768; - saa->picture.colour = 32768; - saa->cap = 0; - saa->nr = num; - saa->playmode = VID_PLAY_NORMAL; - memset(saa->boardcfg, 0, 64); /* clear board config area */ - saa->saa7146_mem = NULL; - saa->dmavid1 = saa->dmavid2 = saa->dmavid3 = saa->dmaa1in = - saa->dmaa1out = saa->dmaa2in = saa->dmaa2out = - saa->pagevid1 = saa->pagevid2 = saa->pagevid3 = saa->pagea1in = - saa->pagea1out = saa->pagea2in = saa->pagea2out = - saa->pagedebi = saa->dmaRPS1 = saa->dmaRPS2 = saa->pageRPS1 = - saa->pageRPS2 = NULL; - saa->audbuf = saa->vidbuf = saa->osdbuf = saa->dmadebi = NULL; - saa->audhead = saa->vidtail = 0; - - init_waitqueue_head(&saa->i2cq); - init_waitqueue_head(&saa->audq); - init_waitqueue_head(&saa->debiq); - init_waitqueue_head(&saa->vidq); - spin_lock_init(&saa->lock); - - retval = pci_enable_device(pdev); - if (retval) { - dev_err(&pdev->dev, "%d: pci_enable_device failed!\n", num); - goto err; - } - - saa->id = pdev->device; - saa->irq = pdev->irq; - saa->saa7146_adr = pci_resource_start(pdev, 0); - pci_read_config_byte(pdev, PCI_CLASS_REVISION, &saa->revision); - - saa->saa7146_mem = ioremap(saa->saa7146_adr, 0x200); - if (saa->saa7146_mem == NULL) { - dev_err(&pdev->dev, "%d: ioremap failed!\n", num); - retval = -EIO; - goto err; - } - - memcpy(&saa->video_dev, &saa_template, sizeof(saa_template)); - saawrite(0, SAA7146_IER); /* turn off all interrupts */ - - retval = request_irq(saa->irq, saa7146_irq, IRQF_SHARED | IRQF_DISABLED, - "stradis", saa); - if (retval == -EINVAL) - dev_err(&pdev->dev, "%d: Bad irq number or handler\n", num); - else if (retval == -EBUSY) - dev_err(&pdev->dev, "%d: IRQ %ld busy, change your PnP config " - "in BIOS\n", num, saa->irq); - if (retval < 0) - goto errio; - - pci_set_master(pdev); - retval = video_register_device(&saa->video_dev, VFL_TYPE_GRABBER, - video_nr); - if (retval < 0) { - dev_err(&pdev->dev, "%d: error in registering video device!\n", - num); - goto errirq; - } - - return 0; - -errirq: - free_irq(saa->irq, saa); -errio: - iounmap(saa->saa7146_mem); -err: - return retval; -} - -static int __devinit init_saa7146(struct pci_dev *pdev) -{ - struct saa7146 *saa = pci_get_drvdata(pdev); - - saa->user = 0; - /* reset the saa7146 */ - saawrite(0xffff0000, SAA7146_MC1); - mdelay(5); - /* enable debi and i2c transfers and pins */ - saawrite(((SAA7146_MC1_EDP | SAA7146_MC1_EI2C | - SAA7146_MC1_TR_E_DEBI) << 16) | 0xffff, SAA7146_MC1); - /* ensure proper state of chip */ - saawrite(0x00000000, SAA7146_PAGE1); - saawrite(0x00f302c0, SAA7146_NUM_LINE_BYTE1); - saawrite(0x00000000, SAA7146_PAGE2); - saawrite(0x01400080, SAA7146_NUM_LINE_BYTE2); - saawrite(0x00000000, SAA7146_DD1_INIT); - saawrite(0x00000000, SAA7146_DD1_STREAM_B); - saawrite(0x00000000, SAA7146_DD1_STREAM_A); - saawrite(0x00000000, SAA7146_BRS_CTRL); - saawrite(0x80400040, SAA7146_BCS_CTRL); - saawrite(0x0000e000 /*| (1<<29) */ , SAA7146_HPS_CTRL); - saawrite(0x00000060, SAA7146_CLIP_FORMAT_CTRL); - saawrite(0x00000000, SAA7146_ACON1); - saawrite(0x00000000, SAA7146_ACON2); - saawrite(0x00000600, SAA7146_I2C_STATUS); - saawrite(((SAA7146_MC2_UPLD_D1_B | SAA7146_MC2_UPLD_D1_A | - SAA7146_MC2_UPLD_BRS | SAA7146_MC2_UPLD_HPS_H | - SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_DMA2 | - SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_I2C) << 16) | 0xffff, - SAA7146_MC2); - /* setup arbitration control registers */ - saawrite(0x1412121a, SAA7146_PCI_BT_V1); - - /* allocate 32k dma buffer + 4k for page table */ - if ((saa->dmadebi = kmalloc(32768 + 4096, GFP_KERNEL)) == NULL) { - dev_err(&pdev->dev, "%d: debi kmalloc failed\n", saa->nr); - goto err; - } -#if 0 - saa->pagedebi = saa->dmadebi + 32768; /* top 4k is for mmu */ - saawrite(virt_to_bus(saa->pagedebi) /*|0x800 */ , SAA7146_DEBI_PAGE); - for (i = 0; i < 12; i++) /* setup mmu page table */ - saa->pagedebi[i] = virt_to_bus((saa->dmadebi + i * 4096)); -#endif - saa->audhead = saa->vidhead = saa->osdhead = 0; - saa->audtail = saa->vidtail = saa->osdtail = 0; - if (saa->vidbuf == NULL && (saa->vidbuf = vmalloc(524288)) == NULL) { - dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr); - goto err; - } - if (saa->audbuf == NULL && (saa->audbuf = vmalloc(65536)) == NULL) { - dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr); - goto errfree; - } - if (saa->osdbuf == NULL && (saa->osdbuf = vmalloc(131072)) == NULL) { - dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr); - goto errfree; - } - /* allocate 81920 byte buffer for clipping */ - if ((saa->dmavid2 = kzalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) { - dev_err(&pdev->dev, "%d: clip kmalloc failed\n", saa->nr); - goto errfree; - } - /* setup clipping registers */ - saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2); - saawrite(virt_to_bus(saa->dmavid2) + 128, SAA7146_BASE_ODD2); - saawrite(virt_to_bus(saa->dmavid2) + VIDEO_CLIPMAP_SIZE, - SAA7146_PROT_ADDR2); - saawrite(256, SAA7146_PITCH2); - saawrite(4, SAA7146_PAGE2); /* dma direction: read, no byteswap */ - saawrite(((SAA7146_MC2_UPLD_DMA2) << 16) | SAA7146_MC2_UPLD_DMA2, - SAA7146_MC2); - I2CBusScan(saa); - - return 0; -errfree: - vfree(saa->osdbuf); - vfree(saa->audbuf); - vfree(saa->vidbuf); - saa->audbuf = saa->osdbuf = saa->vidbuf = NULL; -err: - return -ENOMEM; -} - -static void stradis_release_saa(struct pci_dev *pdev) -{ - u8 command; - struct saa7146 *saa = pci_get_drvdata(pdev); - - /* turn off all capturing, DMA and IRQs */ - saawrite(0xffff0000, SAA7146_MC1); /* reset chip */ - saawrite(0, SAA7146_MC2); - saawrite(0, SAA7146_IER); - saawrite(0xffffffffUL, SAA7146_ISR); - - /* disable PCI bus-mastering */ - pci_read_config_byte(pdev, PCI_COMMAND, &command); - command &= ~PCI_COMMAND_MASTER; - pci_write_config_byte(pdev, PCI_COMMAND, command); - - /* unmap and free memory */ - saa->audhead = saa->audtail = saa->osdhead = 0; - saa->vidhead = saa->vidtail = saa->osdtail = 0; - vfree(saa->vidbuf); - vfree(saa->audbuf); - vfree(saa->osdbuf); - kfree(saa->dmavid2); - saa->audbuf = saa->vidbuf = saa->osdbuf = NULL; - saa->dmavid2 = NULL; - kfree(saa->dmadebi); - kfree(saa->dmavid1); - kfree(saa->dmavid3); - kfree(saa->dmaa1in); - kfree(saa->dmaa1out); - kfree(saa->dmaa2in); - kfree(saa->dmaa2out); - kfree(saa->dmaRPS1); - kfree(saa->dmaRPS2); - free_irq(saa->irq, saa); - if (saa->saa7146_mem) - iounmap(saa->saa7146_mem); - if (video_is_registered(&saa->video_dev)) - video_unregister_device(&saa->video_dev); -} - -static int __devinit stradis_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - int retval = -EINVAL; - - if (saa_num >= SAA7146_MAX) - goto err; - - if (!pdev->subsystem_vendor) - dev_info(&pdev->dev, "%d: rev1 decoder\n", saa_num); - else - dev_info(&pdev->dev, "%d: SDM2xx found\n", saa_num); - - pci_set_drvdata(pdev, &saa7146s[saa_num]); - - retval = configure_saa7146(pdev, saa_num); - if (retval) { - dev_err(&pdev->dev, "%d: error in configuring\n", saa_num); - goto err; - } - - if (init_saa7146(pdev) < 0) { - dev_err(&pdev->dev, "%d: error in initialization\n", saa_num); - retval = -EIO; - goto errrel; - } - - saa_num++; - - return 0; -errrel: - stradis_release_saa(pdev); -err: - return retval; -} - -static void __devexit stradis_remove(struct pci_dev *pdev) -{ - stradis_release_saa(pdev); -} - -static struct pci_device_id stradis_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146) }, - { 0 } -}; - - -static struct pci_driver stradis_driver = { - .name = "stradis", - .id_table = stradis_pci_tbl, - .probe = stradis_probe, - .remove = __devexit_p(stradis_remove) -}; - -static int __init stradis_init(void) -{ - int retval; - - saa_num = 0; - - retval = pci_register_driver(&stradis_driver); - if (retval) - printk(KERN_ERR "stradis: Unable to register pci driver.\n"); - - return retval; -} - -static void __exit stradis_exit(void) -{ - pci_unregister_driver(&stradis_driver); - printk(KERN_INFO "stradis: module cleanup complete\n"); -} - -module_init(stradis_init); -module_exit(stradis_exit); -- cgit v0.10.2 From 439105b122dfa21fbce7201d0f30b5eeac95c918 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 25 Dec 2010 07:46:56 -0300 Subject: [media] feature-removal: update V4L1 removal status While the V4L1 compatibility module has been removed, we still have two V4L1 drivers that prevent full V4L1 removal. Those drivers have been moved to staging and will be removed in 2.6.39, together with the last V4L1 support. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 6c2f55e..d66ed2b 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -98,35 +98,33 @@ Who: Pavel Machek --------------------------- What: Video4Linux API 1 ioctls and from Video devices. -When: kernel 2.6.38 +When: kernel 2.6.39 Files: include/linux/videodev.h Check: include/linux/videodev.h Why: V4L1 AP1 was replaced by V4L2 API during migration from 2.4 to 2.6 series. The old API have lots of drawbacks and don't provide enough means to work with all video and audio standards. The newer API is already available on the main drivers and should be used instead. - Newer drivers should use v4l_compat_translate_ioctl function to handle - old calls, replacing to newer ones. - Decoder iocts are using internally to allow video drivers to - communicate with video decoders. This should also be improved to allow - V4L2 calls being translated into compatible internal ioctls. - Compatibility ioctls will be provided, for a while, via - v4l1-compat module. + + The userspace libv4l1 library can convert V4L1 calls to V4L2. This + replaces the kernel V4L1 compatibility module which was removed in + 2.6.38. The last V4L1 drivers will either be converted to V4L2 or + removed for 2.6.39 at which point the V4L1 API will cease to exist. Who: Mauro Carvalho Chehab --------------------------- What: Video4Linux obsolete drivers using V4L1 API -When: kernel 2.6.38 -Files: drivers/staging/cpia/* drivers/staging/stradis/* -Check: drivers/staging/cpia/cpia.c drivers/staging/stradis/stradis.c +When: kernel 2.6.39 +Files: drivers/staging/se401/* drivers/staging/usbvideo/* +Check: drivers/staging/se401/se401.c drivers/staging/usbvideo/usbvideo.c Why: There are some drivers still using V4L1 API, despite all efforts we've done to migrate. Those drivers are for obsolete hardware that the old maintainer didn't care (or not have the hardware anymore), and that no other developer could find any hardware to buy. They probably have no practical usage today, and people with such old hardware could probably keep using an older version - of the kernel. Those drivers will be moved to staging on 2.6.37 and, if nobody - care enough to port and test them with V4L2 API, they'll be removed on 2.6.38. + of the kernel. Those drivers will be moved to staging on 2.6.38 and, if nobody + cares enough to port and test them with V4L2 API, they'll be removed on 2.6.39. Who: Mauro Carvalho Chehab --------------------------- -- cgit v0.10.2 From 0a58d713062fb49952b9b082514a48a0c83b269d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 25 Dec 2010 08:01:38 -0300 Subject: [media] stk-webcam: remove V4L1 compatibility code, replace with V4L2 controls Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index b5afe5f..d1a2cef 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c @@ -230,120 +230,6 @@ static int stk_initialise(struct stk_camera *dev) return -1; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT - -/* sysfs functions */ -/*FIXME cleanup this */ - -static ssize_t show_brightness(struct device *class, - struct device_attribute *attr, char *buf) -{ - struct video_device *vdev = to_video_device(class); - struct stk_camera *dev = vdev_to_camera(vdev); - - return sprintf(buf, "%X\n", dev->vsettings.brightness); -} - -static ssize_t store_brightness(struct device *class, - struct device_attribute *attr, const char *buf, size_t count) -{ - char *endp; - unsigned long value; - int ret; - - struct video_device *vdev = to_video_device(class); - struct stk_camera *dev = vdev_to_camera(vdev); - - value = simple_strtoul(buf, &endp, 16); - - dev->vsettings.brightness = (int) value; - - ret = stk_sensor_set_brightness(dev, value >> 8); - if (ret) - return ret; - else - return count; -} - -static ssize_t show_hflip(struct device *class, - struct device_attribute *attr, char *buf) -{ - struct video_device *vdev = to_video_device(class); - struct stk_camera *dev = vdev_to_camera(vdev); - - return sprintf(buf, "%d\n", dev->vsettings.hflip); -} - -static ssize_t store_hflip(struct device *class, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct video_device *vdev = to_video_device(class); - struct stk_camera *dev = vdev_to_camera(vdev); - - if (strncmp(buf, "1", 1) == 0) - dev->vsettings.hflip = 1; - else if (strncmp(buf, "0", 1) == 0) - dev->vsettings.hflip = 0; - else - return -EINVAL; - - return strlen(buf); -} - -static ssize_t show_vflip(struct device *class, - struct device_attribute *attr, char *buf) -{ - struct video_device *vdev = to_video_device(class); - struct stk_camera *dev = vdev_to_camera(vdev); - - return sprintf(buf, "%d\n", dev->vsettings.vflip); -} - -static ssize_t store_vflip(struct device *class, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct video_device *vdev = to_video_device(class); - struct stk_camera *dev = vdev_to_camera(vdev); - - if (strncmp(buf, "1", 1) == 0) - dev->vsettings.vflip = 1; - else if (strncmp(buf, "0", 1) == 0) - dev->vsettings.vflip = 0; - else - return -EINVAL; - - return strlen(buf); -} - -static DEVICE_ATTR(brightness, S_IRUGO | S_IWUGO, - show_brightness, store_brightness); -static DEVICE_ATTR(hflip, S_IRUGO | S_IWUGO, show_hflip, store_hflip); -static DEVICE_ATTR(vflip, S_IRUGO | S_IWUGO, show_vflip, store_vflip); - -static int stk_create_sysfs_files(struct video_device *vdev) -{ - int ret; - - ret = device_create_file(&vdev->dev, &dev_attr_brightness); - ret += device_create_file(&vdev->dev, &dev_attr_hflip); - ret += device_create_file(&vdev->dev, &dev_attr_vflip); - if (ret) - STK_WARNING("Could not create sysfs files\n"); - return ret; -} - -static void stk_remove_sysfs_files(struct video_device *vdev) -{ - device_remove_file(&vdev->dev, &dev_attr_brightness); - device_remove_file(&vdev->dev, &dev_attr_hflip); - device_remove_file(&vdev->dev, &dev_attr_vflip); -} - -#else -#define stk_create_sysfs_files(a) -#define stk_remove_sysfs_files(a) -#endif - /* *********************************************** */ /* * This function is called as an URB transfert is complete (Isochronous pipe). @@ -878,7 +764,24 @@ static struct v4l2_queryctrl stk_controls[] = { .step = 0x0100, .default_value = 0x6000, }, - /*TODO: get more controls to work */ + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Horizontal Flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + }, + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Vertical Flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + }, }; static int stk_vidioc_queryctrl(struct file *filp, @@ -906,6 +809,12 @@ static int stk_vidioc_g_ctrl(struct file *filp, case V4L2_CID_BRIGHTNESS: c->value = dev->vsettings.brightness; break; + case V4L2_CID_HFLIP: + c->value = dev->vsettings.hflip; + break; + case V4L2_CID_VFLIP: + c->value = dev->vsettings.vflip; + break; default: return -EINVAL; } @@ -920,6 +829,12 @@ static int stk_vidioc_s_ctrl(struct file *filp, case V4L2_CID_BRIGHTNESS: dev->vsettings.brightness = c->value; return stk_sensor_set_brightness(dev, c->value >> 8); + case V4L2_CID_HFLIP: + dev->vsettings.hflip = c->value; + return 0; + case V4L2_CID_VFLIP: + dev->vsettings.vflip = c->value; + return 0; default: return -EINVAL; } @@ -1394,8 +1309,6 @@ static int stk_camera_probe(struct usb_interface *interface, goto error; } - stk_create_sysfs_files(&dev->vdev); - return 0; error: @@ -1411,7 +1324,6 @@ static void stk_camera_disconnect(struct usb_interface *interface) unset_present(dev); wake_up_interruptible(&dev->wait_frame); - stk_remove_sysfs_files(&dev->vdev); STK_INFO("Syntek USB2.0 Camera release resources device %s\n", video_device_node_name(&dev->vdev)); -- cgit v0.10.2 From fa98447f09641adeeaf02b94133649f03b74d159 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 11 Dec 2010 12:31:45 -0300 Subject: [media] ivtv, cx18: Make ioremap failure messages more useful for users The error messages these drivers emitted for ioremap() failures were misleading and not helpful for users. Reworded those messages to help the user take action to resolve vmalloc address space exhaustion. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 98ac2e9..676e5be 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -925,8 +925,13 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, cx->enc_mem = ioremap_nocache(cx->base_addr + CX18_MEM_OFFSET, CX18_MEM_SIZE); if (!cx->enc_mem) { - CX18_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n"); - CX18_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n"); + CX18_ERR("ioremap failed. Can't get a window into CX23418 " + "memory and register space\n"); + CX18_ERR("Each capture card with a CX23418 needs 64 MB of " + "vmalloc address space for the window\n"); + CX18_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n"); + CX18_ERR("Use the vmalloc= kernel command line option to set " + "VmallocTotal to a larger value\n"); retval = -ENOMEM; goto free_mem; } diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index e421d15..3994642 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -1029,8 +1029,13 @@ static int __devinit ivtv_probe(struct pci_dev *pdev, itv->enc_mem = ioremap_nocache(itv->base_addr + IVTV_ENCODER_OFFSET, IVTV_ENCODER_SIZE); if (!itv->enc_mem) { - IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n"); - IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n"); + IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 " + "encoder memory\n"); + IVTV_ERR("Each capture card with a CX23415/6 needs 8 MB of " + "vmalloc address space for this window\n"); + IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n"); + IVTV_ERR("Use the vmalloc= kernel command line option to set " + "VmallocTotal to a larger value\n"); retval = -ENOMEM; goto free_mem; } @@ -1041,8 +1046,14 @@ static int __devinit ivtv_probe(struct pci_dev *pdev, itv->dec_mem = ioremap_nocache(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); if (!itv->dec_mem) { - IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n"); - IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n"); + IVTV_ERR("ioremap failed. Can't get a window into " + "CX23415 decoder memory\n"); + IVTV_ERR("Each capture card with a CX23415 needs 8 MB " + "of vmalloc address space for this window\n"); + IVTV_ERR("Check the output of 'grep Vmalloc " + "/proc/meminfo'\n"); + IVTV_ERR("Use the vmalloc= kernel command line option " + "to set VmallocTotal to a larger value\n"); retval = -ENOMEM; goto free_mem; } @@ -1057,8 +1068,13 @@ static int __devinit ivtv_probe(struct pci_dev *pdev, itv->reg_mem = ioremap_nocache(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); if (!itv->reg_mem) { - IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n"); - IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n"); + IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 " + "register space\n"); + IVTV_ERR("Each capture card with a CX23415/6 needs 64 kB of " + "vmalloc address space for this window\n"); + IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n"); + IVTV_ERR("Use the vmalloc= kernel command line option to set " + "VmallocTotal to a larger value\n"); retval = -ENOMEM; goto free_io; } -- cgit v0.10.2 From 754f9969c323559a12bce1475f3c1e6574129856 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 11 Dec 2010 20:38:20 -0300 Subject: [media] cx18: Only allocate a struct cx18_dvb for the DVB TS stream The cx18_stream struct contained a struct cx18_dvb for every stream object, most of which were for analog capture. Now we only allocate the cx18_dvb object for the DTV TS stream. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index cf4f20e..f6f3e50 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -325,7 +325,10 @@ struct cx18_queue { spinlock_t lock; }; +struct cx18_stream; /* forward reference */ + struct cx18_dvb { + struct cx18_stream *stream; struct dmx_frontend hw_frontend; struct dmx_frontend mem_frontend; struct dmxdev dmxdev; @@ -365,9 +368,10 @@ struct cx18_in_work_order { #define CX18_INVALID_TASK_HANDLE 0xffffffff struct cx18_stream { - /* These first four fields are always set, even if the stream + /* These first five fields are always set, even if the stream is not actually created. */ struct video_device *video_dev; /* NULL when stream not created */ + struct cx18_dvb *dvb; /* DVB / Digital Transport */ struct cx18 *cx; /* for ease of use */ const char *name; /* name of the stream */ int type; /* stream type */ @@ -397,9 +401,6 @@ struct cx18_stream { struct cx18_queue q_idle; /* idle - not in rotation */ struct work_struct out_work_order; - - /* DVB / Digital Transport */ - struct cx18_dvb dvb; }; struct cx18_open_id { diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index c7f0bad..f0381d6 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c @@ -137,7 +137,7 @@ static int yuan_mpc718_mt352_init(struct dvb_frontend *fe) { struct cx18_dvb *dvb = container_of(fe->dvb, struct cx18_dvb, dvb_adapter); - struct cx18_stream *stream = container_of(dvb, struct cx18_stream, dvb); + struct cx18_stream *stream = dvb->stream; const struct firmware *fw = NULL; int ret; int i; @@ -266,22 +266,22 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) if (!demux->dmx.frontend) return -EINVAL; - mutex_lock(&stream->dvb.feedlock); - if (stream->dvb.feeding++ == 0) { + mutex_lock(&stream->dvb->feedlock); + if (stream->dvb->feeding++ == 0) { CX18_DEBUG_INFO("Starting Transport DMA\n"); mutex_lock(&cx->serialize_lock); set_bit(CX18_F_S_STREAMING, &stream->s_flags); ret = cx18_start_v4l2_encode_stream(stream); if (ret < 0) { CX18_DEBUG_INFO("Failed to start Transport DMA\n"); - stream->dvb.feeding--; - if (stream->dvb.feeding == 0) + stream->dvb->feeding--; + if (stream->dvb->feeding == 0) clear_bit(CX18_F_S_STREAMING, &stream->s_flags); } mutex_unlock(&cx->serialize_lock); } else ret = 0; - mutex_unlock(&stream->dvb.feedlock); + mutex_unlock(&stream->dvb->feedlock); return ret; } @@ -299,15 +299,15 @@ static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed) CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n", feed->pid, feed->index); - mutex_lock(&stream->dvb.feedlock); - if (--stream->dvb.feeding == 0) { + mutex_lock(&stream->dvb->feedlock); + if (--stream->dvb->feeding == 0) { CX18_DEBUG_INFO("Stopping Transport DMA\n"); mutex_lock(&cx->serialize_lock); ret = cx18_stop_v4l2_encode_stream(stream, 0); mutex_unlock(&cx->serialize_lock); } else ret = 0; - mutex_unlock(&stream->dvb.feedlock); + mutex_unlock(&stream->dvb->feedlock); } return ret; @@ -316,7 +316,7 @@ static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed) int cx18_dvb_register(struct cx18_stream *stream) { struct cx18 *cx = stream->cx; - struct cx18_dvb *dvb = &stream->dvb; + struct cx18_dvb *dvb = stream->dvb; struct dvb_adapter *dvb_adapter; struct dvb_demux *dvbdemux; struct dmx_demux *dmx; @@ -325,6 +325,9 @@ int cx18_dvb_register(struct cx18_stream *stream) if (!dvb) return -EINVAL; + dvb->enabled = 0; + dvb->stream = stream; + ret = dvb_register_adapter(&dvb->dvb_adapter, CX18_DRIVER_NAME, THIS_MODULE, &cx->pci_dev->dev, adapter_nr); @@ -378,7 +381,7 @@ int cx18_dvb_register(struct cx18_stream *stream) CX18_INFO("DVB Frontend registered\n"); CX18_INFO("Registered DVB adapter%d for %s (%d x %d.%02d kB)\n", - stream->dvb.dvb_adapter.num, stream->name, + stream->dvb->dvb_adapter.num, stream->name, stream->buffers, stream->buf_size/1024, (stream->buf_size * 100 / 1024) % 100); @@ -405,13 +408,16 @@ err_out: void cx18_dvb_unregister(struct cx18_stream *stream) { struct cx18 *cx = stream->cx; - struct cx18_dvb *dvb = &stream->dvb; + struct cx18_dvb *dvb = stream->dvb; struct dvb_adapter *dvb_adapter; struct dvb_demux *dvbdemux; struct dmx_demux *dmx; CX18_INFO("unregister DVB\n"); + if (dvb == NULL || !dvb->enabled) + return; + dvb_adapter = &dvb->dvb_adapter; dvbdemux = &dvb->demux; dmx = &dvbdemux->dmx; @@ -432,7 +438,7 @@ void cx18_dvb_unregister(struct cx18_stream *stream) */ static int dvb_register(struct cx18_stream *stream) { - struct cx18_dvb *dvb = &stream->dvb; + struct cx18_dvb *dvb = stream->dvb; struct cx18 *cx = stream->cx; int ret = 0; diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 956aa19..c545f3b 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c @@ -136,7 +136,7 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl) { struct cx18_buffer *buf; - if (!s->dvb.enabled || mdl->bytesused == 0) + if (s->dvb == NULL || !s->dvb->enabled || mdl->bytesused == 0) return; /* We ignore mdl and buf readpos accounting here - it doesn't matter */ @@ -146,7 +146,7 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl) buf = list_first_entry(&mdl->buf_list, struct cx18_buffer, list); if (buf->bytesused) - dvb_dmx_swfilter(&s->dvb.demux, + dvb_dmx_swfilter(&s->dvb->demux, buf->buf, buf->bytesused); return; } @@ -154,7 +154,7 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl) list_for_each_entry(buf, &mdl->buf_list, list) { if (buf->bytesused == 0) break; - dvb_dmx_swfilter(&s->dvb.demux, buf->buf, buf->bytesused); + dvb_dmx_swfilter(&s->dvb->demux, buf->buf, buf->bytesused); } } diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index ab461e2..94f5d79 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -107,6 +107,7 @@ static void cx18_stream_init(struct cx18 *cx, int type) s->video_dev = video_dev; /* initialize cx18_stream fields */ + s->dvb = NULL; s->cx = cx; s->type = type; s->name = cx18_stream_info[type].name; @@ -140,10 +141,15 @@ static int cx18_prep_dev(struct cx18 *cx, int type) int num_offset = cx18_stream_info[type].num_offset; int num = cx->instance + cx18_first_minor + num_offset; - /* These four fields are always initialized. If video_dev == NULL, then - this stream is not in use. In that case no other fields but these - four can be used. */ + /* + * These five fields are always initialized. + * For analog capture related streams, if video_dev == NULL then the + * stream is not in use. + * For the TS stream, if dvb == NULL then the stream is not in use. + * In those cases no other fields but these four can be used. + */ s->video_dev = NULL; + s->dvb = NULL; s->cx = cx; s->type = type; s->name = cx18_stream_info[type].name; @@ -167,6 +173,21 @@ static int cx18_prep_dev(struct cx18 *cx, int type) cx18_stream_init(cx, type); + /* Allocate the cx18_dvb struct only for the TS on cards with DTV */ + if (type == CX18_ENC_STREAM_TYPE_TS) { + if (cx->card->hw_all & CX18_HW_DVB) { + s->dvb = kzalloc(sizeof(struct cx18_dvb), GFP_KERNEL); + if (s->dvb == NULL) { + CX18_ERR("Couldn't allocate cx18_dvb structure" + " for %s\n", s->name); + return -ENOMEM; + } + } else { + /* Don't need buffers for the TS, if there is no DVB */ + s->buffers = 0; + } + } + if (num_offset == -1) return 0; @@ -222,13 +243,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type) const char *name; int num, ret; - /* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something? - * We need a VFL_TYPE_TS defined. - */ - if (strcmp("TS", s->name) == 0) { - /* just return if no DVB is supported */ - if ((cx->card->hw_all & CX18_HW_DVB) == 0) - return 0; + if (type == CX18_ENC_STREAM_TYPE_TS && s->dvb != NULL) { ret = cx18_dvb_register(s); if (ret < 0) { CX18_ERR("DVB failed to register\n"); @@ -320,11 +335,13 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister) /* Teardown all streams */ for (type = 0; type < CX18_MAX_STREAMS; type++) { - /* No struct video_device, but can have buffers allocated */ + /* The TS has a cx18_dvb structure, not a video_device */ if (type == CX18_ENC_STREAM_TYPE_TS) { - if (cx->streams[type].dvb.enabled) { - cx18_dvb_unregister(&cx->streams[type]); - cx->streams[type].dvb.enabled = false; + if (cx->streams[type].dvb != NULL) { + if (unregister) + cx18_dvb_unregister(&cx->streams[type]); + kfree(cx->streams[type].dvb); + cx->streams[type].dvb = NULL; cx18_stream_free(&cx->streams[type]); } continue; diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h index 77412be..51765eb 100644 --- a/drivers/media/video/cx18/cx18-streams.h +++ b/drivers/media/video/cx18/cx18-streams.h @@ -33,7 +33,8 @@ void cx18_stream_rotate_idx_mdls(struct cx18 *cx); static inline bool cx18_stream_enabled(struct cx18_stream *s) { - return s->video_dev || s->dvb.enabled || + return s->video_dev || + (s->dvb && s->dvb->enabled) || (s->type == CX18_ENC_STREAM_TYPE_IDX && s->cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] != 0); } -- cgit v0.10.2 From b0c45686c8e8aecc7b0cd04d9b6af48d74418d53 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 18 Dec 2010 10:48:17 -0300 Subject: [media] ivtv: ivtv_write_vbi() should use copy_from_user() for user data buffers ivtv_write_vbi() is used for both VBI data that came from the driver internally and VBI data that came from the user. However, it did not use copy_from_user() for reading the VBI data from the user buffers. This change adds a new version of the function, ivtv_write_vbi_from_user(), that uses copy_from_user() to read the VBI data provided via user buffers. This should resolve a sparse build warning reported by Dave Gilbert. Reported-by: Dr. David Alan Gilbert Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index d727485..4f46b00 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -570,7 +570,8 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c int elems = count / sizeof(struct v4l2_sliced_vbi_data); set_bit(IVTV_F_S_APPL_IO, &s->s_flags); - ivtv_write_vbi(itv, (const struct v4l2_sliced_vbi_data *)user_buf, elems); + ivtv_write_vbi_from_user(itv, + (const struct v4l2_sliced_vbi_data __user *)user_buf, elems); return elems * sizeof(struct v4l2_sliced_vbi_data); } diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index e1c347e..7275f2d 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c @@ -92,54 +92,91 @@ static int odd_parity(u8 c) return c & 1; } -void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t cnt) +static void ivtv_write_vbi_line(struct ivtv *itv, + const struct v4l2_sliced_vbi_data *d, + struct vbi_cc *cc, int *found_cc) { struct vbi_info *vi = &itv->vbi; - struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; - int found_cc = 0; - size_t i; - - for (i = 0; i < cnt; i++) { - const struct v4l2_sliced_vbi_data *d = sliced + i; - if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) { - if (d->field) { - cc.even[0] = d->data[0]; - cc.even[1] = d->data[1]; - } else { - cc.odd[0] = d->data[0]; - cc.odd[1] = d->data[1]; - } - found_cc = 1; + if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) { + if (d->field) { + cc->even[0] = d->data[0]; + cc->even[1] = d->data[1]; + } else { + cc->odd[0] = d->data[0]; + cc->odd[1] = d->data[1]; } - else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) { - struct vbi_vps vps; - - vps.data[0] = d->data[2]; - vps.data[1] = d->data[8]; - vps.data[2] = d->data[9]; - vps.data[3] = d->data[10]; - vps.data[4] = d->data[11]; - if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) { - vi->vps_payload = vps; - set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); - } + *found_cc = 1; + } else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) { + struct vbi_vps vps; + + vps.data[0] = d->data[2]; + vps.data[1] = d->data[8]; + vps.data[2] = d->data[9]; + vps.data[3] = d->data[10]; + vps.data[4] = d->data[11]; + if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) { + vi->vps_payload = vps; + set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); } - else if (d->id == V4L2_SLICED_WSS_625 && d->line == 23 && d->field == 0) { - int wss = d->data[0] | d->data[1] << 8; + } else if (d->id == V4L2_SLICED_WSS_625 && + d->line == 23 && d->field == 0) { + int wss = d->data[0] | d->data[1] << 8; - if (vi->wss_payload != wss) { - vi->wss_payload = wss; - set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); - } + if (vi->wss_payload != wss) { + vi->wss_payload = wss; + set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); } } - if (found_cc && vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) { - vi->cc_payload[vi->cc_payload_idx++] = cc; +} + +static void ivtv_write_vbi_cc_lines(struct ivtv *itv, const struct vbi_cc *cc) +{ + struct vbi_info *vi = &itv->vbi; + + if (vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) { + memcpy(&vi->cc_payload[vi->cc_payload_idx], cc, + sizeof(struct vbi_cc)); + vi->cc_payload_idx++; set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); } } +static void ivtv_write_vbi(struct ivtv *itv, + const struct v4l2_sliced_vbi_data *sliced, + size_t cnt) +{ + struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; + int found_cc = 0; + size_t i; + + for (i = 0; i < cnt; i++) + ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc); + + if (found_cc) + ivtv_write_vbi_cc_lines(itv, &cc); +} + +void ivtv_write_vbi_from_user(struct ivtv *itv, + const struct v4l2_sliced_vbi_data __user *sliced, + size_t cnt) +{ + struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; + int found_cc = 0; + size_t i; + struct v4l2_sliced_vbi_data d; + + for (i = 0; i < cnt; i++) { + if (copy_from_user(&d, sliced + i, + sizeof(struct v4l2_sliced_vbi_data))) + break; + ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc); + } + + if (found_cc) + ivtv_write_vbi_cc_lines(itv, &cc); +} + static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp) { int line = 0; diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/video/ivtv/ivtv-vbi.h index 970567b..eda38d0 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.h +++ b/drivers/media/video/ivtv/ivtv-vbi.h @@ -20,7 +20,9 @@ #ifndef IVTV_VBI_H #define IVTV_VBI_H -void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t count); +void ivtv_write_vbi_from_user(struct ivtv *itv, + const struct v4l2_sliced_vbi_data __user *sliced, + size_t count); void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, u64 pts_stamp, int streamtype); int ivtv_used_line(struct ivtv *itv, int line, int field); -- cgit v0.10.2 From ddda424999817fbc17adf9013feb066903382ede Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 19 Dec 2010 21:59:56 -0300 Subject: [media] ivtv: Return EFAULT when copy_from_user() fails in ivtv_write_vbi_from_user() If write() on a VBI device node fails due to a bad buffer pointer from userspace, we should notify the application properly with EFAULT, per the V4L2 API spec. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 4f46b00..c57a585 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -570,9 +570,8 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c int elems = count / sizeof(struct v4l2_sliced_vbi_data); set_bit(IVTV_F_S_APPL_IO, &s->s_flags); - ivtv_write_vbi_from_user(itv, + return ivtv_write_vbi_from_user(itv, (const struct v4l2_sliced_vbi_data __user *)user_buf, elems); - return elems * sizeof(struct v4l2_sliced_vbi_data); } mode = s->type == IVTV_DEC_STREAM_TYPE_MPG ? OUT_MPG : OUT_YUV; diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index 7275f2d..2dfa957 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c @@ -157,24 +157,30 @@ static void ivtv_write_vbi(struct ivtv *itv, ivtv_write_vbi_cc_lines(itv, &cc); } -void ivtv_write_vbi_from_user(struct ivtv *itv, - const struct v4l2_sliced_vbi_data __user *sliced, - size_t cnt) +ssize_t +ivtv_write_vbi_from_user(struct ivtv *itv, + const struct v4l2_sliced_vbi_data __user *sliced, + size_t cnt) { struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; int found_cc = 0; size_t i; struct v4l2_sliced_vbi_data d; + ssize_t ret = cnt * sizeof(struct v4l2_sliced_vbi_data); for (i = 0; i < cnt; i++) { if (copy_from_user(&d, sliced + i, - sizeof(struct v4l2_sliced_vbi_data))) + sizeof(struct v4l2_sliced_vbi_data))) { + ret = -EFAULT; break; + } ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc); } if (found_cc) ivtv_write_vbi_cc_lines(itv, &cc); + + return ret; } static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp) diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/video/ivtv/ivtv-vbi.h index eda38d0..166dd0b 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.h +++ b/drivers/media/video/ivtv/ivtv-vbi.h @@ -20,9 +20,10 @@ #ifndef IVTV_VBI_H #define IVTV_VBI_H -void ivtv_write_vbi_from_user(struct ivtv *itv, - const struct v4l2_sliced_vbi_data __user *sliced, - size_t count); +ssize_t +ivtv_write_vbi_from_user(struct ivtv *itv, + const struct v4l2_sliced_vbi_data __user *sliced, + size_t count); void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, u64 pts_stamp, int streamtype); int ivtv_used_line(struct ivtv *itv, int line, int field); -- cgit v0.10.2 From f74e3d0eea5fd766230a0ef0d1c24a7960d6f8c2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 07:33:41 -0300 Subject: [media] staging: Add TODO files for se401 and usbvideo/vicam Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/se401/TODO b/drivers/staging/se401/TODO new file mode 100644 index 0000000..3b2c038 --- /dev/null +++ b/drivers/staging/se401/TODO @@ -0,0 +1,5 @@ +This is an obsolete driver for some old webcams that still use V4L1 API. +As V4L1 support is being removed from kernel, if nobody take care on it, +the driver will be removed for 2.6.39. + +Please send patches to linux-media@vger.kernel.org diff --git a/drivers/staging/usbvideo/TODO b/drivers/staging/usbvideo/TODO new file mode 100644 index 0000000..3b2c038 --- /dev/null +++ b/drivers/staging/usbvideo/TODO @@ -0,0 +1,5 @@ +This is an obsolete driver for some old webcams that still use V4L1 API. +As V4L1 support is being removed from kernel, if nobody take care on it, +the driver will be removed for 2.6.39. + +Please send patches to linux-media@vger.kernel.org -- cgit v0.10.2 From 58c66df3e38ffb1d59cc5162bb9e07c859288034 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 07:38:48 -0300 Subject: [media] Remove VIDEO_V4L1 Kconfig option There's no sense on keeping VIDEO_V4L1 Kconfig option just because of two deprecated drivers moved to staging scheduled to die on 2.6.39. Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 9ea1a6d..147c92b 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -40,20 +40,6 @@ config VIDEO_V4L2_COMMON depends on (I2C || I2C=n) && VIDEO_DEV default (I2C || I2C=n) && VIDEO_DEV -config VIDEO_ALLOW_V4L1 - bool "Enable Video For Linux API 1 (DEPRECATED)" - depends on VIDEO_DEV && VIDEO_V4L2_COMMON - default VIDEO_DEV && VIDEO_V4L2_COMMON - ---help--- - Enables drivers based on the legacy V4L1 API. - - This api were developed to be used at Kernel 2.2 and 2.4, but - lacks support for several video standards. There are several - drivers at kernel that still depends on it. - - If you are unsure as to whether this is required, answer Y. - - # # DVB Core # diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index b3bf043..78b8c5d 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -7,11 +7,6 @@ config VIDEO_V4L2 depends on VIDEO_DEV && VIDEO_V4L2_COMMON default VIDEO_DEV && VIDEO_V4L2_COMMON -config VIDEO_V4L1 - tristate - depends on VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1 - default VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1 - config VIDEOBUF_GEN tristate diff --git a/drivers/staging/se401/Kconfig b/drivers/staging/se401/Kconfig index 586fc04..ee7313e 100644 --- a/drivers/staging/se401/Kconfig +++ b/drivers/staging/se401/Kconfig @@ -1,6 +1,6 @@ config USB_SE401 tristate "USB SE401 Camera support (DEPRECATED)" - depends on VIDEO_V4L1 + depends on VIDEO_DEV && VIDEO_V4L2_COMMON ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. See diff --git a/drivers/staging/usbvideo/Kconfig b/drivers/staging/usbvideo/Kconfig index aae863e..d9fc867 100644 --- a/drivers/staging/usbvideo/Kconfig +++ b/drivers/staging/usbvideo/Kconfig @@ -3,7 +3,7 @@ config VIDEO_USBVIDEO config USB_VICAM tristate "USB 3com HomeConnect (aka vicam) support (DEPRECATED)" - depends on VIDEO_V4L1 && EXPERIMENTAL + depends on VIDEO_DEV && VIDEO_V4L2_COMMON select VIDEO_USBVIDEO ---help--- Say Y here if you have 3com homeconnect camera (vicam). diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 8a7aead..f11efbe 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -16,8 +16,6 @@ #include #include -#if defined(CONFIG_VIDEO_V4L1) || defined(CONFIG_VIDEO_V4L1_MODULE) || !defined(__KERNEL__) - #define VID_TYPE_CAPTURE 1 /* Can capture */ #define VID_TYPE_TUNER 2 /* Can tune */ #define VID_TYPE_TELETEXT 4 /* Does teletext */ @@ -311,8 +309,6 @@ struct video_code #define VID_PLAY_RESET 13 #define VID_PLAY_END_MARK 14 -#endif /* CONFIG_VIDEO_V4L1 */ - #endif /* __LINUX_VIDEODEV_H */ /* -- cgit v0.10.2 From 88ae7624a6fe890e5a8ca57b25420f66e1389f8b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 07:47:54 -0300 Subject: [media] V4L1 removal: Remove linux/videodev.h There's no sense on keeping it on 2.6.38, as nobody is using it anymore, at the kernel tree, and installing it at the userspace API. As two deprecated drivers still need it, move it to their internal directories. Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index d66ed2b..e348b7e 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -97,23 +97,6 @@ Who: Pavel Machek --------------------------- -What: Video4Linux API 1 ioctls and from Video devices. -When: kernel 2.6.39 -Files: include/linux/videodev.h -Check: include/linux/videodev.h -Why: V4L1 AP1 was replaced by V4L2 API during migration from 2.4 to 2.6 - series. The old API have lots of drawbacks and don't provide enough - means to work with all video and audio standards. The newer API is - already available on the main drivers and should be used instead. - - The userspace libv4l1 library can convert V4L1 calls to V4L2. This - replaces the kernel V4L1 compatibility module which was removed in - 2.6.38. The last V4L1 drivers will either be converted to V4L2 or - removed for 2.6.39 at which point the V4L1 API will cease to exist. -Who: Mauro Carvalho Chehab - ---------------------------- - What: Video4Linux obsolete drivers using V4L1 API When: kernel 2.6.39 Files: drivers/staging/se401/* drivers/staging/usbvideo/* diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index 425ac1e..65e6f13 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -15,7 +15,6 @@ #include #define __OLD_VIDIOC_ /* To allow fixing old calls*/ -#include #include #include #include diff --git a/drivers/staging/se401/se401.h b/drivers/staging/se401/se401.h index bf7d2e9..2758f47 100644 --- a/drivers/staging/se401/se401.h +++ b/drivers/staging/se401/se401.h @@ -3,7 +3,7 @@ #define __LINUX_se401_H #include -#include +#include "videodev.h" #include #include #include diff --git a/drivers/staging/se401/videodev.h b/drivers/staging/se401/videodev.h new file mode 100644 index 0000000..f11efbe --- /dev/null +++ b/drivers/staging/se401/videodev.h @@ -0,0 +1,318 @@ +/* + * Video for Linux version 1 - OBSOLETE + * + * Header file for v4l1 drivers and applications, for + * Linux kernels 2.2.x or 2.4.x. + * + * Provides header for legacy drivers and applications + * + * See http://linuxtv.org for more info + * + */ +#ifndef __LINUX_VIDEODEV_H +#define __LINUX_VIDEODEV_H + +#include +#include +#include + +#define VID_TYPE_CAPTURE 1 /* Can capture */ +#define VID_TYPE_TUNER 2 /* Can tune */ +#define VID_TYPE_TELETEXT 4 /* Does teletext */ +#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ +#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ +#define VID_TYPE_CLIPPING 32 /* Can clip */ +#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ +#define VID_TYPE_SCALES 128 /* Scalable */ +#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ +#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ +#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ +#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ +#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ +#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ + +struct video_capability +{ + char name[32]; + int type; + int channels; /* Num channels */ + int audios; /* Num audio devices */ + int maxwidth; /* Supported width */ + int maxheight; /* And height */ + int minwidth; /* Supported width */ + int minheight; /* And height */ +}; + + +struct video_channel +{ + int channel; + char name[32]; + int tuners; + __u32 flags; +#define VIDEO_VC_TUNER 1 /* Channel has a tuner */ +#define VIDEO_VC_AUDIO 2 /* Channel has audio */ + __u16 type; +#define VIDEO_TYPE_TV 1 +#define VIDEO_TYPE_CAMERA 2 + __u16 norm; /* Norm set by channel */ +}; + +struct video_tuner +{ + int tuner; + char name[32]; + unsigned long rangelow, rangehigh; /* Tuner range */ + __u32 flags; +#define VIDEO_TUNER_PAL 1 +#define VIDEO_TUNER_NTSC 2 +#define VIDEO_TUNER_SECAM 4 +#define VIDEO_TUNER_LOW 8 /* Uses KHz not MHz */ +#define VIDEO_TUNER_NORM 16 /* Tuner can set norm */ +#define VIDEO_TUNER_STEREO_ON 128 /* Tuner is seeing stereo */ +#define VIDEO_TUNER_RDS_ON 256 /* Tuner is seeing an RDS datastream */ +#define VIDEO_TUNER_MBS_ON 512 /* Tuner is seeing an MBS datastream */ + __u16 mode; /* PAL/NTSC/SECAM/OTHER */ +#define VIDEO_MODE_PAL 0 +#define VIDEO_MODE_NTSC 1 +#define VIDEO_MODE_SECAM 2 +#define VIDEO_MODE_AUTO 3 + __u16 signal; /* Signal strength 16bit scale */ +}; + +struct video_picture +{ + __u16 brightness; + __u16 hue; + __u16 colour; + __u16 contrast; + __u16 whiteness; /* Black and white only */ + __u16 depth; /* Capture depth */ + __u16 palette; /* Palette in use */ +#define VIDEO_PALETTE_GREY 1 /* Linear greyscale */ +#define VIDEO_PALETTE_HI240 2 /* High 240 cube (BT848) */ +#define VIDEO_PALETTE_RGB565 3 /* 565 16 bit RGB */ +#define VIDEO_PALETTE_RGB24 4 /* 24bit RGB */ +#define VIDEO_PALETTE_RGB32 5 /* 32bit RGB */ +#define VIDEO_PALETTE_RGB555 6 /* 555 15bit RGB */ +#define VIDEO_PALETTE_YUV422 7 /* YUV422 capture */ +#define VIDEO_PALETTE_YUYV 8 +#define VIDEO_PALETTE_UYVY 9 /* The great thing about standards is ... */ +#define VIDEO_PALETTE_YUV420 10 +#define VIDEO_PALETTE_YUV411 11 /* YUV411 capture */ +#define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */ +#define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */ +#define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */ +#define VIDEO_PALETTE_YUV420P 15 /* YUV 4:2:0 Planar */ +#define VIDEO_PALETTE_YUV410P 16 /* YUV 4:1:0 Planar */ +#define VIDEO_PALETTE_PLANAR 13 /* start of planar entries */ +#define VIDEO_PALETTE_COMPONENT 7 /* start of component entries */ +}; + +struct video_audio +{ + int audio; /* Audio channel */ + __u16 volume; /* If settable */ + __u16 bass, treble; + __u32 flags; +#define VIDEO_AUDIO_MUTE 1 +#define VIDEO_AUDIO_MUTABLE 2 +#define VIDEO_AUDIO_VOLUME 4 +#define VIDEO_AUDIO_BASS 8 +#define VIDEO_AUDIO_TREBLE 16 +#define VIDEO_AUDIO_BALANCE 32 + char name[16]; +#define VIDEO_SOUND_MONO 1 +#define VIDEO_SOUND_STEREO 2 +#define VIDEO_SOUND_LANG1 4 +#define VIDEO_SOUND_LANG2 8 + __u16 mode; + __u16 balance; /* Stereo balance */ + __u16 step; /* Step actual volume uses */ +}; + +struct video_clip +{ + __s32 x,y; + __s32 width, height; + struct video_clip *next; /* For user use/driver use only */ +}; + +struct video_window +{ + __u32 x,y; /* Position of window */ + __u32 width,height; /* Its size */ + __u32 chromakey; + __u32 flags; + struct video_clip __user *clips; /* Set only */ + int clipcount; +#define VIDEO_WINDOW_INTERLACE 1 +#define VIDEO_WINDOW_CHROMAKEY 16 /* Overlay by chromakey */ +#define VIDEO_CLIP_BITMAP -1 +/* bitmap is 1024x625, a '1' bit represents a clipped pixel */ +#define VIDEO_CLIPMAP_SIZE (128 * 625) +}; + +struct video_capture +{ + __u32 x,y; /* Offsets into image */ + __u32 width, height; /* Area to capture */ + __u16 decimation; /* Decimation divider */ + __u16 flags; /* Flags for capture */ +#define VIDEO_CAPTURE_ODD 0 /* Temporal */ +#define VIDEO_CAPTURE_EVEN 1 +}; + +struct video_buffer +{ + void *base; + int height,width; + int depth; + int bytesperline; +}; + +struct video_mmap +{ + unsigned int frame; /* Frame (0 - n) for double buffer */ + int height,width; + unsigned int format; /* should be VIDEO_PALETTE_* */ +}; + +struct video_key +{ + __u8 key[8]; + __u32 flags; +}; + +struct video_mbuf +{ + int size; /* Total memory to map */ + int frames; /* Frames */ + int offsets[VIDEO_MAX_FRAME]; +}; + +#define VIDEO_NO_UNIT (-1) + +struct video_unit +{ + int video; /* Video minor */ + int vbi; /* VBI minor */ + int radio; /* Radio minor */ + int audio; /* Audio minor */ + int teletext; /* Teletext minor */ +}; + +struct vbi_format { + __u32 sampling_rate; /* in Hz */ + __u32 samples_per_line; + __u32 sample_format; /* VIDEO_PALETTE_RAW only (1 byte) */ + __s32 start[2]; /* starting line for each frame */ + __u32 count[2]; /* count of lines for each frame */ + __u32 flags; +#define VBI_UNSYNC 1 /* can distingues between top/bottom field */ +#define VBI_INTERLACED 2 /* lines are interlaced */ +}; + +/* video_info is biased towards hardware mpeg encode/decode */ +/* but it could apply generically to any hardware compressor/decompressor */ +struct video_info +{ + __u32 frame_count; /* frames output since decode/encode began */ + __u32 h_size; /* current unscaled horizontal size */ + __u32 v_size; /* current unscaled veritcal size */ + __u32 smpte_timecode; /* current SMPTE timecode (for current GOP) */ + __u32 picture_type; /* current picture type */ + __u32 temporal_reference; /* current temporal reference */ + __u8 user_data[256]; /* user data last found in compressed stream */ + /* user_data[0] contains user data flags, user_data[1] has count */ +}; + +/* generic structure for setting playback modes */ +struct video_play_mode +{ + int mode; + int p1; + int p2; +}; + +/* for loading microcode / fpga programming */ +struct video_code +{ + char loadwhat[16]; /* name or tag of file being passed */ + int datasize; + __u8 *data; +}; + +#define VIDIOCGCAP _IOR('v',1,struct video_capability) /* Get capabilities */ +#define VIDIOCGCHAN _IOWR('v',2,struct video_channel) /* Get channel info (sources) */ +#define VIDIOCSCHAN _IOW('v',3,struct video_channel) /* Set channel */ +#define VIDIOCGTUNER _IOWR('v',4,struct video_tuner) /* Get tuner abilities */ +#define VIDIOCSTUNER _IOW('v',5,struct video_tuner) /* Tune the tuner for the current channel */ +#define VIDIOCGPICT _IOR('v',6,struct video_picture) /* Get picture properties */ +#define VIDIOCSPICT _IOW('v',7,struct video_picture) /* Set picture properties */ +#define VIDIOCCAPTURE _IOW('v',8,int) /* Start, end capture */ +#define VIDIOCGWIN _IOR('v',9, struct video_window) /* Get the video overlay window */ +#define VIDIOCSWIN _IOW('v',10, struct video_window) /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */ +#define VIDIOCGFBUF _IOR('v',11, struct video_buffer) /* Get frame buffer */ +#define VIDIOCSFBUF _IOW('v',12, struct video_buffer) /* Set frame buffer - root only */ +#define VIDIOCKEY _IOR('v',13, struct video_key) /* Video key event - to dev 255 is to all - cuts capture on all DMA windows with this key (0xFFFFFFFF == all) */ +#define VIDIOCGFREQ _IOR('v',14, unsigned long) /* Set tuner */ +#define VIDIOCSFREQ _IOW('v',15, unsigned long) /* Set tuner */ +#define VIDIOCGAUDIO _IOR('v',16, struct video_audio) /* Get audio info */ +#define VIDIOCSAUDIO _IOW('v',17, struct video_audio) /* Audio source, mute etc */ +#define VIDIOCSYNC _IOW('v',18, int) /* Sync with mmap grabbing */ +#define VIDIOCMCAPTURE _IOW('v',19, struct video_mmap) /* Grab frames */ +#define VIDIOCGMBUF _IOR('v',20, struct video_mbuf) /* Memory map buffer info */ +#define VIDIOCGUNIT _IOR('v',21, struct video_unit) /* Get attached units */ +#define VIDIOCGCAPTURE _IOR('v',22, struct video_capture) /* Get subcapture */ +#define VIDIOCSCAPTURE _IOW('v',23, struct video_capture) /* Set subcapture */ +#define VIDIOCSPLAYMODE _IOW('v',24, struct video_play_mode) /* Set output video mode/feature */ +#define VIDIOCSWRITEMODE _IOW('v',25, int) /* Set write mode */ +#define VIDIOCGPLAYINFO _IOR('v',26, struct video_info) /* Get current playback info from hardware */ +#define VIDIOCSMICROCODE _IOW('v',27, struct video_code) /* Load microcode into hardware */ +#define VIDIOCGVBIFMT _IOR('v',28, struct vbi_format) /* Get VBI information */ +#define VIDIOCSVBIFMT _IOW('v',29, struct vbi_format) /* Set VBI information */ + + +#define BASE_VIDIOCPRIVATE 192 /* 192-255 are private */ + +/* VIDIOCSWRITEMODE */ +#define VID_WRITE_MPEG_AUD 0 +#define VID_WRITE_MPEG_VID 1 +#define VID_WRITE_OSD 2 +#define VID_WRITE_TTX 3 +#define VID_WRITE_CC 4 +#define VID_WRITE_MJPEG 5 + +/* VIDIOCSPLAYMODE */ +#define VID_PLAY_VID_OUT_MODE 0 + /* p1: = VIDEO_MODE_PAL, VIDEO_MODE_NTSC, etc ... */ +#define VID_PLAY_GENLOCK 1 + /* p1: 0 = OFF, 1 = ON */ + /* p2: GENLOCK FINE DELAY value */ +#define VID_PLAY_NORMAL 2 +#define VID_PLAY_PAUSE 3 +#define VID_PLAY_SINGLE_FRAME 4 +#define VID_PLAY_FAST_FORWARD 5 +#define VID_PLAY_SLOW_MOTION 6 +#define VID_PLAY_IMMEDIATE_NORMAL 7 +#define VID_PLAY_SWITCH_CHANNELS 8 +#define VID_PLAY_FREEZE_FRAME 9 +#define VID_PLAY_STILL_MODE 10 +#define VID_PLAY_MASTER_MODE 11 + /* p1: see below */ +#define VID_PLAY_MASTER_NONE 1 +#define VID_PLAY_MASTER_VIDEO 2 +#define VID_PLAY_MASTER_AUDIO 3 +#define VID_PLAY_ACTIVE_SCANLINES 12 + /* p1 = first active; p2 = last active */ +#define VID_PLAY_RESET 13 +#define VID_PLAY_END_MARK 14 + +#endif /* __LINUX_VIDEODEV_H */ + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/staging/usbvideo/usbvideo.h b/drivers/staging/usbvideo/usbvideo.h index c66985b..95638a0 100644 --- a/drivers/staging/usbvideo/usbvideo.h +++ b/drivers/staging/usbvideo/usbvideo.h @@ -16,7 +16,7 @@ #ifndef usbvideo_h #define usbvideo_h -#include +#include "videodev.h" #include #include #include diff --git a/drivers/staging/usbvideo/vicam.c b/drivers/staging/usbvideo/vicam.c index dc17cce..ecdb121 100644 --- a/drivers/staging/usbvideo/vicam.c +++ b/drivers/staging/usbvideo/vicam.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include "videodev.h" #include #include #include diff --git a/drivers/staging/usbvideo/videodev.h b/drivers/staging/usbvideo/videodev.h new file mode 100644 index 0000000..f11efbe --- /dev/null +++ b/drivers/staging/usbvideo/videodev.h @@ -0,0 +1,318 @@ +/* + * Video for Linux version 1 - OBSOLETE + * + * Header file for v4l1 drivers and applications, for + * Linux kernels 2.2.x or 2.4.x. + * + * Provides header for legacy drivers and applications + * + * See http://linuxtv.org for more info + * + */ +#ifndef __LINUX_VIDEODEV_H +#define __LINUX_VIDEODEV_H + +#include +#include +#include + +#define VID_TYPE_CAPTURE 1 /* Can capture */ +#define VID_TYPE_TUNER 2 /* Can tune */ +#define VID_TYPE_TELETEXT 4 /* Does teletext */ +#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ +#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ +#define VID_TYPE_CLIPPING 32 /* Can clip */ +#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ +#define VID_TYPE_SCALES 128 /* Scalable */ +#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ +#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ +#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ +#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ +#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ +#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ + +struct video_capability +{ + char name[32]; + int type; + int channels; /* Num channels */ + int audios; /* Num audio devices */ + int maxwidth; /* Supported width */ + int maxheight; /* And height */ + int minwidth; /* Supported width */ + int minheight; /* And height */ +}; + + +struct video_channel +{ + int channel; + char name[32]; + int tuners; + __u32 flags; +#define VIDEO_VC_TUNER 1 /* Channel has a tuner */ +#define VIDEO_VC_AUDIO 2 /* Channel has audio */ + __u16 type; +#define VIDEO_TYPE_TV 1 +#define VIDEO_TYPE_CAMERA 2 + __u16 norm; /* Norm set by channel */ +}; + +struct video_tuner +{ + int tuner; + char name[32]; + unsigned long rangelow, rangehigh; /* Tuner range */ + __u32 flags; +#define VIDEO_TUNER_PAL 1 +#define VIDEO_TUNER_NTSC 2 +#define VIDEO_TUNER_SECAM 4 +#define VIDEO_TUNER_LOW 8 /* Uses KHz not MHz */ +#define VIDEO_TUNER_NORM 16 /* Tuner can set norm */ +#define VIDEO_TUNER_STEREO_ON 128 /* Tuner is seeing stereo */ +#define VIDEO_TUNER_RDS_ON 256 /* Tuner is seeing an RDS datastream */ +#define VIDEO_TUNER_MBS_ON 512 /* Tuner is seeing an MBS datastream */ + __u16 mode; /* PAL/NTSC/SECAM/OTHER */ +#define VIDEO_MODE_PAL 0 +#define VIDEO_MODE_NTSC 1 +#define VIDEO_MODE_SECAM 2 +#define VIDEO_MODE_AUTO 3 + __u16 signal; /* Signal strength 16bit scale */ +}; + +struct video_picture +{ + __u16 brightness; + __u16 hue; + __u16 colour; + __u16 contrast; + __u16 whiteness; /* Black and white only */ + __u16 depth; /* Capture depth */ + __u16 palette; /* Palette in use */ +#define VIDEO_PALETTE_GREY 1 /* Linear greyscale */ +#define VIDEO_PALETTE_HI240 2 /* High 240 cube (BT848) */ +#define VIDEO_PALETTE_RGB565 3 /* 565 16 bit RGB */ +#define VIDEO_PALETTE_RGB24 4 /* 24bit RGB */ +#define VIDEO_PALETTE_RGB32 5 /* 32bit RGB */ +#define VIDEO_PALETTE_RGB555 6 /* 555 15bit RGB */ +#define VIDEO_PALETTE_YUV422 7 /* YUV422 capture */ +#define VIDEO_PALETTE_YUYV 8 +#define VIDEO_PALETTE_UYVY 9 /* The great thing about standards is ... */ +#define VIDEO_PALETTE_YUV420 10 +#define VIDEO_PALETTE_YUV411 11 /* YUV411 capture */ +#define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */ +#define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */ +#define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */ +#define VIDEO_PALETTE_YUV420P 15 /* YUV 4:2:0 Planar */ +#define VIDEO_PALETTE_YUV410P 16 /* YUV 4:1:0 Planar */ +#define VIDEO_PALETTE_PLANAR 13 /* start of planar entries */ +#define VIDEO_PALETTE_COMPONENT 7 /* start of component entries */ +}; + +struct video_audio +{ + int audio; /* Audio channel */ + __u16 volume; /* If settable */ + __u16 bass, treble; + __u32 flags; +#define VIDEO_AUDIO_MUTE 1 +#define VIDEO_AUDIO_MUTABLE 2 +#define VIDEO_AUDIO_VOLUME 4 +#define VIDEO_AUDIO_BASS 8 +#define VIDEO_AUDIO_TREBLE 16 +#define VIDEO_AUDIO_BALANCE 32 + char name[16]; +#define VIDEO_SOUND_MONO 1 +#define VIDEO_SOUND_STEREO 2 +#define VIDEO_SOUND_LANG1 4 +#define VIDEO_SOUND_LANG2 8 + __u16 mode; + __u16 balance; /* Stereo balance */ + __u16 step; /* Step actual volume uses */ +}; + +struct video_clip +{ + __s32 x,y; + __s32 width, height; + struct video_clip *next; /* For user use/driver use only */ +}; + +struct video_window +{ + __u32 x,y; /* Position of window */ + __u32 width,height; /* Its size */ + __u32 chromakey; + __u32 flags; + struct video_clip __user *clips; /* Set only */ + int clipcount; +#define VIDEO_WINDOW_INTERLACE 1 +#define VIDEO_WINDOW_CHROMAKEY 16 /* Overlay by chromakey */ +#define VIDEO_CLIP_BITMAP -1 +/* bitmap is 1024x625, a '1' bit represents a clipped pixel */ +#define VIDEO_CLIPMAP_SIZE (128 * 625) +}; + +struct video_capture +{ + __u32 x,y; /* Offsets into image */ + __u32 width, height; /* Area to capture */ + __u16 decimation; /* Decimation divider */ + __u16 flags; /* Flags for capture */ +#define VIDEO_CAPTURE_ODD 0 /* Temporal */ +#define VIDEO_CAPTURE_EVEN 1 +}; + +struct video_buffer +{ + void *base; + int height,width; + int depth; + int bytesperline; +}; + +struct video_mmap +{ + unsigned int frame; /* Frame (0 - n) for double buffer */ + int height,width; + unsigned int format; /* should be VIDEO_PALETTE_* */ +}; + +struct video_key +{ + __u8 key[8]; + __u32 flags; +}; + +struct video_mbuf +{ + int size; /* Total memory to map */ + int frames; /* Frames */ + int offsets[VIDEO_MAX_FRAME]; +}; + +#define VIDEO_NO_UNIT (-1) + +struct video_unit +{ + int video; /* Video minor */ + int vbi; /* VBI minor */ + int radio; /* Radio minor */ + int audio; /* Audio minor */ + int teletext; /* Teletext minor */ +}; + +struct vbi_format { + __u32 sampling_rate; /* in Hz */ + __u32 samples_per_line; + __u32 sample_format; /* VIDEO_PALETTE_RAW only (1 byte) */ + __s32 start[2]; /* starting line for each frame */ + __u32 count[2]; /* count of lines for each frame */ + __u32 flags; +#define VBI_UNSYNC 1 /* can distingues between top/bottom field */ +#define VBI_INTERLACED 2 /* lines are interlaced */ +}; + +/* video_info is biased towards hardware mpeg encode/decode */ +/* but it could apply generically to any hardware compressor/decompressor */ +struct video_info +{ + __u32 frame_count; /* frames output since decode/encode began */ + __u32 h_size; /* current unscaled horizontal size */ + __u32 v_size; /* current unscaled veritcal size */ + __u32 smpte_timecode; /* current SMPTE timecode (for current GOP) */ + __u32 picture_type; /* current picture type */ + __u32 temporal_reference; /* current temporal reference */ + __u8 user_data[256]; /* user data last found in compressed stream */ + /* user_data[0] contains user data flags, user_data[1] has count */ +}; + +/* generic structure for setting playback modes */ +struct video_play_mode +{ + int mode; + int p1; + int p2; +}; + +/* for loading microcode / fpga programming */ +struct video_code +{ + char loadwhat[16]; /* name or tag of file being passed */ + int datasize; + __u8 *data; +}; + +#define VIDIOCGCAP _IOR('v',1,struct video_capability) /* Get capabilities */ +#define VIDIOCGCHAN _IOWR('v',2,struct video_channel) /* Get channel info (sources) */ +#define VIDIOCSCHAN _IOW('v',3,struct video_channel) /* Set channel */ +#define VIDIOCGTUNER _IOWR('v',4,struct video_tuner) /* Get tuner abilities */ +#define VIDIOCSTUNER _IOW('v',5,struct video_tuner) /* Tune the tuner for the current channel */ +#define VIDIOCGPICT _IOR('v',6,struct video_picture) /* Get picture properties */ +#define VIDIOCSPICT _IOW('v',7,struct video_picture) /* Set picture properties */ +#define VIDIOCCAPTURE _IOW('v',8,int) /* Start, end capture */ +#define VIDIOCGWIN _IOR('v',9, struct video_window) /* Get the video overlay window */ +#define VIDIOCSWIN _IOW('v',10, struct video_window) /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */ +#define VIDIOCGFBUF _IOR('v',11, struct video_buffer) /* Get frame buffer */ +#define VIDIOCSFBUF _IOW('v',12, struct video_buffer) /* Set frame buffer - root only */ +#define VIDIOCKEY _IOR('v',13, struct video_key) /* Video key event - to dev 255 is to all - cuts capture on all DMA windows with this key (0xFFFFFFFF == all) */ +#define VIDIOCGFREQ _IOR('v',14, unsigned long) /* Set tuner */ +#define VIDIOCSFREQ _IOW('v',15, unsigned long) /* Set tuner */ +#define VIDIOCGAUDIO _IOR('v',16, struct video_audio) /* Get audio info */ +#define VIDIOCSAUDIO _IOW('v',17, struct video_audio) /* Audio source, mute etc */ +#define VIDIOCSYNC _IOW('v',18, int) /* Sync with mmap grabbing */ +#define VIDIOCMCAPTURE _IOW('v',19, struct video_mmap) /* Grab frames */ +#define VIDIOCGMBUF _IOR('v',20, struct video_mbuf) /* Memory map buffer info */ +#define VIDIOCGUNIT _IOR('v',21, struct video_unit) /* Get attached units */ +#define VIDIOCGCAPTURE _IOR('v',22, struct video_capture) /* Get subcapture */ +#define VIDIOCSCAPTURE _IOW('v',23, struct video_capture) /* Set subcapture */ +#define VIDIOCSPLAYMODE _IOW('v',24, struct video_play_mode) /* Set output video mode/feature */ +#define VIDIOCSWRITEMODE _IOW('v',25, int) /* Set write mode */ +#define VIDIOCGPLAYINFO _IOR('v',26, struct video_info) /* Get current playback info from hardware */ +#define VIDIOCSMICROCODE _IOW('v',27, struct video_code) /* Load microcode into hardware */ +#define VIDIOCGVBIFMT _IOR('v',28, struct vbi_format) /* Get VBI information */ +#define VIDIOCSVBIFMT _IOW('v',29, struct vbi_format) /* Set VBI information */ + + +#define BASE_VIDIOCPRIVATE 192 /* 192-255 are private */ + +/* VIDIOCSWRITEMODE */ +#define VID_WRITE_MPEG_AUD 0 +#define VID_WRITE_MPEG_VID 1 +#define VID_WRITE_OSD 2 +#define VID_WRITE_TTX 3 +#define VID_WRITE_CC 4 +#define VID_WRITE_MJPEG 5 + +/* VIDIOCSPLAYMODE */ +#define VID_PLAY_VID_OUT_MODE 0 + /* p1: = VIDEO_MODE_PAL, VIDEO_MODE_NTSC, etc ... */ +#define VID_PLAY_GENLOCK 1 + /* p1: 0 = OFF, 1 = ON */ + /* p2: GENLOCK FINE DELAY value */ +#define VID_PLAY_NORMAL 2 +#define VID_PLAY_PAUSE 3 +#define VID_PLAY_SINGLE_FRAME 4 +#define VID_PLAY_FAST_FORWARD 5 +#define VID_PLAY_SLOW_MOTION 6 +#define VID_PLAY_IMMEDIATE_NORMAL 7 +#define VID_PLAY_SWITCH_CHANNELS 8 +#define VID_PLAY_FREEZE_FRAME 9 +#define VID_PLAY_STILL_MODE 10 +#define VID_PLAY_MASTER_MODE 11 + /* p1: see below */ +#define VID_PLAY_MASTER_NONE 1 +#define VID_PLAY_MASTER_VIDEO 2 +#define VID_PLAY_MASTER_AUDIO 3 +#define VID_PLAY_ACTIVE_SCANLINES 12 + /* p1 = first active; p2 = last active */ +#define VID_PLAY_RESET 13 +#define VID_PLAY_END_MARK 14 + +#endif /* __LINUX_VIDEODEV_H */ + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index a60579b..175736c 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 97319a8..a354c19 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -367,7 +367,6 @@ header-y += utime.h header-y += utsname.h header-y += veth.h header-y += vhost.h -header-y += videodev.h header-y += videodev2.h header-y += virtio_9p.h header-y += virtio_balloon.h diff --git a/include/linux/videodev.h b/include/linux/videodev.h deleted file mode 100644 index f11efbe..0000000 --- a/include/linux/videodev.h +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Video for Linux version 1 - OBSOLETE - * - * Header file for v4l1 drivers and applications, for - * Linux kernels 2.2.x or 2.4.x. - * - * Provides header for legacy drivers and applications - * - * See http://linuxtv.org for more info - * - */ -#ifndef __LINUX_VIDEODEV_H -#define __LINUX_VIDEODEV_H - -#include -#include -#include - -#define VID_TYPE_CAPTURE 1 /* Can capture */ -#define VID_TYPE_TUNER 2 /* Can tune */ -#define VID_TYPE_TELETEXT 4 /* Does teletext */ -#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ -#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ -#define VID_TYPE_CLIPPING 32 /* Can clip */ -#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ -#define VID_TYPE_SCALES 128 /* Scalable */ -#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ -#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ -#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ -#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ -#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ -#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ - -struct video_capability -{ - char name[32]; - int type; - int channels; /* Num channels */ - int audios; /* Num audio devices */ - int maxwidth; /* Supported width */ - int maxheight; /* And height */ - int minwidth; /* Supported width */ - int minheight; /* And height */ -}; - - -struct video_channel -{ - int channel; - char name[32]; - int tuners; - __u32 flags; -#define VIDEO_VC_TUNER 1 /* Channel has a tuner */ -#define VIDEO_VC_AUDIO 2 /* Channel has audio */ - __u16 type; -#define VIDEO_TYPE_TV 1 -#define VIDEO_TYPE_CAMERA 2 - __u16 norm; /* Norm set by channel */ -}; - -struct video_tuner -{ - int tuner; - char name[32]; - unsigned long rangelow, rangehigh; /* Tuner range */ - __u32 flags; -#define VIDEO_TUNER_PAL 1 -#define VIDEO_TUNER_NTSC 2 -#define VIDEO_TUNER_SECAM 4 -#define VIDEO_TUNER_LOW 8 /* Uses KHz not MHz */ -#define VIDEO_TUNER_NORM 16 /* Tuner can set norm */ -#define VIDEO_TUNER_STEREO_ON 128 /* Tuner is seeing stereo */ -#define VIDEO_TUNER_RDS_ON 256 /* Tuner is seeing an RDS datastream */ -#define VIDEO_TUNER_MBS_ON 512 /* Tuner is seeing an MBS datastream */ - __u16 mode; /* PAL/NTSC/SECAM/OTHER */ -#define VIDEO_MODE_PAL 0 -#define VIDEO_MODE_NTSC 1 -#define VIDEO_MODE_SECAM 2 -#define VIDEO_MODE_AUTO 3 - __u16 signal; /* Signal strength 16bit scale */ -}; - -struct video_picture -{ - __u16 brightness; - __u16 hue; - __u16 colour; - __u16 contrast; - __u16 whiteness; /* Black and white only */ - __u16 depth; /* Capture depth */ - __u16 palette; /* Palette in use */ -#define VIDEO_PALETTE_GREY 1 /* Linear greyscale */ -#define VIDEO_PALETTE_HI240 2 /* High 240 cube (BT848) */ -#define VIDEO_PALETTE_RGB565 3 /* 565 16 bit RGB */ -#define VIDEO_PALETTE_RGB24 4 /* 24bit RGB */ -#define VIDEO_PALETTE_RGB32 5 /* 32bit RGB */ -#define VIDEO_PALETTE_RGB555 6 /* 555 15bit RGB */ -#define VIDEO_PALETTE_YUV422 7 /* YUV422 capture */ -#define VIDEO_PALETTE_YUYV 8 -#define VIDEO_PALETTE_UYVY 9 /* The great thing about standards is ... */ -#define VIDEO_PALETTE_YUV420 10 -#define VIDEO_PALETTE_YUV411 11 /* YUV411 capture */ -#define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */ -#define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */ -#define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */ -#define VIDEO_PALETTE_YUV420P 15 /* YUV 4:2:0 Planar */ -#define VIDEO_PALETTE_YUV410P 16 /* YUV 4:1:0 Planar */ -#define VIDEO_PALETTE_PLANAR 13 /* start of planar entries */ -#define VIDEO_PALETTE_COMPONENT 7 /* start of component entries */ -}; - -struct video_audio -{ - int audio; /* Audio channel */ - __u16 volume; /* If settable */ - __u16 bass, treble; - __u32 flags; -#define VIDEO_AUDIO_MUTE 1 -#define VIDEO_AUDIO_MUTABLE 2 -#define VIDEO_AUDIO_VOLUME 4 -#define VIDEO_AUDIO_BASS 8 -#define VIDEO_AUDIO_TREBLE 16 -#define VIDEO_AUDIO_BALANCE 32 - char name[16]; -#define VIDEO_SOUND_MONO 1 -#define VIDEO_SOUND_STEREO 2 -#define VIDEO_SOUND_LANG1 4 -#define VIDEO_SOUND_LANG2 8 - __u16 mode; - __u16 balance; /* Stereo balance */ - __u16 step; /* Step actual volume uses */ -}; - -struct video_clip -{ - __s32 x,y; - __s32 width, height; - struct video_clip *next; /* For user use/driver use only */ -}; - -struct video_window -{ - __u32 x,y; /* Position of window */ - __u32 width,height; /* Its size */ - __u32 chromakey; - __u32 flags; - struct video_clip __user *clips; /* Set only */ - int clipcount; -#define VIDEO_WINDOW_INTERLACE 1 -#define VIDEO_WINDOW_CHROMAKEY 16 /* Overlay by chromakey */ -#define VIDEO_CLIP_BITMAP -1 -/* bitmap is 1024x625, a '1' bit represents a clipped pixel */ -#define VIDEO_CLIPMAP_SIZE (128 * 625) -}; - -struct video_capture -{ - __u32 x,y; /* Offsets into image */ - __u32 width, height; /* Area to capture */ - __u16 decimation; /* Decimation divider */ - __u16 flags; /* Flags for capture */ -#define VIDEO_CAPTURE_ODD 0 /* Temporal */ -#define VIDEO_CAPTURE_EVEN 1 -}; - -struct video_buffer -{ - void *base; - int height,width; - int depth; - int bytesperline; -}; - -struct video_mmap -{ - unsigned int frame; /* Frame (0 - n) for double buffer */ - int height,width; - unsigned int format; /* should be VIDEO_PALETTE_* */ -}; - -struct video_key -{ - __u8 key[8]; - __u32 flags; -}; - -struct video_mbuf -{ - int size; /* Total memory to map */ - int frames; /* Frames */ - int offsets[VIDEO_MAX_FRAME]; -}; - -#define VIDEO_NO_UNIT (-1) - -struct video_unit -{ - int video; /* Video minor */ - int vbi; /* VBI minor */ - int radio; /* Radio minor */ - int audio; /* Audio minor */ - int teletext; /* Teletext minor */ -}; - -struct vbi_format { - __u32 sampling_rate; /* in Hz */ - __u32 samples_per_line; - __u32 sample_format; /* VIDEO_PALETTE_RAW only (1 byte) */ - __s32 start[2]; /* starting line for each frame */ - __u32 count[2]; /* count of lines for each frame */ - __u32 flags; -#define VBI_UNSYNC 1 /* can distingues between top/bottom field */ -#define VBI_INTERLACED 2 /* lines are interlaced */ -}; - -/* video_info is biased towards hardware mpeg encode/decode */ -/* but it could apply generically to any hardware compressor/decompressor */ -struct video_info -{ - __u32 frame_count; /* frames output since decode/encode began */ - __u32 h_size; /* current unscaled horizontal size */ - __u32 v_size; /* current unscaled veritcal size */ - __u32 smpte_timecode; /* current SMPTE timecode (for current GOP) */ - __u32 picture_type; /* current picture type */ - __u32 temporal_reference; /* current temporal reference */ - __u8 user_data[256]; /* user data last found in compressed stream */ - /* user_data[0] contains user data flags, user_data[1] has count */ -}; - -/* generic structure for setting playback modes */ -struct video_play_mode -{ - int mode; - int p1; - int p2; -}; - -/* for loading microcode / fpga programming */ -struct video_code -{ - char loadwhat[16]; /* name or tag of file being passed */ - int datasize; - __u8 *data; -}; - -#define VIDIOCGCAP _IOR('v',1,struct video_capability) /* Get capabilities */ -#define VIDIOCGCHAN _IOWR('v',2,struct video_channel) /* Get channel info (sources) */ -#define VIDIOCSCHAN _IOW('v',3,struct video_channel) /* Set channel */ -#define VIDIOCGTUNER _IOWR('v',4,struct video_tuner) /* Get tuner abilities */ -#define VIDIOCSTUNER _IOW('v',5,struct video_tuner) /* Tune the tuner for the current channel */ -#define VIDIOCGPICT _IOR('v',6,struct video_picture) /* Get picture properties */ -#define VIDIOCSPICT _IOW('v',7,struct video_picture) /* Set picture properties */ -#define VIDIOCCAPTURE _IOW('v',8,int) /* Start, end capture */ -#define VIDIOCGWIN _IOR('v',9, struct video_window) /* Get the video overlay window */ -#define VIDIOCSWIN _IOW('v',10, struct video_window) /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */ -#define VIDIOCGFBUF _IOR('v',11, struct video_buffer) /* Get frame buffer */ -#define VIDIOCSFBUF _IOW('v',12, struct video_buffer) /* Set frame buffer - root only */ -#define VIDIOCKEY _IOR('v',13, struct video_key) /* Video key event - to dev 255 is to all - cuts capture on all DMA windows with this key (0xFFFFFFFF == all) */ -#define VIDIOCGFREQ _IOR('v',14, unsigned long) /* Set tuner */ -#define VIDIOCSFREQ _IOW('v',15, unsigned long) /* Set tuner */ -#define VIDIOCGAUDIO _IOR('v',16, struct video_audio) /* Get audio info */ -#define VIDIOCSAUDIO _IOW('v',17, struct video_audio) /* Audio source, mute etc */ -#define VIDIOCSYNC _IOW('v',18, int) /* Sync with mmap grabbing */ -#define VIDIOCMCAPTURE _IOW('v',19, struct video_mmap) /* Grab frames */ -#define VIDIOCGMBUF _IOR('v',20, struct video_mbuf) /* Memory map buffer info */ -#define VIDIOCGUNIT _IOR('v',21, struct video_unit) /* Get attached units */ -#define VIDIOCGCAPTURE _IOR('v',22, struct video_capture) /* Get subcapture */ -#define VIDIOCSCAPTURE _IOW('v',23, struct video_capture) /* Set subcapture */ -#define VIDIOCSPLAYMODE _IOW('v',24, struct video_play_mode) /* Set output video mode/feature */ -#define VIDIOCSWRITEMODE _IOW('v',25, int) /* Set write mode */ -#define VIDIOCGPLAYINFO _IOR('v',26, struct video_info) /* Get current playback info from hardware */ -#define VIDIOCSMICROCODE _IOW('v',27, struct video_code) /* Load microcode into hardware */ -#define VIDIOCGVBIFMT _IOR('v',28, struct vbi_format) /* Get VBI information */ -#define VIDIOCSVBIFMT _IOW('v',29, struct vbi_format) /* Set VBI information */ - - -#define BASE_VIDIOCPRIVATE 192 /* 192-255 are private */ - -/* VIDIOCSWRITEMODE */ -#define VID_WRITE_MPEG_AUD 0 -#define VID_WRITE_MPEG_VID 1 -#define VID_WRITE_OSD 2 -#define VID_WRITE_TTX 3 -#define VID_WRITE_CC 4 -#define VID_WRITE_MJPEG 5 - -/* VIDIOCSPLAYMODE */ -#define VID_PLAY_VID_OUT_MODE 0 - /* p1: = VIDEO_MODE_PAL, VIDEO_MODE_NTSC, etc ... */ -#define VID_PLAY_GENLOCK 1 - /* p1: 0 = OFF, 1 = ON */ - /* p2: GENLOCK FINE DELAY value */ -#define VID_PLAY_NORMAL 2 -#define VID_PLAY_PAUSE 3 -#define VID_PLAY_SINGLE_FRAME 4 -#define VID_PLAY_FAST_FORWARD 5 -#define VID_PLAY_SLOW_MOTION 6 -#define VID_PLAY_IMMEDIATE_NORMAL 7 -#define VID_PLAY_SWITCH_CHANNELS 8 -#define VID_PLAY_FREEZE_FRAME 9 -#define VID_PLAY_STILL_MODE 10 -#define VID_PLAY_MASTER_MODE 11 - /* p1: see below */ -#define VID_PLAY_MASTER_NONE 1 -#define VID_PLAY_MASTER_VIDEO 2 -#define VID_PLAY_MASTER_AUDIO 3 -#define VID_PLAY_ACTIVE_SCANLINES 12 - /* p1 = first active; p2 = last active */ -#define VID_PLAY_RESET 13 -#define VID_PLAY_END_MARK 14 - -#endif /* __LINUX_VIDEODEV_H */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/include/media/ovcamchip.h b/include/media/ovcamchip.h deleted file mode 100644 index 05b9569..0000000 --- a/include/media/ovcamchip.h +++ /dev/null @@ -1,90 +0,0 @@ -/* OmniVision* camera chip driver API - * - * Copyright (c) 1999-2004 Mark McClelland - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied. - * - * * OmniVision is a trademark of OmniVision Technologies, Inc. This driver - * is not sponsored or developed by them. - */ - -#ifndef __LINUX_OVCAMCHIP_H -#define __LINUX_OVCAMCHIP_H - -#include -#include - -/* --------------------------------- */ -/* ENUMERATIONS */ -/* --------------------------------- */ - -/* Controls */ -enum { - OVCAMCHIP_CID_CONT, /* Contrast */ - OVCAMCHIP_CID_BRIGHT, /* Brightness */ - OVCAMCHIP_CID_SAT, /* Saturation */ - OVCAMCHIP_CID_HUE, /* Hue */ - OVCAMCHIP_CID_EXP, /* Exposure */ - OVCAMCHIP_CID_FREQ, /* Light frequency */ - OVCAMCHIP_CID_BANDFILT, /* Banding filter */ - OVCAMCHIP_CID_AUTOBRIGHT, /* Auto brightness */ - OVCAMCHIP_CID_AUTOEXP, /* Auto exposure */ - OVCAMCHIP_CID_BACKLIGHT, /* Back light compensation */ - OVCAMCHIP_CID_MIRROR, /* Mirror horizontally */ -}; - -/* Chip types */ -#define NUM_CC_TYPES 9 -enum { - CC_UNKNOWN, - CC_OV76BE, - CC_OV7610, - CC_OV7620, - CC_OV7620AE, - CC_OV6620, - CC_OV6630, - CC_OV6630AE, - CC_OV6630AF, -}; - -/* --------------------------------- */ -/* I2C ADDRESSES */ -/* --------------------------------- */ - -#define OV7xx0_SID (0x42 >> 1) -#define OV6xx0_SID (0xC0 >> 1) - -/* --------------------------------- */ -/* API */ -/* --------------------------------- */ - -struct ovcamchip_control { - __u32 id; - __s32 value; -}; - -struct ovcamchip_window { - int x; - int y; - int width; - int height; - int format; - int quarter; /* Scale width and height down 2x */ - - /* This stuff will be removed eventually */ - int clockdiv; /* Clock divisor setting */ -}; - -/* Commands */ -#define OVCAMCHIP_CMD_Q_SUBTYPE _IOR (0x88, 0x00, int) -#define OVCAMCHIP_CMD_INITIALIZE _IOW (0x88, 0x01, int) -/* You must call OVCAMCHIP_CMD_INITIALIZE before any of commands below! */ -#define OVCAMCHIP_CMD_S_CTRL _IOW (0x88, 0x02, struct ovcamchip_control) -#define OVCAMCHIP_CMD_G_CTRL _IOWR (0x88, 0x03, struct ovcamchip_control) -#define OVCAMCHIP_CMD_S_MODE _IOW (0x88, 0x04, struct ovcamchip_window) -#define OVCAMCHIP_MAX_CMD _IO (0x88, 0x3f) - -#endif -- cgit v0.10.2 From 38af87869e7a255b6ba0f41bf53d2e7b0a54d13b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 08:13:12 -0300 Subject: [media] Documentation/ioctl/ioctl-number.txt: Remove some now freed ioctl ranges The V4L1 removal patches removed a few ioctls. Update it at the docspace. Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index 63ffd78..b2400d7 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt @@ -260,14 +260,11 @@ Code Seq#(hex) Include File Comments 't' 80-8F linux/isdn_ppp.h 't' 90 linux/toshiba.h 'u' 00-1F linux/smb_fs.h gone -'v' all linux/videodev.h conflict! 'v' 00-1F linux/ext2_fs.h conflict! 'v' 00-1F linux/fs.h conflict! 'v' 00-0F linux/sonypi.h conflict! -'v' C0-CF drivers/media/video/ov511.h conflict! 'v' C0-DF media/pwc-ioctl.h conflict! 'v' C0-FF linux/meye.h conflict! -'v' C0-CF drivers/media/video/zoran/zoran.h conflict! 'v' D0-DF drivers/media/video/cpia2/cpia2dev.h conflict! 'w' all CERN SCI driver 'y' 00-1F packet based user level communications @@ -278,7 +275,6 @@ Code Seq#(hex) Include File Comments 'z' 10-4F drivers/s390/crypto/zcrypt_api.h conflict! 0x80 00-1F linux/fb.h -0x88 00-3F media/ovcamchip.h 0x89 00-06 arch/x86/include/asm/sockios.h 0x89 0B-DF linux/sockios.h 0x89 E0-EF linux/sockios.h SIOCPROTOPRIVATE range -- cgit v0.10.2 From 1fb03673b9eddb55a08174d0952c0a1c2438997e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 08:24:58 -0300 Subject: [media] Fix videodev.h references at the V4L DocBook Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/DocBook/v4l/func-ioctl.xml b/Documentation/DocBook/v4l/func-ioctl.xml index 00f9690e..b60fd37 100644 --- a/Documentation/DocBook/v4l/func-ioctl.xml +++ b/Documentation/DocBook/v4l/func-ioctl.xml @@ -34,8 +34,7 @@ request - V4L2 ioctl request code as defined in the videodev.h header file, for example + V4L2 ioctl request code as defined in the videodev2.h header file, for example VIDIOC_QUERYCAP. @@ -57,7 +56,7 @@ file descriptor. An ioctl request has encoded in it whether the argument is an input, output or read/write parameter, and the size of the argument argp in bytes. Macros and defines specifying V4L2 ioctl requests are located -in the videodev.h header file. +in the videodev2.h header file. Applications should use their own copy, not include the version in the kernel sources on the system they compile on. All V4L2 ioctl requests, their respective function and parameters are specified in In V4L2 each format has an identifier which looks like -PIX_FMT_XXX, defined in the videodev.h header file. These identifiers +PIX_FMT_XXX, defined in the videodev2.h +header file. These identifiers represent four character codes which are also listed below, however they are not the same as those used in the Windows world. -- cgit v0.10.2 From 55fe25b418640fad04190103274841b2c907bacd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 08:27:05 -0300 Subject: [media] Remove the old V4L1 v4lgrab.c file This example file uses the old V4L1 API. It also doesn't use libv4l. So, it is completely obsolete. A good example already exists at v4l-utils (v4l2grab.c): http://git.linuxtv.org/v4l-utils.git Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/Makefile b/Documentation/Makefile index 6fc7ea1..9b4bc5c 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -1,3 +1,3 @@ obj-m := DocBook/ accounting/ auxdisplay/ connector/ \ filesystems/ filesystems/configfs/ ia64/ laptops/ networking/ \ - pcmcia/ spi/ timers/ video4linux/ vm/ watchdog/src/ + pcmcia/ spi/ timers/ vm/ watchdog/src/ diff --git a/Documentation/video4linux/Makefile b/Documentation/video4linux/Makefile deleted file mode 100644 index 1ed0e98..0000000 --- a/Documentation/video4linux/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# kbuild trick to avoid linker error. Can be omitted if a module is built. -obj- := dummy.o - -# List of programs to build -hostprogs-y := v4lgrab - -# Tell kbuild to always build the programs -always := $(hostprogs-y) diff --git a/Documentation/video4linux/v4lgrab.c b/Documentation/video4linux/v4lgrab.c deleted file mode 100644 index c8ded17..0000000 --- a/Documentation/video4linux/v4lgrab.c +++ /dev/null @@ -1,201 +0,0 @@ -/* Simple Video4Linux image grabber. */ -/* - * Video4Linux Driver Test/Example Framegrabbing Program - * - * Compile with: - * gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab - * Use as: - * v4lgrab >image.ppm - * - * Copyright (C) 1998-05-03, Phil Blundell - * Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c - * with minor modifications (Dave Forrest, drf5n@virginia.edu). - * - * - * For some cameras you may need to pre-load libv4l to perform - * the necessary decompression, e.g.: - * - * export LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so - * ./v4lgrab >image.ppm - * - * see http://hansdegoede.livejournal.com/3636.html for details. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define VIDEO_DEV "/dev/video0" - -/* Stole this from tvset.c */ - -#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b) \ -{ \ - switch (format) \ - { \ - case VIDEO_PALETTE_GREY: \ - switch (depth) \ - { \ - case 4: \ - case 6: \ - case 8: \ - (r) = (g) = (b) = (*buf++ << 8);\ - break; \ - \ - case 16: \ - (r) = (g) = (b) = \ - *((unsigned short *) buf); \ - buf += 2; \ - break; \ - } \ - break; \ - \ - \ - case VIDEO_PALETTE_RGB565: \ - { \ - unsigned short tmp = *(unsigned short *)buf; \ - (r) = tmp&0xF800; \ - (g) = (tmp<<5)&0xFC00; \ - (b) = (tmp<<11)&0xF800; \ - buf += 2; \ - } \ - break; \ - \ - case VIDEO_PALETTE_RGB555: \ - (r) = (buf[0]&0xF8)<<8; \ - (g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8; \ - (b) = ((buf[1] << 2 ) & 0xF8)<<8; \ - buf += 2; \ - break; \ - \ - case VIDEO_PALETTE_RGB24: \ - (r) = buf[0] << 8; (g) = buf[1] << 8; \ - (b) = buf[2] << 8; \ - buf += 3; \ - break; \ - \ - default: \ - fprintf(stderr, \ - "Format %d not yet supported\n", \ - format); \ - } \ -} - -static int get_brightness_adj(unsigned char *image, long size, int *brightness) { - long i, tot = 0; - for (i=0;i= 126 && (tot/(size*3)) <= 130); -} - -int main(int argc, char ** argv) -{ - int fd = open(VIDEO_DEV, O_RDONLY), f; - struct video_capability cap; - struct video_window win; - struct video_picture vpic; - - unsigned char *buffer, *src; - int bpp = 24, r = 0, g = 0, b = 0; - unsigned int i, src_depth = 16; - - if (fd < 0) { - perror(VIDEO_DEV); - exit(1); - } - - if (ioctl(fd, VIDIOCGCAP, &cap) < 0) { - perror("VIDIOGCAP"); - fprintf(stderr, "(" VIDEO_DEV " not a video4linux device?)\n"); - close(fd); - exit(1); - } - - if (ioctl(fd, VIDIOCGWIN, &win) < 0) { - perror("VIDIOCGWIN"); - close(fd); - exit(1); - } - - if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) { - perror("VIDIOCGPICT"); - close(fd); - exit(1); - } - - if (cap.type & VID_TYPE_MONOCHROME) { - vpic.depth=8; - vpic.palette=VIDEO_PALETTE_GREY; /* 8bit grey */ - if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { - vpic.depth=6; - if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { - vpic.depth=4; - if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { - fprintf(stderr, "Unable to find a supported capture format.\n"); - close(fd); - exit(1); - } - } - } - } else { - vpic.depth=24; - vpic.palette=VIDEO_PALETTE_RGB24; - - if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { - vpic.palette=VIDEO_PALETTE_RGB565; - vpic.depth=16; - - if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { - vpic.palette=VIDEO_PALETTE_RGB555; - vpic.depth=15; - - if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { - fprintf(stderr, "Unable to find a supported capture format.\n"); - return -1; - } - } - } - } - - buffer = malloc(win.width * win.height * bpp); - if (!buffer) { - fprintf(stderr, "Out of memory.\n"); - exit(1); - } - - do { - int newbright; - read(fd, buffer, win.width * win.height * bpp); - f = get_brightness_adj(buffer, win.width * win.height, &newbright); - if (f) { - vpic.brightness += (newbright << 8); - if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { - perror("VIDIOSPICT"); - break; - } - } - } while (f); - - fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height); - - src = buffer; - - for (i = 0; i < win.width * win.height; i++) { - READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b); - fputc(r>>8, stdout); - fputc(g>>8, stdout); - fputc(b>>8, stdout); - } - - close(fd); - return 0; -} -- cgit v0.10.2 From 22efe507705a8437255114f98d0d514524460be0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 08:30:34 -0300 Subject: [media] omap_vout: Remove an obsolete comment This comment mentions a field that doesn't exist, and talks about videodev.h that got removed. So, it doesn't make any sense to keep it. Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index 15f8793..83de97a 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -2230,7 +2230,6 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout) strlcpy(vfd->name, VOUT_NAME, sizeof(vfd->name)); - /* need to register for a VID_HARDWARE_* ID in videodev.h */ vfd->fops = &omap_vout_fops; vfd->v4l2_dev = &vout->vid_dev->v4l2_dev; mutex_init(&vout->lock); -- cgit v0.10.2 From 0334c8a52a8578f7aef501a14f78004f931efe20 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 09:41:05 -0300 Subject: [media] staging/lirc: Fix compilation when LIRC=m drivers/staging/lirc/lirc_bt829.c:141: undefined reference to `lirc_register_driver' drivers/built-in.o:(.rodata+0x20f68): undefined reference to `lirc_dev_fop_read' drivers/built-in.o:(.rodata+0x20f7c): undefined reference to `lirc_dev_fop_poll' drivers/built-in.o:(.rodata+0x20f8c): undefined reference to `lirc_dev_fop_open' drivers/built-in.o:(.rodata+0x20f94): undefined reference to `lirc_dev_fop_close' drivers/built-in.o:(.rodata+0x21030): undefined reference to `lirc_dev_fop_open' drivers/built-in.o:(.rodata+0x21038): undefined reference to `lirc_dev_fop_close' This happens when .config is like: CONFIG_LIRC=m CONFIG_IR_LIRC_CODEC=m CONFIG_LIRC_STAGING=y CONFIG_LIRC_BT829=y Don't allow that. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/lirc/Kconfig b/drivers/staging/lirc/Kconfig index fa790db..be97f7b 100644 --- a/drivers/staging/lirc/Kconfig +++ b/drivers/staging/lirc/Kconfig @@ -14,26 +14,26 @@ if LIRC_STAGING config LIRC_BT829 tristate "BT829 based hardware" - depends on LIRC_STAGING && PCI + depends on LIRC && PCI help Driver for the IR interface on BT829-based hardware config LIRC_I2C tristate "I2C Based IR Receivers" - depends on LIRC_STAGING && I2C + depends on LIRC && I2C help Driver for I2C-based IR receivers, such as those commonly found onboard Hauppauge PVR-150/250/350 video capture cards config LIRC_IGORPLUGUSB tristate "Igor Cesko's USB IR Receiver" - depends on LIRC_STAGING && USB + depends on LIRC && USB help Driver for Igor Cesko's USB IR Receiver config LIRC_IMON tristate "Legacy SoundGraph iMON Receiver and Display" - depends on LIRC_STAGING && USB + depends on LIRC && USB help Driver for the original SoundGraph iMON IR Receiver and Display @@ -41,31 +41,31 @@ config LIRC_IMON config LIRC_IT87 tristate "ITE IT87XX CIR Port Receiver" - depends on LIRC_STAGING && PNP + depends on LIRC && PNP help Driver for the ITE IT87xx IR Receiver config LIRC_ITE8709 tristate "ITE8709 CIR Port Receiver" - depends on LIRC_STAGING && PNP + depends on LIRC && PNP help Driver for the ITE8709 IR Receiver config LIRC_PARALLEL tristate "Homebrew Parallel Port Receiver" - depends on LIRC_STAGING && PARPORT + depends on LIRC && PARPORT help Driver for Homebrew Parallel Port Receivers config LIRC_SASEM tristate "Sasem USB IR Remote" - depends on LIRC_STAGING && USB + depends on LIRC && USB help Driver for the Sasem OnAir Remocon-V or Dign HV5 HTPC IR/VFD Module config LIRC_SERIAL tristate "Homebrew Serial Port Receiver" - depends on LIRC_STAGING + depends on LIRC help Driver for Homebrew Serial Port Receivers @@ -78,19 +78,19 @@ config LIRC_SERIAL_TRANSMITTER config LIRC_SIR tristate "Built-in SIR IrDA port" - depends on LIRC_STAGING + depends on LIRC help Driver for the SIR IrDA port config LIRC_TTUSBIR tristate "Technotrend USB IR Receiver" - depends on LIRC_STAGING && USB + depends on LIRC && USB help Driver for the Technotrend USB IR Receiver config LIRC_ZILOG tristate "Zilog/Hauppauge IR Transmitter" - depends on LIRC_STAGING && I2C + depends on LIRC && I2C help Driver for the Zilog/Hauppauge IR Transmitter, found on PVR-150/500, HVR-1200/1250/1700/1800, HD-PVR and other cards -- cgit v0.10.2 From 1035758d5bdcd6c2f7308a35185f1d6f3b6b5443 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 11:14:52 -0300 Subject: [media] feature_removal_schedule.txt: mark VIDIOC_*_OLD ioctls to die There are some old broken definitions of ioctl's, where the read/write arguments were marked wrong. The last one were added on 2.6.6 kernel. Remove them, in order to cleanup some copy_from_user/copy_to_user logic done inside V4L core. Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index e348b7e..f2742e1 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -112,6 +112,27 @@ Who: Mauro Carvalho Chehab --------------------------- +What: Video4Linux: Remove obsolete ioctl's +When: kernel 2.6.39 +Files: include/media/videodev2.h +Why: Some ioctl's were defined wrong on 2.6.2 and 2.6.6, using the wrong + type of R/W arguments. They were fixed, but the old ioctl names are + still there, maintained to avoid breaking binary compatibility: + #define VIDIOC_OVERLAY_OLD _IOWR('V', 14, int) + #define VIDIOC_S_PARM_OLD _IOW('V', 22, struct v4l2_streamparm) + #define VIDIOC_S_CTRL_OLD _IOW('V', 28, struct v4l2_control) + #define VIDIOC_G_AUDIO_OLD _IOWR('V', 33, struct v4l2_audio) + #define VIDIOC_G_AUDOUT_OLD _IOWR('V', 49, struct v4l2_audioout) + #define VIDIOC_CROPCAP_OLD _IOR('V', 58, struct v4l2_cropcap) + There's no sense on preserving those forever, as it is very doubtful + that someone would try to use a such old binary with a modern kernel. + Removing them will allow us to remove some magic done at the V4L ioctl + handler. + +Who: Mauro Carvalho Chehab + +--------------------------- + What: sys_sysctl When: September 2010 Option: CONFIG_SYSCTL_SYSCALL -- cgit v0.10.2 From 9ae2ae35f8a8a13997b9ec719ae7c151a2182e80 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 11:41:14 -0300 Subject: [media] dmxdev: Fix a compilation warning due to a bad type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/dvb/dvb-core/dmxdev.c: In function ‘dvb_dmxdev_start_feed’: drivers/media/dvb/dvb-core/dmxdev.c:583:13: warning: comparison between ‘enum dmx_ts_pes’ and ‘enum ’ Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index ad1f61d..e4b5c03 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -572,13 +572,13 @@ static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev, dmx_output_t otype; int ret; int ts_type; - enum dmx_ts_pes ts_pes; + dmx_pes_type_t ts_pes; struct dmx_ts_feed *tsfeed; feed->ts = NULL; otype = para->output; - ts_pes = (enum dmx_ts_pes)para->pes_type; + ts_pes = para->pes_type; if (ts_pes < DMX_PES_OTHER) ts_type = TS_DECODER; -- cgit v0.10.2 From fce50ac80e38b1d205939ff7d4777536701263a6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 11:44:50 -0300 Subject: [media] radio-wl1273: Fix two warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/radio/radio-wl1273.c: In function ‘wl1273_fm_upload_firmware_patch’: drivers/media/radio/radio-wl1273.c:675:2: warning: ‘n’ may be used uninitialized in this function drivers/media/radio/radio-wl1273.c:675:2: warning: ‘i’ may be used uninitialized in this function Those vars are never initialized, and the debug message makes no sense, as it will show just two random values. Cc: Matti J. Aaltonen Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c index 1813790..dd6bd36 100644 --- a/drivers/media/radio/radio-wl1273.c +++ b/drivers/media/radio/radio-wl1273.c @@ -645,7 +645,7 @@ static int wl1273_fm_upload_firmware_patch(struct wl1273_device *radio) const char *fw_name = "radio-wl1273-fw.bin"; struct device *dev = radio->dev; __u8 *ptr; - int i, n, r; + int r; dev_dbg(dev, "%s:\n", __func__); @@ -672,7 +672,6 @@ static int wl1273_fm_upload_firmware_patch(struct wl1273_device *radio) /* ignore possible error here */ wl1273_fm_write_cmd(core, WL1273_RESET, 0); - dev_dbg(dev, "n: %d, i: %d\n", n, i); dev_dbg(dev, "%s - download OK, r: %d\n", __func__, r); out: release_firmware(fw_p); -- cgit v0.10.2 From d78aa7292ad38b22ccb9cdba99293cedb52fb342 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 11:47:17 -0300 Subject: [media] lirc_zilog: Fix a warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/staging/lirc/lirc_zilog.c: In function ‘send_code’: drivers/staging/lirc/lirc_zilog.c:886:1: warning: label ‘done’ defined but not used Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/lirc/lirc_zilog.c b/drivers/staging/lirc/lirc_zilog.c index f0076eb..52be6de 100644 --- a/drivers/staging/lirc/lirc_zilog.c +++ b/drivers/staging/lirc/lirc_zilog.c @@ -883,7 +883,6 @@ static int send_code(struct IR *ir, unsigned int code, unsigned int key) return -EFAULT; } -done: /* Oh good, it worked */ dprintk("sent code %u, key %u\n", code, key); return 0; -- cgit v0.10.2 From 2e94b53c55d00b4d4d4b9e65007566f7fbffab7a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 11:55:07 -0300 Subject: [media] dib7000m/dib7000p: Add support for TRANSMISSION_MODE_4K MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes several warnings: drivers/media/dvb/frontends/dib7000m.c: In function ‘dib7000m_set_channel’: drivers/media/dvb/frontends/dib7000m.c:808:3: warning: case value ‘255’ not in enumerated type ‘fe_transmit_mode_t’ drivers/media/dvb/frontends/dib7000m.c:869:3: warning: case value ‘255’ not in enumerated type ‘fe_transmit_mode_t’ drivers/media/dvb/frontends/dib7000m.c: In function ‘dib7000m_tune’: drivers/media/dvb/frontends/dib7000m.c:1023:3: warning: case value ‘255’ not in enumerated type ‘fe_transmit_mode_t’ drivers/media/dvb/frontends/dib7000m.c:1033:3: warning: case value ‘255’ not in enumerated type ‘fe_transmit_mode_t’ drivers/media/dvb/frontends/dib7000m.c:1043:3: warning: case value ‘255’ not in enumerated type ‘fe_transmit_mode_t’ drivers/media/dvb/frontends/dib7000p.c: In function ‘dib7000p_set_channel’: drivers/media/dvb/frontends/dib7000p.c:720:3: warning: case value ‘255’ not in enumerated type ‘fe_transmit_mode_t’ drivers/media/dvb/frontends/dib7000p.c:773:3: warning: case value ‘255’ not in enumerated type ‘fe_transmit_mode_t’ drivers/media/dvb/frontends/dib7000p.c: In function ‘dib7000p_tune’: drivers/media/dvb/frontends/dib7000p.c:997:3: warning: case value ‘255’ not in enumerated type ‘fe_transmit_mode_t’ drivers/media/dvb/frontends/dib7000p.c:1007:3: warning: case value ‘255’ not in enumerated type ‘fe_transmit_mode_t’ drivers/media/dvb/frontends/dib7000p.c:1017:3: warning: case value ‘255’ not in enumerated type ‘fe_transmit_mode_t’ The drivers were prepared to support 4K carriers, but as the define were added later, they were using a "magic" value of 255. Cc: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c index 0f09fd3..c7f5ccf 100644 --- a/drivers/media/dvb/frontends/dib7000m.c +++ b/drivers/media/dvb/frontends/dib7000m.c @@ -805,7 +805,7 @@ static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_fronte value = 0; switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: value |= (0 << 7); break; - case /* 4K MODE */ 255: value |= (2 << 7); break; + case TRANSMISSION_MODE_4K: value |= (2 << 7); break; default: case TRANSMISSION_MODE_8K: value |= (1 << 7); break; } @@ -866,7 +866,7 @@ static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_fronte /* P_dvsy_sync_wait */ switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_8K: value = 256; break; - case /* 4K MODE */ 255: value = 128; break; + case TRANSMISSION_MODE_4K: value = 128; break; case TRANSMISSION_MODE_2K: default: value = 64; break; } @@ -1020,7 +1020,7 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet value = (6 << 8) | 0x80; switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: value |= (7 << 12); break; - case /* 4K MODE */ 255: value |= (8 << 12); break; + case TRANSMISSION_MODE_4K: value |= (8 << 12); break; default: case TRANSMISSION_MODE_8K: value |= (9 << 12); break; } @@ -1030,7 +1030,7 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet value = (0 << 4); switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: value |= 0x6; break; - case /* 4K MODE */ 255: value |= 0x7; break; + case TRANSMISSION_MODE_4K: value |= 0x7; break; default: case TRANSMISSION_MODE_8K: value |= 0x8; break; } @@ -1040,7 +1040,7 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet value = (0 << 4); switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: value |= 0x6; break; - case /* 4K MODE */ 255: value |= 0x7; break; + case TRANSMISSION_MODE_4K: value |= 0x7; break; default: case TRANSMISSION_MODE_8K: value |= 0x8; break; } diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index 3aed0d4..6aa02cb 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c @@ -717,7 +717,7 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte value = 0; switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: value |= (0 << 7); break; - case /* 4K MODE */ 255: value |= (2 << 7); break; + case TRANSMISSION_MODE_4K: value |= (2 << 7); break; default: case TRANSMISSION_MODE_8K: value |= (1 << 7); break; } @@ -770,7 +770,7 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte /* P_dvsy_sync_wait */ switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_8K: value = 256; break; - case /* 4K MODE */ 255: value = 128; break; + case TRANSMISSION_MODE_4K: value = 128; break; case TRANSMISSION_MODE_2K: default: value = 64; break; } @@ -994,7 +994,7 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet tmp = (6 << 8) | 0x80; switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: tmp |= (7 << 12); break; - case /* 4K MODE */ 255: tmp |= (8 << 12); break; + case TRANSMISSION_MODE_4K: tmp |= (8 << 12); break; default: case TRANSMISSION_MODE_8K: tmp |= (9 << 12); break; } @@ -1004,7 +1004,7 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet tmp = (0 << 4); switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: tmp |= 0x6; break; - case /* 4K MODE */ 255: tmp |= 0x7; break; + case TRANSMISSION_MODE_4K: tmp |= 0x7; break; default: case TRANSMISSION_MODE_8K: tmp |= 0x8; break; } @@ -1014,7 +1014,7 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet tmp = (0 << 4); switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: tmp |= 0x6; break; - case /* 4K MODE */ 255: tmp |= 0x7; break; + case TRANSMISSION_MODE_4K: tmp |= 0x7; break; default: case TRANSMISSION_MODE_8K: tmp |= 0x8; break; } -- cgit v0.10.2 From 95f18be2e4f74255b46fcc23a9718cca9c7375c9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 12:00:03 -0300 Subject: [media] gspca: Fix a warning for using len before filling it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The check for status errors is now before the check for len. That's ok. However, the error printk's for the status error prints the URB length. This generates this error: drivers/media/video/gspca/gspca.c: In function ‘fill_frame’: drivers/media/video/gspca/gspca.c:305:9: warning: ‘len’ may be used uninitialized in this function The fix is as simple as moving the len init to happen before the checks. Cc: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 92b5dfb..80b31eb 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -318,6 +318,7 @@ static void fill_frame(struct gspca_dev *gspca_dev, } pkt_scan = gspca_dev->sd_desc->pkt_scan; for (i = 0; i < urb->number_of_packets; i++) { + len = urb->iso_frame_desc[i].actual_length; /* check the packet status and length */ st = urb->iso_frame_desc[i].status; @@ -327,7 +328,6 @@ static void fill_frame(struct gspca_dev *gspca_dev, gspca_dev->last_packet_type = DISCARD_PACKET; continue; } - len = urb->iso_frame_desc[i].actual_length; if (len == 0) { if (gspca_dev->empty_packet == 0) gspca_dev->empty_packet = 1; -- cgit v0.10.2 From 187e7d3b9b4e0b6b1c171846592e679e58a84cd2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 12:16:47 -0300 Subject: [media] stv090x: Fix some compilation warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A few typos at the driver are causing the following warnings: drivers/media/dvb/frontends/stv090x.c: In function ‘stv090x_start_search’: drivers/media/dvb/frontends/stv090x.c:1486:27: warning: comparison between ‘enum stv090x_search’ and ‘enum stv090x_delsys’ drivers/media/dvb/frontends/stv090x.c:1487:24: warning: comparison between ‘enum stv090x_search’ and ‘enum stv090x_delsys’ drivers/media/dvb/frontends/stv090x.c: In function ‘stv090x_optimize_track’: drivers/media/dvb/frontends/stv090x.c:2943:2: warning: case value ‘4’ not in enumerated type ‘enum stv090x_delsys’ The first two are due to the lack of using the delsys types STV090x_DVBS1/STV090x_DSS instead of STV090x_SEARCH_DVBS1/STV090x_SEARCH_DSS The second one is due to the usage of STV090x_UNKNOWN (enum stv090x_modulation) instead of STV090x_ERROR (enum stv090x_delsys). Cc: Manu Abraham Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index 425e7a4..4e0fc2c 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -1483,8 +1483,8 @@ static int stv090x_start_search(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0) goto err; - if ((state->search_mode == STV090x_DVBS1) || - (state->search_mode == STV090x_DSS) || + if ((state->search_mode == STV090x_SEARCH_DVBS1) || + (state->search_mode == STV090x_SEARCH_DSS) || (state->search_mode == STV090x_SEARCH_AUTO)) { if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0) @@ -2940,7 +2940,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67); /* PER */ break; - case STV090x_UNKNOWN: + case STV090x_ERROR: default: reg = STV090x_READ_DEMOD(state, DMDCFGMD); STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); -- cgit v0.10.2 From 465a9e3a2f494b0887db63b7b10bb9370145d9bc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 12:58:02 -0300 Subject: [media] af9013: Fix a compilation warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/dvb/frontends/af9013.c: In function ‘af9013_update_signal_strength.clone.0’: drivers/media/dvb/frontends/af9013.c:967:6: warning: ‘ret’ may be used uninitialized in this function Cc: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c index e2a95c0..ce22205 100644 --- a/drivers/media/dvb/frontends/af9013.c +++ b/drivers/media/dvb/frontends/af9013.c @@ -964,7 +964,7 @@ error: static int af9013_update_signal_strength(struct dvb_frontend *fe) { struct af9013_state *state = fe->demodulator_priv; - int ret; + int ret = 0; u8 rf_gain, if_gain; int signal_strength; -- cgit v0.10.2 From 0170f6bcb243cb9e86c953652f8e62fccb8108f1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 13:00:04 -0300 Subject: [media] streamzap: Fix a compilation warning when compiled builtin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/rc/streamzap.c: In function ‘streamzap_probe’: drivers/media/rc/streamzap.c:460:2: warning: statement with no effect Cc: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c index 7f82f55..6e2911c 100644 --- a/drivers/media/rc/streamzap.c +++ b/drivers/media/rc/streamzap.c @@ -73,7 +73,7 @@ MODULE_DEVICE_TABLE(usb, streamzap_table); #ifdef CONFIG_IR_RC5_SZ_DECODER_MODULE #define load_rc5_sz_decode() request_module("ir-rc5-sz-decoder") #else -#define load_rc5_sz_decode() 0 +#define load_rc5_sz_decode() {} #endif enum StreamzapDecoderState { -- cgit v0.10.2 From 2d5ca76f2b39a31313d7e54224c78b7b311e7dce Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Dec 2010 18:17:12 -0300 Subject: [media] dabusb: Move it to staging to be deprecated dabusb driver were conceived as an experimental driver for a test device. The driver never supported any shipped product, and, while there were some updates on it in 2003, for an ancient product, those changes were never submitted upstream. Also, there's no DocBook for its API, nor any upstream discussion. So, better to remove it, on .39. If later needed, we may rescue it from git logs. For now, let's move it to staging. Acked-by: Deti Fliegl Cc: Deti Fliegl Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 147c92b..81b3ba8 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -92,26 +92,4 @@ source "drivers/media/radio/Kconfig" source "drivers/media/dvb/Kconfig" -config DAB - boolean "DAB adapters" - ---help--- - Allow selecting support for Digital Audio Broadcasting (DAB) - Receiver adapters. - -if DAB -config USB_DABUSB - tristate "DABUSB driver" - depends on USB - ---help--- - A Digital Audio Broadcasting (DAB) Receiver for USB and Linux - brought to you by the DAB-Team - . This driver can be taken - as an example for URB-based bulk, control, and isochronous - transactions. URB's are explained in - . - - To compile this driver as a module, choose M here: the - module will be called dabusb. -endif # DAB - endif # MEDIA_SUPPORT diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index fd684dd..98825e7 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -121,7 +121,6 @@ obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o -obj-$(CONFIG_USB_DABUSB) += dabusb.o obj-$(CONFIG_USB_ZR364XX) += zr364xx.o obj-$(CONFIG_USB_STKWEBCAM) += stkwebcam.o diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c deleted file mode 100644 index f3e25e9..0000000 --- a/drivers/media/video/dabusb.c +++ /dev/null @@ -1,914 +0,0 @@ -/*****************************************************************************/ - -/* - * dabusb.c -- dab usb driver. - * - * Copyright (C) 1999 Deti Fliegl (deti@fliegl.de) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - * - * $Id: dabusb.c,v 1.54 2000/07/24 21:39:39 deti Exp $ - * - */ - -/*****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dabusb.h" - -/* - * Version Information - */ -#define DRIVER_VERSION "v1.54" -#define DRIVER_AUTHOR "Deti Fliegl, deti@fliegl.de" -#define DRIVER_DESC "DAB-USB Interface Driver for Linux (c)1999" - -/* --------------------------------------------------------------------- */ - -#ifdef CONFIG_USB_DYNAMIC_MINORS -#define NRDABUSB 256 -#else -#define NRDABUSB 4 -#endif - -/*-------------------------------------------------------------------*/ - -static dabusb_t dabusb[NRDABUSB]; -static int buffers = 256; -static struct usb_driver dabusb_driver; - -/*-------------------------------------------------------------------*/ - -static int dabusb_add_buf_tail (pdabusb_t s, struct list_head *dst, struct list_head *src) -{ - unsigned long flags; - struct list_head *tmp; - int ret = 0; - - spin_lock_irqsave (&s->lock, flags); - - if (list_empty (src)) { - // no elements in source buffer - ret = -1; - goto err; - } - tmp = src->next; - list_move_tail (tmp, dst); - - err: spin_unlock_irqrestore (&s->lock, flags); - return ret; -} -/*-------------------------------------------------------------------*/ -#ifdef DEBUG -static void dump_urb (struct urb *urb) -{ - dbg("urb :%p", urb); - dbg("dev :%p", urb->dev); - dbg("pipe :%08X", urb->pipe); - dbg("status :%d", urb->status); - dbg("transfer_flags :%08X", urb->transfer_flags); - dbg("transfer_buffer :%p", urb->transfer_buffer); - dbg("transfer_buffer_length:%d", urb->transfer_buffer_length); - dbg("actual_length :%d", urb->actual_length); - dbg("setup_packet :%p", urb->setup_packet); - dbg("start_frame :%d", urb->start_frame); - dbg("number_of_packets :%d", urb->number_of_packets); - dbg("interval :%d", urb->interval); - dbg("error_count :%d", urb->error_count); - dbg("context :%p", urb->context); - dbg("complete :%p", urb->complete); -} -#endif -/*-------------------------------------------------------------------*/ -static int dabusb_cancel_queue (pdabusb_t s, struct list_head *q) -{ - unsigned long flags; - pbuff_t b; - - dbg("dabusb_cancel_queue"); - - spin_lock_irqsave (&s->lock, flags); - - list_for_each_entry(b, q, buff_list) { -#ifdef DEBUG - dump_urb(b->purb); -#endif - usb_unlink_urb (b->purb); - } - spin_unlock_irqrestore (&s->lock, flags); - return 0; -} -/*-------------------------------------------------------------------*/ -static int dabusb_free_queue (struct list_head *q) -{ - struct list_head *tmp; - struct list_head *p; - pbuff_t b; - - dbg("dabusb_free_queue"); - for (p = q->next; p != q;) { - b = list_entry (p, buff_t, buff_list); - -#ifdef DEBUG - dump_urb(b->purb); -#endif - kfree(b->purb->transfer_buffer); - usb_free_urb(b->purb); - tmp = p->next; - list_del (p); - kfree (b); - p = tmp; - } - - return 0; -} -/*-------------------------------------------------------------------*/ -static int dabusb_free_buffers (pdabusb_t s) -{ - unsigned long flags; - dbg("dabusb_free_buffers"); - - spin_lock_irqsave(&s->lock, flags); - - dabusb_free_queue (&s->free_buff_list); - dabusb_free_queue (&s->rec_buff_list); - - spin_unlock_irqrestore(&s->lock, flags); - - s->got_mem = 0; - return 0; -} -/*-------------------------------------------------------------------*/ -static void dabusb_iso_complete (struct urb *purb) -{ - pbuff_t b = purb->context; - pdabusb_t s = b->s; - int i; - int len; - int dst = 0; - void *buf = purb->transfer_buffer; - - dbg("dabusb_iso_complete"); - - // process if URB was not killed - if (purb->status != -ENOENT) { - unsigned int pipe = usb_rcvisocpipe (purb->dev, _DABUSB_ISOPIPE); - int pipesize = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe)); - for (i = 0; i < purb->number_of_packets; i++) - if (!purb->iso_frame_desc[i].status) { - len = purb->iso_frame_desc[i].actual_length; - if (len <= pipesize) { - memcpy (buf + dst, buf + purb->iso_frame_desc[i].offset, len); - dst += len; - } - else - dev_err(&purb->dev->dev, - "dabusb_iso_complete: invalid len %d\n", len); - } - else - dev_warn(&purb->dev->dev, "dabusb_iso_complete: corrupted packet status: %d\n", purb->iso_frame_desc[i].status); - if (dst != purb->actual_length) - dev_err(&purb->dev->dev, - "dst!=purb->actual_length:%d!=%d\n", - dst, purb->actual_length); - } - - if (atomic_dec_and_test (&s->pending_io) && !s->remove_pending && s->state != _stopped) { - s->overruns++; - dev_err(&purb->dev->dev, "overrun (%d)\n", s->overruns); - } - wake_up (&s->wait); -} -/*-------------------------------------------------------------------*/ -static int dabusb_alloc_buffers (pdabusb_t s) -{ - int transfer_len = 0; - pbuff_t b; - unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE); - int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe)); - int packets = _ISOPIPESIZE / pipesize; - int transfer_buffer_length = packets * pipesize; - int i; - - dbg("dabusb_alloc_buffers pipesize:%d packets:%d transfer_buffer_len:%d", - pipesize, packets, transfer_buffer_length); - - while (transfer_len < (s->total_buffer_size << 10)) { - b = kzalloc(sizeof (buff_t), GFP_KERNEL); - if (!b) { - dev_err(&s->usbdev->dev, - "kzalloc(sizeof(buff_t))==NULL\n"); - goto err; - } - b->s = s; - b->purb = usb_alloc_urb(packets, GFP_KERNEL); - if (!b->purb) { - dev_err(&s->usbdev->dev, "usb_alloc_urb == NULL\n"); - kfree (b); - goto err; - } - - b->purb->transfer_buffer = kmalloc (transfer_buffer_length, GFP_KERNEL); - if (!b->purb->transfer_buffer) { - kfree (b->purb); - kfree (b); - dev_err(&s->usbdev->dev, - "kmalloc(%d)==NULL\n", transfer_buffer_length); - goto err; - } - - b->purb->transfer_buffer_length = transfer_buffer_length; - b->purb->number_of_packets = packets; - b->purb->complete = dabusb_iso_complete; - b->purb->context = b; - b->purb->dev = s->usbdev; - b->purb->pipe = pipe; - b->purb->transfer_flags = URB_ISO_ASAP; - - for (i = 0; i < packets; i++) { - b->purb->iso_frame_desc[i].offset = i * pipesize; - b->purb->iso_frame_desc[i].length = pipesize; - } - - transfer_len += transfer_buffer_length; - list_add_tail (&b->buff_list, &s->free_buff_list); - } - s->got_mem = transfer_len; - - return 0; - - err: - dabusb_free_buffers (s); - return -ENOMEM; -} -/*-------------------------------------------------------------------*/ -static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb) -{ - int ret; - unsigned int pipe; - int actual_length; - - dbg("dabusb_bulk"); - - if (!pb->pipe) - pipe = usb_rcvbulkpipe (s->usbdev, 2); - else - pipe = usb_sndbulkpipe (s->usbdev, 2); - - ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 100); - if(ret<0) { - dev_err(&s->usbdev->dev, - "usb_bulk_msg failed(%d)\n", ret); - - if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { - dev_err(&s->usbdev->dev, "set_interface failed\n"); - return -EINVAL; - } - - } - - if( ret == -EPIPE ) { - dev_warn(&s->usbdev->dev, "CLEAR_FEATURE request to remove STALL condition.\n"); - if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe))) - dev_err(&s->usbdev->dev, "request failed\n"); - } - - pb->size = actual_length; - return ret; -} -/* --------------------------------------------------------------------- */ -static int dabusb_writemem (pdabusb_t s, int pos, const unsigned char *data, - int len) -{ - int ret; - unsigned char *transfer_buffer = kmalloc (len, GFP_KERNEL); - - if (!transfer_buffer) { - dev_err(&s->usbdev->dev, - "dabusb_writemem: kmalloc(%d) failed.\n", len); - return -ENOMEM; - } - - memcpy (transfer_buffer, data, len); - - ret=usb_control_msg(s->usbdev, usb_sndctrlpipe( s->usbdev, 0 ), 0xa0, 0x40, pos, 0, transfer_buffer, len, 300); - - kfree (transfer_buffer); - return ret; -} -/* --------------------------------------------------------------------- */ -static int dabusb_8051_reset (pdabusb_t s, unsigned char reset_bit) -{ - dbg("dabusb_8051_reset: %d",reset_bit); - return dabusb_writemem (s, CPUCS_REG, &reset_bit, 1); -} -/* --------------------------------------------------------------------- */ -static int dabusb_loadmem (pdabusb_t s, const char *fname) -{ - int ret; - const struct ihex_binrec *rec; - const struct firmware *uninitialized_var(fw); - - dbg("Enter dabusb_loadmem (internal)"); - - ret = request_ihex_firmware(&fw, "dabusb/firmware.fw", &s->usbdev->dev); - if (ret) { - dev_err(&s->usbdev->dev, - "Failed to load \"dabusb/firmware.fw\": %d\n", ret); - goto out; - } - ret = dabusb_8051_reset (s, 1); - - for (rec = (const struct ihex_binrec *)fw->data; rec; - rec = ihex_next_binrec(rec)) { - dbg("dabusb_writemem: %04X %p %d)", be32_to_cpu(rec->addr), - rec->data, be16_to_cpu(rec->len)); - - ret = dabusb_writemem(s, be32_to_cpu(rec->addr), rec->data, - be16_to_cpu(rec->len)); - if (ret < 0) { - dev_err(&s->usbdev->dev, - "dabusb_writemem failed (%d %04X %p %d)\n", - ret, be32_to_cpu(rec->addr), - rec->data, be16_to_cpu(rec->len)); - break; - } - } - ret = dabusb_8051_reset (s, 0); - release_firmware(fw); - out: - dbg("dabusb_loadmem: exit"); - - return ret; -} -/* --------------------------------------------------------------------- */ -static int dabusb_fpga_clear (pdabusb_t s, pbulk_transfer_t b) -{ - b->size = 4; - b->data[0] = 0x2a; - b->data[1] = 0; - b->data[2] = 0; - b->data[3] = 0; - - dbg("dabusb_fpga_clear"); - - return dabusb_bulk (s, b); -} -/* --------------------------------------------------------------------- */ -static int dabusb_fpga_init (pdabusb_t s, pbulk_transfer_t b) -{ - b->size = 4; - b->data[0] = 0x2c; - b->data[1] = 0; - b->data[2] = 0; - b->data[3] = 0; - - dbg("dabusb_fpga_init"); - - return dabusb_bulk (s, b); -} -/* --------------------------------------------------------------------- */ -static int dabusb_fpga_download (pdabusb_t s, const char *fname) -{ - pbulk_transfer_t b = kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL); - const struct firmware *fw; - unsigned int blen, n; - int ret; - - dbg("Enter dabusb_fpga_download (internal)"); - - if (!b) { - dev_err(&s->usbdev->dev, - "kmalloc(sizeof(bulk_transfer_t))==NULL\n"); - return -ENOMEM; - } - - ret = request_firmware(&fw, "dabusb/bitstream.bin", &s->usbdev->dev); - if (ret) { - dev_err(&s->usbdev->dev, - "Failed to load \"dabusb/bitstream.bin\": %d\n", ret); - kfree(b); - return ret; - } - - b->pipe = 1; - ret = dabusb_fpga_clear (s, b); - mdelay (10); - blen = fw->data[73] + (fw->data[72] << 8); - - dbg("Bitstream len: %i", blen); - - b->data[0] = 0x2b; - b->data[1] = 0; - b->data[2] = 0; - b->data[3] = 60; - - for (n = 0; n <= blen + 60; n += 60) { - // some cclks for startup - b->size = 64; - memcpy (b->data + 4, fw->data + 74 + n, 60); - ret = dabusb_bulk (s, b); - if (ret < 0) { - dev_err(&s->usbdev->dev, "dabusb_bulk failed.\n"); - break; - } - mdelay (1); - } - - ret = dabusb_fpga_init (s, b); - kfree (b); - release_firmware(fw); - - dbg("exit dabusb_fpga_download"); - - return ret; -} - -static int dabusb_stop (pdabusb_t s) -{ - dbg("dabusb_stop"); - - s->state = _stopped; - dabusb_cancel_queue (s, &s->rec_buff_list); - - dbg("pending_io: %d", s->pending_io.counter); - - s->pending_io.counter = 0; - return 0; -} - -static int dabusb_startrek (pdabusb_t s) -{ - if (!s->got_mem && s->state != _started) { - - dbg("dabusb_startrek"); - - if (dabusb_alloc_buffers (s) < 0) - return -ENOMEM; - dabusb_stop (s); - s->state = _started; - s->readptr = 0; - } - - if (!list_empty (&s->free_buff_list)) { - pbuff_t end; - int ret; - - while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) { - - dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list); - - end = list_entry (s->rec_buff_list.prev, buff_t, buff_list); - - ret = usb_submit_urb (end->purb, GFP_KERNEL); - if (ret) { - dev_err(&s->usbdev->dev, - "usb_submit_urb returned:%d\n", ret); - if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list)) - dev_err(&s->usbdev->dev, - "startrek: dabusb_add_buf_tail failed\n"); - break; - } - else - atomic_inc (&s->pending_io); - } - dbg("pending_io: %d",s->pending_io.counter); - } - - return 0; -} - -static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, loff_t * ppos) -{ - pdabusb_t s = (pdabusb_t) file->private_data; - unsigned long flags; - unsigned ret = 0; - int rem; - int cnt; - pbuff_t b; - struct urb *purb = NULL; - - dbg("dabusb_read"); - - if (*ppos) - return -ESPIPE; - - if (s->remove_pending) - return -EIO; - - - if (!s->usbdev) - return -EIO; - - while (count > 0) { - dabusb_startrek (s); - - spin_lock_irqsave (&s->lock, flags); - - if (list_empty (&s->rec_buff_list)) { - - spin_unlock_irqrestore(&s->lock, flags); - - dev_err(&s->usbdev->dev, - "error: rec_buf_list is empty\n"); - goto err; - } - - b = list_entry (s->rec_buff_list.next, buff_t, buff_list); - purb = b->purb; - - spin_unlock_irqrestore(&s->lock, flags); - - if (purb->status == -EINPROGRESS) { - if (file->f_flags & O_NONBLOCK) // return nonblocking - { - if (!ret) - ret = -EAGAIN; - goto err; - } - - interruptible_sleep_on (&s->wait); - - if (signal_pending (current)) { - if (!ret) - ret = -ERESTARTSYS; - goto err; - } - - spin_lock_irqsave (&s->lock, flags); - - if (list_empty (&s->rec_buff_list)) { - spin_unlock_irqrestore(&s->lock, flags); - dev_err(&s->usbdev->dev, - "error: still no buffer available.\n"); - goto err; - } - spin_unlock_irqrestore(&s->lock, flags); - s->readptr = 0; - } - if (s->remove_pending) { - ret = -EIO; - goto err; - } - - rem = purb->actual_length - s->readptr; // set remaining bytes to copy - - if (count >= rem) - cnt = rem; - else - cnt = count; - - dbg("copy_to_user:%p %p %d",buf, purb->transfer_buffer + s->readptr, cnt); - - if (copy_to_user (buf, purb->transfer_buffer + s->readptr, cnt)) { - dev_err(&s->usbdev->dev, "read: copy_to_user failed\n"); - if (!ret) - ret = -EFAULT; - goto err; - } - - s->readptr += cnt; - count -= cnt; - buf += cnt; - ret += cnt; - - if (s->readptr == purb->actual_length) { - // finished, take next buffer - if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list)) - dev_err(&s->usbdev->dev, - "read: dabusb_add_buf_tail failed\n"); - s->readptr = 0; - } - } - err: //mutex_unlock(&s->mutex); - return ret; -} - -static int dabusb_open (struct inode *inode, struct file *file) -{ - int devnum = iminor(inode); - pdabusb_t s; - int r; - - if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB)) - return -EIO; - - s = &dabusb[devnum - DABUSB_MINOR]; - - dbg("dabusb_open"); - mutex_lock(&s->mutex); - - while (!s->usbdev || s->opened) { - mutex_unlock(&s->mutex); - - if (file->f_flags & O_NONBLOCK) - return -EBUSY; - msleep_interruptible(500); - - if (signal_pending (current)) - return -EAGAIN; - mutex_lock(&s->mutex); - } - if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { - mutex_unlock(&s->mutex); - dev_err(&s->usbdev->dev, "set_interface failed\n"); - return -EINVAL; - } - s->opened = 1; - mutex_unlock(&s->mutex); - - file->f_pos = 0; - file->private_data = s; - - r = nonseekable_open(inode, file); - return r; -} - -static int dabusb_release (struct inode *inode, struct file *file) -{ - pdabusb_t s = (pdabusb_t) file->private_data; - - dbg("dabusb_release"); - - mutex_lock(&s->mutex); - dabusb_stop (s); - dabusb_free_buffers (s); - mutex_unlock(&s->mutex); - - if (!s->remove_pending) { - if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) - dev_err(&s->usbdev->dev, "set_interface failed\n"); - } - else - wake_up (&s->remove_ok); - - s->opened = 0; - return 0; -} - -static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg) -{ - pdabusb_t s = (pdabusb_t) file->private_data; - pbulk_transfer_t pbulk; - int ret = 0; - int version = DABUSB_VERSION; - - dbg("dabusb_ioctl"); - - if (s->remove_pending) - return -EIO; - - mutex_lock(&s->mutex); - - if (!s->usbdev) { - mutex_unlock(&s->mutex); - return -EIO; - } - - switch (cmd) { - - case IOCTL_DAB_BULK: - pbulk = memdup_user((void __user *)arg, - sizeof(bulk_transfer_t)); - - if (IS_ERR(pbulk)) { - ret = PTR_ERR(pbulk); - break; - } - - ret=dabusb_bulk (s, pbulk); - if(ret==0) - if (copy_to_user((void __user *)arg, pbulk, - sizeof(bulk_transfer_t))) - ret = -EFAULT; - kfree (pbulk); - break; - - case IOCTL_DAB_OVERRUNS: - ret = put_user (s->overruns, (unsigned int __user *) arg); - break; - - case IOCTL_DAB_VERSION: - ret = put_user (version, (unsigned int __user *) arg); - break; - - default: - ret = -ENOIOCTLCMD; - break; - } - mutex_unlock(&s->mutex); - return ret; -} - -static const struct file_operations dabusb_fops = -{ - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = dabusb_read, - .unlocked_ioctl = dabusb_ioctl, - .open = dabusb_open, - .release = dabusb_release, -}; - -static char *dabusb_devnode(struct device *dev, mode_t *mode) -{ - return kasprintf(GFP_KERNEL, "usb/%s", dev_name(dev)); -} - -static struct usb_class_driver dabusb_class = { - .name = "dabusb%d", - .devnode = dabusb_devnode, - .fops = &dabusb_fops, - .minor_base = DABUSB_MINOR, -}; - - -/* --------------------------------------------------------------------- */ -static int dabusb_probe (struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *usbdev = interface_to_usbdev(intf); - int retval; - pdabusb_t s; - - dbg("dabusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d", - le16_to_cpu(usbdev->descriptor.idVendor), - le16_to_cpu(usbdev->descriptor.idProduct), - intf->altsetting->desc.bInterfaceNumber); - - /* We don't handle multiple configurations */ - if (usbdev->descriptor.bNumConfigurations != 1) - return -ENODEV; - - if (intf->altsetting->desc.bInterfaceNumber != _DABUSB_IF && - le16_to_cpu(usbdev->descriptor.idProduct) == 0x9999) - return -ENODEV; - - - - s = &dabusb[intf->minor]; - - mutex_lock(&s->mutex); - s->remove_pending = 0; - s->usbdev = usbdev; - s->devnum = intf->minor; - - if (usb_reset_configuration (usbdev) < 0) { - dev_err(&intf->dev, "reset_configuration failed\n"); - goto reject; - } - if (le16_to_cpu(usbdev->descriptor.idProduct) == 0x2131) { - dabusb_loadmem (s, NULL); - goto reject; - } - else { - dabusb_fpga_download (s, NULL); - - if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) { - dev_err(&intf->dev, "set_interface failed\n"); - goto reject; - } - } - dbg("bound to interface: %d", intf->altsetting->desc.bInterfaceNumber); - usb_set_intfdata (intf, s); - mutex_unlock(&s->mutex); - - retval = usb_register_dev(intf, &dabusb_class); - if (retval) { - usb_set_intfdata (intf, NULL); - return -ENOMEM; - } - - return 0; - - reject: - mutex_unlock(&s->mutex); - s->usbdev = NULL; - return -ENODEV; -} - -static void dabusb_disconnect (struct usb_interface *intf) -{ - wait_queue_t __wait; - pdabusb_t s = usb_get_intfdata (intf); - - dbg("dabusb_disconnect"); - - init_waitqueue_entry(&__wait, current); - - usb_set_intfdata (intf, NULL); - if (s) { - usb_deregister_dev (intf, &dabusb_class); - s->remove_pending = 1; - wake_up (&s->wait); - add_wait_queue(&s->remove_ok, &__wait); - set_current_state(TASK_UNINTERRUPTIBLE); - if (s->state == _started) - schedule(); - current->state = TASK_RUNNING; - remove_wait_queue(&s->remove_ok, &__wait); - - s->usbdev = NULL; - s->overruns = 0; - } -} - -static struct usb_device_id dabusb_ids [] = { - // { USB_DEVICE(0x0547, 0x2131) }, /* An2131 chip, no boot ROM */ - { USB_DEVICE(0x0547, 0x9999) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, dabusb_ids); - -static struct usb_driver dabusb_driver = { - .name = "dabusb", - .probe = dabusb_probe, - .disconnect = dabusb_disconnect, - .id_table = dabusb_ids, -}; - -/* --------------------------------------------------------------------- */ - -static int __init dabusb_init (void) -{ - int retval; - unsigned u; - - /* initialize struct */ - for (u = 0; u < NRDABUSB; u++) { - pdabusb_t s = &dabusb[u]; - memset (s, 0, sizeof (dabusb_t)); - mutex_init (&s->mutex); - s->usbdev = NULL; - s->total_buffer_size = buffers; - init_waitqueue_head (&s->wait); - init_waitqueue_head (&s->remove_ok); - spin_lock_init (&s->lock); - INIT_LIST_HEAD (&s->free_buff_list); - INIT_LIST_HEAD (&s->rec_buff_list); - } - - /* register misc device */ - retval = usb_register(&dabusb_driver); - if (retval) - goto out; - - dbg("dabusb_init: driver registered"); - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - -out: - return retval; -} - -static void __exit dabusb_cleanup (void) -{ - dbg("dabusb_cleanup"); - - usb_deregister (&dabusb_driver); -} - -/* --------------------------------------------------------------------- */ - -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE("dabusb/firmware.fw"); -MODULE_FIRMWARE("dabusb/bitstream.bin"); - -module_param(buffers, int, 0); -MODULE_PARM_DESC (buffers, "Number of buffers (default=256)"); - -module_init (dabusb_init); -module_exit (dabusb_cleanup); - -/* --------------------------------------------------------------------- */ diff --git a/drivers/media/video/dabusb.h b/drivers/media/video/dabusb.h deleted file mode 100644 index 00eb34c..0000000 --- a/drivers/media/video/dabusb.h +++ /dev/null @@ -1,85 +0,0 @@ -#define _BULK_DATA_LEN 64 -typedef struct -{ - unsigned char data[_BULK_DATA_LEN]; - unsigned int size; - unsigned int pipe; -}bulk_transfer_t,*pbulk_transfer_t; - -#define DABUSB_MINOR 240 /* some unassigned USB minor */ -#define DABUSB_VERSION 0x1000 -#define IOCTL_DAB_BULK _IOWR('d', 0x30, bulk_transfer_t) -#define IOCTL_DAB_OVERRUNS _IOR('d', 0x15, int) -#define IOCTL_DAB_VERSION _IOR('d', 0x3f, int) - -#ifdef __KERNEL__ - -typedef enum { _stopped=0, _started } driver_state_t; - -typedef struct -{ - struct mutex mutex; - struct usb_device *usbdev; - wait_queue_head_t wait; - wait_queue_head_t remove_ok; - spinlock_t lock; - atomic_t pending_io; - driver_state_t state; - int remove_pending; - int got_mem; - int total_buffer_size; - unsigned int overruns; - int readptr; - int opened; - int devnum; - struct list_head free_buff_list; - struct list_head rec_buff_list; -} dabusb_t,*pdabusb_t; - -typedef struct -{ - pdabusb_t s; - struct urb *purb; - struct list_head buff_list; -} buff_t,*pbuff_t; - -typedef struct -{ - wait_queue_head_t wait; -} bulk_completion_context_t, *pbulk_completion_context_t; - - -#define _DABUSB_IF 2 -#define _DABUSB_ISOPIPE 0x09 -#define _ISOPIPESIZE 16384 - -#define _BULK_DATA_LEN 64 -// Vendor specific request code for Anchor Upload/Download -// This one is implemented in the core -#define ANCHOR_LOAD_INTERNAL 0xA0 - -// EZ-USB Control and Status Register. Bit 0 controls 8051 reset -#define CPUCS_REG 0x7F92 -#define _TOTAL_BUFFERS 384 - -#define MAX_INTEL_HEX_RECORD_LENGTH 16 - -#ifndef _BYTE_DEFINED -#define _BYTE_DEFINED -typedef unsigned char BYTE; -#endif // !_BYTE_DEFINED - -#ifndef _WORD_DEFINED -#define _WORD_DEFINED -typedef unsigned short WORD; -#endif // !_WORD_DEFINED - -typedef struct _INTEL_HEX_RECORD -{ - BYTE Length; - WORD Address; - BYTE Type; - BYTE Data[MAX_INTEL_HEX_RECORD_LENGTH]; -} INTEL_HEX_RECORD, *PINTEL_HEX_RECORD; - -#endif diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 7e7b27b..648142e 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -51,6 +51,8 @@ source "drivers/staging/cx25821/Kconfig" source "drivers/staging/tm6000/Kconfig" +source "drivers/staging/dabusb/Kconfig" + source "drivers/staging/se401/Kconfig" source "drivers/staging/usbvideo/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 72e0c83..8185c00 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_SLICOSS) += slicoss/ obj-$(CONFIG_VIDEO_GO7007) += go7007/ obj-$(CONFIG_VIDEO_CX25821) += cx25821/ obj-$(CONFIG_VIDEO_TM6000) += tm6000/ +obj-$(CONFIG_USB_DABUSB) += dabusb/ obj-$(CONFIG_USB_VICAM) += usbvideo/ obj-$(CONFIG_USB_SE401) += se401/ obj-$(CONFIG_LIRC_STAGING) += lirc/ diff --git a/drivers/staging/dabusb/Kconfig b/drivers/staging/dabusb/Kconfig new file mode 100644 index 0000000..87bdc42 --- /dev/null +++ b/drivers/staging/dabusb/Kconfig @@ -0,0 +1,14 @@ +config USB_DABUSB + tristate "DABUSB driver" + depends on USB + ---help--- + A Digital Audio Broadcasting (DAB) Receiver for USB and Linux + brought to you by the DAB-Team + . This driver can be taken + as an example for URB-based bulk, control, and isochronous + transactions. URB's are explained in + . + + To compile this driver as a module, choose M here: the + module will be called dabusb. + diff --git a/drivers/staging/dabusb/Makefile b/drivers/staging/dabusb/Makefile new file mode 100644 index 0000000..2ff2f22 --- /dev/null +++ b/drivers/staging/dabusb/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_USB_DABUSB) += dabusb.o + diff --git a/drivers/staging/dabusb/TODO b/drivers/staging/dabusb/TODO new file mode 100644 index 0000000..f9c0314 --- /dev/null +++ b/drivers/staging/dabusb/TODO @@ -0,0 +1,5 @@ +This is a driver for an experimental sample developed in 2003. The driver +never supported any commercial product, nor had any known user. +If nobody takes care on it, the driver will be removed for 2.6.39. + +Please send patches to linux-media@vger.kernel.org diff --git a/drivers/staging/dabusb/dabusb.c b/drivers/staging/dabusb/dabusb.c new file mode 100644 index 0000000..f3e25e9 --- /dev/null +++ b/drivers/staging/dabusb/dabusb.c @@ -0,0 +1,914 @@ +/*****************************************************************************/ + +/* + * dabusb.c -- dab usb driver. + * + * Copyright (C) 1999 Deti Fliegl (deti@fliegl.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * + * $Id: dabusb.c,v 1.54 2000/07/24 21:39:39 deti Exp $ + * + */ + +/*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dabusb.h" + +/* + * Version Information + */ +#define DRIVER_VERSION "v1.54" +#define DRIVER_AUTHOR "Deti Fliegl, deti@fliegl.de" +#define DRIVER_DESC "DAB-USB Interface Driver for Linux (c)1999" + +/* --------------------------------------------------------------------- */ + +#ifdef CONFIG_USB_DYNAMIC_MINORS +#define NRDABUSB 256 +#else +#define NRDABUSB 4 +#endif + +/*-------------------------------------------------------------------*/ + +static dabusb_t dabusb[NRDABUSB]; +static int buffers = 256; +static struct usb_driver dabusb_driver; + +/*-------------------------------------------------------------------*/ + +static int dabusb_add_buf_tail (pdabusb_t s, struct list_head *dst, struct list_head *src) +{ + unsigned long flags; + struct list_head *tmp; + int ret = 0; + + spin_lock_irqsave (&s->lock, flags); + + if (list_empty (src)) { + // no elements in source buffer + ret = -1; + goto err; + } + tmp = src->next; + list_move_tail (tmp, dst); + + err: spin_unlock_irqrestore (&s->lock, flags); + return ret; +} +/*-------------------------------------------------------------------*/ +#ifdef DEBUG +static void dump_urb (struct urb *urb) +{ + dbg("urb :%p", urb); + dbg("dev :%p", urb->dev); + dbg("pipe :%08X", urb->pipe); + dbg("status :%d", urb->status); + dbg("transfer_flags :%08X", urb->transfer_flags); + dbg("transfer_buffer :%p", urb->transfer_buffer); + dbg("transfer_buffer_length:%d", urb->transfer_buffer_length); + dbg("actual_length :%d", urb->actual_length); + dbg("setup_packet :%p", urb->setup_packet); + dbg("start_frame :%d", urb->start_frame); + dbg("number_of_packets :%d", urb->number_of_packets); + dbg("interval :%d", urb->interval); + dbg("error_count :%d", urb->error_count); + dbg("context :%p", urb->context); + dbg("complete :%p", urb->complete); +} +#endif +/*-------------------------------------------------------------------*/ +static int dabusb_cancel_queue (pdabusb_t s, struct list_head *q) +{ + unsigned long flags; + pbuff_t b; + + dbg("dabusb_cancel_queue"); + + spin_lock_irqsave (&s->lock, flags); + + list_for_each_entry(b, q, buff_list) { +#ifdef DEBUG + dump_urb(b->purb); +#endif + usb_unlink_urb (b->purb); + } + spin_unlock_irqrestore (&s->lock, flags); + return 0; +} +/*-------------------------------------------------------------------*/ +static int dabusb_free_queue (struct list_head *q) +{ + struct list_head *tmp; + struct list_head *p; + pbuff_t b; + + dbg("dabusb_free_queue"); + for (p = q->next; p != q;) { + b = list_entry (p, buff_t, buff_list); + +#ifdef DEBUG + dump_urb(b->purb); +#endif + kfree(b->purb->transfer_buffer); + usb_free_urb(b->purb); + tmp = p->next; + list_del (p); + kfree (b); + p = tmp; + } + + return 0; +} +/*-------------------------------------------------------------------*/ +static int dabusb_free_buffers (pdabusb_t s) +{ + unsigned long flags; + dbg("dabusb_free_buffers"); + + spin_lock_irqsave(&s->lock, flags); + + dabusb_free_queue (&s->free_buff_list); + dabusb_free_queue (&s->rec_buff_list); + + spin_unlock_irqrestore(&s->lock, flags); + + s->got_mem = 0; + return 0; +} +/*-------------------------------------------------------------------*/ +static void dabusb_iso_complete (struct urb *purb) +{ + pbuff_t b = purb->context; + pdabusb_t s = b->s; + int i; + int len; + int dst = 0; + void *buf = purb->transfer_buffer; + + dbg("dabusb_iso_complete"); + + // process if URB was not killed + if (purb->status != -ENOENT) { + unsigned int pipe = usb_rcvisocpipe (purb->dev, _DABUSB_ISOPIPE); + int pipesize = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe)); + for (i = 0; i < purb->number_of_packets; i++) + if (!purb->iso_frame_desc[i].status) { + len = purb->iso_frame_desc[i].actual_length; + if (len <= pipesize) { + memcpy (buf + dst, buf + purb->iso_frame_desc[i].offset, len); + dst += len; + } + else + dev_err(&purb->dev->dev, + "dabusb_iso_complete: invalid len %d\n", len); + } + else + dev_warn(&purb->dev->dev, "dabusb_iso_complete: corrupted packet status: %d\n", purb->iso_frame_desc[i].status); + if (dst != purb->actual_length) + dev_err(&purb->dev->dev, + "dst!=purb->actual_length:%d!=%d\n", + dst, purb->actual_length); + } + + if (atomic_dec_and_test (&s->pending_io) && !s->remove_pending && s->state != _stopped) { + s->overruns++; + dev_err(&purb->dev->dev, "overrun (%d)\n", s->overruns); + } + wake_up (&s->wait); +} +/*-------------------------------------------------------------------*/ +static int dabusb_alloc_buffers (pdabusb_t s) +{ + int transfer_len = 0; + pbuff_t b; + unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE); + int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe)); + int packets = _ISOPIPESIZE / pipesize; + int transfer_buffer_length = packets * pipesize; + int i; + + dbg("dabusb_alloc_buffers pipesize:%d packets:%d transfer_buffer_len:%d", + pipesize, packets, transfer_buffer_length); + + while (transfer_len < (s->total_buffer_size << 10)) { + b = kzalloc(sizeof (buff_t), GFP_KERNEL); + if (!b) { + dev_err(&s->usbdev->dev, + "kzalloc(sizeof(buff_t))==NULL\n"); + goto err; + } + b->s = s; + b->purb = usb_alloc_urb(packets, GFP_KERNEL); + if (!b->purb) { + dev_err(&s->usbdev->dev, "usb_alloc_urb == NULL\n"); + kfree (b); + goto err; + } + + b->purb->transfer_buffer = kmalloc (transfer_buffer_length, GFP_KERNEL); + if (!b->purb->transfer_buffer) { + kfree (b->purb); + kfree (b); + dev_err(&s->usbdev->dev, + "kmalloc(%d)==NULL\n", transfer_buffer_length); + goto err; + } + + b->purb->transfer_buffer_length = transfer_buffer_length; + b->purb->number_of_packets = packets; + b->purb->complete = dabusb_iso_complete; + b->purb->context = b; + b->purb->dev = s->usbdev; + b->purb->pipe = pipe; + b->purb->transfer_flags = URB_ISO_ASAP; + + for (i = 0; i < packets; i++) { + b->purb->iso_frame_desc[i].offset = i * pipesize; + b->purb->iso_frame_desc[i].length = pipesize; + } + + transfer_len += transfer_buffer_length; + list_add_tail (&b->buff_list, &s->free_buff_list); + } + s->got_mem = transfer_len; + + return 0; + + err: + dabusb_free_buffers (s); + return -ENOMEM; +} +/*-------------------------------------------------------------------*/ +static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb) +{ + int ret; + unsigned int pipe; + int actual_length; + + dbg("dabusb_bulk"); + + if (!pb->pipe) + pipe = usb_rcvbulkpipe (s->usbdev, 2); + else + pipe = usb_sndbulkpipe (s->usbdev, 2); + + ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 100); + if(ret<0) { + dev_err(&s->usbdev->dev, + "usb_bulk_msg failed(%d)\n", ret); + + if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { + dev_err(&s->usbdev->dev, "set_interface failed\n"); + return -EINVAL; + } + + } + + if( ret == -EPIPE ) { + dev_warn(&s->usbdev->dev, "CLEAR_FEATURE request to remove STALL condition.\n"); + if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe))) + dev_err(&s->usbdev->dev, "request failed\n"); + } + + pb->size = actual_length; + return ret; +} +/* --------------------------------------------------------------------- */ +static int dabusb_writemem (pdabusb_t s, int pos, const unsigned char *data, + int len) +{ + int ret; + unsigned char *transfer_buffer = kmalloc (len, GFP_KERNEL); + + if (!transfer_buffer) { + dev_err(&s->usbdev->dev, + "dabusb_writemem: kmalloc(%d) failed.\n", len); + return -ENOMEM; + } + + memcpy (transfer_buffer, data, len); + + ret=usb_control_msg(s->usbdev, usb_sndctrlpipe( s->usbdev, 0 ), 0xa0, 0x40, pos, 0, transfer_buffer, len, 300); + + kfree (transfer_buffer); + return ret; +} +/* --------------------------------------------------------------------- */ +static int dabusb_8051_reset (pdabusb_t s, unsigned char reset_bit) +{ + dbg("dabusb_8051_reset: %d",reset_bit); + return dabusb_writemem (s, CPUCS_REG, &reset_bit, 1); +} +/* --------------------------------------------------------------------- */ +static int dabusb_loadmem (pdabusb_t s, const char *fname) +{ + int ret; + const struct ihex_binrec *rec; + const struct firmware *uninitialized_var(fw); + + dbg("Enter dabusb_loadmem (internal)"); + + ret = request_ihex_firmware(&fw, "dabusb/firmware.fw", &s->usbdev->dev); + if (ret) { + dev_err(&s->usbdev->dev, + "Failed to load \"dabusb/firmware.fw\": %d\n", ret); + goto out; + } + ret = dabusb_8051_reset (s, 1); + + for (rec = (const struct ihex_binrec *)fw->data; rec; + rec = ihex_next_binrec(rec)) { + dbg("dabusb_writemem: %04X %p %d)", be32_to_cpu(rec->addr), + rec->data, be16_to_cpu(rec->len)); + + ret = dabusb_writemem(s, be32_to_cpu(rec->addr), rec->data, + be16_to_cpu(rec->len)); + if (ret < 0) { + dev_err(&s->usbdev->dev, + "dabusb_writemem failed (%d %04X %p %d)\n", + ret, be32_to_cpu(rec->addr), + rec->data, be16_to_cpu(rec->len)); + break; + } + } + ret = dabusb_8051_reset (s, 0); + release_firmware(fw); + out: + dbg("dabusb_loadmem: exit"); + + return ret; +} +/* --------------------------------------------------------------------- */ +static int dabusb_fpga_clear (pdabusb_t s, pbulk_transfer_t b) +{ + b->size = 4; + b->data[0] = 0x2a; + b->data[1] = 0; + b->data[2] = 0; + b->data[3] = 0; + + dbg("dabusb_fpga_clear"); + + return dabusb_bulk (s, b); +} +/* --------------------------------------------------------------------- */ +static int dabusb_fpga_init (pdabusb_t s, pbulk_transfer_t b) +{ + b->size = 4; + b->data[0] = 0x2c; + b->data[1] = 0; + b->data[2] = 0; + b->data[3] = 0; + + dbg("dabusb_fpga_init"); + + return dabusb_bulk (s, b); +} +/* --------------------------------------------------------------------- */ +static int dabusb_fpga_download (pdabusb_t s, const char *fname) +{ + pbulk_transfer_t b = kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL); + const struct firmware *fw; + unsigned int blen, n; + int ret; + + dbg("Enter dabusb_fpga_download (internal)"); + + if (!b) { + dev_err(&s->usbdev->dev, + "kmalloc(sizeof(bulk_transfer_t))==NULL\n"); + return -ENOMEM; + } + + ret = request_firmware(&fw, "dabusb/bitstream.bin", &s->usbdev->dev); + if (ret) { + dev_err(&s->usbdev->dev, + "Failed to load \"dabusb/bitstream.bin\": %d\n", ret); + kfree(b); + return ret; + } + + b->pipe = 1; + ret = dabusb_fpga_clear (s, b); + mdelay (10); + blen = fw->data[73] + (fw->data[72] << 8); + + dbg("Bitstream len: %i", blen); + + b->data[0] = 0x2b; + b->data[1] = 0; + b->data[2] = 0; + b->data[3] = 60; + + for (n = 0; n <= blen + 60; n += 60) { + // some cclks for startup + b->size = 64; + memcpy (b->data + 4, fw->data + 74 + n, 60); + ret = dabusb_bulk (s, b); + if (ret < 0) { + dev_err(&s->usbdev->dev, "dabusb_bulk failed.\n"); + break; + } + mdelay (1); + } + + ret = dabusb_fpga_init (s, b); + kfree (b); + release_firmware(fw); + + dbg("exit dabusb_fpga_download"); + + return ret; +} + +static int dabusb_stop (pdabusb_t s) +{ + dbg("dabusb_stop"); + + s->state = _stopped; + dabusb_cancel_queue (s, &s->rec_buff_list); + + dbg("pending_io: %d", s->pending_io.counter); + + s->pending_io.counter = 0; + return 0; +} + +static int dabusb_startrek (pdabusb_t s) +{ + if (!s->got_mem && s->state != _started) { + + dbg("dabusb_startrek"); + + if (dabusb_alloc_buffers (s) < 0) + return -ENOMEM; + dabusb_stop (s); + s->state = _started; + s->readptr = 0; + } + + if (!list_empty (&s->free_buff_list)) { + pbuff_t end; + int ret; + + while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) { + + dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list); + + end = list_entry (s->rec_buff_list.prev, buff_t, buff_list); + + ret = usb_submit_urb (end->purb, GFP_KERNEL); + if (ret) { + dev_err(&s->usbdev->dev, + "usb_submit_urb returned:%d\n", ret); + if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list)) + dev_err(&s->usbdev->dev, + "startrek: dabusb_add_buf_tail failed\n"); + break; + } + else + atomic_inc (&s->pending_io); + } + dbg("pending_io: %d",s->pending_io.counter); + } + + return 0; +} + +static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, loff_t * ppos) +{ + pdabusb_t s = (pdabusb_t) file->private_data; + unsigned long flags; + unsigned ret = 0; + int rem; + int cnt; + pbuff_t b; + struct urb *purb = NULL; + + dbg("dabusb_read"); + + if (*ppos) + return -ESPIPE; + + if (s->remove_pending) + return -EIO; + + + if (!s->usbdev) + return -EIO; + + while (count > 0) { + dabusb_startrek (s); + + spin_lock_irqsave (&s->lock, flags); + + if (list_empty (&s->rec_buff_list)) { + + spin_unlock_irqrestore(&s->lock, flags); + + dev_err(&s->usbdev->dev, + "error: rec_buf_list is empty\n"); + goto err; + } + + b = list_entry (s->rec_buff_list.next, buff_t, buff_list); + purb = b->purb; + + spin_unlock_irqrestore(&s->lock, flags); + + if (purb->status == -EINPROGRESS) { + if (file->f_flags & O_NONBLOCK) // return nonblocking + { + if (!ret) + ret = -EAGAIN; + goto err; + } + + interruptible_sleep_on (&s->wait); + + if (signal_pending (current)) { + if (!ret) + ret = -ERESTARTSYS; + goto err; + } + + spin_lock_irqsave (&s->lock, flags); + + if (list_empty (&s->rec_buff_list)) { + spin_unlock_irqrestore(&s->lock, flags); + dev_err(&s->usbdev->dev, + "error: still no buffer available.\n"); + goto err; + } + spin_unlock_irqrestore(&s->lock, flags); + s->readptr = 0; + } + if (s->remove_pending) { + ret = -EIO; + goto err; + } + + rem = purb->actual_length - s->readptr; // set remaining bytes to copy + + if (count >= rem) + cnt = rem; + else + cnt = count; + + dbg("copy_to_user:%p %p %d",buf, purb->transfer_buffer + s->readptr, cnt); + + if (copy_to_user (buf, purb->transfer_buffer + s->readptr, cnt)) { + dev_err(&s->usbdev->dev, "read: copy_to_user failed\n"); + if (!ret) + ret = -EFAULT; + goto err; + } + + s->readptr += cnt; + count -= cnt; + buf += cnt; + ret += cnt; + + if (s->readptr == purb->actual_length) { + // finished, take next buffer + if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list)) + dev_err(&s->usbdev->dev, + "read: dabusb_add_buf_tail failed\n"); + s->readptr = 0; + } + } + err: //mutex_unlock(&s->mutex); + return ret; +} + +static int dabusb_open (struct inode *inode, struct file *file) +{ + int devnum = iminor(inode); + pdabusb_t s; + int r; + + if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB)) + return -EIO; + + s = &dabusb[devnum - DABUSB_MINOR]; + + dbg("dabusb_open"); + mutex_lock(&s->mutex); + + while (!s->usbdev || s->opened) { + mutex_unlock(&s->mutex); + + if (file->f_flags & O_NONBLOCK) + return -EBUSY; + msleep_interruptible(500); + + if (signal_pending (current)) + return -EAGAIN; + mutex_lock(&s->mutex); + } + if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { + mutex_unlock(&s->mutex); + dev_err(&s->usbdev->dev, "set_interface failed\n"); + return -EINVAL; + } + s->opened = 1; + mutex_unlock(&s->mutex); + + file->f_pos = 0; + file->private_data = s; + + r = nonseekable_open(inode, file); + return r; +} + +static int dabusb_release (struct inode *inode, struct file *file) +{ + pdabusb_t s = (pdabusb_t) file->private_data; + + dbg("dabusb_release"); + + mutex_lock(&s->mutex); + dabusb_stop (s); + dabusb_free_buffers (s); + mutex_unlock(&s->mutex); + + if (!s->remove_pending) { + if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) + dev_err(&s->usbdev->dev, "set_interface failed\n"); + } + else + wake_up (&s->remove_ok); + + s->opened = 0; + return 0; +} + +static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg) +{ + pdabusb_t s = (pdabusb_t) file->private_data; + pbulk_transfer_t pbulk; + int ret = 0; + int version = DABUSB_VERSION; + + dbg("dabusb_ioctl"); + + if (s->remove_pending) + return -EIO; + + mutex_lock(&s->mutex); + + if (!s->usbdev) { + mutex_unlock(&s->mutex); + return -EIO; + } + + switch (cmd) { + + case IOCTL_DAB_BULK: + pbulk = memdup_user((void __user *)arg, + sizeof(bulk_transfer_t)); + + if (IS_ERR(pbulk)) { + ret = PTR_ERR(pbulk); + break; + } + + ret=dabusb_bulk (s, pbulk); + if(ret==0) + if (copy_to_user((void __user *)arg, pbulk, + sizeof(bulk_transfer_t))) + ret = -EFAULT; + kfree (pbulk); + break; + + case IOCTL_DAB_OVERRUNS: + ret = put_user (s->overruns, (unsigned int __user *) arg); + break; + + case IOCTL_DAB_VERSION: + ret = put_user (version, (unsigned int __user *) arg); + break; + + default: + ret = -ENOIOCTLCMD; + break; + } + mutex_unlock(&s->mutex); + return ret; +} + +static const struct file_operations dabusb_fops = +{ + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = dabusb_read, + .unlocked_ioctl = dabusb_ioctl, + .open = dabusb_open, + .release = dabusb_release, +}; + +static char *dabusb_devnode(struct device *dev, mode_t *mode) +{ + return kasprintf(GFP_KERNEL, "usb/%s", dev_name(dev)); +} + +static struct usb_class_driver dabusb_class = { + .name = "dabusb%d", + .devnode = dabusb_devnode, + .fops = &dabusb_fops, + .minor_base = DABUSB_MINOR, +}; + + +/* --------------------------------------------------------------------- */ +static int dabusb_probe (struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *usbdev = interface_to_usbdev(intf); + int retval; + pdabusb_t s; + + dbg("dabusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d", + le16_to_cpu(usbdev->descriptor.idVendor), + le16_to_cpu(usbdev->descriptor.idProduct), + intf->altsetting->desc.bInterfaceNumber); + + /* We don't handle multiple configurations */ + if (usbdev->descriptor.bNumConfigurations != 1) + return -ENODEV; + + if (intf->altsetting->desc.bInterfaceNumber != _DABUSB_IF && + le16_to_cpu(usbdev->descriptor.idProduct) == 0x9999) + return -ENODEV; + + + + s = &dabusb[intf->minor]; + + mutex_lock(&s->mutex); + s->remove_pending = 0; + s->usbdev = usbdev; + s->devnum = intf->minor; + + if (usb_reset_configuration (usbdev) < 0) { + dev_err(&intf->dev, "reset_configuration failed\n"); + goto reject; + } + if (le16_to_cpu(usbdev->descriptor.idProduct) == 0x2131) { + dabusb_loadmem (s, NULL); + goto reject; + } + else { + dabusb_fpga_download (s, NULL); + + if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) { + dev_err(&intf->dev, "set_interface failed\n"); + goto reject; + } + } + dbg("bound to interface: %d", intf->altsetting->desc.bInterfaceNumber); + usb_set_intfdata (intf, s); + mutex_unlock(&s->mutex); + + retval = usb_register_dev(intf, &dabusb_class); + if (retval) { + usb_set_intfdata (intf, NULL); + return -ENOMEM; + } + + return 0; + + reject: + mutex_unlock(&s->mutex); + s->usbdev = NULL; + return -ENODEV; +} + +static void dabusb_disconnect (struct usb_interface *intf) +{ + wait_queue_t __wait; + pdabusb_t s = usb_get_intfdata (intf); + + dbg("dabusb_disconnect"); + + init_waitqueue_entry(&__wait, current); + + usb_set_intfdata (intf, NULL); + if (s) { + usb_deregister_dev (intf, &dabusb_class); + s->remove_pending = 1; + wake_up (&s->wait); + add_wait_queue(&s->remove_ok, &__wait); + set_current_state(TASK_UNINTERRUPTIBLE); + if (s->state == _started) + schedule(); + current->state = TASK_RUNNING; + remove_wait_queue(&s->remove_ok, &__wait); + + s->usbdev = NULL; + s->overruns = 0; + } +} + +static struct usb_device_id dabusb_ids [] = { + // { USB_DEVICE(0x0547, 0x2131) }, /* An2131 chip, no boot ROM */ + { USB_DEVICE(0x0547, 0x9999) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, dabusb_ids); + +static struct usb_driver dabusb_driver = { + .name = "dabusb", + .probe = dabusb_probe, + .disconnect = dabusb_disconnect, + .id_table = dabusb_ids, +}; + +/* --------------------------------------------------------------------- */ + +static int __init dabusb_init (void) +{ + int retval; + unsigned u; + + /* initialize struct */ + for (u = 0; u < NRDABUSB; u++) { + pdabusb_t s = &dabusb[u]; + memset (s, 0, sizeof (dabusb_t)); + mutex_init (&s->mutex); + s->usbdev = NULL; + s->total_buffer_size = buffers; + init_waitqueue_head (&s->wait); + init_waitqueue_head (&s->remove_ok); + spin_lock_init (&s->lock); + INIT_LIST_HEAD (&s->free_buff_list); + INIT_LIST_HEAD (&s->rec_buff_list); + } + + /* register misc device */ + retval = usb_register(&dabusb_driver); + if (retval) + goto out; + + dbg("dabusb_init: driver registered"); + + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); + +out: + return retval; +} + +static void __exit dabusb_cleanup (void) +{ + dbg("dabusb_cleanup"); + + usb_deregister (&dabusb_driver); +} + +/* --------------------------------------------------------------------- */ + +MODULE_AUTHOR( DRIVER_AUTHOR ); +MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE("dabusb/firmware.fw"); +MODULE_FIRMWARE("dabusb/bitstream.bin"); + +module_param(buffers, int, 0); +MODULE_PARM_DESC (buffers, "Number of buffers (default=256)"); + +module_init (dabusb_init); +module_exit (dabusb_cleanup); + +/* --------------------------------------------------------------------- */ diff --git a/drivers/staging/dabusb/dabusb.h b/drivers/staging/dabusb/dabusb.h new file mode 100644 index 0000000..00eb34c --- /dev/null +++ b/drivers/staging/dabusb/dabusb.h @@ -0,0 +1,85 @@ +#define _BULK_DATA_LEN 64 +typedef struct +{ + unsigned char data[_BULK_DATA_LEN]; + unsigned int size; + unsigned int pipe; +}bulk_transfer_t,*pbulk_transfer_t; + +#define DABUSB_MINOR 240 /* some unassigned USB minor */ +#define DABUSB_VERSION 0x1000 +#define IOCTL_DAB_BULK _IOWR('d', 0x30, bulk_transfer_t) +#define IOCTL_DAB_OVERRUNS _IOR('d', 0x15, int) +#define IOCTL_DAB_VERSION _IOR('d', 0x3f, int) + +#ifdef __KERNEL__ + +typedef enum { _stopped=0, _started } driver_state_t; + +typedef struct +{ + struct mutex mutex; + struct usb_device *usbdev; + wait_queue_head_t wait; + wait_queue_head_t remove_ok; + spinlock_t lock; + atomic_t pending_io; + driver_state_t state; + int remove_pending; + int got_mem; + int total_buffer_size; + unsigned int overruns; + int readptr; + int opened; + int devnum; + struct list_head free_buff_list; + struct list_head rec_buff_list; +} dabusb_t,*pdabusb_t; + +typedef struct +{ + pdabusb_t s; + struct urb *purb; + struct list_head buff_list; +} buff_t,*pbuff_t; + +typedef struct +{ + wait_queue_head_t wait; +} bulk_completion_context_t, *pbulk_completion_context_t; + + +#define _DABUSB_IF 2 +#define _DABUSB_ISOPIPE 0x09 +#define _ISOPIPESIZE 16384 + +#define _BULK_DATA_LEN 64 +// Vendor specific request code for Anchor Upload/Download +// This one is implemented in the core +#define ANCHOR_LOAD_INTERNAL 0xA0 + +// EZ-USB Control and Status Register. Bit 0 controls 8051 reset +#define CPUCS_REG 0x7F92 +#define _TOTAL_BUFFERS 384 + +#define MAX_INTEL_HEX_RECORD_LENGTH 16 + +#ifndef _BYTE_DEFINED +#define _BYTE_DEFINED +typedef unsigned char BYTE; +#endif // !_BYTE_DEFINED + +#ifndef _WORD_DEFINED +#define _WORD_DEFINED +typedef unsigned short WORD; +#endif // !_WORD_DEFINED + +typedef struct _INTEL_HEX_RECORD +{ + BYTE Length; + WORD Address; + BYTE Type; + BYTE Data[MAX_INTEL_HEX_RECORD_LENGTH]; +} INTEL_HEX_RECORD, *PINTEL_HEX_RECORD; + +#endif -- cgit v0.10.2 From 730726a6f90740a5954ca2fb1c74fad6f44a2c42 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Mon, 27 Dec 2010 15:41:58 -0300 Subject: [media] DVB: Set scanmask for Budget/SAA7146 cards These devices do not return the full command+address, so set scanmask accordingly. Signed-off-by: David Henningsson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 8ae67c1..b82756d 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -184,6 +184,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) dev->input_phys = budget_ci->ir.phys; dev->input_id.bustype = BUS_PCI; dev->input_id.version = 1; + dev->scanmask = 0xff; if (saa->pci->subsystem_vendor) { dev->input_id.vendor = saa->pci->subsystem_vendor; dev->input_id.product = saa->pci->subsystem_device; -- cgit v0.10.2 From db9285f79b12286a3b525b41ab275796679c1dfa Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Mon, 27 Dec 2010 15:45:19 -0300 Subject: [media] MEDIA: RC: Provide full scancodes for TT-1500 remote control Add 0x15 prefix to scancodes for TT-1500 remote control. Signed-off-by: David Henningsson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/keymaps/rc-tt-1500.c b/drivers/media/rc/keymaps/rc-tt-1500.c index bb19487..295f373 100644 --- a/drivers/media/rc/keymaps/rc-tt-1500.c +++ b/drivers/media/rc/keymaps/rc-tt-1500.c @@ -15,45 +15,45 @@ /* for the Technotrend 1500 bundled remotes (grey and black): */ static struct rc_map_table tt_1500[] = { - { 0x01, KEY_POWER }, - { 0x02, KEY_SHUFFLE }, /* ? double-arrow key */ - { 0x03, KEY_1 }, - { 0x04, KEY_2 }, - { 0x05, KEY_3 }, - { 0x06, KEY_4 }, - { 0x07, KEY_5 }, - { 0x08, KEY_6 }, - { 0x09, KEY_7 }, - { 0x0a, KEY_8 }, - { 0x0b, KEY_9 }, - { 0x0c, KEY_0 }, - { 0x0d, KEY_UP }, - { 0x0e, KEY_LEFT }, - { 0x0f, KEY_OK }, - { 0x10, KEY_RIGHT }, - { 0x11, KEY_DOWN }, - { 0x12, KEY_INFO }, - { 0x13, KEY_EXIT }, - { 0x14, KEY_RED }, - { 0x15, KEY_GREEN }, - { 0x16, KEY_YELLOW }, - { 0x17, KEY_BLUE }, - { 0x18, KEY_MUTE }, - { 0x19, KEY_TEXT }, - { 0x1a, KEY_MODE }, /* ? TV/Radio */ - { 0x21, KEY_OPTION }, - { 0x22, KEY_EPG }, - { 0x23, KEY_CHANNELUP }, - { 0x24, KEY_CHANNELDOWN }, - { 0x25, KEY_VOLUMEUP }, - { 0x26, KEY_VOLUMEDOWN }, - { 0x27, KEY_SETUP }, - { 0x3a, KEY_RECORD }, /* these keys are only in the black remote */ - { 0x3b, KEY_PLAY }, - { 0x3c, KEY_STOP }, - { 0x3d, KEY_REWIND }, - { 0x3e, KEY_PAUSE }, - { 0x3f, KEY_FORWARD }, + { 0x1501, KEY_POWER }, + { 0x1502, KEY_SHUFFLE }, /* ? double-arrow key */ + { 0x1503, KEY_1 }, + { 0x1504, KEY_2 }, + { 0x1505, KEY_3 }, + { 0x1506, KEY_4 }, + { 0x1507, KEY_5 }, + { 0x1508, KEY_6 }, + { 0x1509, KEY_7 }, + { 0x150a, KEY_8 }, + { 0x150b, KEY_9 }, + { 0x150c, KEY_0 }, + { 0x150d, KEY_UP }, + { 0x150e, KEY_LEFT }, + { 0x150f, KEY_OK }, + { 0x1510, KEY_RIGHT }, + { 0x1511, KEY_DOWN }, + { 0x1512, KEY_INFO }, + { 0x1513, KEY_EXIT }, + { 0x1514, KEY_RED }, + { 0x1515, KEY_GREEN }, + { 0x1516, KEY_YELLOW }, + { 0x1517, KEY_BLUE }, + { 0x1518, KEY_MUTE }, + { 0x1519, KEY_TEXT }, + { 0x151a, KEY_MODE }, /* ? TV/Radio */ + { 0x1521, KEY_OPTION }, + { 0x1522, KEY_EPG }, + { 0x1523, KEY_CHANNELUP }, + { 0x1524, KEY_CHANNELDOWN }, + { 0x1525, KEY_VOLUMEUP }, + { 0x1526, KEY_VOLUMEDOWN }, + { 0x1527, KEY_SETUP }, + { 0x153a, KEY_RECORD }, /* these keys are only in the black remote */ + { 0x153b, KEY_PLAY }, + { 0x153c, KEY_STOP }, + { 0x153d, KEY_REWIND }, + { 0x153e, KEY_PAUSE }, + { 0x153f, KEY_FORWARD }, }; static struct rc_map_list tt_1500_map = { -- cgit v0.10.2 From 641d21167f66ef4c574ef4f586fec0ae32179acd Mon Sep 17 00:00:00 2001 From: Dmitri Belimov Date: Wed, 22 Dec 2010 05:57:46 -0300 Subject: [media] tm6000: rework and fix IR Hi This patch didn't kill Stefan's remotes and just for upload my good part of code. 1. Add some code for show IR activity 2. Add filter for IR remotes 3. Split remotes to different types. 4. Fix stop interrupt pipe when isoc pipe started. When we decide general way of IR I'll add support our remotes. For our customers I'll made custom temporary patch without this part. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/tm6000/TODO b/drivers/staging/tm6000/TODO index 34780fc..135d0ea 100644 --- a/drivers/staging/tm6000/TODO +++ b/drivers/staging/tm6000/TODO @@ -1,4 +1,6 @@ There a few things to do before putting this driver in production: + - IR NEC with tm5600/6000 TV cards + - IR RC5 with tm5600/6000/6010 TV cards - CodingStyle; - Fix audio; - Fix some panic/OOPS conditions. diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c index 5a7946c..455038b 100644 --- a/drivers/staging/tm6000/tm6000-cards.c +++ b/drivers/staging/tm6000/tm6000-cards.c @@ -328,6 +328,47 @@ struct usb_device_id tm6000_id_table[] = { { }, }; +/* Control power led for show some activity */ +void tm6000_flash_led(struct tm6000_core *dev, u8 state) +{ + /* Power LED unconfigured */ + if (!dev->gpio.power_led) + return; + + /* ON Power LED */ + if (state) { + switch (dev->model) { + case TM6010_BOARD_HAUPPAUGE_900H: + case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: + case TM6010_BOARD_TWINHAN_TU501: + tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, + dev->gpio.power_led, 0x00); + break; + case TM6010_BOARD_BEHOLD_WANDER: + case TM6010_BOARD_BEHOLD_VOYAGER: + tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, + dev->gpio.power_led, 0x01); + break; + } + } + /* OFF Power LED */ + else { + switch (dev->model) { + case TM6010_BOARD_HAUPPAUGE_900H: + case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: + case TM6010_BOARD_TWINHAN_TU501: + tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, + dev->gpio.power_led, 0x01); + break; + case TM6010_BOARD_BEHOLD_WANDER: + case TM6010_BOARD_BEHOLD_VOYAGER: + tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, + dev->gpio.power_led, 0x00); + break; + } + } +} + /* Tuner callback to provide the proper gpio changes needed for xc5000 */ int tm6000_xc5000_callback(void *ptr, int component, int command, int arg) { diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/staging/tm6000/tm6000-input.c index e02ea67..21e7da4 100644 --- a/drivers/staging/tm6000/tm6000-input.c +++ b/drivers/staging/tm6000/tm6000-input.c @@ -37,6 +37,10 @@ static unsigned int enable_ir = 1; module_param(enable_ir, int, 0644); MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)"); +/* number of 50ms for ON-OFF-ON power led */ +/* show IR activity */ +#define PWLED_OFF 2 + #undef dprintk #define dprintk(fmt, arg...) \ @@ -59,6 +63,9 @@ struct tm6000_IR { struct delayed_work work; u8 wait:1; u8 key:1; + u8 pwled:1; + u8 pwledcnt; + u16 key_addr; struct urb *int_urb; u8 *urb_data; @@ -89,26 +96,49 @@ static int tm6000_ir_config(struct tm6000_IR *ir) u8 buf[10]; int rc; - /* hack */ - buf[0] = 0xff; - buf[1] = 0xff; - buf[2] = 0xf2; - buf[3] = 0x2b; - buf[4] = 0x20; - buf[5] = 0x35; - buf[6] = 0x60; - buf[7] = 0x04; - buf[8] = 0xc0; - buf[9] = 0x08; - - rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, REQ_00_SET_IR_VALUE, 0, 0, buf, 0x0a); - msleep(100); - - if (rc < 0) { - printk(KERN_INFO "IR configuration failed"); - return rc; + switch (ir->rc_type) { + case RC_TYPE_NEC: + /* Setup IR decoder for NEC standard 12MHz system clock */ + /* IR_LEADER_CNT = 0.9ms */ + tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER1, 0xaa); + tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER0, 0x30); + /* IR_PULSE_CNT = 0.7ms */ + tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20); + tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0); + /* Remote WAKEUP = enable */ + tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe); + /* IR_WKUP_SEL = Low byte in decoded IR data */ + tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff); + /* IR_WKU_ADD code */ + tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_ADD, 0xff); + tm6000_flash_led(dev, 0); + msleep(100); + tm6000_flash_led(dev, 1); + break; + default: + /* hack */ + buf[0] = 0xff; + buf[1] = 0xff; + buf[2] = 0xf2; + buf[3] = 0x2b; + buf[4] = 0x20; + buf[5] = 0x35; + buf[6] = 0x60; + buf[7] = 0x04; + buf[8] = 0xc0; + buf[9] = 0x08; + + rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, REQ_00_SET_IR_VALUE, 0, 0, buf, 0x0a); + msleep(100); + + if (rc < 0) { + printk(KERN_INFO "IR configuration failed"); + return rc; + } + break; } + return 0; } @@ -143,10 +173,21 @@ static int default_polling_getkey(struct tm6000_IR *ir, return 0; if (&dev->int_in) { - if (ir->rc_type == RC_TYPE_RC5) + switch (ir->rc_type) { + case RC_TYPE_RC5: poll_result->rc_data = ir->urb_data[0]; - else - poll_result->rc_data = ir->urb_data[0] | ir->urb_data[1] << 8; + break; + case RC_TYPE_NEC: + if (ir->urb_data[1] == ((ir->key_addr >> 8) & 0xff)) { + poll_result->rc_data = ir->urb_data[0] + | ir->urb_data[1] << 8; + } + break; + default: + poll_result->rc_data = ir->urb_data[0] + | ir->urb_data[1] << 8; + break; + } } else { tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0); msleep(10); @@ -186,6 +227,7 @@ static int default_polling_getkey(struct tm6000_IR *ir, static void tm6000_ir_handle_key(struct tm6000_IR *ir) { + struct tm6000_core *dev = ir->dev; int result; struct tm6000_ir_poll_result poll_result; @@ -198,9 +240,21 @@ static void tm6000_ir_handle_key(struct tm6000_IR *ir) dprintk("ir->get_key result data=%04x\n", poll_result.rc_data); + if (ir->pwled) { + if (ir->pwledcnt >= PWLED_OFF) { + ir->pwled = 0; + ir->pwledcnt = 0; + tm6000_flash_led(dev, 1); + } else + ir->pwledcnt += 1; + } + if (ir->key) { rc_keydown(ir->rc, poll_result.rc_data, 0); ir->key = 0; + ir->pwled = 1; + ir->pwledcnt = 0; + tm6000_flash_led(dev, 0); } return; } @@ -234,19 +288,80 @@ int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type) { struct tm6000_IR *ir = rc->priv; + if (!ir) + return 0; + + if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC)) + ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff); + ir->get_key = default_polling_getkey; + ir->rc_type = rc_type; tm6000_ir_config(ir); /* TODO */ return 0; } +int tm6000_ir_int_start(struct tm6000_core *dev) +{ + struct tm6000_IR *ir = dev->ir; + int pipe, size; + int err = -ENOMEM; + + + if (!ir) + return -ENODEV; + + ir->int_urb = usb_alloc_urb(0, GFP_KERNEL); + + pipe = usb_rcvintpipe(dev->udev, + dev->int_in.endp->desc.bEndpointAddress + & USB_ENDPOINT_NUMBER_MASK); + + size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); + dprintk("IR max size: %d\n", size); + + ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL); + if (ir->int_urb->transfer_buffer == NULL) { + usb_free_urb(ir->int_urb); + return err; + } + dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval); + usb_fill_int_urb(ir->int_urb, dev->udev, pipe, + ir->int_urb->transfer_buffer, size, + tm6000_ir_urb_received, dev, + dev->int_in.endp->desc.bInterval); + err = usb_submit_urb(ir->int_urb, GFP_KERNEL); + if (err) { + kfree(ir->int_urb->transfer_buffer); + usb_free_urb(ir->int_urb); + return err; + } + ir->urb_data = kzalloc(size, GFP_KERNEL); + + return 0; +} + +void tm6000_ir_int_stop(struct tm6000_core *dev) +{ + struct tm6000_IR *ir = dev->ir; + + if (!ir) + return; + + usb_kill_urb(ir->int_urb); + kfree(ir->int_urb->transfer_buffer); + usb_free_urb(ir->int_urb); + ir->int_urb = NULL; + kfree(ir->urb_data); + ir->urb_data = NULL; +} + int tm6000_ir_init(struct tm6000_core *dev) { struct tm6000_IR *ir; struct rc_dev *rc; int err = -ENOMEM; - int pipe, size; if (!enable_ir) return -ENODEV; @@ -276,6 +391,9 @@ int tm6000_ir_init(struct tm6000_core *dev) rc->driver_type = RC_DRIVER_SCANCODE; ir->polling = 50; + ir->pwled = 0; + ir->pwledcnt = 0; + snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)", dev->name); @@ -298,32 +416,10 @@ int tm6000_ir_init(struct tm6000_core *dev) if (&dev->int_in) { dprintk("IR over int\n"); - ir->int_urb = usb_alloc_urb(0, GFP_KERNEL); - - pipe = usb_rcvintpipe(dev->udev, - dev->int_in.endp->desc.bEndpointAddress - & USB_ENDPOINT_NUMBER_MASK); + err = tm6000_ir_int_start(dev); - size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); - dprintk("IR max size: %d\n", size); - - ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL); - if (ir->int_urb->transfer_buffer == NULL) { - usb_free_urb(ir->int_urb); - goto out; - } - dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval); - usb_fill_int_urb(ir->int_urb, dev->udev, pipe, - ir->int_urb->transfer_buffer, size, - tm6000_ir_urb_received, dev, - dev->int_in.endp->desc.bInterval); - err = usb_submit_urb(ir->int_urb, GFP_KERNEL); - if (err) { - kfree(ir->int_urb->transfer_buffer); - usb_free_urb(ir->int_urb); + if (err) goto out; - } - ir->urb_data = kzalloc(size, GFP_KERNEL); } /* ir register */ @@ -352,12 +448,7 @@ int tm6000_ir_fini(struct tm6000_core *dev) rc_unregister_device(ir->rc); if (ir->int_urb) { - usb_kill_urb(ir->int_urb); - kfree(ir->int_urb->transfer_buffer); - usb_free_urb(ir->int_urb); - ir->int_urb = NULL; - kfree(ir->urb_data); - ir->urb_data = NULL; + tm6000_ir_int_stop(dev); } kfree(ir); diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/staging/tm6000/tm6000-video.c index 0dae427..8fe017c 100644 --- a/drivers/staging/tm6000/tm6000-video.c +++ b/drivers/staging/tm6000/tm6000-video.c @@ -545,11 +545,16 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev, unsigned int framesize) /* De-allocates all pending stuff */ tm6000_uninit_isoc(dev); + /* Stop interrupt USB pipe */ + tm6000_ir_int_stop(dev); usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, dev->isoc_in.bAlternateSetting); + /* Start interrupt USB pipe */ + tm6000_ir_int_start(dev); + pipe = usb_rcvisocpipe(dev->udev, dev->isoc_in.endp->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); diff --git a/drivers/staging/tm6000/tm6000.h b/drivers/staging/tm6000/tm6000.h index 46017b6..bf11eee 100644 --- a/drivers/staging/tm6000/tm6000.h +++ b/drivers/staging/tm6000/tm6000.h @@ -266,6 +266,7 @@ struct tm6000_fh { int tm6000_tuner_callback(void *ptr, int component, int command, int arg); int tm6000_xc5000_callback(void *ptr, int component, int command, int arg); int tm6000_cards_setup(struct tm6000_core *dev); +void tm6000_flash_led(struct tm6000_core *dev, u8 state); /* In tm6000-core.c */ @@ -332,6 +333,8 @@ int tm6000_queue_init(struct tm6000_core *dev); int tm6000_ir_init(struct tm6000_core *dev); int tm6000_ir_fini(struct tm6000_core *dev); void tm6000_ir_wait(struct tm6000_core *dev, u8 state); +int tm6000_ir_int_start(struct tm6000_core *dev); +void tm6000_ir_int_stop(struct tm6000_core *dev); /* Debug stuff */ -- cgit v0.10.2 From f9d7d787842e92bc768d282f37fc3056c5441ddb Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Wed, 22 Dec 2010 17:31:58 -0300 Subject: [media] saa7115: allow input standard autodetection for more chips Autodetect input's standard using field frequency detection feature (FIDT in status byte at 0x1F) of the chips saa7111/ saa7111a/saa7113/saa7114/saa7118. Signed-off-by: Anatolij Gustschin Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 301c62b..f35459d 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1348,8 +1348,17 @@ static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) int reg1e; *std = V4L2_STD_ALL; - if (state->ident != V4L2_IDENT_SAA7115) + if (state->ident != V4L2_IDENT_SAA7115) { + int reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC); + + if (reg1f & 0x20) + *std = V4L2_STD_525_60; + else + *std = V4L2_STD_625_50; + return 0; + } + reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC); switch (reg1e & 0x03) { -- cgit v0.10.2 From 50155c25bf346b65fec8e215131df397b0a5ee6e Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Wed, 22 Dec 2010 17:31:59 -0300 Subject: [media] fsl_viu: add VIDIOC_QUERYSTD and VIDIOC_G_STD support VIDIOC_QUERYSTD and VIDIOC_G_STD ioctls are currently not supported in the FSL VIU driver. The decoder subdevice driver saa7115 extended by previous patch supports QUERYSTD for saa711x, so we add the appropriate ioctls to the VIU driver to be able to determine the video input's standard. Signed-off-by: Anatolij Gustschin Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/fsl-viu.c b/drivers/media/video/fsl-viu.c index 693e9c0..e4bba88 100644 --- a/drivers/media/video/fsl-viu.c +++ b/drivers/media/video/fsl-viu.c @@ -194,6 +194,8 @@ struct viu_dev { /* decoder */ struct v4l2_subdev *decoder; + + v4l2_std_id std; }; struct viu_fh { @@ -937,14 +939,31 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) #define decoder_call(viu, o, f, args...) \ v4l2_subdev_call(viu->decoder, o, f, ##args) +static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std_id) +{ + struct viu_fh *fh = priv; + + decoder_call(fh->dev, video, querystd, std_id); + return 0; +} + static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id) { struct viu_fh *fh = priv; + fh->dev->std = *id; decoder_call(fh->dev, core, s_std, *id); return 0; } +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std_id) +{ + struct viu_fh *fh = priv; + + *std_id = fh->dev->std; + return 0; +} + /* only one input in this driver */ static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *inp) @@ -1402,7 +1421,9 @@ static const struct v4l2_ioctl_ops viu_ioctl_ops = { .vidioc_querybuf = vidioc_querybuf, .vidioc_qbuf = vidioc_qbuf, .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_g_std = vidioc_g_std, .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, -- cgit v0.10.2 From fe04164647588ec55937e6d696da1ebeca04d000 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 23 Dec 2010 16:38:53 -0300 Subject: [media] cx231xxx: fix typo in saddr_len check The original code compared "saddr_len" with zero twice in a nonsensical way. I asked the list, and Andy Walls and Sri Deevi say that the second check should be if "saddr_len == 1". Signed-off-by: Dan Carpenter Signed-off-by: Srinivasa Deevi Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c index 44d124c..7d62d58 100644 --- a/drivers/media/video/cx231xx/cx231xx-core.c +++ b/drivers/media/video/cx231xx/cx231xx-core.c @@ -1515,7 +1515,7 @@ int cx231xx_read_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr, if (saddr_len == 0) saddr = 0; - else if (saddr_len == 0) + else if (saddr_len == 1) saddr &= 0xff; /* prepare xfer_data struct */ @@ -1566,7 +1566,7 @@ int cx231xx_write_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr, if (saddr_len == 0) saddr = 0; - else if (saddr_len == 0) + else if (saddr_len == 1) saddr &= 0xff; /* prepare xfer_data struct */ @@ -1600,7 +1600,7 @@ int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr, if (saddr_len == 0) saddr = 0; - else if (saddr_len == 0) + else if (saddr_len == 1) saddr &= 0xff; /* prepare xfer_data struct */ @@ -1641,7 +1641,7 @@ int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr, if (saddr_len == 0) saddr = 0; - else if (saddr_len == 0) + else if (saddr_len == 1) saddr &= 0xff; /* prepare xfer_data struct */ -- cgit v0.10.2 From 44c6e2a7c2ec76dd495a0f330f9beac572a2fdd7 Mon Sep 17 00:00:00 2001 From: Ang Way Chuang Date: Fri, 24 Dec 2010 02:40:46 -0300 Subject: [media] cx88-dvb.c: DVB net latency using Hauppauge HVR4000 A Hauppauge HVR 4000 is used on a School On Internet Asia (SOI Asia) project in order to carry IP traffic over ULE. However, there is an issue with high latency jitter. My boss, Husni, identified the problem and provided a patch for it. The default buffer size of 32 TS frames on cx88 causes the high latency, so our deployment changes that to 6 TS frames. This patch made the buffer size tunable, while keeping the default buffer size of 32 TS frames unchanged. Signed-off-by: Achmad Husni Thamrin Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 367a653f..90717ee 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -67,6 +67,10 @@ static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); +static unsigned int dvb_buf_tscnt = 32; +module_param(dvb_buf_tscnt, int, 0644); +MODULE_PARM_DESC(dvb_buf_tscnt, "DVB Buffer TS count [dvb]"); + DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); #define dprintk(level,fmt, arg...) if (debug >= level) \ @@ -80,10 +84,10 @@ static int dvb_buf_setup(struct videobuf_queue *q, struct cx8802_dev *dev = q->priv_data; dev->ts_packet_size = 188 * 4; - dev->ts_packet_count = 32; + dev->ts_packet_count = dvb_buf_tscnt; *size = dev->ts_packet_size * dev->ts_packet_count; - *count = 32; + *count = dvb_buf_tscnt; return 0; } -- cgit v0.10.2 From b7a0f2e793a52b306e682a0e2e9a0b6f0f0a730e Mon Sep 17 00:00:00 2001 From: Ramiro Morales Date: Sun, 26 Dec 2010 18:13:30 -0300 Subject: [media] saa7134: Add support for Compro VideoMate Vista M1F Signed-off-by: Pavel Osnova Signed-off-by: Ramiro Morales Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 8d9afc7..8db1a94 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -180,3 +180,4 @@ 179 -> Beholder BeholdTV A7 [5ace:7090] 180 -> Avermedia PCI M733A [1461:4155,1461:4255] 181 -> TechoTrend TT-budget T-3000 [13c2:2804] +183 -> Compro VideoMate Vista M1F [185b:c900] diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index 148900f..0659e9f 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -81,6 +81,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-trekstor.o \ rc-tt-1500.o \ rc-twinhan1027.o \ + rc-videomate-m1f.o \ rc-videomate-s350.o \ rc-videomate-tv-pvr.o \ rc-winfast.o \ diff --git a/drivers/media/rc/keymaps/rc-videomate-m1f.c b/drivers/media/rc/keymaps/rc-videomate-m1f.c new file mode 100644 index 0000000..4994d40 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-videomate-m1f.c @@ -0,0 +1,92 @@ +/* videomate-m1f.h - Keytable for videomate_m1f Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Pavel Osnova + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct rc_map_table videomate_m1f[] = { + { 0x01, KEY_POWER }, + { 0x31, KEY_TUNER }, + { 0x33, KEY_VIDEO }, + { 0x2f, KEY_RADIO }, + { 0x30, KEY_CAMERA }, + { 0x2d, KEY_NEW }, /* TV record button */ + { 0x17, KEY_CYCLEWINDOWS }, + { 0x2c, KEY_ANGLE }, + { 0x2b, KEY_LANGUAGE }, + { 0x32, KEY_SEARCH }, /* '...' button */ + { 0x11, KEY_UP }, + { 0x13, KEY_LEFT }, + { 0x15, KEY_OK }, + { 0x14, KEY_RIGHT }, + { 0x12, KEY_DOWN }, + { 0x16, KEY_BACKSPACE }, + { 0x02, KEY_ZOOM }, /* WIN key */ + { 0x04, KEY_INFO }, + { 0x05, KEY_VOLUMEUP }, + { 0x03, KEY_MUTE }, + { 0x07, KEY_CHANNELUP }, + { 0x06, KEY_VOLUMEDOWN }, + { 0x08, KEY_CHANNELDOWN }, + { 0x0c, KEY_RECORD }, + { 0x0e, KEY_STOP }, + { 0x0a, KEY_BACK }, + { 0x0b, KEY_PLAY }, + { 0x09, KEY_FORWARD }, + { 0x10, KEY_PREVIOUS }, + { 0x0d, KEY_PAUSE }, + { 0x0f, KEY_NEXT }, + { 0x1e, KEY_1 }, + { 0x1f, KEY_2 }, + { 0x20, KEY_3 }, + { 0x21, KEY_4 }, + { 0x22, KEY_5 }, + { 0x23, KEY_6 }, + { 0x24, KEY_7 }, + { 0x25, KEY_8 }, + { 0x26, KEY_9 }, + { 0x2a, KEY_NUMERIC_STAR }, /* * key */ + { 0x1d, KEY_0 }, + { 0x29, KEY_SUBTITLE }, /* # key */ + { 0x27, KEY_CLEAR }, + { 0x34, KEY_SCREEN }, + { 0x28, KEY_ENTER }, + { 0x19, KEY_RED }, + { 0x1a, KEY_GREEN }, + { 0x1b, KEY_YELLOW }, + { 0x1c, KEY_BLUE }, + { 0x18, KEY_TEXT }, +}; + +static struct rc_map_list videomate_m1f_map = { + .map = { + .scan = videomate_m1f, + .size = ARRAY_SIZE(videomate_m1f), + .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_VIDEOMATE_M1F, + } +}; + +static int __init init_rc_map_videomate_m1f(void) +{ + return rc_map_register(&videomate_m1f_map); +} + +static void __exit exit_rc_map_videomate_m1f(void) +{ + rc_map_unregister(&videomate_m1f_map); +} + +module_init(init_rc_map_videomate_m1f) +module_exit(exit_rc_map_videomate_m1f) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Pavel Osnova "); diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index ff23e6e..e7aa588 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5538,6 +5538,37 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, } }, }, + [SAA7134_BOARD_VIDEOMATE_M1F] = { + /* Pavel Osnova */ + .name = "Compro VideoMate Vista M1F", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .radio_type = TUNER_TEA5767, + .tuner_addr = ADDR_UNSET, + .radio_addr = 0x60, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE2, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + } }, + .radio = { + .name = name_radio, + .amux = LINE1, + }, + .mute = { + .name = name_mute, + .amux = TV, + }, + }, }; @@ -6731,6 +6762,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x7090, .driver_data = SAA7134_BOARD_BEHOLD_A7, }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7135, + .subvendor = 0x185b, + .subdevice = 0xc900, + .driver_data = SAA7134_BOARD_VIDEOMATE_M1F, + }, { /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -7046,6 +7083,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_TV_PVR: case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: + case SAA7134_BOARD_VIDEOMATE_M1F: case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_VIDEOMATE_DVBT_200: case SAA7134_BOARD_VIDEOMATE_DVBT_200A: diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 98678d9..dc646e6 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -721,6 +721,11 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x020000; polling = 50; /* ms */ break; + case SAA7134_BOARD_VIDEOMATE_M1F: + ir_codes = RC_MAP_VIDEOMATE_M1F; + mask_keycode = 0x0ff00; + mask_keyup = 0x040000; + break; } if (NULL == ir_codes) { printk("%s: Oops: IR config error [card=%d]\n", diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index babfbe7..5b0a347 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -326,6 +326,7 @@ struct saa7134_card_ir { #define SAA7134_BOARD_AVERMEDIA_M733A 180 #define SAA7134_BOARD_TECHNOTREND_BUDGET_T3000 181 #define SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG 182 +#define SAA7134_BOARD_VIDEOMATE_M1F 183 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 diff --git a/include/media/rc-map.h b/include/media/rc-map.h index 5d3a457..ee9e2f74 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -138,6 +138,7 @@ void rc_map_init(void); #define RC_MAP_TREKSTOR "rc-trekstor" #define RC_MAP_TT_1500 "rc-tt-1500" #define RC_MAP_TWINHAN_VP1027_DVBS "rc-twinhan1027" +#define RC_MAP_VIDEOMATE_M1F "rc-videomate-m1f" #define RC_MAP_VIDEOMATE_S350 "rc-videomate-s350" #define RC_MAP_VIDEOMATE_TV_PVR "rc-videomate-tv-pvr" #define RC_MAP_WINFAST "rc-winfast" -- cgit v0.10.2 From b5fff5445a077af897e670e98ea54b9b440f8b63 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 28 Dec 2010 08:13:50 -0300 Subject: [media] cardlist: Update lists for em28xx and saa7134 PS.: The cardlists are auto-generated via scripts. Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 3ca1ef7..31b4857 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -9,7 +9,7 @@ 8 -> Kworld USB2800 (em2800) 9 -> Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker (em2820/em2840) [1b80:e302,1b80:e304,2304:0207,2304:021a] 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500] - 11 -> Terratec Hybrid XS (em2880) [0ccd:0042] + 11 -> Terratec Hybrid XS (em2880) 12 -> Kworld PVR TV 2800 RF (em2820/em2840) 13 -> Terratec Prodigy XS (em2880) [0ccd:0047] 14 -> SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0 (em2820/em2840) @@ -53,7 +53,7 @@ 52 -> DNT DA2 Hybrid (em2881) 53 -> Pinnacle Hybrid Pro (em2881) 54 -> Kworld VS-DVB-T 323UR (em2882) [eb1a:e323] - 55 -> Terratec Hybrid XS (em2882) (em2882) [0ccd:005e] + 55 -> Terratec Cinnergy Hybrid T USB XS (em2882) (em2882) [0ccd:005e,0ccd:0042] 56 -> Pinnacle Hybrid Pro (2) (em2882) [2304:0226] 57 -> Kworld PlusTV HD Hybrid 330 (em2883) [eb1a:a316] 58 -> Compro VideoMate ForYou/Stereo (em2820/em2840) [185b:2041] diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 8db1a94..6b4c72d 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -180,4 +180,5 @@ 179 -> Beholder BeholdTV A7 [5ace:7090] 180 -> Avermedia PCI M733A [1461:4155,1461:4255] 181 -> TechoTrend TT-budget T-3000 [13c2:2804] +182 -> Kworld PCI SBTVD/ISDB-T Full-Seg Hybrid [17de:b136] 183 -> Compro VideoMate Vista M1F [185b:c900] -- cgit v0.10.2 From a3fa904ec79b94f0db7faed010ff94d42f7d1d47 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Oct 2010 17:51:15 -0300 Subject: [media] em28xx: Fix audio input for Terratec Grabby The audio input line was wrong. Fix it. Cc: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 5d79d0e..8af302b 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -1660,11 +1660,11 @@ struct em28xx_board em28xx_boards[] = { .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO2, + .amux = EM28XX_AMUX_LINE_IN, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_VIDEO2, + .amux = EM28XX_AMUX_LINE_IN, } }, }, [EM2860_BOARD_TERRATEC_AV350] = { -- cgit v0.10.2 From 5f63306d82131371f464c0e5b7ebe6a23a84c768 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 27 Dec 2010 21:04:58 -0300 Subject: [media] cx231xx: use bitwise negate instead of logical Bitwise negate was intended here. INPUT_SEL_MASK is 0x30. Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx231xx/cx231xx-avcore.c b/drivers/media/video/cx231xx/cx231xx-avcore.c index d52955c..c53e972 100644 --- a/drivers/media/video/cx231xx/cx231xx-avcore.c +++ b/drivers/media/video/cx231xx/cx231xx-avcore.c @@ -274,7 +274,7 @@ int cx231xx_afe_set_input_mux(struct cx231xx *dev, u32 input_mux) if (ch1_setting != 0) { status = afe_read_byte(dev, ADC_INPUT_CH1, &value); - value &= (!INPUT_SEL_MASK); + value &= ~INPUT_SEL_MASK; value |= (ch1_setting - 1) << 4; value &= 0xff; status = afe_write_byte(dev, ADC_INPUT_CH1, value); @@ -282,7 +282,7 @@ int cx231xx_afe_set_input_mux(struct cx231xx *dev, u32 input_mux) if (ch2_setting != 0) { status = afe_read_byte(dev, ADC_INPUT_CH2, &value); - value &= (!INPUT_SEL_MASK); + value &= ~INPUT_SEL_MASK; value |= (ch2_setting - 1) << 4; value &= 0xff; status = afe_write_byte(dev, ADC_INPUT_CH2, value); @@ -292,7 +292,7 @@ int cx231xx_afe_set_input_mux(struct cx231xx *dev, u32 input_mux) 7 less than the input number */ if (ch3_setting != 0) { status = afe_read_byte(dev, ADC_INPUT_CH3, &value); - value &= (!INPUT_SEL_MASK); + value &= ~INPUT_SEL_MASK; value |= (ch3_setting - 1) << 4; value &= 0xff; status = afe_write_byte(dev, ADC_INPUT_CH3, value); -- cgit v0.10.2 From 9028f58f5d7e810a0e88b508ebe6a69daf7e3273 Mon Sep 17 00:00:00 2001 From: Alexey Chernov <4ernov@gmail.com> Date: Mon, 6 Dec 2010 17:09:53 -0300 Subject: [media] support of GoTView PCI-E X5 3D Hybrid in cx23885 Some comments: 1. Everything initialize properly except radio. 2. All analog inputs (TV, composite, S-Video) are tested by myself in several TV norms (SECAM-D, PAL, NTSC), everything work fine. So the patch adds general support/detection of the card with working analog part, DVB part is not supported for now. Signed-off-by: Alexey Chernov <4ernov@gmail.com> Reviewed-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 8861309..b298b73 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -309,6 +309,26 @@ struct cx23885_board cx23885_boards[] = { CX25840_COMPONENT_ON, } }, }, + [CX23885_BOARD_GOTVIEW_X5_3D_HYBRID] = { + .name = "GoTView X5 3D Hybrid", + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x64, + .porta = CX23885_ANALOG_VIDEO, + .portb = CX23885_MPEG_DVB, + .input = {{ + .type = CX23885_VMUX_TELEVISION, + .vmux = CX25840_VIN2_CH1 | + CX25840_VIN5_CH2, + .gpio0 = 0x02, + }, { + .type = CX23885_VMUX_COMPOSITE1, + .vmux = CX23885_VMUX_COMPOSITE1, + }, { + .type = CX23885_VMUX_SVIDEO, + .vmux = CX25840_SVIDEO_LUMA3 | + CX25840_SVIDEO_CHROMA4, + } }, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -496,6 +516,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x107d, .subdevice = 0x6f22, .card = CX23885_BOARD_LEADTEK_WINFAST_PXTV1200, + }, { + .subvendor = 0x5654, + .subdevice = 0x2390, + .card = CX23885_BOARD_GOTVIEW_X5_3D_HYBRID, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -712,6 +736,10 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg) else if (port->nr == 2) bitmask = 0x04; break; + case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID: + /* Tuner Reset Command */ + bitmask = 0x02; + break; } if (bitmask) { @@ -967,6 +995,9 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* CX24228 GPIO */ /* Connected to IF / Mux */ break; + case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID: + cx_set(GP0_IO, 0x00010001); /* Bring the part out of reset */ + break; } } @@ -1218,6 +1249,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_COMPRO_VIDEOMATE_E800: case CX23885_BOARD_HAUPPAUGE_HVR1290: + case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID: default: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ @@ -1245,6 +1277,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_MAGICPRO_PROHDTVE2: case CX23885_BOARD_HAUPPAUGE_HVR1290: case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200: + case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID: dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[2].i2c_adap, "cx25840", 0x88 >> 1, NULL); diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index fd38722..62e41ab 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -84,6 +84,7 @@ #define CX23885_BOARD_HAUPPAUGE_HVR1290 26 #define CX23885_BOARD_MYGICA_X8558PRO 27 #define CX23885_BOARD_LEADTEK_WINFAST_PXTV1200 28 +#define CX23885_BOARD_GOTVIEW_X5_3D_HYBRID 29 #define GPIO_0 0x00000001 #define GPIO_1 0x00000002 -- cgit v0.10.2 From a519d70e0cf346e946202ffcbeaf57a1748d0c03 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Fri, 19 Nov 2010 15:41:49 -0300 Subject: [media] media: video: pvrusb2: fix memory leak Use put_device() instead of kfree() because of device name leak. Signed-off-by: Vasiliy Kulikov Acked-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 3d7e5aa..281806b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -647,7 +647,7 @@ static void class_dev_create(struct pvr2_sysfs *sfp, if (ret) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "device_register failed"); - kfree(class_dev); + put_device(class_dev); return; } -- cgit v0.10.2 From b9218f2f15cdff8991ba041993bf40962c49fdd0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 27 Dec 2010 12:22:46 -0300 Subject: [media] saa6588: rename rds.h to saa6588.h The naming of the media/rds.h header suggested that it was a generic RDS header, when in fact it is just a saa6588 module API that is internal to the kernel. Rename the header and the struct and defines in it to make this clear. Also removed the header include in radio-si470x.h (not used anymore) and from ioctl-number.txt (it's internal to the kernel and never called from userspace). Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index b2400d7..7edf950 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt @@ -155,7 +155,6 @@ Code Seq#(hex) Include File Comments 'Q' all linux/soundcard.h 'R' 00-1F linux/random.h conflict! 'R' 01 linux/rfkill.h conflict! -'R' 01-0F media/rds.h conflict! 'R' C0-DF net/bluetooth/rfcomm.h 'S' all linux/cdrom.h conflict! 'S' 80-81 scsi/scsi_ioctl.h conflict! diff --git a/drivers/media/radio/si470x/radio-si470x.h b/drivers/media/radio/si470x/radio-si470x.h index b9914d7..4a4e908 100644 --- a/drivers/media/radio/si470x/radio-si470x.h +++ b/drivers/media/radio/si470x/radio-si470x.h @@ -37,7 +37,6 @@ #include #include #include -#include #include diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 961d080..849cd17 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -55,7 +55,7 @@ #include #include -#include +#include unsigned int bttv_num; /* number of Bt848s in use */ @@ -3388,7 +3388,7 @@ static int radio_release(struct file *file) { struct bttv_fh *fh = file->private_data; struct bttv *btv = fh->btv; - struct rds_command cmd; + struct saa6588_command cmd; v4l2_prio_close(&btv->prio, fh->prio); file->private_data = NULL; @@ -3396,7 +3396,7 @@ static int radio_release(struct file *file) btv->radio_user--; - bttv_call_all(btv, core, ioctl, RDS_CMD_CLOSE, &cmd); + bttv_call_all(btv, core, ioctl, SAA6588_CMD_CLOSE, &cmd); return 0; } @@ -3523,13 +3523,13 @@ static ssize_t radio_read(struct file *file, char __user *data, { struct bttv_fh *fh = file->private_data; struct bttv *btv = fh->btv; - struct rds_command cmd; + struct saa6588_command cmd; cmd.block_count = count/3; cmd.buffer = data; cmd.instance = file; cmd.result = -ENODEV; - bttv_call_all(btv, core, ioctl, RDS_CMD_READ, &cmd); + bttv_call_all(btv, core, ioctl, SAA6588_CMD_READ, &cmd); return cmd.result; } @@ -3538,11 +3538,11 @@ static unsigned int radio_poll(struct file *file, poll_table *wait) { struct bttv_fh *fh = file->private_data; struct bttv *btv = fh->btv; - struct rds_command cmd; + struct saa6588_command cmd; cmd.instance = file; cmd.event_list = wait; cmd.result = -ENODEV; - bttv_call_all(btv, core, ioctl, RDS_CMD_POLL, &cmd); + bttv_call_all(btv, core, ioctl, SAA6588_CMD_POLL, &cmd); return cmd.result; } diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 984c0fe..99a2ac1 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -31,7 +31,7 @@ #include #include -#include +#include #include #include @@ -181,7 +181,7 @@ static int block_to_user_buf(struct saa6588 *s, unsigned char __user *user_buf) return 1; } -static void read_from_buf(struct saa6588 *s, struct rds_command *a) +static void read_from_buf(struct saa6588 *s, struct saa6588_command *a) { unsigned long flags; @@ -392,25 +392,25 @@ static void saa6588_configure(struct saa6588 *s) static long saa6588_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct saa6588 *s = to_saa6588(sd); - struct rds_command *a = arg; + struct saa6588_command *a = arg; switch (cmd) { /* --- open() for /dev/radio --- */ - case RDS_CMD_OPEN: + case SAA6588_CMD_OPEN: a->result = 0; /* return error if chip doesn't work ??? */ break; /* --- close() for /dev/radio --- */ - case RDS_CMD_CLOSE: + case SAA6588_CMD_CLOSE: s->data_available_for_read = 1; wake_up_interruptible(&s->read_queue); a->result = 0; break; /* --- read() for /dev/radio --- */ - case RDS_CMD_READ: + case SAA6588_CMD_READ: read_from_buf(s, a); break; /* --- poll() for /dev/radio --- */ - case RDS_CMD_POLL: + case SAA6588_CMD_POLL: a->result = 0; if (s->data_available_for_read) { a->result |= POLLIN | POLLRDNORM; diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index ad22be2..ee4ea5f 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -30,7 +30,7 @@ #include "saa7134-reg.h" #include "saa7134.h" #include -#include +#include /* ------------------------------------------------------------------ */ @@ -1459,7 +1459,7 @@ static int video_release(struct file *file) { struct saa7134_fh *fh = file->private_data; struct saa7134_dev *dev = fh->dev; - struct rds_command cmd; + struct saa6588_command cmd; unsigned long flags; /* turn off overlay */ @@ -1494,7 +1494,7 @@ static int video_release(struct file *file) saa_call_all(dev, core, s_power, 0); if (fh->radio) - saa_call_all(dev, core, ioctl, RDS_CMD_CLOSE, &cmd); + saa_call_all(dev, core, ioctl, SAA6588_CMD_CLOSE, &cmd); /* free stuff */ videobuf_mmap_free(&fh->cap); @@ -1520,14 +1520,14 @@ static ssize_t radio_read(struct file *file, char __user *data, { struct saa7134_fh *fh = file->private_data; struct saa7134_dev *dev = fh->dev; - struct rds_command cmd; + struct saa6588_command cmd; cmd.block_count = count/3; cmd.buffer = data; cmd.instance = file; cmd.result = -ENODEV; - saa_call_all(dev, core, ioctl, RDS_CMD_READ, &cmd); + saa_call_all(dev, core, ioctl, SAA6588_CMD_READ, &cmd); return cmd.result; } @@ -1536,12 +1536,12 @@ static unsigned int radio_poll(struct file *file, poll_table *wait) { struct saa7134_fh *fh = file->private_data; struct saa7134_dev *dev = fh->dev; - struct rds_command cmd; + struct saa6588_command cmd; cmd.instance = file; cmd.event_list = wait; cmd.result = -ENODEV; - saa_call_all(dev, core, ioctl, RDS_CMD_POLL, &cmd); + saa_call_all(dev, core, ioctl, SAA6588_CMD_POLL, &cmd); return cmd.result; } diff --git a/include/media/rds.h b/include/media/rds.h deleted file mode 100644 index a894266..0000000 --- a/include/media/rds.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - - Types and defines needed for RDS. This is included by - saa6588.c and every driver (e.g. bttv-driver.c) that wants - to use the saa6588 module. - - Instead of having a separate rds.h, I'd prefer to include - this stuff in one of the already existing files like tuner.h - - (c) 2005 by Hans J. Koch - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef _RDS_H -#define _RDS_H - -struct rds_command { - unsigned int block_count; - int result; - unsigned char __user *buffer; - struct file *instance; - poll_table *event_list; -}; - -#define RDS_CMD_OPEN _IOW('R',1,int) -#define RDS_CMD_CLOSE _IOW('R',2,int) -#define RDS_CMD_READ _IOR('R',3,int) -#define RDS_CMD_POLL _IOR('R',4,int) - -#endif diff --git a/include/media/saa6588.h b/include/media/saa6588.h new file mode 100644 index 0000000..2c3c442 --- /dev/null +++ b/include/media/saa6588.h @@ -0,0 +1,42 @@ +/* + + Types and defines needed for RDS. This is included by + saa6588.c and every driver (e.g. bttv-driver.c) that wants + to use the saa6588 module. + + (c) 2005 by Hans J. Koch + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef _SAA6588_H +#define _SAA6588_H + +struct saa6588_command { + unsigned int block_count; + int result; + unsigned char __user *buffer; + struct file *instance; + poll_table *event_list; +}; + +/* These ioctls are internal to the kernel */ +#define SAA6588_CMD_OPEN _IOW('R', 1, int) +#define SAA6588_CMD_CLOSE _IOW('R', 2, int) +#define SAA6588_CMD_READ _IOR('R', 3, int) +#define SAA6588_CMD_POLL _IOR('R', 4, int) + +#endif -- cgit v0.10.2 From 66832aef0694807f487a8ccc8871cea4e80d78c5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 27 Dec 2010 12:27:50 -0300 Subject: [media] bt819: the ioctls in the header are internal to the kernel Remove bt819.h from ioctl-number.txt and make a note in the header that these ioctls are for internal use only. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index 7edf950..d6a63c7 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt @@ -193,7 +193,6 @@ Code Seq#(hex) Include File Comments 'b' 00-FF conflict! bit3 vme host bridge -'b' 00-0F media/bt819.h conflict! 'c' all linux/cm4000_cs.h conflict! 'c' 00-7F linux/comstats.h conflict! 'c' 00-7F linux/coda.h conflict! diff --git a/include/media/bt819.h b/include/media/bt819.h index 38f666b..8025f4b 100644 --- a/include/media/bt819.h +++ b/include/media/bt819.h @@ -26,7 +26,10 @@ /* v4l2_device notifications. */ /* Needed to reset the FIFO buffer when changing the input - or the video standard. */ + or the video standard. + + Note: these ioctls that internal to the kernel and are never called + from userspace. */ #define BT819_FIFO_RESET_LOW _IO('b', 0) #define BT819_FIFO_RESET_HIGH _IO('b', 1) -- cgit v0.10.2 From d85185902fb669a92d4934b926f8016368e1ad06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Tue, 28 Dec 2010 06:55:01 -0300 Subject: [media] gspca - main: Fix some warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 80b31eb..4429700 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -1297,17 +1297,19 @@ static int vidioc_querycap(struct file *file, void *priv, ret = -ENODEV; goto out; } - strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver); + strncpy((char *) cap->driver, gspca_dev->sd_desc->name, + sizeof cap->driver); if (gspca_dev->dev->product != NULL) { - strncpy(cap->card, gspca_dev->dev->product, + strncpy((char *) cap->card, gspca_dev->dev->product, sizeof cap->card); } else { - snprintf(cap->card, sizeof cap->card, + snprintf((char *) cap->card, sizeof cap->card, "USB Camera (%04x:%04x)", le16_to_cpu(gspca_dev->dev->descriptor.idVendor), le16_to_cpu(gspca_dev->dev->descriptor.idProduct)); } - usb_make_path(gspca_dev->dev, cap->bus_info, sizeof(cap->bus_info)); + usb_make_path(gspca_dev->dev, (char *) cap->bus_info, + sizeof(cap->bus_info)); cap->version = DRIVER_VERSION_NUMBER; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING -- cgit v0.10.2 From 0aeb5ec74b0a95f1699040f0262a6fd5507d6e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Tue, 28 Dec 2010 06:59:04 -0300 Subject: [media] gspca - pac7302/pac7311: Fix some warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index 55fbea7..2700975 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -393,7 +393,7 @@ static const __u8 page3_7302[] = { static void reg_w_buf(struct gspca_dev *gspca_dev, __u8 index, - const char *buffer, int len) + const u8 *buffer, int len) { int ret; diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 7657b43..6820f5d 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -261,7 +261,7 @@ static const __u8 page4_7311[] = { static void reg_w_buf(struct gspca_dev *gspca_dev, __u8 index, - const char *buffer, int len) + const u8 *buffer, int len) { int ret; -- cgit v0.10.2 From 2bbf53bd176e36d1574eeec53bf710d94703535e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Tue, 28 Dec 2010 07:01:04 -0300 Subject: [media] gspca: Bad comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 3c8a63b..97b77a2 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -62,7 +62,7 @@ struct gspca_ctrl { /* device information - set at probe time */ struct cam { const struct v4l2_pix_format *cam_mode; /* size nmodes */ - const struct framerates *mode_framerates; /* must have size nmode, + const struct framerates *mode_framerates; /* must have size nmodes, * just like cam_mode */ struct gspca_ctrl *ctrls; /* control table - size nctrls */ /* may be NULL */ -- cgit v0.10.2 From 7d55a84b0af47b2ec55e16c6dbc8df62a72ac749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Tue, 28 Dec 2010 07:02:32 -0300 Subject: [media] gspca - zc3xx: Keep sorted the device table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 042dc80..6ab2384 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -7066,8 +7066,8 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x046d, 0x08af)}, {USB_DEVICE(0x046d, 0x08b9)}, {USB_DEVICE(0x046d, 0x08d7)}, - {USB_DEVICE(0x046d, 0x08d9)}, {USB_DEVICE(0x046d, 0x08d8)}, + {USB_DEVICE(0x046d, 0x08d9)}, {USB_DEVICE(0x046d, 0x08da)}, {USB_DEVICE(0x046d, 0x08dd), .driver_info = SENSOR_MC501CB}, {USB_DEVICE(0x0471, 0x0325), .driver_info = SENSOR_PAS106}, -- cgit v0.10.2 From 49fb5e60f7e907126aac10af6577fac6fde684f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Tue, 28 Dec 2010 07:09:34 -0300 Subject: [media] gspca - zc3xx: Use the new video control mechanism MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 6ab2384..48b8802 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -35,16 +35,23 @@ static int force_sensor = -1; #define QUANT_VAL 1 /* quantization table */ #include "zc3xx-reg.h" +/* controls */ +enum e_ctrl { + BRIGHTNESS, + CONTRAST, + GAMMA, + AUTOGAIN, + LIGHTFREQ, + SHARPNESS, + NCTRLS /* number of controls */ +}; + /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - u8 brightness; - u8 contrast; - u8 gamma; - u8 autogain; - u8 lightfreq; - u8 sharpness; + struct gspca_ctrl ctrls[NCTRLS]; + u8 quality; /* image quality */ #define QUALITY_MIN 50 #define QUALITY_MAX 80 @@ -84,21 +91,13 @@ enum sensors { }; /* V4L2 controls supported by the driver */ -static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); - -static const struct ctrl sd_ctrls[] = { - { +static void setcontrast(struct gspca_dev *gspca_dev); +static void setautogain(struct gspca_dev *gspca_dev); +static void setlightfreq(struct gspca_dev *gspca_dev); +static void setsharpness(struct gspca_dev *gspca_dev); + +static const struct ctrl sd_ctrls[NCTRLS] = { +[BRIGHTNESS] = { { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, @@ -106,13 +105,11 @@ static const struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 255, .step = 1, -#define BRIGHTNESS_DEF 128 - .default_value = BRIGHTNESS_DEF, + .default_value = 128, }, - .set = sd_setbrightness, - .get = sd_getbrightness, + .set_control = setcontrast }, - { +[CONTRAST] = { { .id = V4L2_CID_CONTRAST, .type = V4L2_CTRL_TYPE_INTEGER, @@ -120,13 +117,11 @@ static const struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 255, .step = 1, -#define CONTRAST_DEF 128 - .default_value = CONTRAST_DEF, + .default_value = 128, }, - .set = sd_setcontrast, - .get = sd_getcontrast, + .set_control = setcontrast }, - { +[GAMMA] = { { .id = V4L2_CID_GAMMA, .type = V4L2_CTRL_TYPE_INTEGER, @@ -136,10 +131,9 @@ static const struct ctrl sd_ctrls[] = { .step = 1, .default_value = 4, }, - .set = sd_setgamma, - .get = sd_getgamma, + .set_control = setcontrast }, - { +[AUTOGAIN] = { { .id = V4L2_CID_AUTOGAIN, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -147,14 +141,11 @@ static const struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, -#define AUTOGAIN_DEF 1 - .default_value = AUTOGAIN_DEF, + .default_value = 1, }, - .set = sd_setautogain, - .get = sd_getautogain, + .set_control = setautogain }, -#define LIGHTFREQ_IDX 4 - { +[LIGHTFREQ] = { { .id = V4L2_CID_POWER_LINE_FREQUENCY, .type = V4L2_CTRL_TYPE_MENU, @@ -162,13 +153,11 @@ static const struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ .step = 1, -#define FREQ_DEF 0 - .default_value = FREQ_DEF, + .default_value = 0, }, - .set = sd_setfreq, - .get = sd_getfreq, + .set_control = setlightfreq }, - { +[SHARPNESS] = { { .id = V4L2_CID_SHARPNESS, .type = V4L2_CTRL_TYPE_INTEGER, @@ -176,11 +165,9 @@ static const struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 3, .step = 1, -#define SHARPNESS_DEF 2 - .default_value = SHARPNESS_DEF, + .default_value = 2, }, - .set = sd_setsharpness, - .get = sd_getsharpness, + .set_control = setsharpness }, }; @@ -5875,7 +5862,7 @@ static void setsharpness(struct gspca_dev *gspca_dev) {0x10, 0x1e} }; - sharpness = sd->sharpness; + sharpness = sd->ctrls[SHARPNESS].val; reg_w(gspca_dev, sharpness_tb[sharpness][0], 0x01c6); reg_r(gspca_dev, 0x01c8); reg_r(gspca_dev, 0x01c9); @@ -5910,10 +5897,10 @@ static void setcontrast(struct gspca_dev *gspca_dev) 0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff}, }; - Tgamma = gamma_tb[sd->gamma - 1]; + Tgamma = gamma_tb[sd->ctrls[GAMMA].val - 1]; - contrast = ((int) sd->contrast - 128); /* -128 / 127 */ - brightness = ((int) sd->brightness - 128); /* -128 / 92 */ + contrast = ((int) sd->ctrls[CONTRAST].val - 128); /* -128 / 127 */ + brightness = ((int) sd->ctrls[BRIGHTNESS].val - 128); /* -128 / 92 */ adj = 0; gp1 = gp2 = 0; for (i = 0; i < 16; i++) { @@ -6060,8 +6047,8 @@ static void setlightfreq(struct gspca_dev *gspca_dev) tas5130c_vf0250_60HZ, tas5130c_vf0250_60HZScale}, }; - i = sd->lightfreq * 2; - mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; + i = sd->ctrls[LIGHTFREQ].val * 2; + mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; if (mode) i++; /* 320x240 */ zc3_freq = freq_tb[sd->sensor][i]; @@ -6070,14 +6057,14 @@ static void setlightfreq(struct gspca_dev *gspca_dev) usb_exchange(gspca_dev, zc3_freq); switch (sd->sensor) { case SENSOR_GC0305: - if (mode /* if 320x240 */ - && sd->lightfreq == 1) /* and 50Hz */ + if (mode /* if 320x240 */ + && sd->ctrls[LIGHTFREQ].val == 1) /* and 50Hz */ reg_w(gspca_dev, 0x85, 0x018d); /* win: 0x80, 0x018d */ break; case SENSOR_OV7620: - if (!mode) { /* if 640x480 */ - if (sd->lightfreq != 0) /* and 50 or 60 Hz */ + if (!mode) { /* if 640x480 */ + if (sd->ctrls[LIGHTFREQ].val != 0) /* and filter */ reg_w(gspca_dev, 0x40, 0x0002); else reg_w(gspca_dev, 0x44, 0x0002); @@ -6094,7 +6081,7 @@ static void setautogain(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; u8 autoval; - if (sd->autogain) + if (sd->ctrls[AUTOGAIN].val) autoval = 0x42; else autoval = 0x02; @@ -6421,11 +6408,7 @@ static int sd_config(struct gspca_dev *gspca_dev, /* define some sensors from the vendor/product */ sd->sensor = id->driver_info; - sd->sharpness = SHARPNESS_DEF; - sd->brightness = BRIGHTNESS_DEF; - sd->contrast = CONTRAST_DEF; - sd->autogain = AUTOGAIN_DEF; - sd->lightfreq = FREQ_DEF; + gspca_dev->cam.ctrls = sd->ctrls; sd->quality = QUALITY_DEF; return 0; @@ -6588,7 +6571,7 @@ static int sd_init(struct gspca_dev *gspca_dev) case 0x2030: PDEBUG(D_PROBE, "Find Sensor PO2030"); sd->sensor = SENSOR_PO2030; - sd->sharpness = 0; /* from win traces */ + sd->ctrls[SHARPNESS].def = 0; /* from win traces */ break; case 0x7620: PDEBUG(D_PROBE, "Find Sensor OV7620"); @@ -6629,11 +6612,12 @@ static int sd_init(struct gspca_dev *gspca_dev) cam->nmodes = ARRAY_SIZE(broken_vga_mode); break; } - sd->gamma = gamma[sd->sensor]; + + sd->ctrls[GAMMA].def = gamma[sd->sensor]; switch (sd->sensor) { case SENSOR_OV7630C: - gspca_dev->ctrl_dis = (1 << LIGHTFREQ_IDX); + gspca_dev->ctrl_dis = (1 << LIGHTFREQ); break; } @@ -6843,114 +6827,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } -static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->brightness = val; - if (gspca_dev->streaming) - setcontrast(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->brightness; - return 0; -} - -static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->contrast = val; - if (gspca_dev->streaming) - setcontrast(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->contrast; - return 0; -} - -static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->autogain = val; - if (gspca_dev->streaming) - setautogain(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->autogain; - return 0; -} - -static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->gamma = val; - if (gspca_dev->streaming) - setcontrast(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->gamma; - return 0; -} - -static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->lightfreq = val; - if (gspca_dev->streaming) - setlightfreq(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->lightfreq; - return 0; -} - -static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->sharpness = val; - if (gspca_dev->streaming) - setsharpness(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->sharpness; - return 0; -} - static int sd_querymenu(struct gspca_dev *gspca_dev, struct v4l2_querymenu *menu) { -- cgit v0.10.2 From 7fbee99aa2c73bdf47add9de58f646fa7713e7e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Tue, 28 Dec 2010 07:17:40 -0300 Subject: [media] gspca - zc3xx: The sensor of the VF0250 is a GC0303 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 48b8802..14b85d4 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -71,6 +71,7 @@ enum sensors { SENSOR_ADCM2700, SENSOR_CS2102, SENSOR_CS2102K, + SENSOR_GC0303, SENSOR_GC0305, SENSOR_HDCS2020b, SENSOR_HV7131B, @@ -86,7 +87,6 @@ enum sensors { SENSOR_PB0330, SENSOR_PO2030, SENSOR_TAS5130C, - SENSOR_TAS5130C_VF0250, SENSOR_MAX }; @@ -5393,7 +5393,7 @@ static const struct usb_action tas5130c_NoFlikerScale[] = { {} }; -static const struct usb_action tas5130c_vf0250_InitialScale[] = { +static const struct usb_action gc0303_InitialScale[] = { {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ @@ -5460,7 +5460,7 @@ static const struct usb_action tas5130c_vf0250_InitialScale[] = { {} }; -static const struct usb_action tas5130c_vf0250_Initial[] = { +static const struct usb_action gc0303_Initial[] = { {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ @@ -5525,7 +5525,7 @@ static const struct usb_action tas5130c_vf0250_Initial[] = { {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */ {} }; -static const struct usb_action tas5130c_vf0250_50HZScale[] = { +static const struct usb_action gc0303_50HZScale[] = { {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */ {0xaa, 0x84, 0x00aa}, /* 00,84,aa,aa */ @@ -5549,7 +5549,7 @@ static const struct usb_action tas5130c_vf0250_50HZScale[] = { {} }; -static const struct usb_action tas5130c_vf0250_50HZ[] = { +static const struct usb_action gc0303_50HZ[] = { {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ {0xaa, 0x83, 0x0003}, /* 00,83,03,aa */ {0xaa, 0x84, 0x0054}, /* 00,84,54,aa */ @@ -5573,7 +5573,7 @@ static const struct usb_action tas5130c_vf0250_50HZ[] = { {} }; -static const struct usb_action tas5130c_vf0250_60HZScale[] = { +static const struct usb_action gc0303_60HZScale[] = { {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */ {0xaa, 0x84, 0x0062}, /* 00,84,62,aa */ @@ -5597,7 +5597,7 @@ static const struct usb_action tas5130c_vf0250_60HZScale[] = { {} }; -static const struct usb_action tas5130c_vf0250_60HZ[] = { +static const struct usb_action gc0303_60HZ[] = { {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ {0xaa, 0x83, 0x0002}, /* 00,83,02,aa */ {0xaa, 0x84, 0x00c4}, /* 00,84,c4,aa */ @@ -5621,7 +5621,7 @@ static const struct usb_action tas5130c_vf0250_60HZ[] = { {} }; -static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = { +static const struct usb_action gc0303_NoFlikerScale[] = { {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ @@ -5643,7 +5643,7 @@ static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = { {} }; -static const struct usb_action tas5130c_vf0250_NoFliker[] = { +static const struct usb_action gc0303_NoFliker[] = { {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ @@ -5820,12 +5820,13 @@ static void setmatrix(struct gspca_dev *gspca_dev) {0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60}; static const u8 tas5130c_matrix[9] = {0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68}; - static const u8 vf0250_matrix[9] = + static const u8 gc0303_matrix[9] = {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b}; static const u8 *matrix_tb[SENSOR_MAX] = { [SENSOR_ADCM2700] = adcm2700_matrix, [SENSOR_CS2102] = ov7620_matrix, [SENSOR_CS2102K] = NULL, + [SENSOR_GC0303] = gc0303_matrix, [SENSOR_GC0305] = gc0305_matrix, [SENSOR_HDCS2020b] = NULL, [SENSOR_HV7131B] = NULL, @@ -5841,7 +5842,6 @@ static void setmatrix(struct gspca_dev *gspca_dev) [SENSOR_PB0330] = gc0305_matrix, [SENSOR_PO2030] = po2030_matrix, [SENSOR_TAS5130C] = tas5130c_matrix, - [SENSOR_TAS5130C_VF0250] = vf0250_matrix, }; matrix = matrix_tb[sd->sensor]; @@ -5981,6 +5981,10 @@ static void setlightfreq(struct gspca_dev *gspca_dev) {cs2102_NoFliker, cs2102_NoFlikerScale, NULL, NULL, /* currently disabled */ NULL, NULL}, + [SENSOR_GC0303] = + {gc0303_NoFliker, gc0303_NoFlikerScale, + gc0303_50HZ, gc0303_50HZScale, + gc0303_60HZ, gc0303_60HZScale}, [SENSOR_GC0305] = {gc0305_NoFliker, gc0305_NoFliker, gc0305_50HZ, gc0305_50HZ, @@ -6041,10 +6045,6 @@ static void setlightfreq(struct gspca_dev *gspca_dev) {tas5130c_NoFliker, tas5130c_NoFlikerScale, tas5130c_50HZ, tas5130c_50HZScale, tas5130c_60HZ, tas5130c_60HZScale}, - [SENSOR_TAS5130C_VF0250] = - {tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale, - tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale, - tas5130c_vf0250_60HZ, tas5130c_vf0250_60HZScale}, }; i = sd->ctrls[LIGHTFREQ].val * 2; @@ -6317,8 +6317,8 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) retword = i2c_read(gspca_dev, 0x00); if (retword != 0) { PDEBUG(D_PROBE, "probe 3wr vga type %02x", retword); - if (retword == 0x0011) /* VF0250 */ - return 0x0250; + if (retword == 0x0011) /* gc0303 */ + return 0x0303; if (retword == 0x0029) /* gc0305 */ send_unknown(gspca_dev, SENSOR_GC0305); return retword; @@ -6379,7 +6379,7 @@ static int zcxx_probeSensor(struct gspca_dev *gspca_dev) switch (sd->sensor) { case SENSOR_MC501CB: return -1; /* don't probe */ - case SENSOR_TAS5130C_VF0250: + case SENSOR_GC0303: /* may probe but with no write in reg 0x0010 */ return -1; /* don't probe */ case SENSOR_PAS106: @@ -6424,6 +6424,7 @@ static int sd_init(struct gspca_dev *gspca_dev) [SENSOR_ADCM2700] = 4, [SENSOR_CS2102] = 4, [SENSOR_CS2102K] = 5, + [SENSOR_GC0303] = 3, [SENSOR_GC0305] = 4, [SENSOR_HDCS2020b] = 4, [SENSOR_HV7131B] = 4, @@ -6439,12 +6440,12 @@ static int sd_init(struct gspca_dev *gspca_dev) [SENSOR_PB0330] = 4, [SENSOR_PO2030] = 4, [SENSOR_TAS5130C] = 3, - [SENSOR_TAS5130C_VF0250] = 3, }; static const u8 mode_tb[SENSOR_MAX] = { [SENSOR_ADCM2700] = 2, [SENSOR_CS2102] = 1, [SENSOR_CS2102K] = 1, + [SENSOR_GC0303] = 1, [SENSOR_GC0305] = 1, [SENSOR_HDCS2020b] = 1, [SENSOR_HV7131B] = 1, @@ -6460,7 +6461,6 @@ static int sd_init(struct gspca_dev *gspca_dev) [SENSOR_PB0330] = 1, [SENSOR_PO2030] = 1, [SENSOR_TAS5130C] = 1, - [SENSOR_TAS5130C_VF0250] = 1, }; sensor = zcxx_probeSensor(gspca_dev); @@ -6476,8 +6476,8 @@ static int sd_init(struct gspca_dev *gspca_dev) case SENSOR_MC501CB: PDEBUG(D_PROBE, "Sensor MC501CB"); break; - case SENSOR_TAS5130C_VF0250: - PDEBUG(D_PROBE, "Sensor Tas5130 (VF0250)"); + case SENSOR_GC0303: + PDEBUG(D_PROBE, "Sensor GC0303"); break; default: warn("Unknown sensor - set to TAS5130C"); @@ -6564,9 +6564,9 @@ static int sd_init(struct gspca_dev *gspca_dev) PDEBUG(D_PROBE, "Find Sensor GC0305"); sd->sensor = SENSOR_GC0305; break; - case 0x0250: - PDEBUG(D_PROBE, "Sensor Tas5130 (VF0250)"); - sd->sensor = SENSOR_TAS5130C_VF0250; + case 0x0303: + PDEBUG(D_PROBE, "Sensor GC0303"); + sd->sensor = SENSOR_GC0303; break; case 0x2030: PDEBUG(D_PROBE, "Find Sensor PO2030"); @@ -6637,6 +6637,8 @@ static int sd_start(struct gspca_dev *gspca_dev) {cs2102_Initial, cs2102_InitialScale}, [SENSOR_CS2102K] = {cs2102K_Initial, cs2102K_InitialScale}, + [SENSOR_GC0303] = + {gc0303_Initial, gc0303_InitialScale}, [SENSOR_GC0305] = {gc0305_Initial, gc0305_InitialScale}, [SENSOR_HDCS2020b] = @@ -6667,8 +6669,6 @@ static int sd_start(struct gspca_dev *gspca_dev) {po2030_Initial, po2030_InitialScale}, [SENSOR_TAS5130C] = {tas5130c_Initial, tas5130c_InitialScale}, - [SENSOR_TAS5130C_VF0250] = - {tas5130c_vf0250_Initial, tas5130c_vf0250_InitialScale}, }; /* create the JPEG header */ @@ -6693,7 +6693,7 @@ static int sd_start(struct gspca_dev *gspca_dev) case SENSOR_OV7620: case SENSOR_PO2030: case SENSOR_TAS5130C: - case SENSOR_TAS5130C_VF0250: + case SENSOR_GC0303: /* msleep(100); * ?? */ reg_r(gspca_dev, 0x0002); /* --> 0x40 */ reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */ @@ -6921,8 +6921,8 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x4035), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x041e, 0x4036)}, {USB_DEVICE(0x041e, 0x403a)}, - {USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_TAS5130C_VF0250}, - {USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_TAS5130C_VF0250}, + {USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_GC0303}, + {USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_GC0303}, {USB_DEVICE(0x0458, 0x7007)}, {USB_DEVICE(0x0458, 0x700c)}, {USB_DEVICE(0x0458, 0x700f)}, -- cgit v0.10.2 From 7e5f9059a807ce9b7a12b2402f5aeae9557c8049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Tue, 28 Dec 2010 07:24:18 -0300 Subject: [media] gspca - vc032x: Cleanup source MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 38a6efe..9b2ae1b 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -47,24 +47,29 @@ struct sd { u8 image_offset; u8 bridge; -#define BRIDGE_VC0321 0 -#define BRIDGE_VC0323 1 u8 sensor; -#define SENSOR_HV7131R 0 -#define SENSOR_MI0360 1 -#define SENSOR_MI1310_SOC 2 -#define SENSOR_MI1320 3 -#define SENSOR_MI1320_SOC 4 -#define SENSOR_OV7660 5 -#define SENSOR_OV7670 6 -#define SENSOR_PO1200 7 -#define SENSOR_PO3130NC 8 -#define SENSOR_POxxxx 9 u8 flags; #define FL_SAMSUNG 0x01 /* SamsungQ1 (2 sensors) */ #define FL_HFLIP 0x02 /* mirrored by default */ #define FL_VFLIP 0x04 /* vertical flipped by default */ }; +enum bridges { + BRIDGE_VC0321, + BRIDGE_VC0323, +}; +enum sensors { + SENSOR_HV7131R, + SENSOR_MI0360, + SENSOR_MI1310_SOC, + SENSOR_MI1320, + SENSOR_MI1320_SOC, + SENSOR_OV7660, + SENSOR_OV7670, + SENSOR_PO1200, + SENSOR_PO3130NC, + SENSOR_POxxxx, + NSENSORS +}; /* V4L2 controls supported by the driver */ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); @@ -260,56 +265,56 @@ static const struct ctrl sd_ctrls[] = { }; /* table of the disabled controls */ -static u32 ctrl_dis[] = { -/* SENSOR_HV7131R 0 */ +static u32 ctrl_dis[NSENSORS] = { + [SENSOR_HV7131R] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_MI0360 1 */ + [SENSOR_MI0360] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_MI1310_SOC 2 */ + [SENSOR_MI1310_SOC] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_MI1320 3 */ + [SENSOR_MI1320] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_MI1320_SOC 4 */ + [SENSOR_MI1320_SOC] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_OV7660 5 */ + [SENSOR_OV7660] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_OV7670 6 */ + [SENSOR_OV7670] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_PO1200 7 */ + [SENSOR_PO1200] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << LIGHTFREQ_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_PO3130NC 8 */ + [SENSOR_PO3130NC] = (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX) | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX), -/* SENSOR_POxxxx 9 */ + [SENSOR_POxxxx] = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX), }; @@ -3420,17 +3425,18 @@ static int sd_init(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; int sensor; - static u8 npkt[] = { /* number of packets per ISOC message */ - 64, /* HV7131R 0 */ - 32, /* MI0360 1 */ - 32, /* MI1310_SOC 2 */ - 64, /* MI1320 3 */ - 128, /* MI1320_SOC 4 */ - 32, /* OV7660 5 */ - 64, /* OV7670 6 */ - 128, /* PO1200 7 */ - 128, /* PO3130NC 8 */ - 128, /* POxxxx 9 */ + /* number of packets per ISOC message */ + static u8 npkt[NSENSORS] = { + [SENSOR_HV7131R] = 64, + [SENSOR_MI0360] = 32, + [SENSOR_MI1310_SOC] = 32, + [SENSOR_MI1320] = 64, + [SENSOR_MI1320_SOC] = 128, + [SENSOR_OV7660] = 32, + [SENSOR_OV7670] = 64, + [SENSOR_PO1200] = 128, + [SENSOR_PO3130NC] = 128, + [SENSOR_POxxxx] = 128, }; if (sd->sensor != SENSOR_POxxxx) -- cgit v0.10.2 From 71e84ea7f082eb02df6ef40f55d2c4a998f6e1df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Tue, 28 Dec 2010 07:35:27 -0300 Subject: [media] gspca - stv06xx/st6422: Use the new video control mechanism MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c index 42f3a1e..8a456de 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c @@ -28,6 +28,20 @@ #include "stv06xx_st6422.h" +/* controls */ +enum e_ctrl { + BRIGHTNESS, + CONTRAST, + GAIN, + EXPOSURE, + NCTRLS /* number of controls */ +}; + +/* sensor settings */ +struct st6422_settings { + struct gspca_ctrl ctrls[NCTRLS]; +}; + static struct v4l2_pix_format st6422_mode[] = { /* Note we actually get 124 lines of data, of which we skip the 4st 4 as they are garbage */ @@ -57,9 +71,14 @@ static struct v4l2_pix_format st6422_mode[] = { }, }; -static const struct ctrl st6422_ctrl[] = { -#define BRIGHTNESS_IDX 0 - { +/* V4L2 controls supported by the driver */ +static void st6422_set_brightness(struct gspca_dev *gspca_dev); +static void st6422_set_contrast(struct gspca_dev *gspca_dev); +static void st6422_set_gain(struct gspca_dev *gspca_dev); +static void st6422_set_exposure(struct gspca_dev *gspca_dev); + +static const struct ctrl st6422_ctrl[NCTRLS] = { +[BRIGHTNESS] = { { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, @@ -69,11 +88,9 @@ static const struct ctrl st6422_ctrl[] = { .step = 1, .default_value = 3 }, - .set = st6422_set_brightness, - .get = st6422_get_brightness + .set_control = st6422_set_brightness }, -#define CONTRAST_IDX 1 - { +[CONTRAST] = { { .id = V4L2_CID_CONTRAST, .type = V4L2_CTRL_TYPE_INTEGER, @@ -83,11 +100,9 @@ static const struct ctrl st6422_ctrl[] = { .step = 1, .default_value = 11 }, - .set = st6422_set_contrast, - .get = st6422_get_contrast + .set_control = st6422_set_contrast }, -#define GAIN_IDX 2 - { +[GAIN] = { { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, @@ -97,49 +112,43 @@ static const struct ctrl st6422_ctrl[] = { .step = 1, .default_value = 64 }, - .set = st6422_set_gain, - .get = st6422_get_gain + .set_control = st6422_set_gain }, -#define EXPOSURE_IDX 3 - { +[EXPOSURE] = { { .id = V4L2_CID_EXPOSURE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Exposure", .minimum = 0, - .maximum = 1023, +#define EXPOSURE_MAX 1023 + .maximum = EXPOSURE_MAX, .step = 1, .default_value = 256 }, - .set = st6422_set_exposure, - .get = st6422_get_exposure + .set_control = st6422_set_exposure }, }; static int st6422_probe(struct sd *sd) { - int i; - s32 *sensor_settings; + struct st6422_settings *sensor_settings; if (sd->bridge != BRIDGE_ST6422) return -ENODEV; info("st6422 sensor detected"); - sensor_settings = kmalloc(ARRAY_SIZE(st6422_ctrl) * sizeof(s32), - GFP_KERNEL); + sensor_settings = kmalloc(sizeof *sensor_settings, GFP_KERNEL); if (!sensor_settings) return -ENOMEM; sd->gspca_dev.cam.cam_mode = st6422_mode; sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode); + sd->gspca_dev.cam.ctrls = sensor_settings->ctrls; sd->desc.ctrls = st6422_ctrl; sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl); sd->sensor_priv = sensor_settings; - for (i = 0; i < sd->desc.nctrls; i++) - sensor_settings[i] = st6422_ctrl[i].qctrl.default_value; - return 0; } @@ -234,77 +243,92 @@ static void st6422_disconnect(struct sd *sd) kfree(sd->sensor_priv); } -static int st6422_start(struct sd *sd) +static int setbrightness(struct sd *sd) +{ + struct st6422_settings *sensor_settings = sd->sensor_priv; + + /* val goes from 0 -> 31 */ + return stv06xx_write_bridge(sd, 0x1432, + sensor_settings->ctrls[BRIGHTNESS].val); +} + +static int setcontrast(struct sd *sd) +{ + struct st6422_settings *sensor_settings = sd->sensor_priv; + + /* Val goes from 0 -> 15 */ + return stv06xx_write_bridge(sd, 0x143a, + sensor_settings->ctrls[CONTRAST].val | 0xf0); +} + +static int setgain(struct sd *sd) { + struct st6422_settings *sensor_settings = sd->sensor_priv; + u8 gain; int err; - struct cam *cam = &sd->gspca_dev.cam; - s32 *sensor_settings = sd->sensor_priv; - if (cam->cam_mode[sd->gspca_dev.curr_mode].priv) - err = stv06xx_write_bridge(sd, 0x1505, 0x0f); - else - err = stv06xx_write_bridge(sd, 0x1505, 0x02); - if (err < 0) - return err; + gain = sensor_settings->ctrls[GAIN].val; - err = st6422_set_brightness(&sd->gspca_dev, - sensor_settings[BRIGHTNESS_IDX]); + /* Set red, green, blue, gain */ + err = stv06xx_write_bridge(sd, 0x0509, gain); if (err < 0) return err; - err = st6422_set_contrast(&sd->gspca_dev, - sensor_settings[CONTRAST_IDX]); + err = stv06xx_write_bridge(sd, 0x050a, gain); if (err < 0) return err; - err = st6422_set_exposure(&sd->gspca_dev, - sensor_settings[EXPOSURE_IDX]); + err = stv06xx_write_bridge(sd, 0x050b, gain); if (err < 0) return err; - err = st6422_set_gain(&sd->gspca_dev, - sensor_settings[GAIN_IDX]); + /* 2 mystery writes */ + err = stv06xx_write_bridge(sd, 0x050c, 0x2a); if (err < 0) return err; - PDEBUG(D_STREAM, "Starting stream"); - - return 0; + return stv06xx_write_bridge(sd, 0x050d, 0x01); } -static int st6422_stop(struct sd *sd) +static int setexposure(struct sd *sd) { - PDEBUG(D_STREAM, "Halting stream"); - - return 0; -} - -static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[BRIGHTNESS_IDX]; + struct st6422_settings *sensor_settings = sd->sensor_priv; + u16 expo; + int err; - PDEBUG(D_V4L2, "Read brightness %d", *val); + expo = sensor_settings->ctrls[EXPOSURE].val; + err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff); + if (err < 0) + return err; - return 0; + return stv06xx_write_bridge(sd, 0x143e, expo >> 8); } -static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val) +static int st6422_start(struct sd *sd) { int err; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; + struct cam *cam = &sd->gspca_dev.cam; - sensor_settings[BRIGHTNESS_IDX] = val; + if (cam->cam_mode[sd->gspca_dev.curr_mode].priv) + err = stv06xx_write_bridge(sd, 0x1505, 0x0f); + else + err = stv06xx_write_bridge(sd, 0x1505, 0x02); + if (err < 0) + return err; - if (!gspca_dev->streaming) - return 0; + err = setbrightness(sd); + if (err < 0) + return err; - /* val goes from 0 -> 31 */ - PDEBUG(D_V4L2, "Set brightness to %d", val); - err = stv06xx_write_bridge(sd, 0x1432, val); + err = setcontrast(sd); + if (err < 0) + return err; + + err = setexposure(sd); + if (err < 0) + return err; + + err = setgain(sd); if (err < 0) return err; @@ -313,125 +337,65 @@ static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val) return (err < 0) ? err : 0; } -static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val) +static int st6422_stop(struct sd *sd) { - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[CONTRAST_IDX]; - - PDEBUG(D_V4L2, "Read contrast %d", *val); + PDEBUG(D_STREAM, "Halting stream"); return 0; } -static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val) +static void st6422_set_brightness(struct gspca_dev *gspca_dev) { int err; struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - sensor_settings[CONTRAST_IDX] = val; - if (!gspca_dev->streaming) - return 0; - - /* Val goes from 0 -> 15 */ - PDEBUG(D_V4L2, "Set contrast to %d\n", val); - err = stv06xx_write_bridge(sd, 0x143a, 0xf0 | val); - if (err < 0) - return err; + err = setbrightness(sd); /* commit settings */ - err = stv06xx_write_bridge(sd, 0x143f, 0x01); - return (err < 0) ? err : 0; -} - -static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[GAIN_IDX]; + if (err >= 0) + err = stv06xx_write_bridge(sd, 0x143f, 0x01); - PDEBUG(D_V4L2, "Read gain %d", *val); - - return 0; + gspca_dev->usb_err = err; } -static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val) +static void st6422_set_contrast(struct gspca_dev *gspca_dev) { int err; struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - sensor_settings[GAIN_IDX] = val; - - if (!gspca_dev->streaming) - return 0; - - PDEBUG(D_V4L2, "Set gain to %d", val); - - /* Set red, green, blue, gain */ - err = stv06xx_write_bridge(sd, 0x0509, val); - if (err < 0) - return err; - - err = stv06xx_write_bridge(sd, 0x050a, val); - if (err < 0) - return err; - - err = stv06xx_write_bridge(sd, 0x050b, val); - if (err < 0) - return err; - - /* 2 mystery writes */ - err = stv06xx_write_bridge(sd, 0x050c, 0x2a); - if (err < 0) - return err; - - err = stv06xx_write_bridge(sd, 0x050d, 0x01); - if (err < 0) - return err; + err = setcontrast(sd); /* commit settings */ - err = stv06xx_write_bridge(sd, 0x143f, 0x01); - return (err < 0) ? err : 0; + if (err >= 0) + err = stv06xx_write_bridge(sd, 0x143f, 0x01); + + gspca_dev->usb_err = err; } -static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) +static void st6422_set_gain(struct gspca_dev *gspca_dev) { + int err; struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - *val = sensor_settings[EXPOSURE_IDX]; + err = setgain(sd); - PDEBUG(D_V4L2, "Read exposure %d", *val); + /* commit settings */ + if (err >= 0) + err = stv06xx_write_bridge(sd, 0x143f, 0x01); - return 0; + gspca_dev->usb_err = err; } -static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val) +static void st6422_set_exposure(struct gspca_dev *gspca_dev) { int err; struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - sensor_settings[EXPOSURE_IDX] = val; - - if (!gspca_dev->streaming) - return 0; - - PDEBUG(D_V4L2, "Set exposure to %d\n", val); - err = stv06xx_write_bridge(sd, 0x143d, val & 0xff); - if (err < 0) - return err; - err = stv06xx_write_bridge(sd, 0x143e, val >> 8); - if (err < 0) - return err; + err = setexposure(sd); /* commit settings */ - err = stv06xx_write_bridge(sd, 0x143f, 0x01); - return (err < 0) ? err : 0; + if (err >= 0) + err = stv06xx_write_bridge(sd, 0x143f, 0x01); + + gspca_dev->usb_err = err; } diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h index 12608ae..d7498e0 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h @@ -37,16 +37,6 @@ static int st6422_init(struct sd *sd); static int st6422_stop(struct sd *sd); static void st6422_disconnect(struct sd *sd); -/* V4L2 controls supported by the driver */ -static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); -static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val); -static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val); -static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val); -static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val); -static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val); -static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); -static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val); - const struct stv06xx_sensor stv06xx_sensor_st6422 = { .name = "ST6422", /* No known way to lower framerate in case of less bandwidth */ -- cgit v0.10.2 From aa777a88b2d73f710b86b955e0c738af91e9e452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Tue, 28 Dec 2010 07:39:13 -0300 Subject: [media] gspca - sonixj: Bad clock for om6802 in 640x480 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 901ca81..2d0bb17 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -2533,7 +2533,7 @@ static int sd_start(struct gspca_dev *gspca_dev) init = om6802_sensor_param1; if (!mode) { /* if 640x480 */ reg17 &= ~MCK_SIZE_MASK; - reg17 |= 0x01; /* clock / 4 */ + reg17 |= 0x04; /* clock / 4 */ } break; case SENSOR_OV7630: -- cgit v0.10.2 From 427aacfe1d0c540bf80e5243d18ba1272f9b756f Mon Sep 17 00:00:00 2001 From: Dmitri Belimov Date: Tue, 28 Dec 2010 21:49:07 -0300 Subject: [media] tm6000: Fix mutex unbalance Hi Fix never unlocked mutex. No more crash after removing USB stick. With my best regards, Dmitry. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/tm6000/tm6000-core.c b/drivers/staging/tm6000/tm6000-core.c index 8c897d7..96aed4a 100644 --- a/drivers/staging/tm6000/tm6000-core.c +++ b/drivers/staging/tm6000/tm6000-core.c @@ -722,5 +722,5 @@ void tm6000_close_extension(struct tm6000_core *dev) ops->fini(dev); } } - mutex_lock(&tm6000_devlist_mutex); + mutex_unlock(&tm6000_devlist_mutex); } -- cgit v0.10.2 From c627b9d1f580f26fe99a8045d37a57f91e9aef66 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 18 Dec 2010 11:06:09 -0300 Subject: [media] usbvision: convert to unlocked_ioctl Convert driver to use core-assisted locking. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index b9dd74f..de58aa7 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -2291,10 +2291,8 @@ static void call_usbvision_power_off(struct work_struct *work) struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, powerOffWork); PDEBUG(DBG_FUNC, ""); - if(mutex_lock_interruptible(&usbvision->lock)) { + if (mutex_lock_interruptible(&usbvision->v4l2_lock)) return; - } - if(usbvision->user == 0) { usbvision_i2c_unregister(usbvision); @@ -2302,7 +2300,7 @@ static void call_usbvision_power_off(struct work_struct *work) usbvision_power_off(usbvision); usbvision->initialized = 0; } - mutex_unlock(&usbvision->lock); + mutex_unlock(&usbvision->v4l2_lock); } static void usbvision_powerOffTimer(unsigned long data) diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 20da6ea..a5709a5 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -356,7 +356,6 @@ static int usbvision_v4l2_open(struct file *file) PDEBUG(DBG_IO, "open"); - mutex_lock(&usbvision->lock); usbvision_reset_powerOffTimer(usbvision); if (usbvision->user) @@ -412,7 +411,6 @@ static int usbvision_v4l2_open(struct file *file) usbvision_empty_framequeues(usbvision); PDEBUG(DBG_IO, "success"); - mutex_unlock(&usbvision->lock); return errCode; } @@ -429,7 +427,6 @@ static int usbvision_v4l2_close(struct file *file) struct usb_usbvision *usbvision = video_drvdata(file); PDEBUG(DBG_IO, "close"); - mutex_lock(&usbvision->lock); usbvision_audio_off(usbvision); usbvision_restart_isoc(usbvision); @@ -449,8 +446,6 @@ static int usbvision_v4l2_close(struct file *file) usbvision->initialized = 0; } - mutex_unlock(&usbvision->lock); - if (usbvision->remove_pending) { printk(KERN_INFO "%s: Final disconnect\n", __func__); usbvision_release(usbvision); @@ -597,13 +592,11 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int input) if (input >= usbvision->video_inputs) return -EINVAL; - mutex_lock(&usbvision->lock); usbvision_muxsel(usbvision, input); usbvision_set_input(usbvision); usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight); - mutex_unlock(&usbvision->lock); return 0; } @@ -613,9 +606,7 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) usbvision->tvnormId=*id; - mutex_lock(&usbvision->lock); call_all(usbvision, core, s_std, usbvision->tvnormId); - mutex_unlock(&usbvision->lock); /* propagate the change to the decoder */ usbvision_muxsel(usbvision, usbvision->ctl_input); @@ -977,9 +968,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, usbvision->curFrame = NULL; /* by now we are committed to the new data... */ - mutex_lock(&usbvision->lock); usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height); - mutex_unlock(&usbvision->lock); return 0; } @@ -1100,16 +1089,12 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) PDEBUG(DBG_MMAP, "mmap"); - mutex_lock(&usbvision->lock); - if (!USBVISION_IS_OPERATIONAL(usbvision)) { - mutex_unlock(&usbvision->lock); return -EFAULT; } if (!(vma->vm_flags & VM_WRITE) || size != PAGE_ALIGN(usbvision->max_frame_size)) { - mutex_unlock(&usbvision->lock); return -EINVAL; } @@ -1121,7 +1106,6 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) if (i == usbvision->num_frames) { PDEBUG(DBG_MMAP, "mmap: user supplied mapping address is out of range"); - mutex_unlock(&usbvision->lock); return -EINVAL; } @@ -1134,7 +1118,6 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { PDEBUG(DBG_MMAP, "mmap: vm_insert_page failed"); - mutex_unlock(&usbvision->lock); return -EAGAIN; } start += PAGE_SIZE; @@ -1142,7 +1125,6 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) size -= PAGE_SIZE; } - mutex_unlock(&usbvision->lock); return 0; } @@ -1158,8 +1140,6 @@ static int usbvision_radio_open(struct file *file) PDEBUG(DBG_IO, "%s:", __func__); - mutex_lock(&usbvision->lock); - if (usbvision->user) { dev_err(&usbvision->rdev->dev, "%s: Someone tried to open an already opened USBVision Radio!\n", @@ -1198,7 +1178,6 @@ static int usbvision_radio_open(struct file *file) } } out: - mutex_unlock(&usbvision->lock); return errCode; } @@ -1210,8 +1189,6 @@ static int usbvision_radio_close(struct file *file) PDEBUG(DBG_IO, ""); - mutex_lock(&usbvision->lock); - /* Set packet size to 0 */ usbvision->ifaceAlt=0; errCode = usb_set_interface(usbvision->dev, usbvision->iface, @@ -1226,8 +1203,6 @@ static int usbvision_radio_close(struct file *file) usbvision->initialized = 0; } - mutex_unlock(&usbvision->lock); - if (usbvision->remove_pending) { printk(KERN_INFO "%s: Final disconnect\n", __func__); usbvision_release(usbvision); @@ -1248,7 +1223,7 @@ static const struct v4l2_file_operations usbvision_fops = { .release = usbvision_v4l2_close, .read = usbvision_v4l2_read, .mmap = usbvision_v4l2_mmap, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, /* .poll = video_poll, */ }; @@ -1298,7 +1273,7 @@ static const struct v4l2_file_operations usbvision_radio_fops = { .owner = THIS_MODULE, .open = usbvision_radio_open, .release = usbvision_radio_close, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops usbvision_radio_ioctl_ops = { @@ -1346,6 +1321,7 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, return NULL; } *vdev = *vdev_template; + vdev->lock = &usbvision->v4l2_lock; vdev->v4l2_dev = &usbvision->v4l2_dev; snprintf(vdev->name, sizeof(vdev->name), "%s", name); video_set_drvdata(vdev, usbvision); @@ -1448,7 +1424,7 @@ static struct usb_usbvision *usbvision_alloc(struct usb_device *dev, if (v4l2_device_register(&intf->dev, &usbvision->v4l2_dev)) goto err_free; - mutex_init(&usbvision->lock); /* available */ + mutex_init(&usbvision->v4l2_lock); // prepare control urb for control messages during interrupts usbvision->ctrlUrb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); @@ -1478,14 +1454,10 @@ static void usbvision_release(struct usb_usbvision *usbvision) { PDEBUG(DBG_PROBE, ""); - mutex_lock(&usbvision->lock); - usbvision_reset_powerOffTimer(usbvision); usbvision->initialized = 0; - mutex_unlock(&usbvision->lock); - usbvision_remove_sysfs(usbvision->vdev); usbvision_unregister_video(usbvision); @@ -1598,8 +1570,6 @@ static int __devinit usbvision_probe(struct usb_interface *intf, } PDEBUG(DBG_PROBE, "bridgeType %d", usbvision->bridgeType); - mutex_lock(&usbvision->lock); - /* compute alternate max packet sizes */ uif = dev->actconfig->interface[0]; @@ -1609,7 +1579,6 @@ static int __devinit usbvision_probe(struct usb_interface *intf, usbvision->num_alt,GFP_KERNEL); if (usbvision->alt_max_pkt_size == NULL) { dev_err(&intf->dev, "usbvision: out of memory!\n"); - mutex_unlock(&usbvision->lock); return -ENOMEM; } @@ -1641,7 +1610,6 @@ static int __devinit usbvision_probe(struct usb_interface *intf, usbvision->streaming = Stream_Off; usbvision_configure_video(usbvision); usbvision_register_video(usbvision); - mutex_unlock(&usbvision->lock); usbvision_create_sysfs(usbvision->vdev); @@ -1669,7 +1637,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) return; } - mutex_lock(&usbvision->lock); + mutex_lock(&usbvision->v4l2_lock); // At this time we ask to cancel outstanding URBs usbvision_stop_isoc(usbvision); @@ -1685,7 +1653,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) usb_put_dev(usbvision->dev); usbvision->dev = NULL; // USB device is no more - mutex_unlock(&usbvision->lock); + mutex_unlock(&usbvision->v4l2_lock); if (usbvision->user) { printk(KERN_INFO "%s: In use, disconnect pending\n", diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h index cc4e96c..2271ede 100644 --- a/drivers/media/video/usbvision/usbvision.h +++ b/drivers/media/video/usbvision/usbvision.h @@ -391,7 +391,7 @@ struct usb_usbvision { unsigned char iface; /* Video interface number */ unsigned char ifaceAlt; /* Alt settings */ unsigned char Vin_Reg2_Preset; - struct mutex lock; + struct mutex v4l2_lock; struct timer_list powerOffTimer; struct work_struct powerOffWork; int power; /* is the device powered on? */ -- cgit v0.10.2 From 5490a7cbe65d63c6ec45f1013287af1e390c95d7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 19 Dec 2010 20:21:36 -0300 Subject: [media] usbvision: get rid of camelCase Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c index 503b13b..acfdb2b 100644 --- a/drivers/media/video/usbvision/usbvision-cards.c +++ b/drivers/media/video/usbvision/usbvision-cards.c @@ -32,998 +32,998 @@ /* Supported Devices: A table for usbvision.c*/ struct usbvision_device_data_st usbvision_device_data[] = { [XANBOO] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 4, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Xanboo", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 4, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = -1, + .y_offset = -1, + .model_string = "Xanboo", }, [BELKIN_VIDEOBUS_II] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Belkin USB VideoBus II Adapter", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Belkin USB VideoBus II Adapter", }, [BELKIN_VIDEOBUS] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Belkin Components USB VideoBus", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 2, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = -1, + .y_offset = -1, + .model_string = "Belkin Components USB VideoBus", }, [BELKIN_USB_VIDEOBUS_II] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Belkin USB VideoBus II", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Belkin USB VideoBus II", }, [ECHOFX_INTERVIEW_LITE] = { - .Interface = 0, - .Codec = CODEC_SAA7111, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 0, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = -1, - .Y_Offset = -1, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "echoFX InterView Lite", + .interface = 0, + .codec = CODEC_SAA7111, + .video_channels = 2, + .video_norm = V4L2_STD_PAL, + .audio_channels = 0, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = -1, + .y_offset = -1, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "echoFX InterView Lite", }, [USBGEAR_USBG_V1] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "USBGear USBG-V1 resp. HAMA USB", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 2, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = -1, + .y_offset = -1, + .model_string = "USBGear USBG-V1 resp. HAMA USB", }, [D_LINK_V100] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 4, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 0, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "D-Link V100", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 4, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 0, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "D-Link V100", }, [X10_USB_CAMERA] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "X10 USB Camera", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 2, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = -1, + .y_offset = -1, + .model_string = "X10 USB Camera", }, [HPG_WINTV_LIVE_PAL_BG] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = -1, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Live (PAL B/G)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 2, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = -1, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Live (PAL B/G)", }, [HPG_WINTV_LIVE_PRO_NTSC_MN] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 0, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Live Pro (NTSC M/N)", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 0, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Live Pro (NTSC M/N)", }, [ZORAN_PMD_NOGATECH] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 2, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Zoran Co. PMD (Nogatech) AV-grabber Manhattan", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_PAL, + .audio_channels = 2, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Zoran Co. PMD (Nogatech) AV-grabber Manhattan", }, [NOGATECH_USB_TV_NTSC_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = -1, - .Y_Offset = 20, - .ModelString = "Nogatech USB-TV (NTSC) FM", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = -1, + .y_offset = 20, + .model_string = "Nogatech USB-TV (NTSC) FM", }, [PNY_USB_TV_NTSC_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = -1, - .Y_Offset = 20, - .ModelString = "PNY USB-TV (NTSC) FM", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = -1, + .y_offset = 20, + .model_string = "PNY USB-TV (NTSC) FM", }, [PV_PLAYTV_USB_PRO_PAL_FM] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "PixelView PlayTv-USB PRO (PAL) FM", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "PixelView PlayTv-USB PRO (PAL) FM", }, [ZT_721] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "ZTV ZT-721 2.4GHz USB A/V Receiver", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "ZTV ZT-721 2.4GHz USB A/V Receiver", }, [HPG_WINTV_NTSC_MN] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = -1, - .Y_Offset = 20, - .ModelString = "Hauppauge WinTV USB (NTSC M/N)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = -1, + .y_offset = 20, + .model_string = "Hauppauge WinTV USB (NTSC M/N)", }, [HPG_WINTV_PAL_BG] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Hauppauge WinTV USB (PAL B/G)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = -1, + .y_offset = -1, + .model_string = "Hauppauge WinTV USB (PAL B/G)", }, [HPG_WINTV_PAL_I] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Hauppauge WinTV USB (PAL I)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = -1, + .y_offset = -1, + .model_string = "Hauppauge WinTV USB (PAL I)", }, [HPG_WINTV_PAL_SECAM_L] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_SECAM, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_SECAM, - .X_Offset = 0x80, - .Y_Offset = 0x16, - .ModelString = "Hauppauge WinTV USB (PAL/SECAM L)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_SECAM, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_SECAM, + .x_offset = 0x80, + .y_offset = 0x16, + .model_string = "Hauppauge WinTV USB (PAL/SECAM L)", }, [HPG_WINTV_PAL_D_K] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Hauppauge WinTV USB (PAL D/K)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = -1, + .y_offset = -1, + .model_string = "Hauppauge WinTV USB (PAL D/K)", }, [HPG_WINTV_NTSC_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Hauppauge WinTV USB (NTSC FM)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = -1, + .y_offset = -1, + .model_string = "Hauppauge WinTV USB (NTSC FM)", }, [HPG_WINTV_PAL_BG_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Hauppauge WinTV USB (PAL B/G FM)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = -1, + .y_offset = -1, + .model_string = "Hauppauge WinTV USB (PAL B/G FM)", }, [HPG_WINTV_PAL_I_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Hauppauge WinTV USB (PAL I FM)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = -1, + .y_offset = -1, + .model_string = "Hauppauge WinTV USB (PAL I FM)", }, [HPG_WINTV_PAL_D_K_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Hauppauge WinTV USB (PAL D/K FM)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = -1, + .y_offset = -1, + .model_string = "Hauppauge WinTV USB (PAL D/K FM)", }, [HPG_WINTV_PRO_NTSC_MN] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_MICROTUNE_4049FM5, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (NTSC M/N)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_MICROTUNE_4049FM5, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (NTSC M/N)", }, [HPG_WINTV_PRO_NTSC_MN_V2] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_MICROTUNE_4049FM5, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (NTSC M/N) V2", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_MICROTUNE_4049FM5, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (NTSC M/N) V2", }, [HPG_WINTV_PRO_PAL] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_FM1216ME_MK3, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L)", }, [HPG_WINTV_PRO_NTSC_MN_V3] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (NTSC M/N) V3", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (NTSC M/N) V3", }, [HPG_WINTV_PRO_PAL_BG] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL B/G)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL B/G)", }, [HPG_WINTV_PRO_PAL_I] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL I)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL I)", }, [HPG_WINTV_PRO_PAL_SECAM_L] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_SECAM, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_SECAM, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL/SECAM L)", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_SECAM, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_SECAM, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL/SECAM L)", }, [HPG_WINTV_PRO_PAL_D_K] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL D/K)", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL D/K)", }, [HPG_WINTV_PRO_PAL_SECAM] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_SECAM, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_SECAM, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L)", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_SECAM, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_SECAM, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L)", }, [HPG_WINTV_PRO_PAL_SECAM_V2] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_SECAM, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_SECAM, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L) V2", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_SECAM, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_SECAM, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L) V2", }, [HPG_WINTV_PRO_PAL_BG_V2] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_ALPS_TSBE1_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL B/G) V2", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_ALPS_TSBE1_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL B/G) V2", }, [HPG_WINTV_PRO_PAL_BG_D_K] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_ALPS_TSBE1_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL B/G,D/K)", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_ALPS_TSBE1_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL B/G,D/K)", }, [HPG_WINTV_PRO_PAL_I_D_K] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_LG_PAL_NEW_TAPC, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL I,D/K)", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL I,D/K)", }, [HPG_WINTV_PRO_NTSC_MN_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (NTSC M/N FM)", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (NTSC M/N FM)", }, [HPG_WINTV_PRO_PAL_BG_FM] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL B/G FM)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL B/G FM)", }, [HPG_WINTV_PRO_PAL_I_FM] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL I FM)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL I FM)", }, [HPG_WINTV_PRO_PAL_D_K_FM] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL D/K FM)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL D/K FM)", }, [HPG_WINTV_PRO_TEMIC_PAL_FM] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_MICROTUNE_4049FM5, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (Temic PAL/SECAM B/G/I/D/K/L FM)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_MICROTUNE_4049FM5, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (Temic PAL/SECAM B/G/I/D/K/L FM)", }, [HPG_WINTV_PRO_TEMIC_PAL_BG_FM] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_MICROTUNE_4049FM5, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (Temic PAL B/G FM)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_MICROTUNE_4049FM5, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (Temic PAL B/G FM)", }, [HPG_WINTV_PRO_PAL_FM] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_FM1216ME_MK3, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L FM)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L FM)", }, [HPG_WINTV_PRO_NTSC_MN_FM_V2] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Hauppauge WinTV USB Pro (NTSC M/N FM) V2", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Hauppauge WinTV USB Pro (NTSC M/N FM) V2", }, [CAMTEL_TVB330] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = 5, - .Y_Offset = 5, - .ModelString = "Camtel Technology USB TV Genie Pro FM Model TVB330", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = 5, + .y_offset = 5, + .model_string = "Camtel Technology USB TV Genie Pro FM Model TVB330", }, [DIGITAL_VIDEO_CREATOR_I] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 0, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Digital Video Creator I", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_PAL, + .audio_channels = 0, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Digital Video Creator I", }, [GLOBAL_VILLAGE_GV_007_NTSC] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 0, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 82, - .Y_Offset = 20, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Global Village GV-007 (NTSC)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 2, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 0, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 82, + .y_offset = 20, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Global Village GV-007 (NTSC)", }, [DAZZLE_DVC_50_REV_1_NTSC] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 0, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Dazzle Fusion Model DVC-50 Rev 1 (NTSC)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 0, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Dazzle Fusion Model DVC-50 Rev 1 (NTSC)", }, [DAZZLE_DVC_80_REV_1_PAL] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 0, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Dazzle Fusion Model DVC-80 Rev 1 (PAL)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_PAL, + .audio_channels = 0, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Dazzle Fusion Model DVC-80 Rev 1 (PAL)", }, [DAZZLE_DVC_90_REV_1_SECAM] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_SECAM, - .AudioChannels = 0, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_SECAM, + .audio_channels = 0, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)", }, [ESKAPE_LABS_MYTV2GO] = { - .Interface = 0, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_FM1216ME_MK3, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Eskape Labs MyTV2Go", + .interface = 0, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Eskape Labs MyTV2Go", }, [PINNA_PCTV_USB_PAL] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 0, - .Tuner = 1, - .TunerType = TUNER_TEMIC_4066FY5_PAL_I, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Pinnacle Studio PCTV USB (PAL)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 0, + .tuner = 1, + .tuner_type = TUNER_TEMIC_4066FY5_PAL_I, + .x_offset = -1, + .y_offset = -1, + .model_string = "Pinnacle Studio PCTV USB (PAL)", }, [PINNA_PCTV_USB_SECAM] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_SECAM, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_SECAM, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Pinnacle Studio PCTV USB (SECAM)", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_SECAM, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_SECAM, + .x_offset = -1, + .y_offset = -1, + .model_string = "Pinnacle Studio PCTV USB (SECAM)", }, [PINNA_PCTV_USB_PAL_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = 128, - .Y_Offset = 23, - .ModelString = "Pinnacle Studio PCTV USB (PAL) FM", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = 128, + .y_offset = 23, + .model_string = "Pinnacle Studio PCTV USB (PAL) FM", }, [MIRO_PCTV_USB] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Miro PCTV USB", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .x_offset = -1, + .y_offset = -1, + .model_string = "Miro PCTV USB", }, [PINNA_PCTV_USB_NTSC_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Pinnacle Studio PCTV USB (NTSC) FM", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = -1, + .y_offset = -1, + .model_string = "Pinnacle Studio PCTV USB (NTSC) FM", }, [PINNA_PCTV_USB_NTSC_FM_V3] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Pinnacle Studio PCTV USB (NTSC) FM V3", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = -1, + .y_offset = -1, + .model_string = "Pinnacle Studio PCTV USB (NTSC) FM V3", }, [PINNA_PCTV_USB_PAL_FM_V2] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_TEMIC_4009FR5_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Pinnacle Studio PCTV USB (PAL) FM V2", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_TEMIC_4009FR5_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Pinnacle Studio PCTV USB (PAL) FM V2", }, [PINNA_PCTV_USB_NTSC_FM_V2] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_TEMIC_4039FR5_NTSC, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Pinnacle Studio PCTV USB (NTSC) FM V2", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_TEMIC_4039FR5_NTSC, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Pinnacle Studio PCTV USB (NTSC) FM V2", }, [PINNA_PCTV_USB_PAL_FM_V3] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_TEMIC_4009FR5_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Pinnacle Studio PCTV USB (PAL) FM V3", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_TEMIC_4009FR5_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Pinnacle Studio PCTV USB (PAL) FM V3", }, [PINNA_LINX_VD_IN_CAB_NTSC] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Pinnacle Studio Linx Video input cable (NTSC)", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Pinnacle Studio Linx Video input cable (NTSC)", }, [PINNA_LINX_VD_IN_CAB_PAL] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 2, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 0, - .TunerType = 0, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Pinnacle Studio Linx Video input cable (PAL)", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 2, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 0, + .tuner_type = 0, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Pinnacle Studio Linx Video input cable (PAL)", }, [PINNA_PCTV_BUNGEE_PAL_FM] = { - .Interface = -1, - .Codec = CODEC_SAA7113, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_PAL, - .AudioChannels = 1, - .Radio = 1, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_TEMIC_4009FR5_PAL, - .X_Offset = 0, - .Y_Offset = 3, - .Dvi_yuv_override = 1, - .Dvi_yuv = 7, - .ModelString = "Pinnacle PCTV Bungee USB (PAL) FM", + .interface = -1, + .codec = CODEC_SAA7113, + .video_channels = 3, + .video_norm = V4L2_STD_PAL, + .audio_channels = 1, + .radio = 1, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_TEMIC_4009FR5_PAL, + .x_offset = 0, + .y_offset = 3, + .dvi_yuv_override = 1, + .dvi_yuv = 7, + .model_string = "Pinnacle PCTV Bungee USB (PAL) FM", }, [HPG_WINTV] = { - .Interface = -1, - .Codec = CODEC_SAA7111, - .VideoChannels = 3, - .VideoNorm = V4L2_STD_NTSC, - .AudioChannels = 1, - .Radio = 0, - .vbi = 1, - .Tuner = 1, - .TunerType = TUNER_PHILIPS_NTSC_M, - .X_Offset = -1, - .Y_Offset = -1, - .ModelString = "Hauppauge WinTv-USB", + .interface = -1, + .codec = CODEC_SAA7111, + .video_channels = 3, + .video_norm = V4L2_STD_NTSC, + .audio_channels = 1, + .radio = 0, + .vbi = 1, + .tuner = 1, + .tuner_type = TUNER_PHILIPS_NTSC_M, + .x_offset = -1, + .y_offset = -1, + .model_string = "Hauppauge WinTv-USB", }, }; const int usbvision_device_data_size=ARRAY_SIZE(usbvision_device_data); diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index de58aa7..372e21b 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -53,23 +53,23 @@ static unsigned int force_testpattern; module_param(force_testpattern,int,0644); MODULE_PARM_DESC(force_testpattern,"enable test pattern display [core]"); -static int adjustCompression = 1; /* Set the compression to be adaptive */ -module_param(adjustCompression, int, 0444); -MODULE_PARM_DESC(adjustCompression, " Set the ADPCM compression for the device. Default: 1 (On)"); +static int adjust_compression = 1; /* Set the compression to be adaptive */ +module_param(adjust_compression, int, 0444); +MODULE_PARM_DESC(adjust_compression, " Set the ADPCM compression for the device. Default: 1 (On)"); /* To help people with Black and White output with using s-video input. * Some cables and input device are wired differently. */ -static int SwitchSVideoInput; -module_param(SwitchSVideoInput, int, 0444); -MODULE_PARM_DESC(SwitchSVideoInput, " Set the S-Video input. Some cables and input device are wired differently. Default: 0 (Off)"); +static int switch_svideo_input; +module_param(switch_svideo_input, int, 0444); +MODULE_PARM_DESC(switch_svideo_input, " Set the S-Video input. Some cables and input device are wired differently. Default: 0 (Off)"); -static unsigned int adjust_X_Offset = -1; -module_param(adjust_X_Offset, int, 0644); -MODULE_PARM_DESC(adjust_X_Offset, "adjust X offset display [core]"); +static unsigned int adjust_x_offset = -1; +module_param(adjust_x_offset, int, 0644); +MODULE_PARM_DESC(adjust_x_offset, "adjust X offset display [core]"); -static unsigned int adjust_Y_Offset = -1; -module_param(adjust_Y_Offset, int, 0644); -MODULE_PARM_DESC(adjust_Y_Offset, "adjust Y offset display [core]"); +static unsigned int adjust_y_offset = -1; +module_param(adjust_y_offset, int, 0644); +MODULE_PARM_DESC(adjust_y_offset, "adjust Y offset display [core]"); #define ENABLE_HEXDUMP 0 /* Enable if you need it */ @@ -327,7 +327,7 @@ static int scratch_get(struct usb_usbvision *usbvision, unsigned char *data, static int scratch_get_header(struct usb_usbvision *usbvision, struct usbvision_frame_header *header) { - int errCode = 0; + int err_code = 0; PDEBUG(DBG_SCRATCH, "from read_ptr=%d", usbvision->scratch_headermarker_read_ptr); @@ -340,15 +340,15 @@ static int scratch_get_header(struct usb_usbvision *usbvision, scratch_get(usbvision, (unsigned char *)header, USBVISION_HEADER_LENGTH); if ((header->magic_1 == USBVISION_MAGIC_1) && (header->magic_2 == USBVISION_MAGIC_2) - && (header->headerLength == USBVISION_HEADER_LENGTH)) { - errCode = USBVISION_HEADER_LENGTH; - header->frameWidth = header->frameWidthLo + (header->frameWidthHi << 8); - header->frameHeight = header->frameHeightLo + (header->frameHeightHi << 8); + && (header->header_length == USBVISION_HEADER_LENGTH)) { + err_code = USBVISION_HEADER_LENGTH; + header->frame_width = header->frame_width_lo + (header->frame_width_hi << 8); + header->frame_height = header->frame_height_lo + (header->frame_height_hi << 8); break; } } - return errCode; + return err_code; } @@ -371,7 +371,7 @@ static void scratch_reset(struct usb_usbvision *usbvision) usbvision->scratch_write_ptr = 0; usbvision->scratch_headermarker_read_ptr = 0; usbvision->scratch_headermarker_write_ptr = 0; - usbvision->isocstate = IsocState_NoFrame; + usbvision->isocstate = isoc_state_no_frame; } int usbvision_scratch_alloc(struct usb_usbvision *usbvision) @@ -420,13 +420,13 @@ static void usbvision_testpattern(struct usb_usbvision *usbvision, printk(KERN_ERR "%s: usbvision == NULL\n", proc); return; } - if (usbvision->curFrame == NULL) { - printk(KERN_ERR "%s: usbvision->curFrame is NULL.\n", proc); + if (usbvision->cur_frame == NULL) { + printk(KERN_ERR "%s: usbvision->cur_frame is NULL.\n", proc); return; } /* Grab the current frame */ - frame = usbvision->curFrame; + frame = usbvision->cur_frame; /* Optionally start at the beginning */ if (fullframe) { @@ -473,7 +473,7 @@ static void usbvision_testpattern(struct usb_usbvision *usbvision, } } - frame->grabstate = FrameState_Done; + frame->grabstate = frame_state_done; frame->scanlength += scan_length; ++num_pass; @@ -487,8 +487,8 @@ static void usbvision_testpattern(struct usb_usbvision *usbvision, int usbvision_decompress_alloc(struct usb_usbvision *usbvision) { int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2; - usbvision->IntraFrameBuffer = vmalloc_32(IFB_size); - if (usbvision->IntraFrameBuffer == NULL) { + usbvision->intra_frame_buffer = vmalloc_32(IFB_size); + if (usbvision->intra_frame_buffer == NULL) { dev_err(&usbvision->dev->dev, "%s: unable to allocate %d for compr. frame buffer\n", __func__, IFB_size); @@ -504,8 +504,8 @@ int usbvision_decompress_alloc(struct usb_usbvision *usbvision) */ void usbvision_decompress_free(struct usb_usbvision *usbvision) { - vfree(usbvision->IntraFrameBuffer); - usbvision->IntraFrameBuffer = NULL; + vfree(usbvision->intra_frame_buffer); + usbvision->intra_frame_buffer = NULL; } @@ -517,77 +517,77 @@ void usbvision_decompress_free(struct usb_usbvision *usbvision) * * Locate one of supported header markers in the scratch buffer. */ -static enum ParseState usbvision_find_header(struct usb_usbvision *usbvision) +static enum parse_state usbvision_find_header(struct usb_usbvision *usbvision) { struct usbvision_frame *frame; - int foundHeader = 0; + int found_header = 0; - frame = usbvision->curFrame; + frame = usbvision->cur_frame; - while (scratch_get_header(usbvision, &frame->isocHeader) == USBVISION_HEADER_LENGTH) { + while (scratch_get_header(usbvision, &frame->isoc_header) == USBVISION_HEADER_LENGTH) { // found header in scratch PDEBUG(DBG_HEADER, "found header: 0x%02x%02x %d %d %d %d %#x 0x%02x %u %u", - frame->isocHeader.magic_2, - frame->isocHeader.magic_1, - frame->isocHeader.headerLength, - frame->isocHeader.frameNum, - frame->isocHeader.framePhase, - frame->isocHeader.frameLatency, - frame->isocHeader.dataFormat, - frame->isocHeader.formatParam, - frame->isocHeader.frameWidth, - frame->isocHeader.frameHeight); - - if (usbvision->requestIntra) { - if (frame->isocHeader.formatParam & 0x80) { - foundHeader = 1; - usbvision->lastIsocFrameNum = -1; // do not check for lost frames this time + frame->isoc_header.magic_2, + frame->isoc_header.magic_1, + frame->isoc_header.header_length, + frame->isoc_header.frame_num, + frame->isoc_header.frame_phase, + frame->isoc_header.frame_latency, + frame->isoc_header.data_format, + frame->isoc_header.format_param, + frame->isoc_header.frame_width, + frame->isoc_header.frame_height); + + if (usbvision->request_intra) { + if (frame->isoc_header.format_param & 0x80) { + found_header = 1; + usbvision->last_isoc_frame_num = -1; // do not check for lost frames this time usbvision_unrequest_intra(usbvision); break; } } else { - foundHeader = 1; + found_header = 1; break; } } - if (foundHeader) { - frame->frmwidth = frame->isocHeader.frameWidth * usbvision->stretch_width; - frame->frmheight = frame->isocHeader.frameHeight * usbvision->stretch_height; + if (found_header) { + frame->frmwidth = frame->isoc_header.frame_width * usbvision->stretch_width; + frame->frmheight = frame->isoc_header.frame_height * usbvision->stretch_height; frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth)>> 3; } else { // no header found PDEBUG(DBG_HEADER, "skipping scratch data, no header"); scratch_reset(usbvision); - return ParseState_EndParse; + return parse_state_end_parse; } // found header - if (frame->isocHeader.dataFormat==ISOC_MODE_COMPRESS) { - //check isocHeader.frameNum for lost frames - if (usbvision->lastIsocFrameNum >= 0) { - if (((usbvision->lastIsocFrameNum + 1) % 32) != frame->isocHeader.frameNum) { + if (frame->isoc_header.data_format==ISOC_MODE_COMPRESS) { + //check isoc_header.frame_num for lost frames + if (usbvision->last_isoc_frame_num >= 0) { + if (((usbvision->last_isoc_frame_num + 1) % 32) != frame->isoc_header.frame_num) { // unexpected frame drop: need to request new intra frame - PDEBUG(DBG_HEADER, "Lost frame before %d on USB", frame->isocHeader.frameNum); + PDEBUG(DBG_HEADER, "Lost frame before %d on USB", frame->isoc_header.frame_num); usbvision_request_intra(usbvision); - return ParseState_NextFrame; + return parse_state_next_frame; } } - usbvision->lastIsocFrameNum = frame->isocHeader.frameNum; + usbvision->last_isoc_frame_num = frame->isoc_header.frame_num; } usbvision->header_count++; - frame->scanstate = ScanState_Lines; + frame->scanstate = scan_state_lines; frame->curline = 0; if (force_testpattern) { usbvision_testpattern(usbvision, 1, 1); - return ParseState_NextFrame; + return parse_state_next_frame; } - return ParseState_Continue; + return parse_state_continue; } -static enum ParseState usbvision_parse_lines_422(struct usb_usbvision *usbvision, +static enum parse_state usbvision_parse_lines_422(struct usb_usbvision *usbvision, long *pcopylen) { volatile struct usbvision_frame *frame; @@ -599,18 +599,18 @@ static enum ParseState usbvision_parse_lines_422(struct usb_usbvision *usbvision int clipmask_index, bytes_per_pixel; int stretch_bytes, clipmask_add; - frame = usbvision->curFrame; + frame = usbvision->cur_frame; f = frame->data + (frame->v4l2_linesize * frame->curline); /* Make sure there's enough data for the entire line */ - len = (frame->isocHeader.frameWidth * 2)+5; + len = (frame->isoc_header.frame_width * 2)+5; if (scratch_len(usbvision) < len) { PDEBUG(DBG_PARSE, "out of data in line %d, need %u.\n", frame->curline, len); - return ParseState_Out; + return parse_state_out; } if ((frame->curline + 1) >= frame->frmheight) { - return ParseState_NextFrame; + return parse_state_next_frame; } bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; @@ -699,99 +699,99 @@ static enum ParseState usbvision_parse_lines_422(struct usb_usbvision *usbvision *pcopylen += frame->v4l2_linesize * usbvision->stretch_height; if (frame->curline >= frame->frmheight) { - return ParseState_NextFrame; + return parse_state_next_frame; } else { - return ParseState_Continue; + return parse_state_continue; } } /* The decompression routine */ -static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *Compressed, - unsigned char *Decompressed, int *StartPos, - int *BlockTypeStartPos, int Len) +static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *compressed, + unsigned char *decompressed, int *start_pos, + int *block_typestart_pos, int len) { - int RestPixel, Idx, MaxPos, Pos, ExtraPos, BlockLen, BlockTypePos, BlockTypeLen; - unsigned char BlockByte, BlockCode, BlockType, BlockTypeByte, Integrator; - - Integrator = 0; - Pos = *StartPos; - BlockTypePos = *BlockTypeStartPos; - MaxPos = 396; //Pos + Len; - ExtraPos = Pos; - BlockLen = 0; - BlockByte = 0; - BlockCode = 0; - BlockType = 0; - BlockTypeByte = 0; - BlockTypeLen = 0; - RestPixel = Len; - - for (Idx = 0; Idx < Len; Idx++) { - - if (BlockLen == 0) { - if (BlockTypeLen==0) { - BlockTypeByte = Compressed[BlockTypePos]; - BlockTypePos++; - BlockTypeLen = 4; + int rest_pixel, idx, max_pos, pos, extra_pos, block_len, block_type_pos, block_type_len; + unsigned char block_byte, block_code, block_type, block_type_byte, integrator; + + integrator = 0; + pos = *start_pos; + block_type_pos = *block_typestart_pos; + max_pos = 396; //pos + len; + extra_pos = pos; + block_len = 0; + block_byte = 0; + block_code = 0; + block_type = 0; + block_type_byte = 0; + block_type_len = 0; + rest_pixel = len; + + for (idx = 0; idx < len; idx++) { + + if (block_len == 0) { + if (block_type_len==0) { + block_type_byte = compressed[block_type_pos]; + block_type_pos++; + block_type_len = 4; } - BlockType = (BlockTypeByte & 0xC0) >> 6; + block_type = (block_type_byte & 0xC0) >> 6; //statistic: - usbvision->ComprBlockTypes[BlockType]++; - - Pos = ExtraPos; - if (BlockType == 0) { - if(RestPixel >= 24) { - Idx += 23; - RestPixel -= 24; - Integrator = Decompressed[Idx]; + usbvision->compr_block_types[block_type]++; + + pos = extra_pos; + if (block_type == 0) { + if(rest_pixel >= 24) { + idx += 23; + rest_pixel -= 24; + integrator = decompressed[idx]; } else { - Idx += RestPixel - 1; - RestPixel = 0; + idx += rest_pixel - 1; + rest_pixel = 0; } } else { - BlockCode = Compressed[Pos]; - Pos++; - if (RestPixel >= 24) { - BlockLen = 24; + block_code = compressed[pos]; + pos++; + if (rest_pixel >= 24) { + block_len = 24; } else { - BlockLen = RestPixel; + block_len = rest_pixel; } - RestPixel -= BlockLen; - ExtraPos = Pos + (BlockLen / 4); + rest_pixel -= block_len; + extra_pos = pos + (block_len / 4); } - BlockTypeByte <<= 2; - BlockTypeLen -= 1; + block_type_byte <<= 2; + block_type_len -= 1; } - if (BlockLen > 0) { - if ((BlockLen%4) == 0) { - BlockByte = Compressed[Pos]; - Pos++; + if (block_len > 0) { + if ((block_len%4) == 0) { + block_byte = compressed[pos]; + pos++; } - if (BlockType == 1) { //inter Block - Integrator = Decompressed[Idx]; + if (block_type == 1) { //inter Block + integrator = decompressed[idx]; } - switch (BlockByte & 0xC0) { + switch (block_byte & 0xC0) { case 0x03<<6: - Integrator += Compressed[ExtraPos]; - ExtraPos++; + integrator += compressed[extra_pos]; + extra_pos++; break; case 0x02<<6: - Integrator += BlockCode; + integrator += block_code; break; case 0x00: - Integrator -= BlockCode; + integrator -= block_code; break; } - Decompressed[Idx] = Integrator; - BlockByte <<= 2; - BlockLen -= 1; + decompressed[idx] = integrator; + block_byte <<= 2; + block_len -= 1; } } - *StartPos = ExtraPos; - *BlockTypeStartPos = BlockTypePos; - return Idx; + *start_pos = extra_pos; + *block_typestart_pos = block_type_pos; + return idx; } @@ -803,7 +803,7 @@ static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *C * number of bytes (RGB) to the *pcopylen. * */ -static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision, +static enum parse_state usbvision_parse_compress(struct usb_usbvision *usbvision, long *pcopylen) { #define USBVISION_STRIP_MAGIC 0x5A @@ -812,16 +812,16 @@ static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision, struct usbvision_frame *frame; unsigned char *f,*u = NULL ,*v = NULL; - unsigned char StripData[USBVISION_STRIP_LEN_MAX]; - unsigned char StripHeader[USBVISION_STRIP_HEADER_LEN]; - int Idx, IdxEnd, StripLen, StripPtr, StartBlockPos, BlockPos, BlockTypePos; + unsigned char strip_data[USBVISION_STRIP_LEN_MAX]; + unsigned char strip_header[USBVISION_STRIP_HEADER_LEN]; + int idx, idx_end, strip_len, strip_ptr, Startblock_pos, block_pos, block_type_pos; int clipmask_index, bytes_per_pixel, rc; - int imageSize; + int image_size; unsigned char rv, gv, bv; static unsigned char *Y, *U, *V; - frame = usbvision->curFrame; - imageSize = frame->frmwidth * frame->frmheight; + frame = usbvision->cur_frame; + image_size = frame->frmwidth * frame->frmheight; if ( (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) || (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) ) { // this is a planar format //... v4l2_linesize not used here. @@ -833,14 +833,14 @@ static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision, // get base of u and b planes add halfoffset u = frame->data - + imageSize + + image_size + (frame->frmwidth >>1) * frame->curline ; - v = u + (imageSize >>1 ); + v = u + (image_size >>1 ); } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420){ - v = frame->data + imageSize + ((frame->curline* (frame->width))>>2) ; - u = v + (imageSize >>2) ; + v = frame->data + image_size + ((frame->curline* (frame->width))>>2) ; + u = v + (image_size >>2) ; } if (frame->curline == 0) { @@ -848,112 +848,112 @@ static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision, } if (scratch_len(usbvision) < USBVISION_STRIP_HEADER_LEN) { - return ParseState_Out; + return parse_state_out; } //get strip header without changing the scratch_read_ptr - scratch_set_extra_ptr(usbvision, &StripPtr, 0); - scratch_get_extra(usbvision, &StripHeader[0], &StripPtr, + scratch_set_extra_ptr(usbvision, &strip_ptr, 0); + scratch_get_extra(usbvision, &strip_header[0], &strip_ptr, USBVISION_STRIP_HEADER_LEN); - if (StripHeader[0] != USBVISION_STRIP_MAGIC) { + if (strip_header[0] != USBVISION_STRIP_MAGIC) { // wrong strip magic - usbvision->stripMagicErrors++; - return ParseState_NextFrame; + usbvision->strip_magic_errors++; + return parse_state_next_frame; } - if (frame->curline != (int)StripHeader[2]) { + if (frame->curline != (int)strip_header[2]) { //line number missmatch error - usbvision->stripLineNumberErrors++; + usbvision->strip_line_number_errors++; } - StripLen = 2 * (unsigned int)StripHeader[1]; - if (StripLen > USBVISION_STRIP_LEN_MAX) { + strip_len = 2 * (unsigned int)strip_header[1]; + if (strip_len > USBVISION_STRIP_LEN_MAX) { // strip overrun // I think this never happens usbvision_request_intra(usbvision); } - if (scratch_len(usbvision) < StripLen) { + if (scratch_len(usbvision) < strip_len) { //there is not enough data for the strip - return ParseState_Out; + return parse_state_out; } - if (usbvision->IntraFrameBuffer) { - Y = usbvision->IntraFrameBuffer + frame->frmwidth * frame->curline; - U = usbvision->IntraFrameBuffer + imageSize + (frame->frmwidth / 2) * (frame->curline / 2); - V = usbvision->IntraFrameBuffer + imageSize / 4 * 5 + (frame->frmwidth / 2) * (frame->curline / 2); + if (usbvision->intra_frame_buffer) { + Y = usbvision->intra_frame_buffer + frame->frmwidth * frame->curline; + U = usbvision->intra_frame_buffer + image_size + (frame->frmwidth / 2) * (frame->curline / 2); + V = usbvision->intra_frame_buffer + image_size / 4 * 5 + (frame->frmwidth / 2) * (frame->curline / 2); } else { - return ParseState_NextFrame; + return parse_state_next_frame; } bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; clipmask_index = frame->curline * MAX_FRAME_WIDTH; - scratch_get(usbvision, StripData, StripLen); + scratch_get(usbvision, strip_data, strip_len); - IdxEnd = frame->frmwidth; - BlockTypePos = USBVISION_STRIP_HEADER_LEN; - StartBlockPos = BlockTypePos + (IdxEnd - 1) / 96 + (IdxEnd / 2 - 1) / 96 + 2; - BlockPos = StartBlockPos; + idx_end = frame->frmwidth; + block_type_pos = USBVISION_STRIP_HEADER_LEN; + Startblock_pos = block_type_pos + (idx_end - 1) / 96 + (idx_end / 2 - 1) / 96 + 2; + block_pos = Startblock_pos; - usbvision->BlockPos = BlockPos; + usbvision->block_pos = block_pos; - if ((rc = usbvision_decompress(usbvision, StripData, Y, &BlockPos, &BlockTypePos, IdxEnd)) != IdxEnd) { - //return ParseState_Continue; + if ((rc = usbvision_decompress(usbvision, strip_data, Y, &block_pos, &block_type_pos, idx_end)) != idx_end) { + //return parse_state_continue; } - if (StripLen > usbvision->maxStripLen) { - usbvision->maxStripLen = StripLen; + if (strip_len > usbvision->max_strip_len) { + usbvision->max_strip_len = strip_len; } if (frame->curline%2) { - if ((rc = usbvision_decompress(usbvision, StripData, V, &BlockPos, &BlockTypePos, IdxEnd/2)) != IdxEnd/2) { - //return ParseState_Continue; + if ((rc = usbvision_decompress(usbvision, strip_data, V, &block_pos, &block_type_pos, idx_end/2)) != idx_end/2) { + //return parse_state_continue; } } else { - if ((rc = usbvision_decompress(usbvision, StripData, U, &BlockPos, &BlockTypePos, IdxEnd/2)) != IdxEnd/2) { - //return ParseState_Continue; + if ((rc = usbvision_decompress(usbvision, strip_data, U, &block_pos, &block_type_pos, idx_end/2)) != idx_end/2) { + //return parse_state_continue; } } - if (BlockPos > usbvision->comprBlockPos) { - usbvision->comprBlockPos = BlockPos; + if (block_pos > usbvision->comprblock_pos) { + usbvision->comprblock_pos = block_pos; } - if (BlockPos > StripLen) { - usbvision->stripLenErrors++; + if (block_pos > strip_len) { + usbvision->strip_len_errors++; } - for (Idx = 0; Idx < IdxEnd; Idx++) { + for (idx = 0; idx < idx_end; idx++) { if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f++ = Y[Idx]; - *f++ = Idx & 0x01 ? U[Idx/2] : V[Idx/2]; + *f++ = Y[idx]; + *f++ = idx & 0x01 ? U[idx/2] : V[idx/2]; } else if(frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) { - *f++ = Y[Idx]; - if ( Idx & 0x01) - *u++ = U[Idx>>1] ; + *f++ = Y[idx]; + if ( idx & 0x01) + *u++ = U[idx>>1] ; else - *v++ = V[Idx>>1]; + *v++ = V[idx>>1]; } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) { - *f++ = Y [Idx]; - if ( !(( Idx & 0x01 ) | ( frame->curline & 0x01 )) ){ + *f++ = Y [idx]; + if ( !(( idx & 0x01 ) | ( frame->curline & 0x01 )) ){ /* only need do this for 1 in 4 pixels */ /* intraframe buffer is YUV420 format */ - *u++ = U[Idx >>1]; - *v++ = V[Idx >>1]; + *u++ = U[idx >>1]; + *v++ = V[idx >>1]; } } else { - YUV_TO_RGB_BY_THE_BOOK(Y[Idx], U[Idx/2], V[Idx/2], rv, gv, bv); + YUV_TO_RGB_BY_THE_BOOK(Y[idx], U[idx/2], V[idx/2], rv, gv, bv); switch (frame->v4l2_format.format) { case V4L2_PIX_FMT_GREY: - *f++ = Y[Idx]; + *f++ = Y[idx]; break; case V4L2_PIX_FMT_RGB555: *f++ = (0x1F & rv) | @@ -991,10 +991,10 @@ static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision, frame->curline += 1; if (frame->curline >= frame->frmheight) { - return ParseState_NextFrame; + return parse_state_next_frame; } else { - return ParseState_Continue; + return parse_state_continue; } } @@ -1008,7 +1008,7 @@ static enum ParseState usbvision_parse_compress(struct usb_usbvision *usbvision, * number of bytes (RGB) to the *pcopylen. * */ -static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision, +static enum parse_state usbvision_parse_lines_420(struct usb_usbvision *usbvision, long *pcopylen) { struct usbvision_frame *frame; @@ -1028,7 +1028,7 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision int clipmask_even_index, clipmask_odd_index, bytes_per_pixel; int clipmask_add, stretch_bytes; - frame = usbvision->curFrame; + frame = usbvision->cur_frame; f_even = frame->data + (frame->v4l2_linesize * frame->curline); f_odd = f_even + frame->v4l2_linesize * usbvision->stretch_height; @@ -1040,15 +1040,15 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision clipmask_even_index = frame->curline * MAX_FRAME_WIDTH; clipmask_odd_index = clipmask_even_index + MAX_FRAME_WIDTH; clipmask_add = usbvision->stretch_width; - pixel_per_line = frame->isocHeader.frameWidth; + pixel_per_line = frame->isoc_header.frame_width; if (scratch_len(usbvision) < (int)pixel_per_line * 3) { //printk(KERN_DEBUG "out of data, need %d\n", len); - return ParseState_Out; + return parse_state_out; } if ((frame->curline + 1) >= frame->frmheight) { - return ParseState_NextFrame; + return parse_state_next_frame; } block_split = (pixel_per_line%y_block_size) ? 1 : 0; //are some blocks splitted into different lines? @@ -1272,9 +1272,9 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision *pcopylen += frame->v4l2_linesize * 2 * usbvision->stretch_height; if (frame->curline >= frame->frmheight) - return ParseState_NextFrame; + return parse_state_next_frame; else - return ParseState_Continue; + return parse_state_continue; } /* @@ -1288,53 +1288,53 @@ static enum ParseState usbvision_parse_lines_420(struct usb_usbvision *usbvision static void usbvision_parse_data(struct usb_usbvision *usbvision) { struct usbvision_frame *frame; - enum ParseState newstate; + enum parse_state newstate; long copylen = 0; unsigned long lock_flags; - frame = usbvision->curFrame; + frame = usbvision->cur_frame; PDEBUG(DBG_PARSE, "parsing len=%d\n", scratch_len(usbvision)); while (1) { - newstate = ParseState_Out; + newstate = parse_state_out; if (scratch_len(usbvision)) { - if (frame->scanstate == ScanState_Scanning) { + if (frame->scanstate == scan_state_scanning) { newstate = usbvision_find_header(usbvision); } - else if (frame->scanstate == ScanState_Lines) { - if (usbvision->isocMode == ISOC_MODE_YUV420) { + else if (frame->scanstate == scan_state_lines) { + if (usbvision->isoc_mode == ISOC_MODE_YUV420) { newstate = usbvision_parse_lines_420(usbvision, ©len); } - else if (usbvision->isocMode == ISOC_MODE_YUV422) { + else if (usbvision->isoc_mode == ISOC_MODE_YUV422) { newstate = usbvision_parse_lines_422(usbvision, ©len); } - else if (usbvision->isocMode == ISOC_MODE_COMPRESS) { + else if (usbvision->isoc_mode == ISOC_MODE_COMPRESS) { newstate = usbvision_parse_compress(usbvision, ©len); } } } - if (newstate == ParseState_Continue) { + if (newstate == parse_state_continue) { continue; } - else if ((newstate == ParseState_NextFrame) || (newstate == ParseState_Out)) { + else if ((newstate == parse_state_next_frame) || (newstate == parse_state_out)) { break; } else { - return; /* ParseState_EndParse */ + return; /* parse_state_end_parse */ } } - if (newstate == ParseState_NextFrame) { - frame->grabstate = FrameState_Done; + if (newstate == parse_state_next_frame) { + frame->grabstate = frame_state_done; do_gettimeofday(&(frame->timestamp)); frame->sequence = usbvision->frame_num; spin_lock_irqsave(&usbvision->queue_lock, lock_flags); list_move_tail(&(frame->frame), &usbvision->outqueue); - usbvision->curFrame = NULL; + usbvision->cur_frame = NULL; spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); usbvision->frame_num++; @@ -1346,7 +1346,7 @@ static void usbvision_parse_data(struct usb_usbvision *usbvision) } } else - frame->grabstate = FrameState_Grabbing; + frame->grabstate = frame_state_grabbing; /* Update the frame's uncompressed length. */ @@ -1372,32 +1372,32 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, /* Detect and ignore errored packets */ if (packet_stat) { // packet_stat != 0 ????????????? PDEBUG(DBG_ISOC, "data error: [%d] len=%d, status=%X", i, packet_len, packet_stat); - usbvision->isocErrCount++; + usbvision->isoc_err_count++; continue; } /* Detect and ignore empty packets */ if (packet_len < 0) { PDEBUG(DBG_ISOC, "error packet [%d]", i); - usbvision->isocSkipCount++; + usbvision->isoc_skip_count++; continue; } else if (packet_len == 0) { /* Frame end ????? */ PDEBUG(DBG_ISOC, "null packet [%d]", i); - usbvision->isocstate=IsocState_NoFrame; - usbvision->isocSkipCount++; + usbvision->isocstate=isoc_state_no_frame; + usbvision->isoc_skip_count++; continue; } - else if (packet_len > usbvision->isocPacketSize) { - PDEBUG(DBG_ISOC, "packet[%d] > isocPacketSize", i); - usbvision->isocSkipCount++; + else if (packet_len > usbvision->isoc_packet_size) { + PDEBUG(DBG_ISOC, "packet[%d] > isoc_packet_size", i); + usbvision->isoc_skip_count++; continue; } PDEBUG(DBG_ISOC, "packet ok [%d] len=%d", i, packet_len); - if (usbvision->isocstate==IsocState_NoFrame) { //new frame begins - usbvision->isocstate=IsocState_InFrame; + if (usbvision->isocstate==isoc_state_no_frame) { //new frame begins + usbvision->isocstate=isoc_state_in_frame; scratch_mark_header(usbvision); usbvision_measure_bandwidth(usbvision); PDEBUG(DBG_ISOC, "packet with header"); @@ -1422,8 +1422,8 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, /* Now we know that there is enough room in scratch buffer */ scratch_put(usbvision, packet_data, packet_len); totlen += packet_len; - usbvision->isocDataCount += packet_len; - usbvision->isocPacketCount++; + usbvision->isoc_data_count += packet_len; + usbvision->isoc_packet_count++; } #if ENABLE_HEXDUMP if (totlen > 0) { @@ -1438,13 +1438,13 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, return totlen; } -static void usbvision_isocIrq(struct urb *urb) +static void usbvision_isoc_irq(struct urb *urb) { - int errCode = 0; + int err_code = 0; int len; struct usb_usbvision *usbvision = urb->context; int i; - unsigned long startTime = jiffies; + unsigned long start_time = jiffies; struct usbvision_frame **f; /* We don't want to do anything if we are about to be removed! */ @@ -1456,14 +1456,14 @@ static void usbvision_isocIrq(struct urb *urb) return; } - f = &usbvision->curFrame; + f = &usbvision->cur_frame; /* Manage streaming interruption */ - if (usbvision->streaming == Stream_Interrupt) { - usbvision->streaming = Stream_Idle; + if (usbvision->streaming == stream_interrupt) { + usbvision->streaming = stream_idle; if ((*f)) { - (*f)->grabstate = FrameState_Ready; - (*f)->scanstate = ScanState_Scanning; + (*f)->grabstate = frame_state_ready; + (*f)->scanstate = scan_state_scanning; } PDEBUG(DBG_IRQ, "stream interrupted"); wake_up_interruptible(&usbvision->wait_stream); @@ -1472,10 +1472,10 @@ static void usbvision_isocIrq(struct urb *urb) /* Copy the data received into our scratch buffer */ len = usbvision_compress_isochronous(usbvision, urb); - usbvision->isocUrbCount++; + usbvision->isoc_urb_count++; usbvision->urb_length = len; - if (usbvision->streaming == Stream_On) { + if (usbvision->streaming == stream_on) { /* If we collected enough data let's parse! */ if ((scratch_len(usbvision) > USBVISION_HEADER_LENGTH) && @@ -1500,7 +1500,7 @@ static void usbvision_isocIrq(struct urb *urb) scratch_reset(usbvision); } - usbvision->timeInIrq += jiffies - startTime; + usbvision->time_in_irq += jiffies - start_time; for (i = 0; i < USBVISION_URB_FRAMES; i++) { urb->iso_frame_desc[i].status = 0; @@ -1509,12 +1509,12 @@ static void usbvision_isocIrq(struct urb *urb) urb->status = 0; urb->dev = usbvision->dev; - errCode = usb_submit_urb (urb, GFP_ATOMIC); + err_code = usb_submit_urb (urb, GFP_ATOMIC); - if(errCode) { + if(err_code) { dev_err(&usbvision->dev->dev, "%s: usb_submit_urb failed: error %d\n", - __func__, errCode); + __func__, err_code); } return; @@ -1533,21 +1533,21 @@ static void usbvision_isocIrq(struct urb *urb) int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg) { - int errCode = 0; + int err_code = 0; unsigned char buffer[1]; if (!USBVISION_IS_OPERATIONAL(usbvision)) return -1; - errCode = usb_control_msg(usbvision->dev, usb_rcvctrlpipe(usbvision->dev, 1), + err_code = usb_control_msg(usbvision->dev, usb_rcvctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, (__u16) reg, buffer, 1, HZ); - if (errCode < 0) { + if (err_code < 0) { dev_err(&usbvision->dev->dev, - "%s: failed: error %d\n", __func__, errCode); - return errCode; + "%s: failed: error %d\n", __func__, err_code); + return err_code; } return buffer[0]; } @@ -1563,32 +1563,32 @@ int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg) int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, unsigned char value) { - int errCode = 0; + int err_code = 0; if (!USBVISION_IS_OPERATIONAL(usbvision)) return 0; - errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), + err_code = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ); - if (errCode < 0) { + if (err_code < 0) { dev_err(&usbvision->dev->dev, - "%s: failed: error %d\n", __func__, errCode); + "%s: failed: error %d\n", __func__, err_code); } - return errCode; + return err_code; } -static void usbvision_ctrlUrb_complete(struct urb *urb) +static void usbvision_ctrl_urb_complete(struct urb *urb) { struct usb_usbvision *usbvision = (struct usb_usbvision *)urb->context; PDEBUG(DBG_IRQ, ""); - usbvision->ctrlUrbBusy = 0; - if (waitqueue_active(&usbvision->ctrlUrb_wq)) { - wake_up_interruptible(&usbvision->ctrlUrb_wq); + usbvision->ctrl_urb_busy = 0; + if (waitqueue_active(&usbvision->ctrl_urb_wq)) { + wake_up_interruptible(&usbvision->ctrl_urb_wq); } } @@ -1596,146 +1596,146 @@ static void usbvision_ctrlUrb_complete(struct urb *urb) static int usbvision_write_reg_irq(struct usb_usbvision *usbvision,int address, unsigned char *data, int len) { - int errCode = 0; + int err_code = 0; PDEBUG(DBG_IRQ, ""); if (len > 8) { return -EFAULT; } - if (usbvision->ctrlUrbBusy) { + if (usbvision->ctrl_urb_busy) { return -EBUSY; } - usbvision->ctrlUrbBusy = 1; + usbvision->ctrl_urb_busy = 1; - usbvision->ctrlUrbSetup.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; - usbvision->ctrlUrbSetup.bRequest = USBVISION_OP_CODE; - usbvision->ctrlUrbSetup.wValue = 0; - usbvision->ctrlUrbSetup.wIndex = cpu_to_le16(address); - usbvision->ctrlUrbSetup.wLength = cpu_to_le16(len); - usb_fill_control_urb (usbvision->ctrlUrb, usbvision->dev, + usbvision->ctrl_urb_setup.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; + usbvision->ctrl_urb_setup.bRequest = USBVISION_OP_CODE; + usbvision->ctrl_urb_setup.wValue = 0; + usbvision->ctrl_urb_setup.wIndex = cpu_to_le16(address); + usbvision->ctrl_urb_setup.wLength = cpu_to_le16(len); + usb_fill_control_urb (usbvision->ctrl_urb, usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), - (unsigned char *)&usbvision->ctrlUrbSetup, - (void *)usbvision->ctrlUrbBuffer, len, - usbvision_ctrlUrb_complete, + (unsigned char *)&usbvision->ctrl_urb_setup, + (void *)usbvision->ctrl_urb_buffer, len, + usbvision_ctrl_urb_complete, (void *)usbvision); - memcpy(usbvision->ctrlUrbBuffer, data, len); + memcpy(usbvision->ctrl_urb_buffer, data, len); - errCode = usb_submit_urb(usbvision->ctrlUrb, GFP_ATOMIC); - if (errCode < 0) { + err_code = usb_submit_urb(usbvision->ctrl_urb, GFP_ATOMIC); + if (err_code < 0) { // error in usb_submit_urb() - usbvision->ctrlUrbBusy = 0; + usbvision->ctrl_urb_busy = 0; } - PDEBUG(DBG_IRQ, "submit %d byte: error %d", len, errCode); - return errCode; + PDEBUG(DBG_IRQ, "submit %d byte: error %d", len, err_code); + return err_code; } static int usbvision_init_compression(struct usb_usbvision *usbvision) { - int errCode = 0; - - usbvision->lastIsocFrameNum = -1; - usbvision->isocDataCount = 0; - usbvision->isocPacketCount = 0; - usbvision->isocSkipCount = 0; - usbvision->comprLevel = 50; - usbvision->lastComprLevel = -1; - usbvision->isocUrbCount = 0; - usbvision->requestIntra = 1; - usbvision->isocMeasureBandwidthCount = 0; - - return errCode; + int err_code = 0; + + usbvision->last_isoc_frame_num = -1; + usbvision->isoc_data_count = 0; + usbvision->isoc_packet_count = 0; + usbvision->isoc_skip_count = 0; + usbvision->compr_level = 50; + usbvision->last_compr_level = -1; + usbvision->isoc_urb_count = 0; + usbvision->request_intra = 1; + usbvision->isoc_measure_bandwidth_count = 0; + + return err_code; } /* this function measures the used bandwidth since last call * return: 0 : no error - * sets usedBandwidth to 1-100 : 1-100% of full bandwidth resp. to isocPacketSize + * sets used_bandwidth to 1-100 : 1-100% of full bandwidth resp. to isoc_packet_size */ static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision) { - int errCode = 0; - - if (usbvision->isocMeasureBandwidthCount < 2) { // this gives an average bandwidth of 3 frames - usbvision->isocMeasureBandwidthCount++; - return errCode; - } - if ((usbvision->isocPacketSize > 0) && (usbvision->isocPacketCount > 0)) { - usbvision->usedBandwidth = usbvision->isocDataCount / - (usbvision->isocPacketCount + usbvision->isocSkipCount) * - 100 / usbvision->isocPacketSize; - } - usbvision->isocMeasureBandwidthCount = 0; - usbvision->isocDataCount = 0; - usbvision->isocPacketCount = 0; - usbvision->isocSkipCount = 0; - return errCode; + int err_code = 0; + + if (usbvision->isoc_measure_bandwidth_count < 2) { // this gives an average bandwidth of 3 frames + usbvision->isoc_measure_bandwidth_count++; + return err_code; + } + if ((usbvision->isoc_packet_size > 0) && (usbvision->isoc_packet_count > 0)) { + usbvision->used_bandwidth = usbvision->isoc_data_count / + (usbvision->isoc_packet_count + usbvision->isoc_skip_count) * + 100 / usbvision->isoc_packet_size; + } + usbvision->isoc_measure_bandwidth_count = 0; + usbvision->isoc_data_count = 0; + usbvision->isoc_packet_count = 0; + usbvision->isoc_skip_count = 0; + return err_code; } static int usbvision_adjust_compression (struct usb_usbvision *usbvision) { - int errCode = 0; + int err_code = 0; unsigned char buffer[6]; PDEBUG(DBG_IRQ, ""); - if ((adjustCompression) && (usbvision->usedBandwidth > 0)) { - usbvision->comprLevel += (usbvision->usedBandwidth - 90) / 2; - RESTRICT_TO_RANGE(usbvision->comprLevel, 0, 100); - if (usbvision->comprLevel != usbvision->lastComprLevel) { + if ((adjust_compression) && (usbvision->used_bandwidth > 0)) { + usbvision->compr_level += (usbvision->used_bandwidth - 90) / 2; + RESTRICT_TO_RANGE(usbvision->compr_level, 0, 100); + if (usbvision->compr_level != usbvision->last_compr_level) { int distorsion; - if (usbvision->bridgeType == BRIDGE_NT1004 || usbvision->bridgeType == BRIDGE_NT1005) { - buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100); // PCM Threshold 1 - buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100); // PCM Threshold 2 - distorsion = 7 + 248 * usbvision->comprLevel / 100; + if (usbvision->bridge_type == BRIDGE_NT1004 || usbvision->bridge_type == BRIDGE_NT1005) { + buffer[0] = (unsigned char)(4 + 16 * usbvision->compr_level / 100); // PCM Threshold 1 + buffer[1] = (unsigned char)(4 + 8 * usbvision->compr_level / 100); // PCM Threshold 2 + distorsion = 7 + 248 * usbvision->compr_level / 100; buffer[2] = (unsigned char)(distorsion & 0xFF); // Average distorsion Threshold (inter) buffer[3] = (unsigned char)(distorsion & 0xFF); // Average distorsion Threshold (intra) - distorsion = 1 + 42 * usbvision->comprLevel / 100; + distorsion = 1 + 42 * usbvision->compr_level / 100; buffer[4] = (unsigned char)(distorsion & 0xFF); // Maximum distorsion Threshold (inter) buffer[5] = (unsigned char)(distorsion & 0xFF); // Maximum distorsion Threshold (intra) } else { //BRIDGE_NT1003 - buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100); // PCM threshold 1 - buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100); // PCM threshold 2 - distorsion = 2 + 253 * usbvision->comprLevel / 100; + buffer[0] = (unsigned char)(4 + 16 * usbvision->compr_level / 100); // PCM threshold 1 + buffer[1] = (unsigned char)(4 + 8 * usbvision->compr_level / 100); // PCM threshold 2 + distorsion = 2 + 253 * usbvision->compr_level / 100; buffer[2] = (unsigned char)(distorsion & 0xFF); // distorsion threshold bit0-7 buffer[3] = 0; //(unsigned char)((distorsion >> 8) & 0x0F); // distorsion threshold bit 8-11 - distorsion = 0 + 43 * usbvision->comprLevel / 100; + distorsion = 0 + 43 * usbvision->compr_level / 100; buffer[4] = (unsigned char)(distorsion & 0xFF); // maximum distorsion bit0-7 buffer[5] = 0; //(unsigned char)((distorsion >> 8) & 0x01); // maximum distorsion bit 8 } - errCode = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6); - if (errCode == 0){ + err_code = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6); + if (err_code == 0){ PDEBUG(DBG_IRQ, "new compr params %#02x %#02x %#02x %#02x %#02x %#02x", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); - usbvision->lastComprLevel = usbvision->comprLevel; + usbvision->last_compr_level = usbvision->compr_level; } } } - return errCode; + return err_code; } static int usbvision_request_intra (struct usb_usbvision *usbvision) { - int errCode = 0; + int err_code = 0; unsigned char buffer[1]; PDEBUG(DBG_IRQ, ""); - usbvision->requestIntra = 1; + usbvision->request_intra = 1; buffer[0] = 1; usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); - return errCode; + return err_code; } static int usbvision_unrequest_intra (struct usb_usbvision *usbvision) { - int errCode = 0; + int err_code = 0; unsigned char buffer[1]; PDEBUG(DBG_IRQ, ""); - usbvision->requestIntra = 0; + usbvision->request_intra = 0; buffer[0] = 0; usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); - return errCode; + return err_code; } /******************************* @@ -1744,16 +1744,16 @@ static int usbvision_unrequest_intra (struct usb_usbvision *usbvision) int usbvision_power_off(struct usb_usbvision *usbvision) { - int errCode = 0; + int err_code = 0; PDEBUG(DBG_FUNC, ""); - errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); - if (errCode == 1) { + err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); + if (err_code == 1) { usbvision->power = 0; } - PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode!=1)?"ERROR":"power is off", errCode); - return errCode; + PDEBUG(DBG_FUNC, "%s: err_code %d", (err_code!=1)?"ERROR":"power is off", err_code); + return err_code; } /* @@ -1769,7 +1769,7 @@ static int usbvision_set_video_format(struct usb_usbvision *usbvision, int forma if (!USBVISION_IS_OPERATIONAL(usbvision)) return 0; - PDEBUG(DBG_FUNC, "isocMode %#02x", format); + PDEBUG(DBG_FUNC, "isoc_mode %#02x", format); if ((format != ISOC_MODE_YUV422) && (format != ISOC_MODE_YUV420) @@ -1790,7 +1790,7 @@ static int usbvision_set_video_format(struct usb_usbvision *usbvision, int forma printk(KERN_ERR "%s: ERROR=%d. USBVISION stopped - " "reconnect or reload driver.\n", proc, rc); } - usbvision->isocMode = format; + usbvision->isoc_mode = format; return rc; } @@ -1802,9 +1802,9 @@ static int usbvision_set_video_format(struct usb_usbvision *usbvision, int forma int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height) { - int errCode = 0; - int UsbWidth, UsbHeight; - unsigned int frameRate=0, frameDrop=0; + int err_code = 0; + int usb_width, usb_height; + unsigned int frame_rate=0, frame_drop=0; unsigned char value[4]; if (!USBVISION_IS_OPERATIONAL(usbvision)) { @@ -1812,86 +1812,86 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width, } if (width > MAX_USB_WIDTH) { - UsbWidth = width / 2; + usb_width = width / 2; usbvision->stretch_width = 2; } else { - UsbWidth = width; + usb_width = width; usbvision->stretch_width = 1; } if (height > MAX_USB_HEIGHT) { - UsbHeight = height / 2; + usb_height = height / 2; usbvision->stretch_height = 2; } else { - UsbHeight = height; + usb_height = height; usbvision->stretch_height = 1; } - RESTRICT_TO_RANGE(UsbWidth, MIN_FRAME_WIDTH, MAX_USB_WIDTH); - UsbWidth &= ~(MIN_FRAME_WIDTH-1); - RESTRICT_TO_RANGE(UsbHeight, MIN_FRAME_HEIGHT, MAX_USB_HEIGHT); - UsbHeight &= ~(1); + RESTRICT_TO_RANGE(usb_width, MIN_FRAME_WIDTH, MAX_USB_WIDTH); + usb_width &= ~(MIN_FRAME_WIDTH-1); + RESTRICT_TO_RANGE(usb_height, MIN_FRAME_HEIGHT, MAX_USB_HEIGHT); + usb_height &= ~(1); PDEBUG(DBG_FUNC, "usb %dx%d; screen %dx%d; stretch %dx%d", - UsbWidth, UsbHeight, width, height, + usb_width, usb_height, width, height, usbvision->stretch_width, usbvision->stretch_height); /* I'll not rewrite the same values */ - if ((UsbWidth != usbvision->curwidth) || (UsbHeight != usbvision->curheight)) { - value[0] = UsbWidth & 0xff; //LSB - value[1] = (UsbWidth >> 8) & 0x03; //MSB - value[2] = UsbHeight & 0xff; //LSB - value[3] = (UsbHeight >> 8) & 0x03; //MSB + if ((usb_width != usbvision->curwidth) || (usb_height != usbvision->curheight)) { + value[0] = usb_width & 0xff; //LSB + value[1] = (usb_width >> 8) & 0x03; //MSB + value[2] = usb_height & 0xff; //LSB + value[3] = (usb_height >> 8) & 0x03; //MSB - errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), + err_code = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ); - if (errCode < 0) { + if (err_code < 0) { dev_err(&usbvision->dev->dev, - "%s failed: error %d\n", __func__, errCode); - return errCode; + "%s failed: error %d\n", __func__, err_code); + return err_code; } - usbvision->curwidth = usbvision->stretch_width * UsbWidth; - usbvision->curheight = usbvision->stretch_height * UsbHeight; + usbvision->curwidth = usbvision->stretch_width * usb_width; + usbvision->curheight = usbvision->stretch_height * usb_height; } - if (usbvision->isocMode == ISOC_MODE_YUV422) { - frameRate = (usbvision->isocPacketSize * 1000) / (UsbWidth * UsbHeight * 2); + if (usbvision->isoc_mode == ISOC_MODE_YUV422) { + frame_rate = (usbvision->isoc_packet_size * 1000) / (usb_width * usb_height * 2); } - else if (usbvision->isocMode == ISOC_MODE_YUV420) { - frameRate = (usbvision->isocPacketSize * 1000) / ((UsbWidth * UsbHeight * 12) / 8); + else if (usbvision->isoc_mode == ISOC_MODE_YUV420) { + frame_rate = (usbvision->isoc_packet_size * 1000) / ((usb_width * usb_height * 12) / 8); } else { - frameRate = FRAMERATE_MAX; + frame_rate = FRAMERATE_MAX; } - if (usbvision->tvnormId & V4L2_STD_625_50) { - frameDrop = frameRate * 32 / 25 - 1; + if (usbvision->tvnorm_id & V4L2_STD_625_50) { + frame_drop = frame_rate * 32 / 25 - 1; } - else if (usbvision->tvnormId & V4L2_STD_525_60) { - frameDrop = frameRate * 32 / 30 - 1; + else if (usbvision->tvnorm_id & V4L2_STD_525_60) { + frame_drop = frame_rate * 32 / 30 - 1; } - RESTRICT_TO_RANGE(frameDrop, FRAMERATE_MIN, FRAMERATE_MAX); + RESTRICT_TO_RANGE(frame_drop, FRAMERATE_MIN, FRAMERATE_MAX); - PDEBUG(DBG_FUNC, "frameRate %d fps, frameDrop %d", frameRate, frameDrop); + PDEBUG(DBG_FUNC, "frame_rate %d fps, frame_drop %d", frame_rate, frame_drop); - frameDrop = FRAMERATE_MAX; // We can allow the maximum here, because dropping is controlled + frame_drop = FRAMERATE_MAX; // We can allow the maximum here, because dropping is controlled - /* frameDrop = 7; => framePhase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ... - => frameSkip = 4; - => frameRate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25; + /* frame_drop = 7; => frame_phase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ... + => frame_skip = 4; + => frame_rate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25; - frameDrop = 9; => framePhase = 1, 5, 8, 11, 14, 17, 21, 24, 27, 1, 4, 8, ... - => frameSkip = 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, ... - => frameRate = (9 + 1) * 25 / 32 = 250 / 32 = 7.8125; + frame_drop = 9; => frame_phase = 1, 5, 8, 11, 14, 17, 21, 24, 27, 1, 4, 8, ... + => frame_skip = 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, ... + => frame_rate = (9 + 1) * 25 / 32 = 250 / 32 = 7.8125; */ - errCode = usbvision_write_reg(usbvision, USBVISION_FRM_RATE, frameDrop); - return errCode; + err_code = usbvision_write_reg(usbvision, USBVISION_FRM_RATE, frame_drop); + return err_code; } @@ -1925,7 +1925,7 @@ int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames /* Allocate all buffers */ for (i = 0; i < usbvision->num_frames; i++) { usbvision->frame[i].index = i; - usbvision->frame[i].grabstate = FrameState_Unused; + usbvision->frame[i].grabstate = frame_state_unused; usbvision->frame[i].data = usbvision->fbuf + i * usbvision->max_frame_size; /* @@ -1969,7 +1969,7 @@ void usbvision_empty_framequeues(struct usb_usbvision *usbvision) INIT_LIST_HEAD(&(usbvision->outqueue)); for (i = 0; i < USBVISION_NUMFRAMES; i++) { - usbvision->frame[i].grabstate = FrameState_Unused; + usbvision->frame[i].grabstate = frame_state_unused; usbvision->frame[i].bytes_read = 0; } } @@ -1984,9 +1984,9 @@ int usbvision_stream_interrupt(struct usb_usbvision *usbvision) /* stop reading from the device */ - usbvision->streaming = Stream_Interrupt; + usbvision->streaming = stream_interrupt; ret = wait_event_timeout(usbvision->wait_stream, - (usbvision->streaming == Stream_Idle), + (usbvision->streaming == stream_idle), msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES)); return ret; } @@ -2030,7 +2030,7 @@ static int usbvision_set_compress_params(struct usb_usbvision *usbvision) return rc; } - if (usbvision->bridgeType == BRIDGE_NT1004) { + if (usbvision->bridge_type == BRIDGE_NT1004) { value[0] = 20; // PCM Threshold 1 value[1] = 12; // PCM Threshold 2 value[2] = 255; // Distorsion Threshold inter @@ -2085,9 +2085,9 @@ int usbvision_set_input(struct usb_usbvision *usbvision) return 0; /* Set input format expected from decoder*/ - if (usbvision_device_data[usbvision->DevModel].Vin_Reg1_override) { - value[0] = usbvision_device_data[usbvision->DevModel].Vin_Reg1; - } else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) { + if (usbvision_device_data[usbvision->dev_model].vin_reg1_override) { + value[0] = usbvision_device_data[usbvision->dev_model].vin_reg1; + } else if(usbvision_device_data[usbvision->dev_model].codec == CODEC_SAA7113) { /* SAA7113 uses 8 bit output */ value[0] = USBVISION_8_422_SYNC; } else { @@ -2105,7 +2105,7 @@ int usbvision_set_input(struct usb_usbvision *usbvision) } - if (usbvision->tvnormId & V4L2_STD_PAL) { + if (usbvision->tvnorm_id & V4L2_STD_PAL) { value[0] = 0xC0; value[1] = 0x02; //0x02C0 -> 704 Input video line length value[2] = 0x20; @@ -2114,7 +2114,7 @@ int usbvision_set_input(struct usb_usbvision *usbvision) value[5] = 0x00; //0x0060 -> 96 Input video h offset value[6] = 0x16; value[7] = 0x00; //0x0016 -> 22 Input video v offset - } else if (usbvision->tvnormId & V4L2_STD_SECAM) { + } else if (usbvision->tvnorm_id & V4L2_STD_SECAM) { value[0] = 0xC0; value[1] = 0x02; //0x02C0 -> 704 Input video line length value[2] = 0x20; @@ -2134,24 +2134,24 @@ int usbvision_set_input(struct usb_usbvision *usbvision) value[7] = 0x00; //0x0010 -> 16 Input video v offset } - if (usbvision_device_data[usbvision->DevModel].X_Offset >= 0) { - value[4]=usbvision_device_data[usbvision->DevModel].X_Offset & 0xff; - value[5]=(usbvision_device_data[usbvision->DevModel].X_Offset & 0x0300) >> 8; + if (usbvision_device_data[usbvision->dev_model].x_offset >= 0) { + value[4]=usbvision_device_data[usbvision->dev_model].x_offset & 0xff; + value[5]=(usbvision_device_data[usbvision->dev_model].x_offset & 0x0300) >> 8; } - if (adjust_X_Offset != -1) { - value[4] = adjust_X_Offset & 0xff; - value[5] = (adjust_X_Offset & 0x0300) >> 8; + if (adjust_x_offset != -1) { + value[4] = adjust_x_offset & 0xff; + value[5] = (adjust_x_offset & 0x0300) >> 8; } - if (usbvision_device_data[usbvision->DevModel].Y_Offset >= 0) { - value[6]=usbvision_device_data[usbvision->DevModel].Y_Offset & 0xff; - value[7]=(usbvision_device_data[usbvision->DevModel].Y_Offset & 0x0300) >> 8; + if (usbvision_device_data[usbvision->dev_model].y_offset >= 0) { + value[6]=usbvision_device_data[usbvision->dev_model].y_offset & 0xff; + value[7]=(usbvision_device_data[usbvision->dev_model].y_offset & 0x0300) >> 8; } - if (adjust_Y_Offset != -1) { - value[6] = adjust_Y_Offset & 0xff; - value[7] = (adjust_Y_Offset & 0x0300) >> 8; + if (adjust_y_offset != -1) { + value[6] = adjust_y_offset & 0xff; + value[7] = (adjust_y_offset & 0x0300) >> 8; } rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), @@ -2167,10 +2167,10 @@ int usbvision_set_input(struct usb_usbvision *usbvision) dvi_yuv_value = 0x00; /* U comes after V, Ya comes after U/V, Yb comes after Yb */ - if(usbvision_device_data[usbvision->DevModel].Dvi_yuv_override){ - dvi_yuv_value = usbvision_device_data[usbvision->DevModel].Dvi_yuv; + if(usbvision_device_data[usbvision->dev_model].dvi_yuv_override){ + dvi_yuv_value = usbvision_device_data[usbvision->dev_model].dvi_yuv; } - else if(usbvision_device_data[usbvision->DevModel].Codec == CODEC_SAA7113) { + else if(usbvision_device_data[usbvision->dev_model].codec == CODEC_SAA7113) { /* This changes as the fine sync control changes. Further investigation necessary */ dvi_yuv_value = 0x06; } @@ -2192,7 +2192,7 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) int rc; unsigned char value[8]; - if (usbvision->isocMode == ISOC_MODE_COMPRESS) { + if (usbvision->isoc_mode == ISOC_MODE_COMPRESS) { value[0] = 0x42; value[1] = 0x71; value[2] = 0xff; @@ -2261,7 +2261,7 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) int usbvision_power_on(struct usb_usbvision *usbvision) { - int errCode = 0; + int err_code = 0; PDEBUG(DBG_FUNC, ""); @@ -2271,13 +2271,13 @@ int usbvision_power_on(struct usb_usbvision *usbvision) usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN | USBVISION_PWR_VID); - errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG, + err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2); - if (errCode == 1) { + if (err_code == 1) { usbvision->power = 1; } - PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode<0)?"ERROR":"power is on", errCode); - return errCode; + PDEBUG(DBG_FUNC, "%s: err_code %d", (err_code<0)?"ERROR":"power is on", err_code); + return err_code; } @@ -2288,7 +2288,7 @@ int usbvision_power_on(struct usb_usbvision *usbvision) // to call usbvision_power_off from task queue static void call_usbvision_power_off(struct work_struct *work) { - struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, powerOffWork); + struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, power_off_work); PDEBUG(DBG_FUNC, ""); if (mutex_lock_interruptible(&usbvision->v4l2_lock)) @@ -2303,32 +2303,32 @@ static void call_usbvision_power_off(struct work_struct *work) mutex_unlock(&usbvision->v4l2_lock); } -static void usbvision_powerOffTimer(unsigned long data) +static void usbvision_power_off_timer(unsigned long data) { struct usb_usbvision *usbvision = (void *) data; PDEBUG(DBG_FUNC, ""); - del_timer(&usbvision->powerOffTimer); - INIT_WORK(&usbvision->powerOffWork, call_usbvision_power_off); - (void) schedule_work(&usbvision->powerOffWork); + del_timer(&usbvision->power_off_timer); + INIT_WORK(&usbvision->power_off_work, call_usbvision_power_off); + (void) schedule_work(&usbvision->power_off_work); } -void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision) +void usbvision_init_power_off_timer(struct usb_usbvision *usbvision) { - init_timer(&usbvision->powerOffTimer); - usbvision->powerOffTimer.data = (long) usbvision; - usbvision->powerOffTimer.function = usbvision_powerOffTimer; + init_timer(&usbvision->power_off_timer); + usbvision->power_off_timer.data = (long) usbvision; + usbvision->power_off_timer.function = usbvision_power_off_timer; } -void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision) +void usbvision_set_power_off_timer(struct usb_usbvision *usbvision) { - mod_timer(&usbvision->powerOffTimer, jiffies + USBVISION_POWEROFF_TIME); + mod_timer(&usbvision->power_off_timer, jiffies + USBVISION_POWEROFF_TIME); } -void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision) +void usbvision_reset_power_off_timer(struct usb_usbvision *usbvision) { - if (timer_pending(&usbvision->powerOffTimer)) { - del_timer(&usbvision->powerOffTimer); + if (timer_pending(&usbvision->power_off_timer)) { + del_timer(&usbvision->power_off_timer); } } @@ -2339,14 +2339,14 @@ void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision) */ int usbvision_begin_streaming(struct usb_usbvision *usbvision) { - int errCode = 0; + int err_code = 0; - if (usbvision->isocMode == ISOC_MODE_COMPRESS) { + if (usbvision->isoc_mode == ISOC_MODE_COMPRESS) { usbvision_init_compression(usbvision); } - errCode = usbvision_write_reg(usbvision, USBVISION_VIN_REG2, USBVISION_NOHVALID | - usbvision->Vin_Reg2_Preset); - return errCode; + err_code = usbvision_write_reg(usbvision, USBVISION_VIN_REG2, USBVISION_NOHVALID | + usbvision->vin_reg2_preset); + return err_code; } /* @@ -2373,7 +2373,7 @@ int usbvision_restart_isoc(struct usb_usbvision *usbvision) (ret = usbvision_write_reg(usbvision, USBVISION_VIN_REG2, USBVISION_KEEP_BLANK | USBVISION_NOHVALID | - usbvision->Vin_Reg2_Preset)) < 0) return ret; + usbvision->vin_reg2_preset)) < 0) return ret; /* TODO: schedule timeout */ while ((usbvision_read_reg(usbvision, USBVISION_STATUS_REG) & 0x01) != 1); @@ -2387,20 +2387,20 @@ int usbvision_audio_off(struct usb_usbvision *usbvision) printk(KERN_ERR "usbvision_audio_off: can't wirte reg\n"); return -1; } - usbvision->AudioMute = 0; - usbvision->AudioChannel = USBVISION_AUDIO_MUTE; + usbvision->audio_mute = 0; + usbvision->audio_channel = USBVISION_AUDIO_MUTE; return 0; } -int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel) +int usbvision_set_audio(struct usb_usbvision *usbvision, int audio_channel) { - if (!usbvision->AudioMute) { - if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, AudioChannel) < 0) { + if (!usbvision->audio_mute) { + if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, audio_channel) < 0) { printk(KERN_ERR "usbvision_set_audio: can't write iopin register for audio switching\n"); return -1; } } - usbvision->AudioChannel = AudioChannel; + usbvision->audio_channel = audio_channel; return 0; } @@ -2419,27 +2419,27 @@ int usbvision_setup(struct usb_usbvision *usbvision,int format) int usbvision_set_alternate(struct usb_usbvision *dev) { - int errCode, prev_alt = dev->ifaceAlt; + int err_code, prev_alt = dev->iface_alt; int i; - dev->ifaceAlt=0; + dev->iface_alt=0; for(i=0;i< dev->num_alt; i++) - if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->ifaceAlt]) - dev->ifaceAlt=i; - - if (dev->ifaceAlt != prev_alt) { - dev->isocPacketSize = dev->alt_max_pkt_size[dev->ifaceAlt]; - PDEBUG(DBG_FUNC,"setting alternate %d with wMaxPacketSize=%u", dev->ifaceAlt,dev->isocPacketSize); - errCode = usb_set_interface(dev->dev, dev->iface, dev->ifaceAlt); - if (errCode < 0) { + if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->iface_alt]) + dev->iface_alt=i; + + if (dev->iface_alt != prev_alt) { + dev->isoc_packet_size = dev->alt_max_pkt_size[dev->iface_alt]; + PDEBUG(DBG_FUNC,"setting alternate %d with max_packet_size=%u", dev->iface_alt,dev->isoc_packet_size); + err_code = usb_set_interface(dev->dev, dev->iface, dev->iface_alt); + if (err_code < 0) { dev_err(&dev->dev->dev, "cannot change alternate number to %d (error=%i)\n", - dev->ifaceAlt, errCode); - return errCode; + dev->iface_alt, err_code); + return err_code; } } - PDEBUG(DBG_ISOC, "ISO Packet Length:%d", dev->isocPacketSize); + PDEBUG(DBG_ISOC, "ISO Packet Length:%d", dev->isoc_packet_size); return 0; } @@ -2451,27 +2451,27 @@ int usbvision_set_alternate(struct usb_usbvision *dev) int usbvision_init_isoc(struct usb_usbvision *usbvision) { struct usb_device *dev = usbvision->dev; - int bufIdx, errCode, regValue; + int buf_idx, err_code, reg_value; int sb_size; if (!USBVISION_IS_OPERATIONAL(usbvision)) return -EFAULT; - usbvision->curFrame = NULL; + usbvision->cur_frame = NULL; scratch_reset(usbvision); /* Alternate interface 1 is is the biggest frame size */ - errCode = usbvision_set_alternate(usbvision); - if (errCode < 0) { - usbvision->last_error = errCode; + err_code = usbvision_set_alternate(usbvision); + if (err_code < 0) { + usbvision->last_error = err_code; return -EBUSY; } - sb_size = USBVISION_URB_FRAMES * usbvision->isocPacketSize; + sb_size = USBVISION_URB_FRAMES * usbvision->isoc_packet_size; - regValue = (16 - usbvision_read_reg(usbvision, + reg_value = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; - usbvision->usb_bandwidth = regValue >> 1; + usbvision->usb_bandwidth = reg_value >> 1; PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); @@ -2479,7 +2479,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) /* We double buffer the Iso lists */ - for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { + for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) { int j, k; struct urb *urb; @@ -2489,8 +2489,8 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) "%s: usb_alloc_urb() failed\n", __func__); return -ENOMEM; } - usbvision->sbuf[bufIdx].urb = urb; - usbvision->sbuf[bufIdx].data = + usbvision->sbuf[buf_idx].urb = urb; + usbvision->sbuf[buf_idx].data = usb_alloc_coherent(usbvision->dev, sb_size, GFP_KERNEL, @@ -2500,31 +2500,31 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp); urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; urb->interval = 1; - urb->transfer_buffer = usbvision->sbuf[bufIdx].data; - urb->complete = usbvision_isocIrq; + urb->transfer_buffer = usbvision->sbuf[buf_idx].data; + urb->complete = usbvision_isoc_irq; urb->number_of_packets = USBVISION_URB_FRAMES; urb->transfer_buffer_length = - usbvision->isocPacketSize * USBVISION_URB_FRAMES; + usbvision->isoc_packet_size * USBVISION_URB_FRAMES; for (j = k = 0; j < USBVISION_URB_FRAMES; j++, - k += usbvision->isocPacketSize) { + k += usbvision->isoc_packet_size) { urb->iso_frame_desc[j].offset = k; urb->iso_frame_desc[j].length = - usbvision->isocPacketSize; + usbvision->isoc_packet_size; } } /* Submit all URBs */ - for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { - errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb, + for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) { + err_code = usb_submit_urb(usbvision->sbuf[buf_idx].urb, GFP_KERNEL); - if (errCode) { + if (err_code) { dev_err(&usbvision->dev->dev, "%s: usb_submit_urb(%d) failed: error %d\n", - __func__, bufIdx, errCode); + __func__, buf_idx, err_code); } } - usbvision->streaming = Stream_Idle; + usbvision->streaming = stream_idle; PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __func__, usbvision->video_endp); @@ -2540,47 +2540,47 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) */ void usbvision_stop_isoc(struct usb_usbvision *usbvision) { - int bufIdx, errCode, regValue; - int sb_size = USBVISION_URB_FRAMES * usbvision->isocPacketSize; + int buf_idx, err_code, reg_value; + int sb_size = USBVISION_URB_FRAMES * usbvision->isoc_packet_size; - if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL)) + if ((usbvision->streaming == stream_off) || (usbvision->dev == NULL)) return; /* Unschedule all of the iso td's */ - for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { - usb_kill_urb(usbvision->sbuf[bufIdx].urb); - if (usbvision->sbuf[bufIdx].data){ + for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) { + usb_kill_urb(usbvision->sbuf[buf_idx].urb); + if (usbvision->sbuf[buf_idx].data){ usb_free_coherent(usbvision->dev, sb_size, - usbvision->sbuf[bufIdx].data, - usbvision->sbuf[bufIdx].urb->transfer_dma); + usbvision->sbuf[buf_idx].data, + usbvision->sbuf[buf_idx].urb->transfer_dma); } - usb_free_urb(usbvision->sbuf[bufIdx].urb); - usbvision->sbuf[bufIdx].urb = NULL; + usb_free_urb(usbvision->sbuf[buf_idx].urb); + usbvision->sbuf[buf_idx].urb = NULL; } - PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __func__); - usbvision->streaming = Stream_Off; + PDEBUG(DBG_ISOC, "%s: streaming=stream_off\n", __func__); + usbvision->streaming = stream_off; if (!usbvision->remove_pending) { /* Set packet size to 0 */ - usbvision->ifaceAlt=0; - errCode = usb_set_interface(usbvision->dev, usbvision->iface, - usbvision->ifaceAlt); - if (errCode < 0) { + usbvision->iface_alt=0; + err_code = usb_set_interface(usbvision->dev, usbvision->iface, + usbvision->iface_alt); + if (err_code < 0) { dev_err(&usbvision->dev->dev, "%s: usb_set_interface() failed: error %d\n", - __func__, errCode); - usbvision->last_error = errCode; + __func__, err_code); + usbvision->last_error = err_code; } - regValue = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; - usbvision->isocPacketSize = - (regValue == 0) ? 0 : (regValue * 64) - 1; + reg_value = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; + usbvision->isoc_packet_size = + (reg_value == 0) ? 0 : (reg_value * 64) - 1; PDEBUG(DBG_ISOC, "ISO Packet Length:%d", - usbvision->isocPacketSize); + usbvision->isoc_packet_size); - usbvision->usb_bandwidth = regValue >> 1; + usbvision->usb_bandwidth = reg_value >> 1; PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); } @@ -2604,12 +2604,12 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) // Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video // Four video input devices -> channel: 0 = Chan White, 1 = Chan Green, 2 = Chan Yellow, 3 = Chan Red - switch (usbvision_device_data[usbvision->DevModel].Codec) { + switch (usbvision_device_data[usbvision->dev_model].codec) { case CODEC_SAA7113: mode[1] = SAA7115_COMPOSITE2; - if (SwitchSVideoInput) { + if (switch_svideo_input) { /* To handle problems with S-Video Input for - * some devices. Use SwitchSVideoInput + * some devices. Use switch_svideo_input * parameter when loading the module.*/ mode[2] = SAA7115_COMPOSITE1; } diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index 81dd53b..7b2cd00 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c @@ -244,7 +244,7 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision) PDEBUG(DBG_I2C, "i2c bus for %s registered", usbvision->i2c_adap.name); /* Request the load of the i2c modules we need */ - switch (usbvision_device_data[usbvision->DevModel].Codec) { + switch (usbvision_device_data[usbvision->dev_model].codec) { case CODEC_SAA7113: case CODEC_SAA7111: /* Without this delay the detection of the saa711x is @@ -255,7 +255,7 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision) "saa7115_auto", 0, saa711x_addrs); break; } - if (usbvision_device_data[usbvision->DevModel].Tuner == 1) { + if (usbvision_device_data[usbvision->dev_model].tuner == 1) { struct v4l2_subdev *sd; enum v4l2_i2c_tuner_type type; struct tuner_setup tun_setup; @@ -426,18 +426,18 @@ static int usbvision_i2c_write_max4(struct usb_usbvision *usbvision, static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf, short len) { - char *bufPtr = buf; + char *buf_ptr = buf; int retval; int wrcount = 0; int count; - int maxLen = 4; + int max_len = 4; while (len > 0) { - count = (len > maxLen) ? maxLen : len; - retval = usbvision_i2c_write_max4(usbvision, addr, bufPtr, count); + count = (len > max_len) ? max_len : len; + retval = usbvision_i2c_write_max4(usbvision, addr, buf_ptr, count); if (retval > 0) { len -= count; - bufPtr += count; + buf_ptr += count; wrcount += count; } else return (retval < 0) ? retval : -EFAULT; diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index a5709a5..4882ea0 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -127,11 +127,11 @@ static void usbvision_release(struct usb_usbvision *usbvision); /* Default initialization of device driver parameters */ /* Set the default format for ISOC endpoint */ -static int isocMode = ISOC_MODE_COMPRESS; +static int isoc_mode = ISOC_MODE_COMPRESS; /* Set the default Debug Mode of the device driver */ static int video_debug; /* Set the default device to power on at startup */ -static int PowerOnAtOpen = 1; +static int power_on_at_open = 1; /* Sequential Number of Video Device */ static int video_nr = -1; /* Sequential Number of Radio Device */ @@ -140,15 +140,15 @@ static int radio_nr = -1; /* Grab parameters for the device driver */ /* Showing parameters under SYSFS */ -module_param(isocMode, int, 0444); +module_param(isoc_mode, int, 0444); module_param(video_debug, int, 0444); -module_param(PowerOnAtOpen, int, 0444); +module_param(power_on_at_open, int, 0444); module_param(video_nr, int, 0444); module_param(radio_nr, int, 0444); -MODULE_PARM_DESC(isocMode, " Set the default format for ISOC endpoint. Default: 0x60 (Compression On)"); +MODULE_PARM_DESC(isoc_mode, " Set the default format for ISOC endpoint. Default: 0x60 (Compression On)"); MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver. Default: 0 (Off)"); -MODULE_PARM_DESC(PowerOnAtOpen, " Set the default device to power on when device is opened. Default: 1 (On)"); +MODULE_PARM_DESC(power_on_at_open, " Set the default device to power on when device is opened. Default: 1 (On)"); MODULE_PARM_DESC(video_nr, "Set video device number (/dev/videoX). Default: -1 (autodetect)"); MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX). Default: -1 (autodetect)"); @@ -192,7 +192,7 @@ static ssize_t show_model(struct device *cd, container_of(cd, struct video_device, dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%s\n", - usbvision_device_data[usbvision->DevModel].ModelString); + usbvision_device_data[usbvision->dev_model].model_string); } static DEVICE_ATTR(model, S_IRUGO, show_model, NULL); @@ -263,7 +263,7 @@ static ssize_t show_streaming(struct device *cd, container_of(cd, struct video_device, dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%s\n", - YES_NO(usbvision->streaming==Stream_On?1:0)); + YES_NO(usbvision->streaming==stream_on?1:0)); } static DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL); @@ -274,7 +274,7 @@ static ssize_t show_compression(struct device *cd, container_of(cd, struct video_device, dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%s\n", - YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS)); + YES_NO(usbvision->isoc_mode==ISOC_MODE_COMPRESS)); } static DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL); @@ -284,7 +284,7 @@ static ssize_t show_device_bridge(struct device *cd, struct video_device *vdev = container_of(cd, struct video_device, dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); - return sprintf(buf, "%d\n", usbvision->bridgeType); + return sprintf(buf, "%d\n", usbvision->bridge_type); } static DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL); @@ -352,23 +352,23 @@ static void usbvision_remove_sysfs(struct video_device *vdev) static int usbvision_v4l2_open(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); - int errCode = 0; + int err_code = 0; PDEBUG(DBG_IO, "open"); - usbvision_reset_powerOffTimer(usbvision); + usbvision_reset_power_off_timer(usbvision); if (usbvision->user) - errCode = -EBUSY; + err_code = -EBUSY; else { /* Allocate memory for the scratch ring buffer */ - errCode = usbvision_scratch_alloc(usbvision); - if (isocMode==ISOC_MODE_COMPRESS) { + err_code = usbvision_scratch_alloc(usbvision); + if (isoc_mode==ISOC_MODE_COMPRESS) { /* Allocate intermediate decompression buffers only if needed */ - errCode = usbvision_decompress_alloc(usbvision); + err_code = usbvision_decompress_alloc(usbvision); } - if (errCode) { + if (err_code) { /* Deallocate all buffers if trouble */ usbvision_scratch_free(usbvision); usbvision_decompress_free(usbvision); @@ -376,7 +376,7 @@ static int usbvision_v4l2_open(struct file *file) } /* If so far no errors then we shall start the camera */ - if (!errCode) { + if (!err_code) { if (usbvision->power == 0) { usbvision_power_on(usbvision); usbvision_i2c_register(usbvision); @@ -385,21 +385,21 @@ static int usbvision_v4l2_open(struct file *file) /* Send init sequence only once, it's large! */ if (!usbvision->initialized) { int setup_ok = 0; - setup_ok = usbvision_setup(usbvision,isocMode); + setup_ok = usbvision_setup(usbvision,isoc_mode); if (setup_ok) usbvision->initialized = 1; else - errCode = -EBUSY; + err_code = -EBUSY; } - if (!errCode) { + if (!err_code) { usbvision_begin_streaming(usbvision); - errCode = usbvision_init_isoc(usbvision); + err_code = usbvision_init_isoc(usbvision); /* device must be initialized before isoc transfer */ usbvision_muxsel(usbvision,0); usbvision->user++; } else { - if (PowerOnAtOpen) { + if (power_on_at_open) { usbvision_i2c_unregister(usbvision); usbvision_power_off(usbvision); usbvision->initialized = 0; @@ -411,7 +411,7 @@ static int usbvision_v4l2_open(struct file *file) usbvision_empty_framequeues(usbvision); PDEBUG(DBG_IO, "success"); - return errCode; + return err_code; } /* @@ -439,10 +439,10 @@ static int usbvision_v4l2_close(struct file *file) usbvision->user--; - if (PowerOnAtOpen) { + if (power_on_at_open) { /* power off in a little while to avoid off/on every close/open short sequences */ - usbvision_set_powerOffTimer(usbvision); + usbvision_set_power_off_timer(usbvision); usbvision->initialized = 0; } @@ -467,19 +467,19 @@ static int vidioc_g_register (struct file *file, void *priv, struct v4l2_dbg_register *reg) { struct usb_usbvision *usbvision = video_drvdata(file); - int errCode; + int err_code; if (!v4l2_chip_match_host(®->match)) return -EINVAL; /* NT100x has a 8-bit register space */ - errCode = usbvision_read_reg(usbvision, reg->reg&0xff); - if (errCode < 0) { + err_code = usbvision_read_reg(usbvision, reg->reg&0xff); + if (err_code < 0) { dev_err(&usbvision->vdev->dev, "%s: VIDIOC_DBG_G_REGISTER failed: error %d\n", - __func__, errCode); - return errCode; + __func__, err_code); + return err_code; } - reg->val = errCode; + reg->val = err_code; reg->size = 1; return 0; } @@ -488,17 +488,17 @@ static int vidioc_s_register (struct file *file, void *priv, struct v4l2_dbg_register *reg) { struct usb_usbvision *usbvision = video_drvdata(file); - int errCode; + int err_code; if (!v4l2_chip_match_host(®->match)) return -EINVAL; /* NT100x has a 8-bit register space */ - errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); - if (errCode < 0) { + err_code = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); + if (err_code < 0) { dev_err(&usbvision->vdev->dev, "%s: VIDIOC_DBG_S_REGISTER failed: error %d\n", - __func__, errCode); - return errCode; + __func__, err_code); + return err_code; } return 0; } @@ -511,7 +511,7 @@ static int vidioc_querycap (struct file *file, void *priv, strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); strlcpy(vc->card, - usbvision_device_data[usbvision->DevModel].ModelString, + usbvision_device_data[usbvision->dev_model].model_string, sizeof(vc->card)); usb_make_path(usbvision->dev, vc->bus_info, sizeof(vc->bus_info)); vc->version = USBVISION_DRIVER_VERSION; @@ -540,7 +540,7 @@ static int vidioc_enum_input (struct file *file, void *priv, specific for each usbvision card model */ switch(chan) { case 0: - if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { + if (usbvision_device_data[usbvision->dev_model].video_channels == 4) { strcpy(vi->name, "White Video Input"); } else { strcpy(vi->name, "Television"); @@ -552,7 +552,7 @@ static int vidioc_enum_input (struct file *file, void *priv, break; case 1: vi->type = V4L2_INPUT_TYPE_CAMERA; - if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { + if (usbvision_device_data[usbvision->dev_model].video_channels == 4) { strcpy(vi->name, "Green Video Input"); } else { strcpy(vi->name, "Composite Video Input"); @@ -561,7 +561,7 @@ static int vidioc_enum_input (struct file *file, void *priv, break; case 2: vi->type = V4L2_INPUT_TYPE_CAMERA; - if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { + if (usbvision_device_data[usbvision->dev_model].video_channels == 4) { strcpy(vi->name, "Yellow Video Input"); } else { strcpy(vi->name, "S-Video Input"); @@ -604,9 +604,9 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) { struct usb_usbvision *usbvision = video_drvdata(file); - usbvision->tvnormId=*id; + usbvision->tvnorm_id=*id; - call_all(usbvision, core, s_std, usbvision->tvnormId); + call_all(usbvision, core, s_std, usbvision->tvnorm_id); /* propagate the change to the decoder */ usbvision_muxsel(usbvision, usbvision->ctl_input); @@ -744,7 +744,7 @@ static int vidioc_reqbufs (struct file *file, if (vr->memory != V4L2_MEMORY_MMAP) return -EINVAL; - if(usbvision->streaming == Stream_On) { + if(usbvision->streaming == stream_on) { if ((ret = usbvision_stream_interrupt(usbvision))) return ret; } @@ -753,7 +753,7 @@ static int vidioc_reqbufs (struct file *file, usbvision_empty_framequeues(usbvision); vr->count = usbvision_frames_alloc(usbvision,vr->count); - usbvision->curFrame = NULL; + usbvision->cur_frame = NULL; return 0; } @@ -772,11 +772,11 @@ static int vidioc_querybuf (struct file *file, /* Updating the corresponding frame state */ vb->flags = 0; frame = &usbvision->frame[vb->index]; - if(frame->grabstate >= FrameState_Ready) + if(frame->grabstate >= frame_state_ready) vb->flags |= V4L2_BUF_FLAG_QUEUED; - if(frame->grabstate >= FrameState_Done) + if(frame->grabstate >= frame_state_done) vb->flags |= V4L2_BUF_FLAG_DONE; - if(frame->grabstate == FrameState_Unused) + if(frame->grabstate == frame_state_unused) vb->flags |= V4L2_BUF_FLAG_MAPPED; vb->memory = V4L2_MEMORY_MMAP; @@ -805,13 +805,13 @@ static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb) frame = &usbvision->frame[vb->index]; - if (frame->grabstate != FrameState_Unused) { + if (frame->grabstate != frame_state_unused) { return -EAGAIN; } /* Mark it as ready and enqueue frame */ - frame->grabstate = FrameState_Ready; - frame->scanstate = ScanState_Scanning; + frame->grabstate = frame_state_ready; + frame->scanstate = scan_state_scanning; frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ vb->flags &= ~V4L2_BUF_FLAG_DONE; @@ -834,7 +834,7 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) unsigned long lock_flags; if (list_empty(&(usbvision->outqueue))) { - if (usbvision->streaming == Stream_Idle) + if (usbvision->streaming == stream_idle) return -EINVAL; ret = wait_event_interruptible (usbvision->wait_frame, @@ -849,7 +849,7 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) list_del(usbvision->outqueue.next); spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); - f->grabstate = FrameState_Unused; + f->grabstate = frame_state_unused; vb->memory = V4L2_MEMORY_MMAP; vb->flags = V4L2_BUF_FLAG_MAPPED | @@ -868,7 +868,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { struct usb_usbvision *usbvision = video_drvdata(file); - usbvision->streaming = Stream_On; + usbvision->streaming = stream_on; call_all(usbvision, video, s_stream, 1); return 0; @@ -882,7 +882,7 @@ static int vidioc_streamoff(struct file *file, if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - if(usbvision->streaming == Stream_On) { + if(usbvision->streaming == stream_on) { usbvision_stream_interrupt(usbvision); /* Stop all video streamings */ call_all(usbvision, video, s_stream, 0); @@ -923,18 +923,18 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, struct v4l2_format *vf) { struct usb_usbvision *usbvision = video_drvdata(file); - int formatIdx; + int format_idx; /* Find requested format in available ones */ - for(formatIdx=0;formatIdxfmt.pix.pixelformat == - usbvision_v4l2_format[formatIdx].format) { - usbvision->palette = usbvision_v4l2_format[formatIdx]; + usbvision_v4l2_format[format_idx].format) { + usbvision->palette = usbvision_v4l2_format[format_idx]; break; } } /* robustness */ - if(formatIdx == USBVISION_SUPPORTED_PALETTES) { + if(format_idx == USBVISION_SUPPORTED_PALETTES) { return -EINVAL; } RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH); @@ -958,14 +958,14 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, } /* stop io in case it is already in progress */ - if(usbvision->streaming == Stream_On) { + if(usbvision->streaming == stream_on) { if ((ret = usbvision_stream_interrupt(usbvision))) return ret; } usbvision_frames_free(usbvision); usbvision_empty_framequeues(usbvision); - usbvision->curFrame = NULL; + usbvision->cur_frame = NULL; /* by now we are committed to the new data... */ usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height); @@ -1000,9 +1000,9 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, usbvision_frames_alloc(usbvision,USBVISION_NUMFRAMES); } - if(usbvision->streaming != Stream_On) { + if(usbvision->streaming != stream_on) { /* no stream is running, make it running ! */ - usbvision->streaming = Stream_On; + usbvision->streaming = stream_on; call_all(usbvision, video, s_stream, 1); } @@ -1010,10 +1010,10 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, (like a user of VIDIOC_QBUF would do) */ for(i=0;inum_frames;i++) { frame = &usbvision->frame[i]; - if(frame->grabstate == FrameState_Unused) { + if(frame->grabstate == frame_state_unused) { /* Mark it as ready and enqueue frame */ - frame->grabstate = FrameState_Ready; - frame->scanstate = ScanState_Scanning; + frame->grabstate = frame_state_ready; + frame->scanstate = scan_state_scanning; /* Accumulated in usbvision_parse_data() */ frame->scanlength = 0; @@ -1046,7 +1046,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); /* An error returns an empty frame */ - if (frame->grabstate == FrameState_Error) { + if (frame->grabstate == frame_state_error) { frame->bytes_read = 0; return 0; } @@ -1073,7 +1073,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, frame->bytes_read = 0; /* Mark it as available to be used again. */ - frame->grabstate = FrameState_Unused; + frame->grabstate = frame_state_unused; /* } */ return count; @@ -1136,7 +1136,7 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) static int usbvision_radio_open(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); - int errCode = 0; + int err_code = 0; PDEBUG(DBG_IO, "%s:", __func__); @@ -1144,11 +1144,11 @@ static int usbvision_radio_open(struct file *file) dev_err(&usbvision->rdev->dev, "%s: Someone tried to open an already opened USBVision Radio!\n", __func__); - errCode = -EBUSY; + err_code = -EBUSY; } else { - if(PowerOnAtOpen) { - usbvision_reset_powerOffTimer(usbvision); + if(power_on_at_open) { + usbvision_reset_power_off_timer(usbvision); if (usbvision->power == 0) { usbvision_power_on(usbvision); usbvision_i2c_register(usbvision); @@ -1156,10 +1156,10 @@ static int usbvision_radio_open(struct file *file) } /* Alternate interface 1 is is the biggest frame size */ - errCode = usbvision_set_alternate(usbvision); - if (errCode < 0) { - usbvision->last_error = errCode; - errCode = -EBUSY; + err_code = usbvision_set_alternate(usbvision); + if (err_code < 0) { + usbvision->last_error = err_code; + err_code = -EBUSY; goto out; } @@ -1170,36 +1170,36 @@ static int usbvision_radio_open(struct file *file) usbvision->user++; } - if (errCode) { - if (PowerOnAtOpen) { + if (err_code) { + if (power_on_at_open) { usbvision_i2c_unregister(usbvision); usbvision_power_off(usbvision); usbvision->initialized = 0; } } out: - return errCode; + return err_code; } static int usbvision_radio_close(struct file *file) { struct usb_usbvision *usbvision = video_drvdata(file); - int errCode = 0; + int err_code = 0; PDEBUG(DBG_IO, ""); /* Set packet size to 0 */ - usbvision->ifaceAlt=0; - errCode = usb_set_interface(usbvision->dev, usbvision->iface, - usbvision->ifaceAlt); + usbvision->iface_alt=0; + err_code = usb_set_interface(usbvision->dev, usbvision->iface, + usbvision->iface_alt); usbvision_audio_off(usbvision); usbvision->radio=0; usbvision->user--; - if (PowerOnAtOpen) { - usbvision_set_powerOffTimer(usbvision); + if (power_on_at_open) { + usbvision_set_power_off_timer(usbvision); usbvision->initialized = 0; } @@ -1209,7 +1209,7 @@ static int usbvision_radio_close(struct file *file) } PDEBUG(DBG_IO, "success"); - return errCode; + return err_code; } // @@ -1375,7 +1375,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) usbvision->nr, video_device_node_name(usbvision->vdev)); // Radio Device: - if (usbvision_device_data[usbvision->DevModel].Radio) { + if (usbvision_device_data[usbvision->dev_model].radio) { // usbvision has radio usbvision->rdev = usbvision_vdev_init(usbvision, &usbvision_radio_template, @@ -1427,12 +1427,12 @@ static struct usb_usbvision *usbvision_alloc(struct usb_device *dev, mutex_init(&usbvision->v4l2_lock); // prepare control urb for control messages during interrupts - usbvision->ctrlUrb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); - if (usbvision->ctrlUrb == NULL) + usbvision->ctrl_urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); + if (usbvision->ctrl_urb == NULL) goto err_unreg; - init_waitqueue_head(&usbvision->ctrlUrb_wq); + init_waitqueue_head(&usbvision->ctrl_urb_wq); - usbvision_init_powerOffTimer(usbvision); + usbvision_init_power_off_timer(usbvision); return usbvision; @@ -1454,15 +1454,15 @@ static void usbvision_release(struct usb_usbvision *usbvision) { PDEBUG(DBG_PROBE, ""); - usbvision_reset_powerOffTimer(usbvision); + usbvision_reset_power_off_timer(usbvision); usbvision->initialized = 0; usbvision_remove_sysfs(usbvision->vdev); usbvision_unregister_video(usbvision); - if (usbvision->ctrlUrb) { - usb_free_urb(usbvision->ctrlUrb); + if (usbvision->ctrl_urb) { + usb_free_urb(usbvision->ctrl_urb); } v4l2_device_unregister(&usbvision->v4l2_dev); @@ -1481,25 +1481,25 @@ static void usbvision_configure_video(struct usb_usbvision *usbvision) if (usbvision == NULL) return; - model = usbvision->DevModel; + model = usbvision->dev_model; usbvision->palette = usbvision_v4l2_format[2]; // V4L2_PIX_FMT_RGB24; - if (usbvision_device_data[usbvision->DevModel].Vin_Reg2_override) { - usbvision->Vin_Reg2_Preset = - usbvision_device_data[usbvision->DevModel].Vin_Reg2; + if (usbvision_device_data[usbvision->dev_model].vin_reg2_override) { + usbvision->vin_reg2_preset = + usbvision_device_data[usbvision->dev_model].vin_reg2; } else { - usbvision->Vin_Reg2_Preset = 0; + usbvision->vin_reg2_preset = 0; } - usbvision->tvnormId = usbvision_device_data[model].VideoNorm; + usbvision->tvnorm_id = usbvision_device_data[model].video_norm; - usbvision->video_inputs = usbvision_device_data[model].VideoChannels; + usbvision->video_inputs = usbvision_device_data[model].video_channels; usbvision->ctl_input = 0; /* This should be here to make i2c clients to be able to register */ /* first switch off audio */ usbvision_audio_off(usbvision); - if (!PowerOnAtOpen) { + if (!power_on_at_open) { /* and then power up the noisy tuner */ usbvision_power_on(usbvision); usbvision_i2c_register(usbvision); @@ -1534,10 +1534,10 @@ static int __devinit usbvision_probe(struct usb_interface *intf, return -ENODEV; } printk(KERN_INFO "%s: %s found\n", __func__, - usbvision_device_data[model].ModelString); + usbvision_device_data[model].model_string); - if (usbvision_device_data[model].Interface >= 0) { - interface = &dev->actconfig->interface[usbvision_device_data[model].Interface]->altsetting[0]; + if (usbvision_device_data[model].interface >= 0) { + interface = &dev->actconfig->interface[usbvision_device_data[model].interface]->altsetting[0]; } else { interface = &dev->actconfig->interface[ifnum]->altsetting[0]; } @@ -1562,13 +1562,13 @@ static int __devinit usbvision_probe(struct usb_interface *intf, } if (dev->descriptor.bNumConfigurations > 1) { - usbvision->bridgeType = BRIDGE_NT1004; + usbvision->bridge_type = BRIDGE_NT1004; } else if (model == DAZZLE_DVC_90_REV_1_SECAM) { - usbvision->bridgeType = BRIDGE_NT1005; + usbvision->bridge_type = BRIDGE_NT1005; } else { - usbvision->bridgeType = BRIDGE_NT1003; + usbvision->bridge_type = BRIDGE_NT1003; } - PDEBUG(DBG_PROBE, "bridgeType %d", usbvision->bridgeType); + PDEBUG(DBG_PROBE, "bridge_type %d", usbvision->bridge_type); /* compute alternate max packet sizes */ uif = dev->actconfig->interface[0]; @@ -1594,20 +1594,20 @@ static int __devinit usbvision_probe(struct usb_interface *intf, usbvision->nr = usbvision_nr++; - usbvision->have_tuner = usbvision_device_data[model].Tuner; + usbvision->have_tuner = usbvision_device_data[model].tuner; if (usbvision->have_tuner) { - usbvision->tuner_type = usbvision_device_data[model].TunerType; + usbvision->tuner_type = usbvision_device_data[model].tuner_type; } - usbvision->DevModel = model; + usbvision->dev_model = model; usbvision->remove_pending = 0; usbvision->iface = ifnum; - usbvision->ifaceAlt = 0; + usbvision->iface_alt = 0; usbvision->video_endp = endpoint->bEndpointAddress; - usbvision->isocPacketSize = 0; + usbvision->isoc_packet_size = 0; usbvision->usb_bandwidth = 0; usbvision->user = 0; - usbvision->streaming = Stream_Off; + usbvision->streaming = stream_off; usbvision_configure_video(usbvision); usbvision_register_video(usbvision); @@ -1682,7 +1682,7 @@ static struct usb_driver usbvision_driver = { */ static int __init usbvision_init(void) { - int errCode; + int err_code; PDEBUG(DBG_PROBE, ""); @@ -1691,19 +1691,19 @@ static int __init usbvision_init(void) PDEBUG(DBG_MMAP, "MMAP debugging is enabled [video]"); /* disable planar mode support unless compression enabled */ - if (isocMode != ISOC_MODE_COMPRESS ) { + if (isoc_mode != ISOC_MODE_COMPRESS ) { // FIXME : not the right way to set supported flag usbvision_v4l2_format[6].supported = 0; // V4L2_PIX_FMT_YVU420 usbvision_v4l2_format[7].supported = 0; // V4L2_PIX_FMT_YUV422P } - errCode = usb_register(&usbvision_driver); + err_code = usb_register(&usbvision_driver); - if (errCode == 0) { + if (err_code == 0) { printk(KERN_INFO DRIVER_DESC " : " USBVISION_VERSION_STRING "\n"); PDEBUG(DBG_PROBE, "success"); } - return errCode; + return err_code; } static void __exit usbvision_exit(void) diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h index 2271ede..42189e5 100644 --- a/drivers/media/video/usbvision/usbvision.h +++ b/drivers/media/video/usbvision/usbvision.h @@ -223,39 +223,39 @@ enum { /* ----------------------------------------------------------------- */ /* usbvision video structures */ /* ----------------------------------------------------------------- */ -enum ScanState { - ScanState_Scanning, /* Scanning for header */ - ScanState_Lines /* Parsing lines */ +enum scan_state { + scan_state_scanning, /* Scanning for header */ + scan_state_lines /* Parsing lines */ }; /* Completion states of the data parser */ -enum ParseState { - ParseState_Continue, /* Just parse next item */ - ParseState_NextFrame, /* Frame done, send it to V4L */ - ParseState_Out, /* Not enough data for frame */ - ParseState_EndParse /* End parsing */ +enum parse_state { + parse_state_continue, /* Just parse next item */ + parse_state_next_frame, /* Frame done, send it to V4L */ + parse_state_out, /* Not enough data for frame */ + parse_state_end_parse /* End parsing */ }; -enum FrameState { - FrameState_Unused, /* Unused (no MCAPTURE) */ - FrameState_Ready, /* Ready to start grabbing */ - FrameState_Grabbing, /* In the process of being grabbed into */ - FrameState_Done, /* Finished grabbing, but not been synced yet */ - FrameState_DoneHold, /* Are syncing or reading */ - FrameState_Error, /* Something bad happened while processing */ +enum frame_state { + frame_state_unused, /* Unused (no MCAPTURE) */ + frame_state_ready, /* Ready to start grabbing */ + frame_state_grabbing, /* In the process of being grabbed into */ + frame_state_done, /* Finished grabbing, but not been synced yet */ + frame_state_done_hold, /* Are syncing or reading */ + frame_state_error, /* Something bad happened while processing */ }; /* stream states */ -enum StreamState { - Stream_Off, /* Driver streaming is completely OFF */ - Stream_Idle, /* Driver streaming is ready to be put ON by the application */ - Stream_Interrupt, /* Driver streaming must be interrupted */ - Stream_On, /* Driver streaming is put ON by the application */ +enum stream_state { + stream_off, /* Driver streaming is completely OFF */ + stream_idle, /* Driver streaming is ready to be put ON by the application */ + stream_interrupt, /* Driver streaming must be interrupted */ + stream_on, /* Driver streaming is put ON by the application */ }; -enum IsocState { - IsocState_InFrame, /* Isoc packet is member of frame */ - IsocState_NoFrame, /* Isoc packet is not member of any frame */ +enum isoc_state { + isoc_state_in_frame, /* Isoc packet is member of frame */ + isoc_state_no_frame, /* Isoc packet is not member of any frame */ }; struct usb_device; @@ -286,23 +286,23 @@ struct usbvision_v4l2_format_st { struct usbvision_frame_header { unsigned char magic_1; /* 0 magic */ unsigned char magic_2; /* 1 magic */ - unsigned char headerLength; /* 2 */ - unsigned char frameNum; /* 3 */ - unsigned char framePhase; /* 4 */ - unsigned char frameLatency; /* 5 */ - unsigned char dataFormat; /* 6 */ - unsigned char formatParam; /* 7 */ - unsigned char frameWidthLo; /* 8 */ - unsigned char frameWidthHi; /* 9 */ - unsigned char frameHeightLo; /* 10 */ - unsigned char frameHeightHi; /* 11 */ - __u16 frameWidth; /* 8 - 9 after endian correction*/ - __u16 frameHeight; /* 10 - 11 after endian correction*/ + unsigned char header_length; /* 2 */ + unsigned char frame_num; /* 3 */ + unsigned char frame_phase; /* 4 */ + unsigned char frame_latency; /* 5 */ + unsigned char data_format; /* 6 */ + unsigned char format_param; /* 7 */ + unsigned char frame_width_lo; /* 8 */ + unsigned char frame_width_hi; /* 9 */ + unsigned char frame_height_lo; /* 10 */ + unsigned char frame_height_hi; /* 11 */ + __u16 frame_width; /* 8 - 9 after endian correction*/ + __u16 frame_height; /* 10 - 11 after endian correction*/ }; struct usbvision_frame { char *data; /* Frame buffer */ - struct usbvision_frame_header isocHeader; /* Header from stream */ + struct usbvision_frame_header isoc_header; /* Header from stream */ int width; /* Width application is expecting */ int height; /* Height */ @@ -332,24 +332,24 @@ struct usbvision_frame { #define BRIDGE_NT1005 1005 struct usbvision_device_data_st { - __u64 VideoNorm; - const char *ModelString; - int Interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */ - __u16 Codec; - unsigned VideoChannels:3; - unsigned AudioChannels:2; - unsigned Radio:1; + __u64 video_norm; + const char *model_string; + int interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */ + __u16 codec; + unsigned video_channels:3; + unsigned audio_channels:2; + unsigned radio:1; unsigned vbi:1; - unsigned Tuner:1; - unsigned Vin_Reg1_override:1; /* Override default value with */ - unsigned Vin_Reg2_override:1; /* Vin_Reg1, Vin_Reg2, etc. */ - unsigned Dvi_yuv_override:1; - __u8 Vin_Reg1; - __u8 Vin_Reg2; - __u8 Dvi_yuv; - __u8 TunerType; - __s16 X_Offset; - __s16 Y_Offset; + unsigned tuner:1; + unsigned vin_reg1_override:1; /* Override default value with */ + unsigned vin_reg2_override:1; /* vin_reg1, vin_reg2, etc. */ + unsigned dvi_yuv_override:1; + __u8 vin_reg1; + __u8 vin_reg2; + __u8 dvi_yuv; + __u8 tuner_type; + __s16 x_offset; + __s16 y_offset; }; /* Declared on usbvision-cards.c */ @@ -365,40 +365,40 @@ struct usb_usbvision { struct i2c_adapter i2c_adap; int registered_i2c; - struct urb *ctrlUrb; - unsigned char ctrlUrbBuffer[8]; - int ctrlUrbBusy; - struct usb_ctrlrequest ctrlUrbSetup; - wait_queue_head_t ctrlUrb_wq; // Processes waiting + struct urb *ctrl_urb; + unsigned char ctrl_urb_buffer[8]; + int ctrl_urb_busy; + struct usb_ctrlrequest ctrl_urb_setup; + wait_queue_head_t ctrl_urb_wq; // Processes waiting /* configuration part */ int have_tuner; int tuner_type; - int bridgeType; // NT1003, NT1004, NT1005 + int bridge_type; // NT1003, NT1004, NT1005 int radio; int video_inputs; // # of inputs unsigned long freq; - int AudioMute; - int AudioChannel; - int isocMode; // format of video data for the usb isoc-transfer + int audio_mute; + int audio_channel; + int isoc_mode; // format of video data for the usb isoc-transfer unsigned int nr; // Number of the device /* Device structure */ struct usb_device *dev; /* usb transfer */ int num_alt; /* Number of alternative settings */ - unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ + unsigned int *alt_max_pkt_size; /* array of max_packet_size */ unsigned char iface; /* Video interface number */ - unsigned char ifaceAlt; /* Alt settings */ - unsigned char Vin_Reg2_Preset; + unsigned char iface_alt; /* Alt settings */ + unsigned char vin_reg2_preset; struct mutex v4l2_lock; - struct timer_list powerOffTimer; - struct work_struct powerOffWork; + struct timer_list power_off_timer; + struct work_struct power_off_work; int power; /* is the device powered on? */ int user; /* user count for exclusive use */ int initialized; /* Had we already sent init sequence? */ - int DevModel; /* What type of USBVISION device we got? */ - enum StreamState streaming; /* Are we streaming Isochronous? */ + int dev_model; /* What type of USBVISION device we got? */ + enum stream_state streaming; /* Are we streaming Isochronous? */ int last_error; /* What calamity struck us? */ int curwidth; /* width of the frame the device is currently set to*/ int curheight; /* height of the frame the device is currently set to*/ @@ -411,7 +411,7 @@ struct usb_usbvision { struct list_head inqueue, outqueue; /* queued frame list and ready to dequeue frame list */ wait_queue_head_t wait_frame; /* Processes waiting */ wait_queue_head_t wait_stream; /* Processes waiting */ - struct usbvision_frame *curFrame; // pointer to current frame, set by usbvision_find_header + struct usbvision_frame *cur_frame; // pointer to current frame, set by usbvision_find_header struct usbvision_frame frame[USBVISION_NUMFRAMES]; // frame buffer int num_frames; // number of frames allocated struct usbvision_sbuf sbuf[USBVISION_NUMSBUF]; // S buffering @@ -424,43 +424,43 @@ struct usb_usbvision { int scratch_headermarker[USBVISION_NUM_HEADERMARKER]; int scratch_headermarker_read_ptr; int scratch_headermarker_write_ptr; - enum IsocState isocstate; + enum isoc_state isocstate; struct usbvision_v4l2_format_st palette; struct v4l2_capability vcap; /* Video capabilities */ unsigned int ctl_input; /* selected input */ - v4l2_std_id tvnormId; /* selected tv norm */ + v4l2_std_id tvnorm_id; /* selected tv norm */ unsigned char video_endp; /* 0x82 for USBVISION devices based */ // Decompression stuff: - unsigned char *IntraFrameBuffer; /* Buffer for reference frame */ - int BlockPos; //for test only - int requestIntra; // 0 = normal; 1 = intra frame is requested; - int lastIsocFrameNum; // check for lost isoc frames - int isocPacketSize; // need to calculate usedBandwidth - int usedBandwidth; // used bandwidth 0-100%, need to set comprLevel - int comprLevel; // How strong (100) or weak (0) is compression - int lastComprLevel; // How strong (100) or weak (0) was compression + unsigned char *intra_frame_buffer; /* Buffer for reference frame */ + int block_pos; //for test only + int request_intra; // 0 = normal; 1 = intra frame is requested; + int last_isoc_frame_num; // check for lost isoc frames + int isoc_packet_size; // need to calculate used_bandwidth + int used_bandwidth; // used bandwidth 0-100%, need to set compr_level + int compr_level; // How strong (100) or weak (0) is compression + int last_compr_level; // How strong (100) or weak (0) was compression int usb_bandwidth; /* Mbit/s */ /* Statistics that can be overlayed on the screen */ - unsigned long isocUrbCount; // How many URBs we received so far + unsigned long isoc_urb_count; // How many URBs we received so far unsigned long urb_length; /* Length of last URB */ - unsigned long isocDataCount; /* How many bytes we received */ + unsigned long isoc_data_count; /* How many bytes we received */ unsigned long header_count; /* How many frame headers we found */ unsigned long scratch_ovf_count; /* How many times we overflowed scratch */ - unsigned long isocSkipCount; /* How many empty ISO packets received */ - unsigned long isocErrCount; /* How many bad ISO packets received */ - unsigned long isocPacketCount; // How many packets we totally got - unsigned long timeInIrq; // How long do we need for interrupt - int isocMeasureBandwidthCount; + unsigned long isoc_skip_count; /* How many empty ISO packets received */ + unsigned long isoc_err_count; /* How many bad ISO packets received */ + unsigned long isoc_packet_count; // How many packets we totally got + unsigned long time_in_irq; // How long do we need for interrupt + int isoc_measure_bandwidth_count; int frame_num; // How many video frames we send to user - int maxStripLen; // How big is the biggest strip - int comprBlockPos; - int stripLenErrors; // How many times was BlockPos greater than StripLen - int stripMagicErrors; - int stripLineNumberErrors; - int ComprBlockTypes[4]; + int max_strip_len; // How big is the biggest strip + int comprblock_pos; + int strip_len_errors; // How many times was block_pos greater than strip_len + int strip_magic_errors; + int strip_line_number_errors; + int compr_block_types[4]; }; static inline struct usb_usbvision *to_usbvision(struct v4l2_device *v4l2_dev) @@ -500,7 +500,7 @@ int usbvision_restart_isoc(struct usb_usbvision *usbvision); void usbvision_stop_isoc(struct usb_usbvision *usbvision); int usbvision_set_alternate(struct usb_usbvision *dev); -int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel); +int usbvision_set_audio(struct usb_usbvision *usbvision, int audio_channel); int usbvision_audio_off(struct usb_usbvision *usbvision); int usbvision_begin_streaming(struct usb_usbvision *usbvision); @@ -511,9 +511,9 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel); int usbvision_set_input(struct usb_usbvision *usbvision); int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height); -void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision); -void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision); -void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision); +void usbvision_init_power_off_timer(struct usb_usbvision *usbvision); +void usbvision_set_power_off_timer(struct usb_usbvision *usbvision); +void usbvision_reset_power_off_timer(struct usb_usbvision *usbvision); int usbvision_power_off(struct usb_usbvision *usbvision); int usbvision_power_on(struct usb_usbvision *usbvision); -- cgit v0.10.2 From 52cb0bf275debe4ec8950157f11b9d9f14447a88 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 19 Dec 2010 20:33:51 -0300 Subject: [media] usbvision: convert // to /* */ Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index 372e21b..64a9133 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -103,10 +103,10 @@ static const int min_imgheight = MIN_FRAME_HEIGHT; * to work with. This setting can be adjusted, but the default value * should be OK for most desktop users. */ -#define DEFAULT_SCRATCH_BUF_SIZE (0x20000) // 128kB memory scratch buffer +#define DEFAULT_SCRATCH_BUF_SIZE (0x20000) /* 128kB memory scratch buffer */ static const int scratch_buf_size = DEFAULT_SCRATCH_BUF_SIZE; -// Function prototypes +/* Function prototypes */ static int usbvision_request_intra (struct usb_usbvision *usbvision); static int usbvision_unrequest_intra (struct usb_usbvision *usbvision); static int usbvision_adjust_compression (struct usb_usbvision *usbvision); @@ -183,7 +183,7 @@ static void usbvision_hexdump(const unsigned char *data, int len) /******************************** * scratch ring buffer handling ********************************/ -static int scratch_len(struct usb_usbvision *usbvision) /*This returns the amount of data actually in the buffer */ +static int scratch_len(struct usb_usbvision *usbvision) /* This returns the amount of data actually in the buffer */ { int len = usbvision->scratch_write_ptr - usbvision->scratch_read_ptr; if (len < 0) { @@ -287,7 +287,7 @@ static void scratch_set_extra_ptr(struct usb_usbvision *usbvision, int *ptr, } -/*This increments the scratch extra read pointer */ +/* This increments the scratch extra read pointer */ static void scratch_inc_extra_ptr(int *ptr, int len) { *ptr = (*ptr + len) % scratch_buf_size; @@ -352,7 +352,7 @@ static int scratch_get_header(struct usb_usbvision *usbvision, } -/*This removes len bytes of old data from the buffer */ +/* This removes len bytes of old data from the buffer */ static void scratch_rm_old(struct usb_usbvision *usbvision, int len) { @@ -362,7 +362,7 @@ static void scratch_rm_old(struct usb_usbvision *usbvision, int len) } -/*This resets the buffer - kills all data in it too */ +/* This resets the buffer - kills all data in it too */ static void scratch_reset(struct usb_usbvision *usbvision) { PDEBUG(DBG_SCRATCH, "\n"); @@ -525,7 +525,7 @@ static enum parse_state usbvision_find_header(struct usb_usbvision *usbvision) frame = usbvision->cur_frame; while (scratch_get_header(usbvision, &frame->isoc_header) == USBVISION_HEADER_LENGTH) { - // found header in scratch + /* found header in scratch */ PDEBUG(DBG_HEADER, "found header: 0x%02x%02x %d %d %d %d %#x 0x%02x %u %u", frame->isoc_header.magic_2, frame->isoc_header.magic_1, @@ -541,7 +541,7 @@ static enum parse_state usbvision_find_header(struct usb_usbvision *usbvision) if (usbvision->request_intra) { if (frame->isoc_header.format_param & 0x80) { found_header = 1; - usbvision->last_isoc_frame_num = -1; // do not check for lost frames this time + usbvision->last_isoc_frame_num = -1; /* do not check for lost frames this time */ usbvision_unrequest_intra(usbvision); break; } @@ -557,18 +557,18 @@ static enum parse_state usbvision_find_header(struct usb_usbvision *usbvision) frame->frmheight = frame->isoc_header.frame_height * usbvision->stretch_height; frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth)>> 3; } - else { // no header found + else { /* no header found */ PDEBUG(DBG_HEADER, "skipping scratch data, no header"); scratch_reset(usbvision); return parse_state_end_parse; } - // found header + /* found header */ if (frame->isoc_header.data_format==ISOC_MODE_COMPRESS) { - //check isoc_header.frame_num for lost frames + /* check isoc_header.frame_num for lost frames */ if (usbvision->last_isoc_frame_num >= 0) { if (((usbvision->last_isoc_frame_num + 1) % 32) != frame->isoc_header.frame_num) { - // unexpected frame drop: need to request new intra frame + /* unexpected frame drop: need to request new intra frame */ PDEBUG(DBG_HEADER, "Lost frame before %d on USB", frame->isoc_header.frame_num); usbvision_request_intra(usbvision); return parse_state_next_frame; @@ -594,8 +594,8 @@ static enum parse_state usbvision_parse_lines_422(struct usb_usbvision *usbvisio unsigned char *f; int len; int i; - unsigned char yuyv[4]={180, 128, 10, 128}; // YUV components - unsigned char rv, gv, bv; // RGB components + unsigned char yuyv[4]={180, 128, 10, 128}; /* YUV components */ + unsigned char rv, gv, bv; /* RGB components */ int clipmask_index, bytes_per_pixel; int stretch_bytes, clipmask_add; @@ -623,8 +623,8 @@ static enum parse_state usbvision_parse_lines_422(struct usb_usbvision *usbvisio scratch_get(usbvision, &yuyv[0], 4); if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f++ = yuyv[0]; // Y - *f++ = yuyv[3]; // U + *f++ = yuyv[0]; /* Y */ + *f++ = yuyv[3]; /* U */ } else { @@ -659,8 +659,8 @@ static enum parse_state usbvision_parse_lines_422(struct usb_usbvision *usbvisio f += stretch_bytes; if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f++ = yuyv[2]; // Y - *f++ = yuyv[1]; // V + *f++ = yuyv[2]; /* Y */ + *f++ = yuyv[1]; /* V */ } else { @@ -717,7 +717,7 @@ static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *c integrator = 0; pos = *start_pos; block_type_pos = *block_typestart_pos; - max_pos = 396; //pos + len; + max_pos = 396; /* pos + len; */ extra_pos = pos; block_len = 0; block_byte = 0; @@ -737,7 +737,7 @@ static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *c } block_type = (block_type_byte & 0xC0) >> 6; - //statistic: + /* statistic: */ usbvision->compr_block_types[block_type]++; pos = extra_pos; @@ -769,7 +769,7 @@ static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *c block_byte = compressed[pos]; pos++; } - if (block_type == 1) { //inter Block + if (block_type == 1) { /* inter Block */ integrator = decompressed[idx]; } switch (block_byte & 0xC0) { @@ -823,14 +823,14 @@ static enum parse_state usbvision_parse_compress(struct usb_usbvision *usbvision frame = usbvision->cur_frame; image_size = frame->frmwidth * frame->frmheight; if ( (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) || - (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) ) { // this is a planar format - //... v4l2_linesize not used here. + (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) ) { /* this is a planar format */ + /* ... v4l2_linesize not used here. */ f = frame->data + (frame->width * frame->curline); } else f = frame->data + (frame->v4l2_linesize * frame->curline); - if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV){ //initialise u and v pointers - // get base of u and b planes add halfoffset + if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV){ /* initialise u and v pointers */ + /* get base of u and b planes add halfoffset */ u = frame->data + image_size @@ -851,31 +851,31 @@ static enum parse_state usbvision_parse_compress(struct usb_usbvision *usbvision return parse_state_out; } - //get strip header without changing the scratch_read_ptr + /* get strip header without changing the scratch_read_ptr */ scratch_set_extra_ptr(usbvision, &strip_ptr, 0); scratch_get_extra(usbvision, &strip_header[0], &strip_ptr, USBVISION_STRIP_HEADER_LEN); if (strip_header[0] != USBVISION_STRIP_MAGIC) { - // wrong strip magic + /* wrong strip magic */ usbvision->strip_magic_errors++; return parse_state_next_frame; } if (frame->curline != (int)strip_header[2]) { - //line number missmatch error + /* line number missmatch error */ usbvision->strip_line_number_errors++; } strip_len = 2 * (unsigned int)strip_header[1]; if (strip_len > USBVISION_STRIP_LEN_MAX) { - // strip overrun - // I think this never happens + /* strip overrun */ + /* I think this never happens */ usbvision_request_intra(usbvision); } if (scratch_len(usbvision) < strip_len) { - //there is not enough data for the strip + /* there is not enough data for the strip */ return parse_state_out; } @@ -901,7 +901,7 @@ static enum parse_state usbvision_parse_compress(struct usb_usbvision *usbvision usbvision->block_pos = block_pos; if ((rc = usbvision_decompress(usbvision, strip_data, Y, &block_pos, &block_type_pos, idx_end)) != idx_end) { - //return parse_state_continue; + /* return parse_state_continue; */ } if (strip_len > usbvision->max_strip_len) { usbvision->max_strip_len = strip_len; @@ -909,12 +909,12 @@ static enum parse_state usbvision_parse_compress(struct usb_usbvision *usbvision if (frame->curline%2) { if ((rc = usbvision_decompress(usbvision, strip_data, V, &block_pos, &block_type_pos, idx_end/2)) != idx_end/2) { - //return parse_state_continue; + /* return parse_state_continue; */ } } else { if ((rc = usbvision_decompress(usbvision, strip_data, U, &block_pos, &block_type_pos, idx_end/2)) != idx_end/2) { - //return parse_state_continue; + /* return parse_state_continue; */ } } @@ -1043,7 +1043,7 @@ static enum parse_state usbvision_parse_lines_420(struct usb_usbvision *usbvisio pixel_per_line = frame->isoc_header.frame_width; if (scratch_len(usbvision) < (int)pixel_per_line * 3) { - //printk(KERN_DEBUG "out of data, need %d\n", len); + /* printk(KERN_DEBUG "out of data, need %d\n", len); */ return parse_state_out; } @@ -1051,7 +1051,7 @@ static enum parse_state usbvision_parse_lines_420(struct usb_usbvision *usbvisio return parse_state_next_frame; } - block_split = (pixel_per_line%y_block_size) ? 1 : 0; //are some blocks splitted into different lines? + block_split = (pixel_per_line%y_block_size) ? 1 : 0; /* are some blocks splitted into different lines? */ y_odd_offset = (pixel_per_line / y_block_size) * (y_block_size + uv_block_size) + block_split * uv_block_size; @@ -1070,7 +1070,7 @@ static enum parse_state usbvision_parse_lines_420(struct usb_usbvision *usbvisio scratch_get_extra(usbvision, &u, &u_ptr, 1); scratch_get_extra(usbvision, &v, &v_ptr, 1); - //I don't use the YUV_TO_RGB macro for better performance + /* I don't use the YUV_TO_RGB macro for better performance */ v_ = v - 128; u_ = u - 128; vb = 132252 * v_; @@ -1370,7 +1370,7 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, packet_data = urb->transfer_buffer + urb->iso_frame_desc[i].offset; /* Detect and ignore errored packets */ - if (packet_stat) { // packet_stat != 0 ????????????? + if (packet_stat) { /* packet_stat != 0 ????????????? */ PDEBUG(DBG_ISOC, "data error: [%d] len=%d, status=%X", i, packet_len, packet_stat); usbvision->isoc_err_count++; continue; @@ -1396,7 +1396,7 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, PDEBUG(DBG_ISOC, "packet ok [%d] len=%d", i, packet_len); - if (usbvision->isocstate==isoc_state_no_frame) { //new frame begins + if (usbvision->isocstate==isoc_state_no_frame) { /* new frame begins */ usbvision->isocstate=isoc_state_in_frame; scratch_mark_header(usbvision); usbvision_measure_bandwidth(usbvision); @@ -1488,7 +1488,7 @@ static void usbvision_isoc_irq(struct urb *urb) usbvision_parse_data(usbvision); } else { - /*If we don't have a frame + /* If we don't have a frame we're current working on, complain */ PDEBUG(DBG_IRQ, "received data, but no one needs it"); @@ -1623,7 +1623,7 @@ static int usbvision_write_reg_irq(struct usb_usbvision *usbvision,int address, err_code = usb_submit_urb(usbvision->ctrl_urb, GFP_ATOMIC); if (err_code < 0) { - // error in usb_submit_urb() + /* error in usb_submit_urb() */ usbvision->ctrl_urb_busy = 0; } PDEBUG(DBG_IRQ, "submit %d byte: error %d", len, err_code); @@ -1656,7 +1656,7 @@ static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision) { int err_code = 0; - if (usbvision->isoc_measure_bandwidth_count < 2) { // this gives an average bandwidth of 3 frames + if (usbvision->isoc_measure_bandwidth_count < 2) { /* this gives an average bandwidth of 3 frames */ usbvision->isoc_measure_bandwidth_count++; return err_code; } @@ -1684,24 +1684,24 @@ static int usbvision_adjust_compression (struct usb_usbvision *usbvision) if (usbvision->compr_level != usbvision->last_compr_level) { int distorsion; if (usbvision->bridge_type == BRIDGE_NT1004 || usbvision->bridge_type == BRIDGE_NT1005) { - buffer[0] = (unsigned char)(4 + 16 * usbvision->compr_level / 100); // PCM Threshold 1 - buffer[1] = (unsigned char)(4 + 8 * usbvision->compr_level / 100); // PCM Threshold 2 + buffer[0] = (unsigned char)(4 + 16 * usbvision->compr_level / 100); /* PCM Threshold 1 */ + buffer[1] = (unsigned char)(4 + 8 * usbvision->compr_level / 100); /* PCM Threshold 2 */ distorsion = 7 + 248 * usbvision->compr_level / 100; - buffer[2] = (unsigned char)(distorsion & 0xFF); // Average distorsion Threshold (inter) - buffer[3] = (unsigned char)(distorsion & 0xFF); // Average distorsion Threshold (intra) + buffer[2] = (unsigned char)(distorsion & 0xFF); /* Average distorsion Threshold (inter) */ + buffer[3] = (unsigned char)(distorsion & 0xFF); /* Average distorsion Threshold (intra) */ distorsion = 1 + 42 * usbvision->compr_level / 100; - buffer[4] = (unsigned char)(distorsion & 0xFF); // Maximum distorsion Threshold (inter) - buffer[5] = (unsigned char)(distorsion & 0xFF); // Maximum distorsion Threshold (intra) + buffer[4] = (unsigned char)(distorsion & 0xFF); /* Maximum distorsion Threshold (inter) */ + buffer[5] = (unsigned char)(distorsion & 0xFF); /* Maximum distorsion Threshold (intra) */ } - else { //BRIDGE_NT1003 - buffer[0] = (unsigned char)(4 + 16 * usbvision->compr_level / 100); // PCM threshold 1 - buffer[1] = (unsigned char)(4 + 8 * usbvision->compr_level / 100); // PCM threshold 2 + else { /* BRIDGE_NT1003 */ + buffer[0] = (unsigned char)(4 + 16 * usbvision->compr_level / 100); /* PCM threshold 1 */ + buffer[1] = (unsigned char)(4 + 8 * usbvision->compr_level / 100); /* PCM threshold 2 */ distorsion = 2 + 253 * usbvision->compr_level / 100; - buffer[2] = (unsigned char)(distorsion & 0xFF); // distorsion threshold bit0-7 - buffer[3] = 0; //(unsigned char)((distorsion >> 8) & 0x0F); // distorsion threshold bit 8-11 + buffer[2] = (unsigned char)(distorsion & 0xFF); /* distorsion threshold bit0-7 */ + buffer[3] = 0; /* (unsigned char)((distorsion >> 8) & 0x0F); distorsion threshold bit 8-11 */ distorsion = 0 + 43 * usbvision->compr_level / 100; - buffer[4] = (unsigned char)(distorsion & 0xFF); // maximum distorsion bit0-7 - buffer[5] = 0; //(unsigned char)((distorsion >> 8) & 0x01); // maximum distorsion bit 8 + buffer[4] = (unsigned char)(distorsion & 0xFF); /* maximum distorsion bit0-7 */ + buffer[5] = 0; /* (unsigned char)((distorsion >> 8) & 0x01); maximum distorsion bit 8 */ } err_code = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6); if (err_code == 0){ @@ -1778,8 +1778,8 @@ static int usbvision_set_video_format(struct usb_usbvision *usbvision, int forma format); format = ISOC_MODE_YUV420; } - value[0] = 0x0A; //TODO: See the effect of the filter - value[1] = format; // Sets the VO_MODE register which follows FILT_CONT + value[0] = 0x0A; /* TODO: See the effect of the filter */ + value[1] = format; /* Sets the VO_MODE register which follows FILT_CONT */ rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, USB_DIR_OUT | USB_TYPE_VENDOR | @@ -1840,10 +1840,10 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width, /* I'll not rewrite the same values */ if ((usb_width != usbvision->curwidth) || (usb_height != usbvision->curheight)) { - value[0] = usb_width & 0xff; //LSB - value[1] = (usb_width >> 8) & 0x03; //MSB - value[2] = usb_height & 0xff; //LSB - value[3] = (usb_height >> 8) & 0x03; //MSB + value[0] = usb_width & 0xff; /* LSB */ + value[1] = (usb_width >> 8) & 0x03; /* MSB */ + value[2] = usb_height & 0xff; /* LSB */ + value[3] = (usb_height >> 8) & 0x03; /* MSB */ err_code = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, @@ -1880,7 +1880,7 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width, PDEBUG(DBG_FUNC, "frame_rate %d fps, frame_drop %d", frame_rate, frame_drop); - frame_drop = FRAMERATE_MAX; // We can allow the maximum here, because dropping is controlled + frame_drop = FRAMERATE_MAX; /* We can allow the maximum here, because dropping is controlled */ /* frame_drop = 7; => frame_phase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ... => frame_skip = 4; @@ -1903,7 +1903,7 @@ int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames { int i; - /*needs to be page aligned cause the buffers can be mapped individually! */ + /* needs to be page aligned cause the buffers can be mapped individually! */ usbvision->max_frame_size = PAGE_ALIGN(usbvision->curwidth * usbvision->curheight * usbvision->palette.bytes_per_pixel); @@ -2002,19 +2002,19 @@ static int usbvision_set_compress_params(struct usb_usbvision *usbvision) int rc; unsigned char value[6]; - value[0] = 0x0F; // Intra-Compression cycle - value[1] = 0x01; // Reg.45 one line per strip - value[2] = 0x00; // Reg.46 Force intra mode on all new frames - value[3] = 0x00; // Reg.47 FORCE_UP <- 0 normal operation (not force) - value[4] = 0xA2; // Reg.48 BUF_THR I'm not sure if this does something in not compressed mode. - value[5] = 0x00; // Reg.49 DVI_YUV This has nothing to do with compression - - //catched values for NT1004 - // value[0] = 0xFF; // Never apply intra mode automatically - // value[1] = 0xF1; // Use full frame height for virtual strip width; One line per strip - // value[2] = 0x01; // Force intra mode on all new frames - // value[3] = 0x00; // Strip size 400 Bytes; do not force up - // value[4] = 0xA2; // + value[0] = 0x0F; /* Intra-Compression cycle */ + value[1] = 0x01; /* Reg.45 one line per strip */ + value[2] = 0x00; /* Reg.46 Force intra mode on all new frames */ + value[3] = 0x00; /* Reg.47 FORCE_UP <- 0 normal operation (not force) */ + value[4] = 0xA2; /* Reg.48 BUF_THR I'm not sure if this does something in not compressed mode. */ + value[5] = 0x00; /* Reg.49 DVI_YUV This has nothing to do with compression */ + + /* catched values for NT1004 */ + /* value[0] = 0xFF; Never apply intra mode automatically */ + /* value[1] = 0xF1; Use full frame height for virtual strip width; One line per strip */ + /* value[2] = 0x01; Force intra mode on all new frames */ + /* value[3] = 0x00; Strip size 400 Bytes; do not force up */ + /* value[4] = 0xA2; */ if (!USBVISION_IS_OPERATIONAL(usbvision)) return 0; @@ -2031,20 +2031,20 @@ static int usbvision_set_compress_params(struct usb_usbvision *usbvision) } if (usbvision->bridge_type == BRIDGE_NT1004) { - value[0] = 20; // PCM Threshold 1 - value[1] = 12; // PCM Threshold 2 - value[2] = 255; // Distorsion Threshold inter - value[3] = 255; // Distorsion Threshold intra - value[4] = 43; // Max Distorsion inter - value[5] = 43; // Max Distorsion intra + value[0] = 20; /* PCM Threshold 1 */ + value[1] = 12; /* PCM Threshold 2 */ + value[2] = 255; /* Distorsion Threshold inter */ + value[3] = 255; /* Distorsion Threshold intra */ + value[4] = 43; /* Max Distorsion inter */ + value[5] = 43; /* Max Distorsion intra */ } else { - value[0] = 20; // PCM Threshold 1 - value[1] = 12; // PCM Threshold 2 - value[2] = 255; // Distorsion Threshold d7-d0 - value[3] = 0; // Distorsion Threshold d11-d8 - value[4] = 43; // Max Distorsion d7-d0 - value[5] = 0; // Max Distorsion d8 + value[0] = 20; /* PCM Threshold 1 */ + value[1] = 12; /* PCM Threshold 2 */ + value[2] = 255; /* Distorsion Threshold d7-d0 */ + value[3] = 0; /* Distorsion Threshold d11-d8 */ + value[4] = 43; /* Max Distorsion d7-d0 */ + value[5] = 0; /* Max Distorsion d8 */ } if (!USBVISION_IS_OPERATIONAL(usbvision)) @@ -2107,31 +2107,31 @@ int usbvision_set_input(struct usb_usbvision *usbvision) if (usbvision->tvnorm_id & V4L2_STD_PAL) { value[0] = 0xC0; - value[1] = 0x02; //0x02C0 -> 704 Input video line length + value[1] = 0x02; /* 0x02C0 -> 704 Input video line length */ value[2] = 0x20; - value[3] = 0x01; //0x0120 -> 288 Input video n. of lines + value[3] = 0x01; /* 0x0120 -> 288 Input video n. of lines */ value[4] = 0x60; - value[5] = 0x00; //0x0060 -> 96 Input video h offset + value[5] = 0x00; /* 0x0060 -> 96 Input video h offset */ value[6] = 0x16; - value[7] = 0x00; //0x0016 -> 22 Input video v offset + value[7] = 0x00; /* 0x0016 -> 22 Input video v offset */ } else if (usbvision->tvnorm_id & V4L2_STD_SECAM) { value[0] = 0xC0; - value[1] = 0x02; //0x02C0 -> 704 Input video line length + value[1] = 0x02; /* 0x02C0 -> 704 Input video line length */ value[2] = 0x20; - value[3] = 0x01; //0x0120 -> 288 Input video n. of lines + value[3] = 0x01; /* 0x0120 -> 288 Input video n. of lines */ value[4] = 0x01; - value[5] = 0x00; //0x0001 -> 01 Input video h offset + value[5] = 0x00; /* 0x0001 -> 01 Input video h offset */ value[6] = 0x01; - value[7] = 0x00; //0x0001 -> 01 Input video v offset + value[7] = 0x00; /* 0x0001 -> 01 Input video v offset */ } else { /* V4L2_STD_NTSC */ value[0] = 0xD0; - value[1] = 0x02; //0x02D0 -> 720 Input video line length + value[1] = 0x02; /* 0x02D0 -> 720 Input video line length */ value[2] = 0xF0; - value[3] = 0x00; //0x00F0 -> 240 Input video number of lines + value[3] = 0x00; /* 0x00F0 -> 240 Input video number of lines */ value[4] = 0x50; - value[5] = 0x00; //0x0050 -> 80 Input video h offset + value[5] = 0x00; /* 0x0050 -> 80 Input video h offset */ value[6] = 0x10; - value[7] = 0x00; //0x0010 -> 16 Input video v offset + value[7] = 0x00; /* 0x0010 -> 16 Input video v offset */ } if (usbvision_device_data[usbvision->dev_model].x_offset >= 0) { @@ -2201,9 +2201,9 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) value[5] = 0xe0; value[6] = 0x71; value[7] = 0xff; - // UR: 0x0E200-0x3FFFF = 204288 Words (1 Word = 2 Byte) - // FDL: 0x00000-0x0E099 = 57498 Words - // VDW: 0x0E3FF-0x3FFFF + /* UR: 0x0E200-0x3FFFF = 204288 Words (1 Word = 2 Byte) */ + /* FDL: 0x00000-0x0E099 = 57498 Words */ + /* VDW: 0x0E3FF-0x3FFFF */ } else { value[0] = 0x42; @@ -2285,7 +2285,7 @@ int usbvision_power_on(struct usb_usbvision *usbvision) * usbvision timer stuff */ -// to call usbvision_power_off from task queue +/* to call usbvision_power_off from task queue */ static void call_usbvision_power_off(struct work_struct *work) { struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, power_off_work); @@ -2592,17 +2592,17 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) /* inputs #1 and #2 are variable for SAA7111 and SAA7113 */ int mode[4]= {SAA7115_COMPOSITE0, 0, 0, SAA7115_COMPOSITE3}; int audio[]= {1, 0, 0, 0}; - //channel 0 is TV with audiochannel 1 (tuner mono) - //channel 1 is Composite with audio channel 0 (line in) - //channel 2 is S-Video with audio channel 0 (line in) - //channel 3 is additional video inputs to the device with audio channel 0 (line in) + /* channel 0 is TV with audiochannel 1 (tuner mono) */ + /* channel 1 is Composite with audio channel 0 (line in) */ + /* channel 2 is S-Video with audio channel 0 (line in) */ + /* channel 3 is additional video inputs to the device with audio channel 0 (line in) */ RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs); usbvision->ctl_input = channel; - // set the new channel - // Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video - // Four video input devices -> channel: 0 = Chan White, 1 = Chan Green, 2 = Chan Yellow, 3 = Chan Red + /* set the new channel */ + /* Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video */ + /* Four video input devices -> channel: 0 = Chan White, 1 = Chan Green, 2 = Chan Yellow, 3 = Chan Red */ switch (usbvision_device_data[usbvision->dev_model].codec) { case CODEC_SAA7113: diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index 7b2cd00..cb19c84 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c @@ -39,7 +39,7 @@ static int i2c_debug; -module_param (i2c_debug, int, 0644); // debug_i2c_usb mode of the device driver +module_param (i2c_debug, int, 0644); /* debug_i2c_usb mode of the device driver */ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); #define PDEBUG(level, fmt, args...) { \ diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 4882ea0..375355a 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -103,7 +103,7 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL) #define DBG_PROBE 1<<2 #define DBG_MMAP 1<<3 -//String operations +/* String operations */ #define rmspace(str) while(*str==' ') str++; #define goto2next(str) while(*str!=' ') str++; while(*str==' ') str++; @@ -118,7 +118,7 @@ static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = { { 1, 4, 32, V4L2_PIX_FMT_RGB32 , "RGB32" }, { 1, 2, 16, V4L2_PIX_FMT_RGB555 , "RGB555" }, { 1, 2, 16, V4L2_PIX_FMT_YUYV , "YUV422" }, - { 1, 2, 12, V4L2_PIX_FMT_YVU420 , "YUV420P" }, // 1.5 ! + { 1, 2, 12, V4L2_PIX_FMT_YVU420 , "YUV420P" }, /* 1.5 ! */ { 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" } }; @@ -153,7 +153,7 @@ MODULE_PARM_DESC(video_nr, "Set video device number (/dev/videoX). Default: -1 MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX). Default: -1 (autodetect)"); -// Misc stuff +/* Misc stuff */ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE(DRIVER_LICENSE); @@ -534,7 +534,7 @@ static int vidioc_enum_input (struct file *file, void *priv, if (usbvision->have_tuner) { chan = vi->index; } else { - chan = vi->index + 1; /*skip Television string*/ + chan = vi->index + 1; /* skip Television string*/ } /* Determine the requested input characteristics specific for each usbvision card model */ @@ -618,7 +618,7 @@ static int vidioc_g_tuner (struct file *file, void *priv, { struct usb_usbvision *usbvision = video_drvdata(file); - if (!usbvision->have_tuner || vt->index) // Only tuner 0 + if (!usbvision->have_tuner || vt->index) /* Only tuner 0 */ return -EINVAL; if(usbvision->radio) { strcpy(vt->name, "Radio"); @@ -637,7 +637,7 @@ static int vidioc_s_tuner (struct file *file, void *priv, { struct usb_usbvision *usbvision = video_drvdata(file); - // Only no or one tuner for now + /* Only no or one tuner for now */ if (!usbvision->have_tuner || vt->index) return -EINVAL; /* let clients handle this */ @@ -651,7 +651,7 @@ static int vidioc_g_frequency (struct file *file, void *priv, { struct usb_usbvision *usbvision = video_drvdata(file); - freq->tuner = 0; // Only one tuner + freq->tuner = 0; /* Only one tuner */ if(usbvision->radio) { freq->type = V4L2_TUNER_RADIO; } else { @@ -667,7 +667,7 @@ static int vidioc_s_frequency (struct file *file, void *priv, { struct usb_usbvision *usbvision = video_drvdata(file); - // Only no or one tuner for now + /* Only no or one tuner for now */ if (!usbvision->have_tuner || freq->tuner) return -EINVAL; @@ -1069,7 +1069,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, (unsigned long)count, frame->bytes_read); /* For now, forget the frame if it has not been read in one shot. */ -/* if (frame->bytes_read >= frame->scanlength) {// All data has been read */ +/* if (frame->bytes_read >= frame->scanlength) {*/ /* All data has been read */ frame->bytes_read = 0; /* Mark it as available to be used again. */ @@ -1163,7 +1163,7 @@ static int usbvision_radio_open(struct file *file) goto out; } - // If so far no errors then we shall start the radio + /* If so far no errors then we shall start the radio */ usbvision->radio = 1; call_all(usbvision, tuner, s_radio); usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO); @@ -1212,11 +1212,9 @@ static int usbvision_radio_close(struct file *file) return err_code; } -// -// Video registration stuff -// +/* Video registration stuff */ -// Video template +/* Video template */ static const struct v4l2_file_operations usbvision_fops = { .owner = THIS_MODULE, .open = usbvision_v4l2_open, @@ -1268,7 +1266,7 @@ static struct video_device usbvision_video_template = { }; -// Radio template +/* Radio template */ static const struct v4l2_file_operations usbvision_radio_fops = { .owner = THIS_MODULE, .open = usbvision_radio_open, @@ -1328,10 +1326,10 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, return vdev; } -// unregister video4linux devices +/* unregister video4linux devices */ static void usbvision_unregister_video(struct usb_usbvision *usbvision) { - // Radio Device: + /* Radio Device: */ if (usbvision->rdev) { PDEBUG(DBG_PROBE, "unregister %s [v4l2]", video_device_node_name(usbvision->rdev)); @@ -1343,7 +1341,7 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) usbvision->rdev = NULL; } - // Video Device: + /* Video Device: */ if (usbvision->vdev) { PDEBUG(DBG_PROBE, "unregister %s [v4l2]", video_device_node_name(usbvision->vdev)); @@ -1356,10 +1354,10 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) } } -// register video4linux devices +/* register video4linux devices */ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) { - // Video Device: + /* Video Device: */ usbvision->vdev = usbvision_vdev_init(usbvision, &usbvision_video_template, "USBVision Video"); @@ -1374,9 +1372,9 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) printk(KERN_INFO "USBVision[%d]: registered USBVision Video device %s [v4l2]\n", usbvision->nr, video_device_node_name(usbvision->vdev)); - // Radio Device: + /* Radio Device: */ if (usbvision_device_data[usbvision->dev_model].radio) { - // usbvision has radio + /* usbvision has radio */ usbvision->rdev = usbvision_vdev_init(usbvision, &usbvision_radio_template, "USBVision Radio"); @@ -1391,7 +1389,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device %s [v4l2]\n", usbvision->nr, video_device_node_name(usbvision->rdev)); } - // all done + /* all done */ return 0; err_exit: @@ -1426,7 +1424,7 @@ static struct usb_usbvision *usbvision_alloc(struct usb_device *dev, mutex_init(&usbvision->v4l2_lock); - // prepare control urb for control messages during interrupts + /* prepare control urb for control messages during interrupts */ usbvision->ctrl_urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); if (usbvision->ctrl_urb == NULL) goto err_unreg; @@ -1482,7 +1480,7 @@ static void usbvision_configure_video(struct usb_usbvision *usbvision) return; model = usbvision->dev_model; - usbvision->palette = usbvision_v4l2_format[2]; // V4L2_PIX_FMT_RGB24; + usbvision->palette = usbvision_v4l2_format[2]; /* V4L2_PIX_FMT_RGB24; */ if (usbvision_device_data[usbvision->dev_model].vin_reg2_override) { usbvision->vin_reg2_preset = @@ -1639,7 +1637,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) mutex_lock(&usbvision->v4l2_lock); - // At this time we ask to cancel outstanding URBs + /* At this time we ask to cancel outstanding URBs */ usbvision_stop_isoc(usbvision); v4l2_device_disconnect(&usbvision->v4l2_dev); @@ -1648,10 +1646,10 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) usbvision_i2c_unregister(usbvision); usbvision_power_off(usbvision); } - usbvision->remove_pending = 1; // Now all ISO data will be ignored + usbvision->remove_pending = 1; /* Now all ISO data will be ignored */ usb_put_dev(usbvision->dev); - usbvision->dev = NULL; // USB device is no more + usbvision->dev = NULL; /* USB device is no more */ mutex_unlock(&usbvision->v4l2_lock); @@ -1692,9 +1690,9 @@ static int __init usbvision_init(void) /* disable planar mode support unless compression enabled */ if (isoc_mode != ISOC_MODE_COMPRESS ) { - // FIXME : not the right way to set supported flag - usbvision_v4l2_format[6].supported = 0; // V4L2_PIX_FMT_YVU420 - usbvision_v4l2_format[7].supported = 0; // V4L2_PIX_FMT_YUV422P + /* FIXME : not the right way to set supported flag */ + usbvision_v4l2_format[6].supported = 0; /* V4L2_PIX_FMT_YVU420 */ + usbvision_v4l2_format[7].supported = 0; /* V4L2_PIX_FMT_YUV422P */ } err_code = usb_register(&usbvision_driver); diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h index 42189e5..5141159 100644 --- a/drivers/media/video/usbvision/usbvision.h +++ b/drivers/media/video/usbvision/usbvision.h @@ -132,15 +132,15 @@ #define MAX_BYTES_PER_PIXEL 4 #define MIN_FRAME_WIDTH 64 -#define MAX_USB_WIDTH 320 //384 -#define MAX_FRAME_WIDTH 320 //384 /*streching sometimes causes crashes*/ +#define MAX_USB_WIDTH 320 /* 384 */ +#define MAX_FRAME_WIDTH 320 /* 384 */ /* streching sometimes causes crashes*/ #define MIN_FRAME_HEIGHT 48 -#define MAX_USB_HEIGHT 240 //288 -#define MAX_FRAME_HEIGHT 240 //288 /*Streching sometimes causes crashes*/ +#define MAX_USB_HEIGHT 240 /* 288 */ +#define MAX_FRAME_HEIGHT 240 /* 288 */ /* Streching sometimes causes crashes*/ #define MAX_FRAME_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * MAX_BYTES_PER_PIXEL) -#define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) //bytesize of clipmask +#define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) /* bytesize of clipmask */ #define USBVISION_URB_FRAMES 32 @@ -148,7 +148,7 @@ #define USBVISION_NUMFRAMES 3 /* Maximum number of frames an application can get */ #define USBVISION_NUMSBUF 2 /* Dimensioning the USB S buffering */ -#define USBVISION_POWEROFF_TIME 3 * (HZ) // 3 seconds +#define USBVISION_POWEROFF_TIME 3 * (HZ) /* 3 seconds */ #define FRAMERATE_MIN 0 @@ -287,7 +287,7 @@ struct usbvision_frame_header { unsigned char magic_1; /* 0 magic */ unsigned char magic_2; /* 1 magic */ unsigned char header_length; /* 2 */ - unsigned char frame_num; /* 3 */ + unsigned char frame_num; /* 3 */ unsigned char frame_phase; /* 4 */ unsigned char frame_latency; /* 5 */ unsigned char data_format; /* 6 */ @@ -322,7 +322,7 @@ struct usbvision_frame { struct usbvision_v4l2_format_st v4l2_format; /* format the user needs*/ int v4l2_linesize; /* bytes for one videoline*/ struct timeval timestamp; - int sequence; // How many video frames we send to user + int sequence; /* How many video frames we send to user */ }; #define CODEC_SAA7113 7113 @@ -369,19 +369,19 @@ struct usb_usbvision { unsigned char ctrl_urb_buffer[8]; int ctrl_urb_busy; struct usb_ctrlrequest ctrl_urb_setup; - wait_queue_head_t ctrl_urb_wq; // Processes waiting + wait_queue_head_t ctrl_urb_wq; /* Processes waiting */ /* configuration part */ int have_tuner; int tuner_type; - int bridge_type; // NT1003, NT1004, NT1005 + int bridge_type; /* NT1003, NT1004, NT1005 */ int radio; - int video_inputs; // # of inputs + int video_inputs; /* # of inputs */ unsigned long freq; int audio_mute; int audio_channel; - int isoc_mode; // format of video data for the usb isoc-transfer - unsigned int nr; // Number of the device + int isoc_mode; /* format of video data for the usb isoc-transfer */ + unsigned int nr; /* Number of the device */ /* Device structure */ struct usb_device *dev; @@ -389,7 +389,7 @@ struct usb_usbvision { int num_alt; /* Number of alternative settings */ unsigned int *alt_max_pkt_size; /* array of max_packet_size */ unsigned char iface; /* Video interface number */ - unsigned char iface_alt; /* Alt settings */ + unsigned char iface_alt; /* Alt settings */ unsigned char vin_reg2_preset; struct mutex v4l2_lock; struct timer_list power_off_timer; @@ -411,10 +411,10 @@ struct usb_usbvision { struct list_head inqueue, outqueue; /* queued frame list and ready to dequeue frame list */ wait_queue_head_t wait_frame; /* Processes waiting */ wait_queue_head_t wait_stream; /* Processes waiting */ - struct usbvision_frame *cur_frame; // pointer to current frame, set by usbvision_find_header - struct usbvision_frame frame[USBVISION_NUMFRAMES]; // frame buffer - int num_frames; // number of frames allocated - struct usbvision_sbuf sbuf[USBVISION_NUMSBUF]; // S buffering + struct usbvision_frame *cur_frame; /* pointer to current frame, set by usbvision_find_header */ + struct usbvision_frame frame[USBVISION_NUMFRAMES]; /* frame buffer */ + int num_frames; /* number of frames allocated */ + struct usbvision_sbuf sbuf[USBVISION_NUMSBUF]; /* S buffering */ volatile int remove_pending; /* If set then about to exit */ /* Scratch space from the Isochronous Pipe.*/ @@ -432,32 +432,32 @@ struct usb_usbvision { v4l2_std_id tvnorm_id; /* selected tv norm */ unsigned char video_endp; /* 0x82 for USBVISION devices based */ - // Decompression stuff: + /* Decompression stuff: */ unsigned char *intra_frame_buffer; /* Buffer for reference frame */ - int block_pos; //for test only - int request_intra; // 0 = normal; 1 = intra frame is requested; - int last_isoc_frame_num; // check for lost isoc frames - int isoc_packet_size; // need to calculate used_bandwidth - int used_bandwidth; // used bandwidth 0-100%, need to set compr_level - int compr_level; // How strong (100) or weak (0) is compression - int last_compr_level; // How strong (100) or weak (0) was compression + int block_pos; /* for test only */ + int request_intra; /* 0 = normal; 1 = intra frame is requested; */ + int last_isoc_frame_num; /* check for lost isoc frames */ + int isoc_packet_size; /* need to calculate used_bandwidth */ + int used_bandwidth; /* used bandwidth 0-100%, need to set compr_level */ + int compr_level; /* How strong (100) or weak (0) is compression */ + int last_compr_level; /* How strong (100) or weak (0) was compression */ int usb_bandwidth; /* Mbit/s */ /* Statistics that can be overlayed on the screen */ - unsigned long isoc_urb_count; // How many URBs we received so far + unsigned long isoc_urb_count; /* How many URBs we received so far */ unsigned long urb_length; /* Length of last URB */ unsigned long isoc_data_count; /* How many bytes we received */ unsigned long header_count; /* How many frame headers we found */ unsigned long scratch_ovf_count; /* How many times we overflowed scratch */ unsigned long isoc_skip_count; /* How many empty ISO packets received */ unsigned long isoc_err_count; /* How many bad ISO packets received */ - unsigned long isoc_packet_count; // How many packets we totally got - unsigned long time_in_irq; // How long do we need for interrupt + unsigned long isoc_packet_count; /* How many packets we totally got */ + unsigned long time_in_irq; /* How long do we need for interrupt */ int isoc_measure_bandwidth_count; - int frame_num; // How many video frames we send to user - int max_strip_len; // How big is the biggest strip + int frame_num; /* How many video frames we send to user */ + int max_strip_len; /* How big is the biggest strip */ int comprblock_pos; - int strip_len_errors; // How many times was block_pos greater than strip_len + int strip_len_errors; /* How many times was block_pos greater than strip_len */ int strip_magic_errors; int strip_line_number_errors; int compr_block_types[4]; -- cgit v0.10.2 From 6d6a48e51fd3bcb40c5b88d0f9690ba960eedfd2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 Dec 2010 13:53:21 -0300 Subject: [media] usbvision: coding style Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c index acfdb2b..68b998b 100644 --- a/drivers/media/video/usbvision/usbvision-cards.c +++ b/drivers/media/video/usbvision/usbvision-cards.c @@ -1026,78 +1026,78 @@ struct usbvision_device_data_st usbvision_device_data[] = { .model_string = "Hauppauge WinTv-USB", }, }; -const int usbvision_device_data_size=ARRAY_SIZE(usbvision_device_data); +const int usbvision_device_data_size = ARRAY_SIZE(usbvision_device_data); /* Supported Devices */ -struct usb_device_id usbvision_table [] = { - { USB_DEVICE(0x0a6f, 0x0400), .driver_info=XANBOO }, - { USB_DEVICE(0x050d, 0x0106), .driver_info=BELKIN_VIDEOBUS_II }, - { USB_DEVICE(0x050d, 0x0207), .driver_info=BELKIN_VIDEOBUS }, - { USB_DEVICE(0x050d, 0x0208), .driver_info=BELKIN_USB_VIDEOBUS_II }, - { USB_DEVICE(0x0571, 0x0002), .driver_info=ECHOFX_INTERVIEW_LITE }, - { USB_DEVICE(0x0573, 0x0003), .driver_info=USBGEAR_USBG_V1 }, - { USB_DEVICE(0x0573, 0x0400), .driver_info=D_LINK_V100 }, - { USB_DEVICE(0x0573, 0x2000), .driver_info=X10_USB_CAMERA }, - { USB_DEVICE(0x0573, 0x2d00), .driver_info=HPG_WINTV_LIVE_PAL_BG }, - { USB_DEVICE(0x0573, 0x2d01), .driver_info=HPG_WINTV_LIVE_PRO_NTSC_MN }, - { USB_DEVICE(0x0573, 0x2101), .driver_info=ZORAN_PMD_NOGATECH }, - { USB_DEVICE(0x0573, 0x4100), .driver_info=NOGATECH_USB_TV_NTSC_FM }, - { USB_DEVICE(0x0573, 0x4110), .driver_info=PNY_USB_TV_NTSC_FM }, - { USB_DEVICE(0x0573, 0x4450), .driver_info=PV_PLAYTV_USB_PRO_PAL_FM }, - { USB_DEVICE(0x0573, 0x4550), .driver_info=ZT_721 }, - { USB_DEVICE(0x0573, 0x4d00), .driver_info=HPG_WINTV_NTSC_MN }, - { USB_DEVICE(0x0573, 0x4d01), .driver_info=HPG_WINTV_PAL_BG }, - { USB_DEVICE(0x0573, 0x4d02), .driver_info=HPG_WINTV_PAL_I }, - { USB_DEVICE(0x0573, 0x4d03), .driver_info=HPG_WINTV_PAL_SECAM_L }, - { USB_DEVICE(0x0573, 0x4d04), .driver_info=HPG_WINTV_PAL_D_K }, - { USB_DEVICE(0x0573, 0x4d10), .driver_info=HPG_WINTV_NTSC_FM }, - { USB_DEVICE(0x0573, 0x4d11), .driver_info=HPG_WINTV_PAL_BG_FM }, - { USB_DEVICE(0x0573, 0x4d12), .driver_info=HPG_WINTV_PAL_I_FM }, - { USB_DEVICE(0x0573, 0x4d14), .driver_info=HPG_WINTV_PAL_D_K_FM }, - { USB_DEVICE(0x0573, 0x4d2a), .driver_info=HPG_WINTV_PRO_NTSC_MN }, - { USB_DEVICE(0x0573, 0x4d2b), .driver_info=HPG_WINTV_PRO_NTSC_MN_V2 }, - { USB_DEVICE(0x0573, 0x4d2c), .driver_info=HPG_WINTV_PRO_PAL }, +struct usb_device_id usbvision_table[] = { + { USB_DEVICE(0x0a6f, 0x0400), .driver_info = XANBOO }, + { USB_DEVICE(0x050d, 0x0106), .driver_info = BELKIN_VIDEOBUS_II }, + { USB_DEVICE(0x050d, 0x0207), .driver_info = BELKIN_VIDEOBUS }, + { USB_DEVICE(0x050d, 0x0208), .driver_info = BELKIN_USB_VIDEOBUS_II }, + { USB_DEVICE(0x0571, 0x0002), .driver_info = ECHOFX_INTERVIEW_LITE }, + { USB_DEVICE(0x0573, 0x0003), .driver_info = USBGEAR_USBG_V1 }, + { USB_DEVICE(0x0573, 0x0400), .driver_info = D_LINK_V100 }, + { USB_DEVICE(0x0573, 0x2000), .driver_info = X10_USB_CAMERA }, + { USB_DEVICE(0x0573, 0x2d00), .driver_info = HPG_WINTV_LIVE_PAL_BG }, + { USB_DEVICE(0x0573, 0x2d01), .driver_info = HPG_WINTV_LIVE_PRO_NTSC_MN }, + { USB_DEVICE(0x0573, 0x2101), .driver_info = ZORAN_PMD_NOGATECH }, + { USB_DEVICE(0x0573, 0x4100), .driver_info = NOGATECH_USB_TV_NTSC_FM }, + { USB_DEVICE(0x0573, 0x4110), .driver_info = PNY_USB_TV_NTSC_FM }, + { USB_DEVICE(0x0573, 0x4450), .driver_info = PV_PLAYTV_USB_PRO_PAL_FM }, + { USB_DEVICE(0x0573, 0x4550), .driver_info = ZT_721 }, + { USB_DEVICE(0x0573, 0x4d00), .driver_info = HPG_WINTV_NTSC_MN }, + { USB_DEVICE(0x0573, 0x4d01), .driver_info = HPG_WINTV_PAL_BG }, + { USB_DEVICE(0x0573, 0x4d02), .driver_info = HPG_WINTV_PAL_I }, + { USB_DEVICE(0x0573, 0x4d03), .driver_info = HPG_WINTV_PAL_SECAM_L }, + { USB_DEVICE(0x0573, 0x4d04), .driver_info = HPG_WINTV_PAL_D_K }, + { USB_DEVICE(0x0573, 0x4d10), .driver_info = HPG_WINTV_NTSC_FM }, + { USB_DEVICE(0x0573, 0x4d11), .driver_info = HPG_WINTV_PAL_BG_FM }, + { USB_DEVICE(0x0573, 0x4d12), .driver_info = HPG_WINTV_PAL_I_FM }, + { USB_DEVICE(0x0573, 0x4d14), .driver_info = HPG_WINTV_PAL_D_K_FM }, + { USB_DEVICE(0x0573, 0x4d2a), .driver_info = HPG_WINTV_PRO_NTSC_MN }, + { USB_DEVICE(0x0573, 0x4d2b), .driver_info = HPG_WINTV_PRO_NTSC_MN_V2 }, + { USB_DEVICE(0x0573, 0x4d2c), .driver_info = HPG_WINTV_PRO_PAL }, { USB_DEVICE(0x0573, 0x4d20), .driver_info = HPG_WINTV_PRO_NTSC_MN_V3 }, - { USB_DEVICE(0x0573, 0x4d21), .driver_info=HPG_WINTV_PRO_PAL_BG }, - { USB_DEVICE(0x0573, 0x4d22), .driver_info=HPG_WINTV_PRO_PAL_I }, - { USB_DEVICE(0x0573, 0x4d23), .driver_info=HPG_WINTV_PRO_PAL_SECAM_L }, - { USB_DEVICE(0x0573, 0x4d24), .driver_info=HPG_WINTV_PRO_PAL_D_K }, - { USB_DEVICE(0x0573, 0x4d25), .driver_info=HPG_WINTV_PRO_PAL_SECAM }, - { USB_DEVICE(0x0573, 0x4d26), .driver_info=HPG_WINTV_PRO_PAL_SECAM_V2 }, - { USB_DEVICE(0x0573, 0x4d27), .driver_info=HPG_WINTV_PRO_PAL_BG_V2 }, - { USB_DEVICE(0x0573, 0x4d28), .driver_info=HPG_WINTV_PRO_PAL_BG_D_K }, - { USB_DEVICE(0x0573, 0x4d29), .driver_info=HPG_WINTV_PRO_PAL_I_D_K }, - { USB_DEVICE(0x0573, 0x4d30), .driver_info=HPG_WINTV_PRO_NTSC_MN_FM }, - { USB_DEVICE(0x0573, 0x4d31), .driver_info=HPG_WINTV_PRO_PAL_BG_FM }, - { USB_DEVICE(0x0573, 0x4d32), .driver_info=HPG_WINTV_PRO_PAL_I_FM }, - { USB_DEVICE(0x0573, 0x4d34), .driver_info=HPG_WINTV_PRO_PAL_D_K_FM }, - { USB_DEVICE(0x0573, 0x4d35), .driver_info=HPG_WINTV_PRO_TEMIC_PAL_FM }, - { USB_DEVICE(0x0573, 0x4d36), .driver_info=HPG_WINTV_PRO_TEMIC_PAL_BG_FM }, - { USB_DEVICE(0x0573, 0x4d37), .driver_info=HPG_WINTV_PRO_PAL_FM }, - { USB_DEVICE(0x0573, 0x4d38), .driver_info=HPG_WINTV_PRO_NTSC_MN_FM_V2 }, - { USB_DEVICE(0x0768, 0x0006), .driver_info=CAMTEL_TVB330 }, - { USB_DEVICE(0x07d0, 0x0001), .driver_info=DIGITAL_VIDEO_CREATOR_I }, - { USB_DEVICE(0x07d0, 0x0002), .driver_info=GLOBAL_VILLAGE_GV_007_NTSC }, - { USB_DEVICE(0x07d0, 0x0003), .driver_info=DAZZLE_DVC_50_REV_1_NTSC }, - { USB_DEVICE(0x07d0, 0x0004), .driver_info=DAZZLE_DVC_80_REV_1_PAL }, - { USB_DEVICE(0x07d0, 0x0005), .driver_info=DAZZLE_DVC_90_REV_1_SECAM }, - { USB_DEVICE(0x07f8, 0x9104), .driver_info=ESKAPE_LABS_MYTV2GO }, - { USB_DEVICE(0x2304, 0x010d), .driver_info=PINNA_PCTV_USB_PAL }, - { USB_DEVICE(0x2304, 0x0109), .driver_info=PINNA_PCTV_USB_SECAM }, - { USB_DEVICE(0x2304, 0x0110), .driver_info=PINNA_PCTV_USB_PAL_FM }, - { USB_DEVICE(0x2304, 0x0111), .driver_info=MIRO_PCTV_USB }, - { USB_DEVICE(0x2304, 0x0112), .driver_info=PINNA_PCTV_USB_NTSC_FM }, + { USB_DEVICE(0x0573, 0x4d21), .driver_info = HPG_WINTV_PRO_PAL_BG }, + { USB_DEVICE(0x0573, 0x4d22), .driver_info = HPG_WINTV_PRO_PAL_I }, + { USB_DEVICE(0x0573, 0x4d23), .driver_info = HPG_WINTV_PRO_PAL_SECAM_L }, + { USB_DEVICE(0x0573, 0x4d24), .driver_info = HPG_WINTV_PRO_PAL_D_K }, + { USB_DEVICE(0x0573, 0x4d25), .driver_info = HPG_WINTV_PRO_PAL_SECAM }, + { USB_DEVICE(0x0573, 0x4d26), .driver_info = HPG_WINTV_PRO_PAL_SECAM_V2 }, + { USB_DEVICE(0x0573, 0x4d27), .driver_info = HPG_WINTV_PRO_PAL_BG_V2 }, + { USB_DEVICE(0x0573, 0x4d28), .driver_info = HPG_WINTV_PRO_PAL_BG_D_K }, + { USB_DEVICE(0x0573, 0x4d29), .driver_info = HPG_WINTV_PRO_PAL_I_D_K }, + { USB_DEVICE(0x0573, 0x4d30), .driver_info = HPG_WINTV_PRO_NTSC_MN_FM }, + { USB_DEVICE(0x0573, 0x4d31), .driver_info = HPG_WINTV_PRO_PAL_BG_FM }, + { USB_DEVICE(0x0573, 0x4d32), .driver_info = HPG_WINTV_PRO_PAL_I_FM }, + { USB_DEVICE(0x0573, 0x4d34), .driver_info = HPG_WINTV_PRO_PAL_D_K_FM }, + { USB_DEVICE(0x0573, 0x4d35), .driver_info = HPG_WINTV_PRO_TEMIC_PAL_FM }, + { USB_DEVICE(0x0573, 0x4d36), .driver_info = HPG_WINTV_PRO_TEMIC_PAL_BG_FM }, + { USB_DEVICE(0x0573, 0x4d37), .driver_info = HPG_WINTV_PRO_PAL_FM }, + { USB_DEVICE(0x0573, 0x4d38), .driver_info = HPG_WINTV_PRO_NTSC_MN_FM_V2 }, + { USB_DEVICE(0x0768, 0x0006), .driver_info = CAMTEL_TVB330 }, + { USB_DEVICE(0x07d0, 0x0001), .driver_info = DIGITAL_VIDEO_CREATOR_I }, + { USB_DEVICE(0x07d0, 0x0002), .driver_info = GLOBAL_VILLAGE_GV_007_NTSC }, + { USB_DEVICE(0x07d0, 0x0003), .driver_info = DAZZLE_DVC_50_REV_1_NTSC }, + { USB_DEVICE(0x07d0, 0x0004), .driver_info = DAZZLE_DVC_80_REV_1_PAL }, + { USB_DEVICE(0x07d0, 0x0005), .driver_info = DAZZLE_DVC_90_REV_1_SECAM }, + { USB_DEVICE(0x07f8, 0x9104), .driver_info = ESKAPE_LABS_MYTV2GO }, + { USB_DEVICE(0x2304, 0x010d), .driver_info = PINNA_PCTV_USB_PAL }, + { USB_DEVICE(0x2304, 0x0109), .driver_info = PINNA_PCTV_USB_SECAM }, + { USB_DEVICE(0x2304, 0x0110), .driver_info = PINNA_PCTV_USB_PAL_FM }, + { USB_DEVICE(0x2304, 0x0111), .driver_info = MIRO_PCTV_USB }, + { USB_DEVICE(0x2304, 0x0112), .driver_info = PINNA_PCTV_USB_NTSC_FM }, { USB_DEVICE(0x2304, 0x0113), .driver_info = PINNA_PCTV_USB_NTSC_FM_V3 }, - { USB_DEVICE(0x2304, 0x0210), .driver_info=PINNA_PCTV_USB_PAL_FM_V2 }, - { USB_DEVICE(0x2304, 0x0212), .driver_info=PINNA_PCTV_USB_NTSC_FM_V2 }, - { USB_DEVICE(0x2304, 0x0214), .driver_info=PINNA_PCTV_USB_PAL_FM_V3 }, - { USB_DEVICE(0x2304, 0x0300), .driver_info=PINNA_LINX_VD_IN_CAB_NTSC }, - { USB_DEVICE(0x2304, 0x0301), .driver_info=PINNA_LINX_VD_IN_CAB_PAL }, - { USB_DEVICE(0x2304, 0x0419), .driver_info=PINNA_PCTV_BUNGEE_PAL_FM }, - { USB_DEVICE(0x2400, 0x4200), .driver_info=HPG_WINTV }, + { USB_DEVICE(0x2304, 0x0210), .driver_info = PINNA_PCTV_USB_PAL_FM_V2 }, + { USB_DEVICE(0x2304, 0x0212), .driver_info = PINNA_PCTV_USB_NTSC_FM_V2 }, + { USB_DEVICE(0x2304, 0x0214), .driver_info = PINNA_PCTV_USB_PAL_FM_V3 }, + { USB_DEVICE(0x2304, 0x0300), .driver_info = PINNA_LINX_VD_IN_CAB_NTSC }, + { USB_DEVICE(0x2304, 0x0301), .driver_info = PINNA_LINX_VD_IN_CAB_PAL }, + { USB_DEVICE(0x2304, 0x0419), .driver_info = PINNA_PCTV_BUNGEE_PAL_FM }, + { USB_DEVICE(0x2400, 0x4200), .driver_info = HPG_WINTV }, { }, /* terminate list */ }; -MODULE_DEVICE_TABLE (usb, usbvision_table); +MODULE_DEVICE_TABLE(usb, usbvision_table); diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index 64a9133..c8feb0d 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include @@ -46,12 +46,12 @@ #include "usbvision.h" static unsigned int core_debug; -module_param(core_debug,int,0644); -MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); +module_param(core_debug, int, 0644); +MODULE_PARM_DESC(core_debug, "enable debug messages [core]"); static unsigned int force_testpattern; -module_param(force_testpattern,int,0644); -MODULE_PARM_DESC(force_testpattern,"enable test pattern display [core]"); +module_param(force_testpattern, int, 0644); +MODULE_PARM_DESC(force_testpattern, "enable test pattern display [core]"); static int adjust_compression = 1; /* Set the compression to be adaptive */ module_param(adjust_compression, int, 0444); @@ -82,15 +82,15 @@ MODULE_PARM_DESC(adjust_y_offset, "adjust Y offset display [core]"); __func__, __LINE__ , ## args); \ } #else - #define PDEBUG(level, fmt, args...) do {} while(0) + #define PDEBUG(level, fmt, args...) do {} while (0) #endif -#define DBG_HEADER 1<<0 -#define DBG_IRQ 1<<1 -#define DBG_ISOC 1<<2 -#define DBG_PARSE 1<<3 -#define DBG_SCRATCH 1<<4 -#define DBG_FUNC 1<<5 +#define DBG_HEADER (1 << 0) +#define DBG_IRQ (1 << 1) +#define DBG_ISOC (1 << 2) +#define DBG_PARSE (1 << 3) +#define DBG_SCRATCH (1 << 4) +#define DBG_FUNC (1 << 5) static const int max_imgwidth = MAX_FRAME_WIDTH; static const int max_imgheight = MAX_FRAME_HEIGHT; @@ -107,10 +107,10 @@ static const int min_imgheight = MIN_FRAME_HEIGHT; static const int scratch_buf_size = DEFAULT_SCRATCH_BUF_SIZE; /* Function prototypes */ -static int usbvision_request_intra (struct usb_usbvision *usbvision); -static int usbvision_unrequest_intra (struct usb_usbvision *usbvision); -static int usbvision_adjust_compression (struct usb_usbvision *usbvision); -static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision); +static int usbvision_request_intra(struct usb_usbvision *usbvision); +static int usbvision_unrequest_intra(struct usb_usbvision *usbvision); +static int usbvision_adjust_compression(struct usb_usbvision *usbvision); +static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision); /*******************************/ /* Memory management functions */ @@ -176,7 +176,7 @@ static void usbvision_hexdump(const unsigned char *data, int len) k += sprintf(&tmp[k], "%02x ", data[i]); } if (k > 0) - printk("%s\n", tmp); + printk(KERN_CONT "%s\n", tmp); } #endif @@ -186,9 +186,9 @@ static void usbvision_hexdump(const unsigned char *data, int len) static int scratch_len(struct usb_usbvision *usbvision) /* This returns the amount of data actually in the buffer */ { int len = usbvision->scratch_write_ptr - usbvision->scratch_read_ptr; - if (len < 0) { + + if (len < 0) len += scratch_buf_size; - } PDEBUG(DBG_SCRATCH, "scratch_len() = %d\n", len); return len; @@ -199,9 +199,8 @@ static int scratch_len(struct usb_usbvision *usbvision) /* This returns the a static int scratch_free(struct usb_usbvision *usbvision) { int free = usbvision->scratch_read_ptr - usbvision->scratch_write_ptr; - if (free <= 0) { + if (free <= 0) free += scratch_buf_size; - } if (free) { free -= 1; /* at least one byte in the buffer must */ /* left blank, otherwise there is no chance to differ between full and empty */ @@ -221,14 +220,12 @@ static int scratch_put(struct usb_usbvision *usbvision, unsigned char *data, if (usbvision->scratch_write_ptr + len < scratch_buf_size) { memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len); usbvision->scratch_write_ptr += len; - } - else { + } else { len_part = scratch_buf_size - usbvision->scratch_write_ptr; memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len_part); if (len == len_part) { usbvision->scratch_write_ptr = 0; /* just set write_ptr to zero */ - } - else { + } else { memcpy(usbvision->scratch, data + len_part, len - len_part); usbvision->scratch_write_ptr = len - len_part; } @@ -255,17 +252,16 @@ static int scratch_get_extra(struct usb_usbvision *usbvision, unsigned char *data, int *ptr, int len) { int len_part; + if (*ptr + len < scratch_buf_size) { memcpy(data, usbvision->scratch + *ptr, len); *ptr += len; - } - else { + } else { len_part = scratch_buf_size - *ptr; memcpy(data, usbvision->scratch + *ptr, len_part); if (len == len_part) { *ptr = 0; /* just set the y_ptr to zero */ - } - else { + } else { memcpy(data + len_part, usbvision->scratch, len - len_part); *ptr = len - len_part; } @@ -281,7 +277,7 @@ static int scratch_get_extra(struct usb_usbvision *usbvision, static void scratch_set_extra_ptr(struct usb_usbvision *usbvision, int *ptr, int len) { - *ptr = (usbvision->scratch_read_ptr + len)%scratch_buf_size; + *ptr = (usbvision->scratch_read_ptr + len) % scratch_buf_size; PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr); } @@ -301,17 +297,16 @@ static int scratch_get(struct usb_usbvision *usbvision, unsigned char *data, int len) { int len_part; + if (usbvision->scratch_read_ptr + len < scratch_buf_size) { memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len); usbvision->scratch_read_ptr += len; - } - else { + } else { len_part = scratch_buf_size - usbvision->scratch_read_ptr; memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len_part); if (len == len_part) { usbvision->scratch_read_ptr = 0; /* just set the read_ptr to zero */ - } - else { + } else { memcpy(data + len_part, usbvision->scratch, len - len_part); usbvision->scratch_read_ptr = len - len_part; } @@ -355,7 +350,6 @@ static int scratch_get_header(struct usb_usbvision *usbvision, /* This removes len bytes of old data from the buffer */ static void scratch_rm_old(struct usb_usbvision *usbvision, int len) { - usbvision->scratch_read_ptr += len; usbvision->scratch_read_ptr %= scratch_buf_size; PDEBUG(DBG_SCRATCH, "read_ptr is now %d\n", usbvision->scratch_read_ptr); @@ -378,7 +372,7 @@ int usbvision_scratch_alloc(struct usb_usbvision *usbvision) { usbvision->scratch = vmalloc_32(scratch_buf_size); scratch_reset(usbvision); - if(usbvision->scratch == NULL) { + if (usbvision->scratch == NULL) { dev_err(&usbvision->dev->dev, "%s: unable to allocate %d bytes for scratch\n", __func__, scratch_buf_size); @@ -391,7 +385,6 @@ void usbvision_scratch_free(struct usb_usbvision *usbvision) { vfree(usbvision->scratch); usbvision->scratch = NULL; - } /* @@ -476,7 +469,6 @@ static void usbvision_testpattern(struct usb_usbvision *usbvision, frame->grabstate = frame_state_done; frame->scanlength += scan_length; ++num_pass; - } /* @@ -487,6 +479,7 @@ static void usbvision_testpattern(struct usb_usbvision *usbvision, int usbvision_decompress_alloc(struct usb_usbvision *usbvision) { int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2; + usbvision->intra_frame_buffer = vmalloc_32(IFB_size); if (usbvision->intra_frame_buffer == NULL) { dev_err(&usbvision->dev->dev, @@ -545,8 +538,7 @@ static enum parse_state usbvision_find_header(struct usb_usbvision *usbvision) usbvision_unrequest_intra(usbvision); break; } - } - else { + } else { found_header = 1; break; } @@ -555,16 +547,15 @@ static enum parse_state usbvision_find_header(struct usb_usbvision *usbvision) if (found_header) { frame->frmwidth = frame->isoc_header.frame_width * usbvision->stretch_width; frame->frmheight = frame->isoc_header.frame_height * usbvision->stretch_height; - frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth)>> 3; - } - else { /* no header found */ + frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth) >> 3; + } else { /* no header found */ PDEBUG(DBG_HEADER, "skipping scratch data, no header"); scratch_reset(usbvision); return parse_state_end_parse; } /* found header */ - if (frame->isoc_header.data_format==ISOC_MODE_COMPRESS) { + if (frame->isoc_header.data_format == ISOC_MODE_COMPRESS) { /* check isoc_header.frame_num for lost frames */ if (usbvision->last_isoc_frame_num >= 0) { if (((usbvision->last_isoc_frame_num + 1) % 32) != frame->isoc_header.frame_num) { @@ -594,7 +585,7 @@ static enum parse_state usbvision_parse_lines_422(struct usb_usbvision *usbvisio unsigned char *f; int len; int i; - unsigned char yuyv[4]={180, 128, 10, 128}; /* YUV components */ + unsigned char yuyv[4] = { 180, 128, 10, 128 }; /* YUV components */ unsigned char rv, gv, bv; /* RGB components */ int clipmask_index, bytes_per_pixel; int stretch_bytes, clipmask_add; @@ -603,31 +594,27 @@ static enum parse_state usbvision_parse_lines_422(struct usb_usbvision *usbvisio f = frame->data + (frame->v4l2_linesize * frame->curline); /* Make sure there's enough data for the entire line */ - len = (frame->isoc_header.frame_width * 2)+5; + len = (frame->isoc_header.frame_width * 2) + 5; if (scratch_len(usbvision) < len) { PDEBUG(DBG_PARSE, "out of data in line %d, need %u.\n", frame->curline, len); return parse_state_out; } - if ((frame->curline + 1) >= frame->frmheight) { + if ((frame->curline + 1) >= frame->frmheight) return parse_state_next_frame; - } bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel; clipmask_index = frame->curline * MAX_FRAME_WIDTH; clipmask_add = usbvision->stretch_width; - for (i = 0; i < frame->frmwidth; i+=(2 * usbvision->stretch_width)) { - + for (i = 0; i < frame->frmwidth; i += (2 * usbvision->stretch_width)) { scratch_get(usbvision, &yuyv[0], 4); if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { *f++ = yuyv[0]; /* Y */ *f++ = yuyv[3]; /* U */ - } - else { - + } else { YUV_TO_RGB_BY_THE_BOOK(yuyv[0], yuyv[1], yuyv[3], rv, gv, bv); switch (frame->v4l2_format.format) { case V4L2_PIX_FMT_RGB565: @@ -661,9 +648,7 @@ static enum parse_state usbvision_parse_lines_422(struct usb_usbvision *usbvisio if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { *f++ = yuyv[2]; /* Y */ *f++ = yuyv[1]; /* V */ - } - else { - + } else { YUV_TO_RGB_BY_THE_BOOK(yuyv[2], yuyv[1], yuyv[3], rv, gv, bv); switch (frame->v4l2_format.format) { case V4L2_PIX_FMT_RGB565: @@ -698,16 +683,13 @@ static enum parse_state usbvision_parse_lines_422(struct usb_usbvision *usbvisio frame->curline += usbvision->stretch_height; *pcopylen += frame->v4l2_linesize * usbvision->stretch_height; - if (frame->curline >= frame->frmheight) { + if (frame->curline >= frame->frmheight) return parse_state_next_frame; - } - else { - return parse_state_continue; - } + return parse_state_continue; } /* The decompression routine */ -static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *compressed, +static int usbvision_decompress(struct usb_usbvision *usbvision, unsigned char *compressed, unsigned char *decompressed, int *start_pos, int *block_typestart_pos, int len) { @@ -728,9 +710,8 @@ static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *c rest_pixel = len; for (idx = 0; idx < len; idx++) { - if (block_len == 0) { - if (block_type_len==0) { + if (block_type_len == 0) { block_type_byte = compressed[block_type_pos]; block_type_pos++; block_type_len = 4; @@ -742,7 +723,7 @@ static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *c pos = extra_pos; if (block_type == 0) { - if(rest_pixel >= 24) { + if (rest_pixel >= 24) { idx += 23; rest_pixel -= 24; integrator = decompressed[idx]; @@ -753,11 +734,10 @@ static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *c } else { block_code = compressed[pos]; pos++; - if (rest_pixel >= 24) { + if (rest_pixel >= 24) block_len = 24; - } else { + else block_len = rest_pixel; - } rest_pixel -= block_len; extra_pos = pos + (block_len / 4); } @@ -765,24 +745,23 @@ static int usbvision_decompress(struct usb_usbvision *usbvision,unsigned char *c block_type_len -= 1; } if (block_len > 0) { - if ((block_len%4) == 0) { + if ((block_len % 4) == 0) { block_byte = compressed[pos]; pos++; } - if (block_type == 1) { /* inter Block */ + if (block_type == 1) /* inter Block */ integrator = decompressed[idx]; - } switch (block_byte & 0xC0) { - case 0x03<<6: - integrator += compressed[extra_pos]; - extra_pos++; - break; - case 0x02<<6: - integrator += block_code; - break; - case 0x00: - integrator -= block_code; - break; + case 0x03 << 6: + integrator += compressed[extra_pos]; + extra_pos++; + break; + case 0x02 << 6: + integrator += block_code; + break; + case 0x00: + integrator -= block_code; + break; } decompressed[idx] = integrator; block_byte <<= 2; @@ -811,45 +790,40 @@ static enum parse_state usbvision_parse_compress(struct usb_usbvision *usbvision #define USBVISION_STRIP_HEADER_LEN 3 struct usbvision_frame *frame; - unsigned char *f,*u = NULL ,*v = NULL; + unsigned char *f, *u = NULL, *v = NULL; unsigned char strip_data[USBVISION_STRIP_LEN_MAX]; unsigned char strip_header[USBVISION_STRIP_HEADER_LEN]; - int idx, idx_end, strip_len, strip_ptr, Startblock_pos, block_pos, block_type_pos; + int idx, idx_end, strip_len, strip_ptr, startblock_pos, block_pos, block_type_pos; int clipmask_index, bytes_per_pixel, rc; int image_size; unsigned char rv, gv, bv; static unsigned char *Y, *U, *V; - frame = usbvision->cur_frame; + frame = usbvision->cur_frame; image_size = frame->frmwidth * frame->frmheight; - if ( (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) || - (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) ) { /* this is a planar format */ + if ((frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) || + (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420)) { /* this is a planar format */ /* ... v4l2_linesize not used here. */ f = frame->data + (frame->width * frame->curline); } else f = frame->data + (frame->v4l2_linesize * frame->curline); - if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV){ /* initialise u and v pointers */ + if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { /* initialise u and v pointers */ /* get base of u and b planes add halfoffset */ - u = frame->data + image_size - + (frame->frmwidth >>1) * frame->curline ; - v = u + (image_size >>1 ); - - } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420){ - - v = frame->data + image_size + ((frame->curline* (frame->width))>>2) ; - u = v + (image_size >>2) ; + + (frame->frmwidth >> 1) * frame->curline; + v = u + (image_size >> 1); + } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) { + v = frame->data + image_size + ((frame->curline * (frame->width)) >> 2); + u = v + (image_size >> 2); } - if (frame->curline == 0) { + if (frame->curline == 0) usbvision_adjust_compression(usbvision); - } - if (scratch_len(usbvision) < USBVISION_STRIP_HEADER_LEN) { + if (scratch_len(usbvision) < USBVISION_STRIP_HEADER_LEN) return parse_state_out; - } /* get strip header without changing the scratch_read_ptr */ scratch_set_extra_ptr(usbvision, &strip_ptr, 0); @@ -863,7 +837,7 @@ static enum parse_state usbvision_parse_compress(struct usb_usbvision *usbvision } if (frame->curline != (int)strip_header[2]) { - /* line number missmatch error */ + /* line number mismatch error */ usbvision->strip_line_number_errors++; } @@ -883,8 +857,7 @@ static enum parse_state usbvision_parse_compress(struct usb_usbvision *usbvision Y = usbvision->intra_frame_buffer + frame->frmwidth * frame->curline; U = usbvision->intra_frame_buffer + image_size + (frame->frmwidth / 2) * (frame->curline / 2); V = usbvision->intra_frame_buffer + image_size / 4 * 5 + (frame->frmwidth / 2) * (frame->curline / 2); - } - else { + } else { return parse_state_next_frame; } @@ -895,107 +868,87 @@ static enum parse_state usbvision_parse_compress(struct usb_usbvision *usbvision idx_end = frame->frmwidth; block_type_pos = USBVISION_STRIP_HEADER_LEN; - Startblock_pos = block_type_pos + (idx_end - 1) / 96 + (idx_end / 2 - 1) / 96 + 2; - block_pos = Startblock_pos; + startblock_pos = block_type_pos + (idx_end - 1) / 96 + (idx_end / 2 - 1) / 96 + 2; + block_pos = startblock_pos; usbvision->block_pos = block_pos; - if ((rc = usbvision_decompress(usbvision, strip_data, Y, &block_pos, &block_type_pos, idx_end)) != idx_end) { - /* return parse_state_continue; */ - } - if (strip_len > usbvision->max_strip_len) { + rc = usbvision_decompress(usbvision, strip_data, Y, &block_pos, &block_type_pos, idx_end); + if (strip_len > usbvision->max_strip_len) usbvision->max_strip_len = strip_len; - } - if (frame->curline%2) { - if ((rc = usbvision_decompress(usbvision, strip_data, V, &block_pos, &block_type_pos, idx_end/2)) != idx_end/2) { - /* return parse_state_continue; */ - } - } - else { - if ((rc = usbvision_decompress(usbvision, strip_data, U, &block_pos, &block_type_pos, idx_end/2)) != idx_end/2) { - /* return parse_state_continue; */ - } - } + if (frame->curline % 2) + rc = usbvision_decompress(usbvision, strip_data, V, &block_pos, &block_type_pos, idx_end / 2); + else + rc = usbvision_decompress(usbvision, strip_data, U, &block_pos, &block_type_pos, idx_end / 2); - if (block_pos > usbvision->comprblock_pos) { + if (block_pos > usbvision->comprblock_pos) usbvision->comprblock_pos = block_pos; - } - if (block_pos > strip_len) { + if (block_pos > strip_len) usbvision->strip_len_errors++; - } for (idx = 0; idx < idx_end; idx++) { - if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { + if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { *f++ = Y[idx]; - *f++ = idx & 0x01 ? U[idx/2] : V[idx/2]; - } - else if(frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) { + *f++ = idx & 0x01 ? U[idx / 2] : V[idx / 2]; + } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) { *f++ = Y[idx]; - if ( idx & 0x01) - *u++ = U[idx>>1] ; + if (idx & 0x01) + *u++ = U[idx >> 1]; else - *v++ = V[idx>>1]; - } - else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) { - *f++ = Y [idx]; - if ( !(( idx & 0x01 ) | ( frame->curline & 0x01 )) ){ - -/* only need do this for 1 in 4 pixels */ -/* intraframe buffer is YUV420 format */ - - *u++ = U[idx >>1]; - *v++ = V[idx >>1]; + *v++ = V[idx >> 1]; + } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) { + *f++ = Y[idx]; + if (!((idx & 0x01) | (frame->curline & 0x01))) { + /* only need do this for 1 in 4 pixels */ + /* intraframe buffer is YUV420 format */ + *u++ = U[idx >> 1]; + *v++ = V[idx >> 1]; } - - } - else { - YUV_TO_RGB_BY_THE_BOOK(Y[idx], U[idx/2], V[idx/2], rv, gv, bv); + } else { + YUV_TO_RGB_BY_THE_BOOK(Y[idx], U[idx / 2], V[idx / 2], rv, gv, bv); switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_GREY: - *f++ = Y[idx]; - break; - case V4L2_PIX_FMT_RGB555: - *f++ = (0x1F & rv) | - (0xE0 & (gv << 5)); - *f++ = (0x03 & (gv >> 3)) | - (0x7C & (bv << 2)); - break; - case V4L2_PIX_FMT_RGB565: - *f++ = (0x1F & rv) | - (0xE0 & (gv << 5)); - *f++ = (0x07 & (gv >> 3)) | - (0xF8 & bv); - break; - case V4L2_PIX_FMT_RGB24: - *f++ = rv; - *f++ = gv; - *f++ = bv; - break; - case V4L2_PIX_FMT_RGB32: - *f++ = rv; - *f++ = gv; - *f++ = bv; - f++; - break; + case V4L2_PIX_FMT_GREY: + *f++ = Y[idx]; + break; + case V4L2_PIX_FMT_RGB555: + *f++ = (0x1F & rv) | + (0xE0 & (gv << 5)); + *f++ = (0x03 & (gv >> 3)) | + (0x7C & (bv << 2)); + break; + case V4L2_PIX_FMT_RGB565: + *f++ = (0x1F & rv) | + (0xE0 & (gv << 5)); + *f++ = (0x07 & (gv >> 3)) | + (0xF8 & bv); + break; + case V4L2_PIX_FMT_RGB24: + *f++ = rv; + *f++ = gv; + *f++ = bv; + break; + case V4L2_PIX_FMT_RGB32: + *f++ = rv; + *f++ = gv; + *f++ = bv; + f++; + break; } } clipmask_index++; } /* Deal with non-integer no. of bytes for YUV420P */ - if (frame->v4l2_format.format != V4L2_PIX_FMT_YVU420 ) + if (frame->v4l2_format.format != V4L2_PIX_FMT_YVU420) *pcopylen += frame->v4l2_linesize; else *pcopylen += frame->curline & 0x01 ? frame->v4l2_linesize : frame->v4l2_linesize << 1; frame->curline += 1; - if (frame->curline >= frame->frmheight) { + if (frame->curline >= frame->frmheight) return parse_state_next_frame; - } - else { - return parse_state_continue; - } + return parse_state_continue; } @@ -1016,11 +969,11 @@ static enum parse_state usbvision_parse_lines_420(struct usb_usbvision *usbvisio unsigned int pixel_per_line, block; int pixel, block_split; int y_ptr, u_ptr, v_ptr, y_odd_offset; - const int y_block_size = 128; - const int uv_block_size = 64; + const int y_block_size = 128; + const int uv_block_size = 64; const int sub_block_size = 32; - const int y_step[] = { 0, 0, 0, 2 }, y_step_size = 4; - const int uv_step[]= { 0, 0, 0, 4 }, uv_step_size = 4; + const int y_step[] = { 0, 0, 0, 2 }, y_step_size = 4; + const int uv_step[] = { 0, 0, 0, 4 }, uv_step_size = 4; unsigned char y[2], u, v; /* YUV components */ int y_, u_, v_, vb, uvg, ur; int r_, g_, b_; /* RGB components */ @@ -1047,9 +1000,8 @@ static enum parse_state usbvision_parse_lines_420(struct usb_usbvision *usbvisio return parse_state_out; } - if ((frame->curline + 1) >= frame->frmheight) { + if ((frame->curline + 1) >= frame->frmheight) return parse_state_next_frame; - } block_split = (pixel_per_line%y_block_size) ? 1 : 0; /* are some blocks splitted into different lines? */ @@ -1061,11 +1013,8 @@ static enum parse_state usbvision_parse_lines_420(struct usb_usbvision *usbvisio scratch_set_extra_ptr(usbvision, &v_ptr, y_odd_offset + (4 - block_split) * sub_block_size); - for (block = 0; block < (pixel_per_line / sub_block_size); - block++) { - - - for (pixel = 0; pixel < sub_block_size; pixel +=2) { + for (block = 0; block < (pixel_per_line / sub_block_size); block++) { + for (pixel = 0; pixel < sub_block_size; pixel += 2) { scratch_get(usbvision, &y[0], 2); scratch_get_extra(usbvision, &u, &u_ptr, 1); scratch_get_extra(usbvision, &v, &v_ptr, 1); @@ -1073,19 +1022,18 @@ static enum parse_state usbvision_parse_lines_420(struct usb_usbvision *usbvisio /* I don't use the YUV_TO_RGB macro for better performance */ v_ = v - 128; u_ = u - 128; - vb = 132252 * v_; - uvg= -53281 * u_ - 25625 * v_; + vb = 132252 * v_; + uvg = -53281 * u_ - 25625 * v_; ur = 104595 * u_; - if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { + if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { *f_even++ = y[0]; *f_even++ = v; - } - else { + } else { y_ = 76284 * (y[0] - 16); b_ = (y_ + vb) >> 16; - g_ = (y_ + uvg)>> 16; + g_ = (y_ + uvg) >> 16; r_ = (y_ + ur) >> 16; switch (frame->v4l2_format.format) { @@ -1121,15 +1069,14 @@ static enum parse_state usbvision_parse_lines_420(struct usb_usbvision *usbvisio clipmask_even_index += clipmask_add; f_even += stretch_bytes; - if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { + if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { *f_even++ = y[1]; *f_even++ = u; - } - else { + } else { y_ = 76284 * (y[1] - 16); b_ = (y_ + vb) >> 16; - g_ = (y_ + uvg)>> 16; + g_ = (y_ + uvg) >> 16; r_ = (y_ + ur) >> 16; switch (frame->v4l2_format.format) { @@ -1167,15 +1114,14 @@ static enum parse_state usbvision_parse_lines_420(struct usb_usbvision *usbvisio scratch_get_extra(usbvision, &y[0], &y_ptr, 2); - if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { + if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { *f_odd++ = y[0]; *f_odd++ = v; - } - else { + } else { y_ = 76284 * (y[0] - 16); b_ = (y_ + vb) >> 16; - g_ = (y_ + uvg)>> 16; + g_ = (y_ + uvg) >> 16; r_ = (y_ + ur) >> 16; switch (frame->v4l2_format.format) { @@ -1211,15 +1157,14 @@ static enum parse_state usbvision_parse_lines_420(struct usb_usbvision *usbvisio clipmask_odd_index += clipmask_add; f_odd += stretch_bytes; - if(frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { + if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { *f_odd++ = y[1]; *f_odd++ = u; - } - else { + } else { y_ = 76284 * (y[1] - 16); b_ = (y_ + vb) >> 16; - g_ = (y_ + uvg)>> 16; + g_ = (y_ + uvg) >> 16; r_ = (y_ + ur) >> 16; switch (frame->v4l2_format.format) { @@ -1256,7 +1201,7 @@ static enum parse_state usbvision_parse_lines_420(struct usb_usbvision *usbvisio f_odd += stretch_bytes; } - scratch_rm_old(usbvision,y_step[block % y_step_size] * sub_block_size); + scratch_rm_old(usbvision, y_step[block % y_step_size] * sub_block_size); scratch_inc_extra_ptr(&y_ptr, y_step[(block + 2 * block_split) % y_step_size] * sub_block_size); scratch_inc_extra_ptr(&u_ptr, uv_step[block % uv_step_size] @@ -1273,8 +1218,7 @@ static enum parse_state usbvision_parse_lines_420(struct usb_usbvision *usbvisio if (frame->curline >= frame->frmheight) return parse_state_next_frame; - else - return parse_state_continue; + return parse_state_continue; } /* @@ -1297,34 +1241,24 @@ static void usbvision_parse_data(struct usb_usbvision *usbvision) PDEBUG(DBG_PARSE, "parsing len=%d\n", scratch_len(usbvision)); while (1) { - newstate = parse_state_out; if (scratch_len(usbvision)) { if (frame->scanstate == scan_state_scanning) { newstate = usbvision_find_header(usbvision); - } - else if (frame->scanstate == scan_state_lines) { - if (usbvision->isoc_mode == ISOC_MODE_YUV420) { + } else if (frame->scanstate == scan_state_lines) { + if (usbvision->isoc_mode == ISOC_MODE_YUV420) newstate = usbvision_parse_lines_420(usbvision, ©len); - } - else if (usbvision->isoc_mode == ISOC_MODE_YUV422) { + else if (usbvision->isoc_mode == ISOC_MODE_YUV422) newstate = usbvision_parse_lines_422(usbvision, ©len); - } - else if (usbvision->isoc_mode == ISOC_MODE_COMPRESS) { + else if (usbvision->isoc_mode == ISOC_MODE_COMPRESS) newstate = usbvision_parse_compress(usbvision, ©len); - } - } } - if (newstate == parse_state_continue) { + if (newstate == parse_state_continue) continue; - } - else if ((newstate == parse_state_next_frame) || (newstate == parse_state_out)) { + if ((newstate == parse_state_next_frame) || (newstate == parse_state_out)) break; - } - else { - return; /* parse_state_end_parse */ - } + return; /* parse_state_end_parse */ } if (newstate == parse_state_next_frame) { @@ -1344,10 +1278,9 @@ static void usbvision_parse_data(struct usb_usbvision *usbvision) PDEBUG(DBG_PARSE, "Wake up !"); wake_up_interruptible(&usbvision->wait_frame); } - } - else + } else { frame->grabstate = frame_state_grabbing; - + } /* Update the frame's uncompressed length. */ frame->scanlength += copylen; @@ -1381,14 +1314,12 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, PDEBUG(DBG_ISOC, "error packet [%d]", i); usbvision->isoc_skip_count++; continue; - } - else if (packet_len == 0) { /* Frame end ????? */ + } else if (packet_len == 0) { /* Frame end ????? */ PDEBUG(DBG_ISOC, "null packet [%d]", i); - usbvision->isocstate=isoc_state_no_frame; + usbvision->isocstate = isoc_state_no_frame; usbvision->isoc_skip_count++; continue; - } - else if (packet_len > usbvision->isoc_packet_size) { + } else if (packet_len > usbvision->isoc_packet_size) { PDEBUG(DBG_ISOC, "packet[%d] > isoc_packet_size", i); usbvision->isoc_skip_count++; continue; @@ -1396,8 +1327,8 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, PDEBUG(DBG_ISOC, "packet ok [%d] len=%d", i, packet_len); - if (usbvision->isocstate==isoc_state_no_frame) { /* new frame begins */ - usbvision->isocstate=isoc_state_in_frame; + if (usbvision->isocstate == isoc_state_no_frame) { /* new frame begins */ + usbvision->isocstate = isoc_state_in_frame; scratch_mark_header(usbvision); usbvision_measure_bandwidth(usbvision); PDEBUG(DBG_ISOC, "packet with header"); @@ -1412,7 +1343,6 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, * your favorite evil here. */ if (scratch_free(usbvision) < packet_len) { - usbvision->scratch_ovf_count++; PDEBUG(DBG_ISOC, "scratch buf overflow! scr_len: %d, n: %d", scratch_len(usbvision), packet_len); @@ -1428,6 +1358,7 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, #if ENABLE_HEXDUMP if (totlen > 0) { static int foo; + if (foo < 1) { printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen); usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen); @@ -1435,7 +1366,7 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, } } #endif - return totlen; + return totlen; } static void usbvision_isoc_irq(struct urb *urb) @@ -1452,9 +1383,8 @@ static void usbvision_isoc_irq(struct urb *urb) return; /* any urb with wrong status is ignored without acknowledgement */ - if (urb->status == -ENOENT) { + if (urb->status == -ENOENT) return; - } f = &usbvision->cur_frame; @@ -1476,26 +1406,23 @@ static void usbvision_isoc_irq(struct urb *urb) usbvision->urb_length = len; if (usbvision->streaming == stream_on) { - /* If we collected enough data let's parse! */ - if ((scratch_len(usbvision) > USBVISION_HEADER_LENGTH) && - (!list_empty(&(usbvision->inqueue))) ) { + if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH && + !list_empty(&(usbvision->inqueue))) { if (!(*f)) { (*f) = list_entry(usbvision->inqueue.next, struct usbvision_frame, frame); } usbvision_parse_data(usbvision); - } - else { + } else { /* If we don't have a frame we're current working on, complain */ PDEBUG(DBG_IRQ, "received data, but no one needs it"); scratch_reset(usbvision); } - } - else { + } else { PDEBUG(DBG_IRQ, "received data, but no one needs it"); scratch_reset(usbvision); } @@ -1509,9 +1436,9 @@ static void usbvision_isoc_irq(struct urb *urb) urb->status = 0; urb->dev = usbvision->dev; - err_code = usb_submit_urb (urb, GFP_ATOMIC); + err_code = usb_submit_urb(urb, GFP_ATOMIC); - if(err_code) { + if (err_code) { dev_err(&usbvision->dev->dev, "%s: usb_submit_urb failed: error %d\n", __func__, err_code); @@ -1587,24 +1514,21 @@ static void usbvision_ctrl_urb_complete(struct urb *urb) PDEBUG(DBG_IRQ, ""); usbvision->ctrl_urb_busy = 0; - if (waitqueue_active(&usbvision->ctrl_urb_wq)) { + if (waitqueue_active(&usbvision->ctrl_urb_wq)) wake_up_interruptible(&usbvision->ctrl_urb_wq); - } } -static int usbvision_write_reg_irq(struct usb_usbvision *usbvision,int address, - unsigned char *data, int len) +static int usbvision_write_reg_irq(struct usb_usbvision *usbvision, int address, + unsigned char *data, int len) { int err_code = 0; PDEBUG(DBG_IRQ, ""); - if (len > 8) { + if (len > 8) return -EFAULT; - } - if (usbvision->ctrl_urb_busy) { + if (usbvision->ctrl_urb_busy) return -EBUSY; - } usbvision->ctrl_urb_busy = 1; usbvision->ctrl_urb_setup.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; @@ -1612,7 +1536,7 @@ static int usbvision_write_reg_irq(struct usb_usbvision *usbvision,int address, usbvision->ctrl_urb_setup.wValue = 0; usbvision->ctrl_urb_setup.wIndex = cpu_to_le16(address); usbvision->ctrl_urb_setup.wLength = cpu_to_le16(len); - usb_fill_control_urb (usbvision->ctrl_urb, usbvision->dev, + usb_fill_control_urb(usbvision->ctrl_urb, usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), (unsigned char *)&usbvision->ctrl_urb_setup, (void *)usbvision->ctrl_urb_buffer, len, @@ -1652,7 +1576,7 @@ static int usbvision_init_compression(struct usb_usbvision *usbvision) * return: 0 : no error * sets used_bandwidth to 1-100 : 1-100% of full bandwidth resp. to isoc_packet_size */ -static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision) +static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision) { int err_code = 0; @@ -1672,7 +1596,7 @@ static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision) return err_code; } -static int usbvision_adjust_compression (struct usb_usbvision *usbvision) +static int usbvision_adjust_compression(struct usb_usbvision *usbvision) { int err_code = 0; unsigned char buffer[6]; @@ -1682,29 +1606,29 @@ static int usbvision_adjust_compression (struct usb_usbvision *usbvision) usbvision->compr_level += (usbvision->used_bandwidth - 90) / 2; RESTRICT_TO_RANGE(usbvision->compr_level, 0, 100); if (usbvision->compr_level != usbvision->last_compr_level) { - int distorsion; + int distortion; + if (usbvision->bridge_type == BRIDGE_NT1004 || usbvision->bridge_type == BRIDGE_NT1005) { buffer[0] = (unsigned char)(4 + 16 * usbvision->compr_level / 100); /* PCM Threshold 1 */ buffer[1] = (unsigned char)(4 + 8 * usbvision->compr_level / 100); /* PCM Threshold 2 */ - distorsion = 7 + 248 * usbvision->compr_level / 100; - buffer[2] = (unsigned char)(distorsion & 0xFF); /* Average distorsion Threshold (inter) */ - buffer[3] = (unsigned char)(distorsion & 0xFF); /* Average distorsion Threshold (intra) */ - distorsion = 1 + 42 * usbvision->compr_level / 100; - buffer[4] = (unsigned char)(distorsion & 0xFF); /* Maximum distorsion Threshold (inter) */ - buffer[5] = (unsigned char)(distorsion & 0xFF); /* Maximum distorsion Threshold (intra) */ - } - else { /* BRIDGE_NT1003 */ + distortion = 7 + 248 * usbvision->compr_level / 100; + buffer[2] = (unsigned char)(distortion & 0xFF); /* Average distortion Threshold (inter) */ + buffer[3] = (unsigned char)(distortion & 0xFF); /* Average distortion Threshold (intra) */ + distortion = 1 + 42 * usbvision->compr_level / 100; + buffer[4] = (unsigned char)(distortion & 0xFF); /* Maximum distortion Threshold (inter) */ + buffer[5] = (unsigned char)(distortion & 0xFF); /* Maximum distortion Threshold (intra) */ + } else { /* BRIDGE_NT1003 */ buffer[0] = (unsigned char)(4 + 16 * usbvision->compr_level / 100); /* PCM threshold 1 */ buffer[1] = (unsigned char)(4 + 8 * usbvision->compr_level / 100); /* PCM threshold 2 */ - distorsion = 2 + 253 * usbvision->compr_level / 100; - buffer[2] = (unsigned char)(distorsion & 0xFF); /* distorsion threshold bit0-7 */ - buffer[3] = 0; /* (unsigned char)((distorsion >> 8) & 0x0F); distorsion threshold bit 8-11 */ - distorsion = 0 + 43 * usbvision->compr_level / 100; - buffer[4] = (unsigned char)(distorsion & 0xFF); /* maximum distorsion bit0-7 */ - buffer[5] = 0; /* (unsigned char)((distorsion >> 8) & 0x01); maximum distorsion bit 8 */ + distortion = 2 + 253 * usbvision->compr_level / 100; + buffer[2] = (unsigned char)(distortion & 0xFF); /* distortion threshold bit0-7 */ + buffer[3] = 0; /* (unsigned char)((distortion >> 8) & 0x0F); distortion threshold bit 8-11 */ + distortion = 0 + 43 * usbvision->compr_level / 100; + buffer[4] = (unsigned char)(distortion & 0xFF); /* maximum distortion bit0-7 */ + buffer[5] = 0; /* (unsigned char)((distortion >> 8) & 0x01); maximum distortion bit 8 */ } err_code = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6); - if (err_code == 0){ + if (err_code == 0) { PDEBUG(DBG_IRQ, "new compr params %#02x %#02x %#02x %#02x %#02x %#02x", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); usbvision->last_compr_level = usbvision->compr_level; @@ -1714,7 +1638,7 @@ static int usbvision_adjust_compression (struct usb_usbvision *usbvision) return err_code; } -static int usbvision_request_intra (struct usb_usbvision *usbvision) +static int usbvision_request_intra(struct usb_usbvision *usbvision) { int err_code = 0; unsigned char buffer[1]; @@ -1726,7 +1650,7 @@ static int usbvision_request_intra (struct usb_usbvision *usbvision) return err_code; } -static int usbvision_unrequest_intra (struct usb_usbvision *usbvision) +static int usbvision_unrequest_intra(struct usb_usbvision *usbvision) { int err_code = 0; unsigned char buffer[1]; @@ -1749,10 +1673,9 @@ int usbvision_power_off(struct usb_usbvision *usbvision) PDEBUG(DBG_FUNC, ""); err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); - if (err_code == 1) { + if (err_code == 1) usbvision->power = 0; - } - PDEBUG(DBG_FUNC, "%s: err_code %d", (err_code!=1)?"ERROR":"power is off", err_code); + PDEBUG(DBG_FUNC, "%s: err_code %d", (err_code != 1) ? "ERROR" : "power is off", err_code); return err_code; } @@ -1804,18 +1727,16 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width, { int err_code = 0; int usb_width, usb_height; - unsigned int frame_rate=0, frame_drop=0; + unsigned int frame_rate = 0, frame_drop = 0; unsigned char value[4]; - if (!USBVISION_IS_OPERATIONAL(usbvision)) { + if (!USBVISION_IS_OPERATIONAL(usbvision)) return 0; - } if (width > MAX_USB_WIDTH) { usb_width = width / 2; usbvision->stretch_width = 2; - } - else { + } else { usb_width = width; usbvision->stretch_width = 1; } @@ -1823,8 +1744,7 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width, if (height > MAX_USB_HEIGHT) { usb_height = height / 2; usbvision->stretch_height = 2; - } - else { + } else { usb_height = height; usbvision->stretch_height = 1; } @@ -1859,28 +1779,23 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width, usbvision->curheight = usbvision->stretch_height * usb_height; } - if (usbvision->isoc_mode == ISOC_MODE_YUV422) { + if (usbvision->isoc_mode == ISOC_MODE_YUV422) frame_rate = (usbvision->isoc_packet_size * 1000) / (usb_width * usb_height * 2); - } - else if (usbvision->isoc_mode == ISOC_MODE_YUV420) { + else if (usbvision->isoc_mode == ISOC_MODE_YUV420) frame_rate = (usbvision->isoc_packet_size * 1000) / ((usb_width * usb_height * 12) / 8); - } - else { + else frame_rate = FRAMERATE_MAX; - } - if (usbvision->tvnorm_id & V4L2_STD_625_50) { + if (usbvision->tvnorm_id & V4L2_STD_625_50) frame_drop = frame_rate * 32 / 25 - 1; - } - else if (usbvision->tvnorm_id & V4L2_STD_525_60) { + else if (usbvision->tvnorm_id & V4L2_STD_525_60) frame_drop = frame_rate * 32 / 30 - 1; - } RESTRICT_TO_RANGE(frame_drop, FRAMERATE_MIN, FRAMERATE_MAX); PDEBUG(DBG_FUNC, "frame_rate %d fps, frame_drop %d", frame_rate, frame_drop); - frame_drop = FRAMERATE_MAX; /* We can allow the maximum here, because dropping is controlled */ + frame_drop = FRAMERATE_MAX; /* We can allow the maximum here, because dropping is controlled */ /* frame_drop = 7; => frame_phase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ... => frame_skip = 4; @@ -1904,7 +1819,7 @@ int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames int i; /* needs to be page aligned cause the buffers can be mapped individually! */ - usbvision->max_frame_size = PAGE_ALIGN(usbvision->curwidth * + usbvision->max_frame_size = PAGE_ALIGN(usbvision->curwidth * usbvision->curheight * usbvision->palette.bytes_per_pixel); @@ -1912,9 +1827,9 @@ int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames usbvision->num_frames = number_of_frames; while (usbvision->num_frames > 0) { usbvision->fbuf_size = usbvision->num_frames * usbvision->max_frame_size; - if((usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size))) { + usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size); + if (usbvision->fbuf) break; - } usbvision->num_frames--; } @@ -1937,7 +1852,8 @@ int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames usbvision->frame[i].height = usbvision->curheight; usbvision->frame[i].bytes_read = 0; } - PDEBUG(DBG_FUNC, "allocated %d frames (%d bytes per frame)",usbvision->num_frames,usbvision->max_frame_size); + PDEBUG(DBG_FUNC, "allocated %d frames (%d bytes per frame)", + usbvision->num_frames, usbvision->max_frame_size); return usbvision->num_frames; } @@ -1948,7 +1864,7 @@ int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames void usbvision_frames_free(struct usb_usbvision *usbvision) { /* Have to free all that memory */ - PDEBUG(DBG_FUNC, "free %d frames",usbvision->num_frames); + PDEBUG(DBG_FUNC, "free %d frames", usbvision->num_frames); if (usbvision->fbuf != NULL) { usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size); @@ -2033,18 +1949,17 @@ static int usbvision_set_compress_params(struct usb_usbvision *usbvision) if (usbvision->bridge_type == BRIDGE_NT1004) { value[0] = 20; /* PCM Threshold 1 */ value[1] = 12; /* PCM Threshold 2 */ - value[2] = 255; /* Distorsion Threshold inter */ - value[3] = 255; /* Distorsion Threshold intra */ - value[4] = 43; /* Max Distorsion inter */ - value[5] = 43; /* Max Distorsion intra */ - } - else { + value[2] = 255; /* Distortion Threshold inter */ + value[3] = 255; /* Distortion Threshold intra */ + value[4] = 43; /* Max Distortion inter */ + value[5] = 43; /* Max Distortion intra */ + } else { value[0] = 20; /* PCM Threshold 1 */ value[1] = 12; /* PCM Threshold 2 */ - value[2] = 255; /* Distorsion Threshold d7-d0 */ - value[3] = 0; /* Distorsion Threshold d11-d8 */ - value[4] = 43; /* Max Distorsion d7-d0 */ - value[5] = 0; /* Max Distorsion d8 */ + value[2] = 255; /* Distortion Threshold d7-d0 */ + value[3] = 0; /* Distortion Threshold d11-d8 */ + value[4] = 43; /* Max Distortion d7-d0 */ + value[5] = 0; /* Max Distortion d8 */ } if (!USBVISION_IS_OPERATIONAL(usbvision)) @@ -2059,10 +1974,7 @@ static int usbvision_set_compress_params(struct usb_usbvision *usbvision) if (rc < 0) { printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " "reconnect or reload driver.\n", proc, rc); - return rc; } - - return rc; } @@ -2087,7 +1999,7 @@ int usbvision_set_input(struct usb_usbvision *usbvision) /* Set input format expected from decoder*/ if (usbvision_device_data[usbvision->dev_model].vin_reg1_override) { value[0] = usbvision_device_data[usbvision->dev_model].vin_reg1; - } else if(usbvision_device_data[usbvision->dev_model].codec == CODEC_SAA7113) { + } else if (usbvision_device_data[usbvision->dev_model].codec == CODEC_SAA7113) { /* SAA7113 uses 8 bit output */ value[0] = USBVISION_8_422_SYNC; } else { @@ -2135,8 +2047,8 @@ int usbvision_set_input(struct usb_usbvision *usbvision) } if (usbvision_device_data[usbvision->dev_model].x_offset >= 0) { - value[4]=usbvision_device_data[usbvision->dev_model].x_offset & 0xff; - value[5]=(usbvision_device_data[usbvision->dev_model].x_offset & 0x0300) >> 8; + value[4] = usbvision_device_data[usbvision->dev_model].x_offset & 0xff; + value[5] = (usbvision_device_data[usbvision->dev_model].x_offset & 0x0300) >> 8; } if (adjust_x_offset != -1) { @@ -2145,8 +2057,8 @@ int usbvision_set_input(struct usb_usbvision *usbvision) } if (usbvision_device_data[usbvision->dev_model].y_offset >= 0) { - value[6]=usbvision_device_data[usbvision->dev_model].y_offset & 0xff; - value[7]=(usbvision_device_data[usbvision->dev_model].y_offset & 0x0300) >> 8; + value[6] = usbvision_device_data[usbvision->dev_model].y_offset & 0xff; + value[7] = (usbvision_device_data[usbvision->dev_model].y_offset & 0x0300) >> 8; } if (adjust_y_offset != -1) { @@ -2167,15 +2079,14 @@ int usbvision_set_input(struct usb_usbvision *usbvision) dvi_yuv_value = 0x00; /* U comes after V, Ya comes after U/V, Yb comes after Yb */ - if(usbvision_device_data[usbvision->dev_model].dvi_yuv_override){ + if (usbvision_device_data[usbvision->dev_model].dvi_yuv_override) { dvi_yuv_value = usbvision_device_data[usbvision->dev_model].dvi_yuv; - } - else if(usbvision_device_data[usbvision->dev_model].codec == CODEC_SAA7113) { - /* This changes as the fine sync control changes. Further investigation necessary */ + } else if (usbvision_device_data[usbvision->dev_model].codec == CODEC_SAA7113) { + /* This changes as the fine sync control changes. Further investigation necessary */ dvi_yuv_value = 0x06; } - return (usbvision_write_reg(usbvision, USBVISION_DVI_YUV, dvi_yuv_value)); + return usbvision_write_reg(usbvision, USBVISION_DVI_YUV, dvi_yuv_value); } @@ -2204,8 +2115,7 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) /* UR: 0x0E200-0x3FFFF = 204288 Words (1 Word = 2 Byte) */ /* FDL: 0x00000-0x0E099 = 57498 Words */ /* VDW: 0x0E3FF-0x3FFFF */ - } - else { + } else { value[0] = 0x42; value[1] = 0x00; value[2] = 0xff; @@ -2218,14 +2128,14 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) /* These are the values of the address of the video buffer, * they have to be loaded into the USBVISION_DRM_PRM1-8 * - * Start address of video output buffer for read: drm_prm1-2 -> 0x00000 - * End address of video output buffer for read: drm_prm1-3 -> 0x1ffff - * Start address of video frame delay buffer: drm_prm1-4 -> 0x20000 + * Start address of video output buffer for read: drm_prm1-2 -> 0x00000 + * End address of video output buffer for read: drm_prm1-3 -> 0x1ffff + * Start address of video frame delay buffer: drm_prm1-4 -> 0x20000 * Only used in compressed mode - * End address of video frame delay buffer: drm_prm1-5-6 -> 0x3ffff + * End address of video frame delay buffer: drm_prm1-5-6 -> 0x3ffff * Only used in compressed mode - * Start address of video output buffer for write: drm_prm1-7 -> 0x00000 - * End address of video output buffer for write: drm_prm1-8 -> 0x1ffff + * Start address of video output buffer for write: drm_prm1-7 -> 0x00000 + * End address of video output buffer for write: drm_prm1-8 -> 0x1ffff */ if (!USBVISION_IS_OPERATIONAL(usbvision)) @@ -2243,8 +2153,9 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) } /* Restart the video buffer logic */ - if ((rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, USBVISION_RES_UR | - USBVISION_RES_FDL | USBVISION_RES_VDW)) < 0) + rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, USBVISION_RES_UR | + USBVISION_RES_FDL | USBVISION_RES_VDW); + if (rc < 0) return rc; rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, 0x00); @@ -2267,16 +2178,15 @@ int usbvision_power_on(struct usb_usbvision *usbvision) usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); usbvision_write_reg(usbvision, USBVISION_PWR_REG, - USBVISION_SSPND_EN | USBVISION_RES2); + USBVISION_SSPND_EN | USBVISION_RES2); usbvision_write_reg(usbvision, USBVISION_PWR_REG, - USBVISION_SSPND_EN | USBVISION_PWR_VID); + USBVISION_SSPND_EN | USBVISION_PWR_VID); err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG, - USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2); - if (err_code == 1) { + USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2); + if (err_code == 1) usbvision->power = 1; - } - PDEBUG(DBG_FUNC, "%s: err_code %d", (err_code<0)?"ERROR":"power is on", err_code); + PDEBUG(DBG_FUNC, "%s: err_code %d", (err_code < 0) ? "ERROR" : "power is on", err_code); return err_code; } @@ -2294,7 +2204,7 @@ static void call_usbvision_power_off(struct work_struct *work) if (mutex_lock_interruptible(&usbvision->v4l2_lock)) return; - if(usbvision->user == 0) { + if (usbvision->user == 0) { usbvision_i2c_unregister(usbvision); usbvision_power_off(usbvision); @@ -2305,7 +2215,7 @@ static void call_usbvision_power_off(struct work_struct *work) static void usbvision_power_off_timer(unsigned long data) { - struct usb_usbvision *usbvision = (void *) data; + struct usb_usbvision *usbvision = (void *)data; PDEBUG(DBG_FUNC, ""); del_timer(&usbvision->power_off_timer); @@ -2316,7 +2226,7 @@ static void usbvision_power_off_timer(unsigned long data) void usbvision_init_power_off_timer(struct usb_usbvision *usbvision) { init_timer(&usbvision->power_off_timer); - usbvision->power_off_timer.data = (long) usbvision; + usbvision->power_off_timer.data = (long)usbvision; usbvision->power_off_timer.function = usbvision_power_off_timer; } @@ -2327,9 +2237,8 @@ void usbvision_set_power_off_timer(struct usb_usbvision *usbvision) void usbvision_reset_power_off_timer(struct usb_usbvision *usbvision) { - if (timer_pending(&usbvision->power_off_timer)) { + if (timer_pending(&usbvision->power_off_timer)) del_timer(&usbvision->power_off_timer); - } } /* @@ -2339,14 +2248,10 @@ void usbvision_reset_power_off_timer(struct usb_usbvision *usbvision) */ int usbvision_begin_streaming(struct usb_usbvision *usbvision) { - int err_code = 0; - - if (usbvision->isoc_mode == ISOC_MODE_COMPRESS) { + if (usbvision->isoc_mode == ISOC_MODE_COMPRESS) usbvision_init_compression(usbvision); - } - err_code = usbvision_write_reg(usbvision, USBVISION_VIN_REG2, USBVISION_NOHVALID | - usbvision->vin_reg2_preset); - return err_code; + return usbvision_write_reg(usbvision, USBVISION_VIN_REG2, + USBVISION_NOHVALID | usbvision->vin_reg2_preset); } /* @@ -2358,25 +2263,24 @@ int usbvision_restart_isoc(struct usb_usbvision *usbvision) { int ret; - if ( - (ret = - usbvision_write_reg(usbvision, USBVISION_PWR_REG, - USBVISION_SSPND_EN | USBVISION_PWR_VID)) < 0) + ret = usbvision_write_reg(usbvision, USBVISION_PWR_REG, + USBVISION_SSPND_EN | USBVISION_PWR_VID); + if (ret < 0) return ret; - if ( - (ret = - usbvision_write_reg(usbvision, USBVISION_PWR_REG, + ret = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN | USBVISION_PWR_VID | - USBVISION_RES2)) < 0) + USBVISION_RES2); + if (ret < 0) return ret; - if ( - (ret = - usbvision_write_reg(usbvision, USBVISION_VIN_REG2, + ret = usbvision_write_reg(usbvision, USBVISION_VIN_REG2, USBVISION_KEEP_BLANK | USBVISION_NOHVALID | - usbvision->vin_reg2_preset)) < 0) return ret; + usbvision->vin_reg2_preset); + if (ret < 0) + return ret; /* TODO: schedule timeout */ - while ((usbvision_read_reg(usbvision, USBVISION_STATUS_REG) & 0x01) != 1); + while ((usbvision_read_reg(usbvision, USBVISION_STATUS_REG) & 0x01) != 1) + ; return 0; } @@ -2384,7 +2288,7 @@ int usbvision_restart_isoc(struct usb_usbvision *usbvision) int usbvision_audio_off(struct usb_usbvision *usbvision) { if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, USBVISION_AUDIO_MUTE) < 0) { - printk(KERN_ERR "usbvision_audio_off: can't wirte reg\n"); + printk(KERN_ERR "usbvision_audio_off: can't write reg\n"); return -1; } usbvision->audio_mute = 0; @@ -2404,7 +2308,7 @@ int usbvision_set_audio(struct usb_usbvision *usbvision, int audio_channel) return 0; } -int usbvision_setup(struct usb_usbvision *usbvision,int format) +int usbvision_setup(struct usb_usbvision *usbvision, int format) { usbvision_set_video_format(usbvision, format); usbvision_set_dram_settings(usbvision); @@ -2422,14 +2326,15 @@ int usbvision_set_alternate(struct usb_usbvision *dev) int err_code, prev_alt = dev->iface_alt; int i; - dev->iface_alt=0; - for(i=0;i< dev->num_alt; i++) - if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->iface_alt]) - dev->iface_alt=i; + dev->iface_alt = 0; + for (i = 0; i < dev->num_alt; i++) + if (dev->alt_max_pkt_size[i] > dev->alt_max_pkt_size[dev->iface_alt]) + dev->iface_alt = i; if (dev->iface_alt != prev_alt) { dev->isoc_packet_size = dev->alt_max_pkt_size[dev->iface_alt]; - PDEBUG(DBG_FUNC,"setting alternate %d with max_packet_size=%u", dev->iface_alt,dev->isoc_packet_size); + PDEBUG(DBG_FUNC, "setting alternate %d with max_packet_size=%u", + dev->iface_alt, dev->isoc_packet_size); err_code = usb_set_interface(dev->dev, dev->iface, dev->iface_alt); if (err_code < 0) { dev_err(&dev->dev->dev, @@ -2549,7 +2454,7 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision) /* Unschedule all of the iso td's */ for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) { usb_kill_urb(usbvision->sbuf[buf_idx].urb); - if (usbvision->sbuf[buf_idx].data){ + if (usbvision->sbuf[buf_idx].data) { usb_free_coherent(usbvision->dev, sb_size, usbvision->sbuf[buf_idx].data, @@ -2563,9 +2468,8 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision) usbvision->streaming = stream_off; if (!usbvision->remove_pending) { - /* Set packet size to 0 */ - usbvision->iface_alt=0; + usbvision->iface_alt = 0; err_code = usb_set_interface(usbvision->dev, usbvision->iface, usbvision->iface_alt); if (err_code < 0) { @@ -2590,8 +2494,8 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) { /* inputs #0 and #3 are constant for every SAA711x. */ /* inputs #1 and #2 are variable for SAA7111 and SAA7113 */ - int mode[4]= {SAA7115_COMPOSITE0, 0, 0, SAA7115_COMPOSITE3}; - int audio[]= {1, 0, 0, 0}; + int mode[4] = { SAA7115_COMPOSITE0, 0, 0, SAA7115_COMPOSITE3 }; + int audio[] = { 1, 0, 0, 0 }; /* channel 0 is TV with audiochannel 1 (tuner mono) */ /* channel 1 is Composite with audio channel 0 (line in) */ /* channel 2 is S-Video with audio channel 0 (line in) */ @@ -2605,24 +2509,23 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) /* Four video input devices -> channel: 0 = Chan White, 1 = Chan Green, 2 = Chan Yellow, 3 = Chan Red */ switch (usbvision_device_data[usbvision->dev_model].codec) { - case CODEC_SAA7113: - mode[1] = SAA7115_COMPOSITE2; - if (switch_svideo_input) { - /* To handle problems with S-Video Input for - * some devices. Use switch_svideo_input - * parameter when loading the module.*/ - mode[2] = SAA7115_COMPOSITE1; - } - else { - mode[2] = SAA7115_SVIDEO1; - } - break; - case CODEC_SAA7111: - default: - /* modes for saa7111 */ - mode[1] = SAA7115_COMPOSITE1; + case CODEC_SAA7113: + mode[1] = SAA7115_COMPOSITE2; + if (switch_svideo_input) { + /* To handle problems with S-Video Input for + * some devices. Use switch_svideo_input + * parameter when loading the module.*/ + mode[2] = SAA7115_COMPOSITE1; + } else { mode[2] = SAA7115_SVIDEO1; - break; + } + break; + case CODEC_SAA7111: + default: + /* modes for saa7111 */ + mode[1] = SAA7115_COMPOSITE1; + mode[2] = SAA7115_SVIDEO1; + break; } call_all(usbvision, video, s_routing, mode[channel], 0, 0); usbvision_set_audio(usbvision, audio[channel]); diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index cb19c84..05b1344 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c @@ -28,18 +28,18 @@ #include #include #include -#include +#include #include #include #include #include #include "usbvision.h" -#define DBG_I2C 1<<0 +#define DBG_I2C (1 << 0) static int i2c_debug; -module_param (i2c_debug, int, 0644); /* debug_i2c_usb mode of the device driver */ +module_param(i2c_debug, int, 0644); /* debug_i2c_usb mode of the device driver */ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); #define PDEBUG(level, fmt, args...) { \ @@ -72,8 +72,8 @@ static inline int try_write_address(struct i2c_adapter *i2c_adap, udelay(10); } if (i) { - PDEBUG(DBG_I2C,"Needed %d retries for address %#2x", i, addr); - PDEBUG(DBG_I2C,"Maybe there's no device at this address"); + PDEBUG(DBG_I2C, "Needed %d retries for address %#2x", i, addr); + PDEBUG(DBG_I2C, "Maybe there's no device at this address"); } return ret; } @@ -96,8 +96,8 @@ static inline int try_read_address(struct i2c_adapter *i2c_adap, udelay(10); } if (i) { - PDEBUG(DBG_I2C,"Needed %d retries for address %#2x", i, addr); - PDEBUG(DBG_I2C,"Maybe there's no device at this address"); + PDEBUG(DBG_I2C, "Needed %d retries for address %#2x", i, addr); + PDEBUG(DBG_I2C, "Maybe there's no device at this address"); } return ret; } @@ -143,9 +143,8 @@ static inline int usb_find_address(struct i2c_adapter *i2c_adap, else ret = try_write_address(i2c_adap, addr, retries); - if (ret != 1) { + if (ret != 1) return -EREMOTEIO; - } } return 0; } @@ -164,22 +163,20 @@ usbvision_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) pmsg = &msgs[i]; ret = usb_find_address(i2c_adap, pmsg, i2c_adap->retries, &addr); if (ret != 0) { - PDEBUG(DBG_I2C,"got NAK from device, message #%d", i); + PDEBUG(DBG_I2C, "got NAK from device, message #%d", i); return (ret < 0) ? ret : -EREMOTEIO; } if (pmsg->flags & I2C_M_RD) { /* read bytes into buffer */ ret = (usbvision_i2c_read(usbvision, addr, pmsg->buf, pmsg->len)); - if (ret < pmsg->len) { + if (ret < pmsg->len) return (ret < 0) ? ret : -EREMOTEIO; - } } else { /* write bytes from buffer */ ret = (usbvision_i2c_write(usbvision, addr, pmsg->buf, pmsg->len)); - if (ret < pmsg->len) { + if (ret < pmsg->len) return (ret < 0) ? ret : -EREMOTEIO; - } } } return num; @@ -219,7 +216,7 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision) sprintf(usbvision->i2c_adap.name, "%s-%d-%s", i2c_adap_template.name, usbvision->dev->bus->busnum, usbvision->dev->devpath); - PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name); + PDEBUG(DBG_I2C, "Adaptername: %s", usbvision->i2c_adap.name); usbvision->i2c_adap.dev.parent = &usbvision->dev->dev; i2c_set_adapdata(&usbvision->i2c_adap, &usbvision->v4l2_dev); @@ -293,7 +290,7 @@ int usbvision_i2c_unregister(struct usb_usbvision *usbvision) i2c_del_adapter(&(usbvision->i2c_adap)); usbvision->registered_i2c = 0; - PDEBUG(DBG_I2C,"i2c bus for %s unregistered", usbvision->i2c_adap.name); + PDEBUG(DBG_I2C, "i2c bus for %s unregistered", usbvision->i2c_adap.name); return 0; } @@ -355,9 +352,9 @@ usbvision_i2c_read_max4(struct usb_usbvision *usbvision, unsigned char addr, if (i2c_debug & DBG_I2C) { int idx; - for (idx = 0; idx < len; idx++) { - PDEBUG(DBG_I2C,"read %x from address %x", (unsigned char)buf[idx], addr); - } + + for (idx = 0; idx < len; idx++) + PDEBUG(DBG_I2C, "read %x from address %x", (unsigned char)buf[idx], addr); } return len; } @@ -416,9 +413,9 @@ static int usbvision_i2c_write_max4(struct usb_usbvision *usbvision, if (i2c_debug & DBG_I2C) { int idx; - for (idx = 0; idx < len; idx++) { - PDEBUG(DBG_I2C,"wrote %x at address %x", (unsigned char)buf[idx], addr); - } + + for (idx = 0; idx < len; idx++) + PDEBUG(DBG_I2C, "wrote %x at address %x", (unsigned char)buf[idx], addr); } return len; } diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 375355a..6083137 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -56,7 +56,7 @@ #include #include #include -#include +#include #include #include @@ -70,8 +70,8 @@ #include "usbvision.h" #include "usbvision-cards.h" -#define DRIVER_AUTHOR "Joerg Heckenbach ,\ - Dwaine Garden " +#define DRIVER_AUTHOR "Joerg Heckenbach , \ +Dwaine Garden " #define DRIVER_NAME "usbvision" #define DRIVER_ALIAS "USBVision" #define DRIVER_DESC "USBVision USB Video Device Driver for Linux" @@ -82,9 +82,9 @@ #define USBVISION_DRIVER_VERSION KERNEL_VERSION(USBVISION_DRIVER_VERSION_MAJOR,\ USBVISION_DRIVER_VERSION_MINOR,\ USBVISION_DRIVER_VERSION_PATCHLEVEL) -#define USBVISION_VERSION_STRING __stringify(USBVISION_DRIVER_VERSION_MAJOR)\ - "." __stringify(USBVISION_DRIVER_VERSION_MINOR)\ - "." __stringify(USBVISION_DRIVER_VERSION_PATCHLEVEL) +#define USBVISION_VERSION_STRING __stringify(USBVISION_DRIVER_VERSION_MAJOR) \ +"." __stringify(USBVISION_DRIVER_VERSION_MINOR) \ +"." __stringify(USBVISION_DRIVER_VERSION_PATCHLEVEL) #define ENABLE_HEXDUMP 0 /* Enable if you need it */ @@ -96,16 +96,16 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL) __func__, __LINE__ , ## args); \ } #else - #define PDEBUG(level, fmt, args...) do {} while(0) + #define PDEBUG(level, fmt, args...) do {} while (0) #endif -#define DBG_IO 1<<1 -#define DBG_PROBE 1<<2 -#define DBG_MMAP 1<<3 +#define DBG_IO (1 << 1) +#define DBG_PROBE (1 << 2) +#define DBG_MMAP (1 << 3) /* String operations */ -#define rmspace(str) while(*str==' ') str++; -#define goto2next(str) while(*str!=' ') str++; while(*str==' ') str++; +#define rmspace(str) while (*str == ' ') str++; +#define goto2next(str) while (*str != ' ') str++; while (*str == ' ') str++; /* sequential number of usbvision device */ @@ -205,7 +205,7 @@ static ssize_t show_hue(struct device *cd, struct v4l2_control ctrl; ctrl.id = V4L2_CID_HUE; ctrl.value = 0; - if(usbvision->user) + if (usbvision->user) call_all(usbvision, core, g_ctrl, &ctrl); return sprintf(buf, "%d\n", ctrl.value); } @@ -220,7 +220,7 @@ static ssize_t show_contrast(struct device *cd, struct v4l2_control ctrl; ctrl.id = V4L2_CID_CONTRAST; ctrl.value = 0; - if(usbvision->user) + if (usbvision->user) call_all(usbvision, core, g_ctrl, &ctrl); return sprintf(buf, "%d\n", ctrl.value); } @@ -235,7 +235,7 @@ static ssize_t show_brightness(struct device *cd, struct v4l2_control ctrl; ctrl.id = V4L2_CID_BRIGHTNESS; ctrl.value = 0; - if(usbvision->user) + if (usbvision->user) call_all(usbvision, core, g_ctrl, &ctrl); return sprintf(buf, "%d\n", ctrl.value); } @@ -250,7 +250,7 @@ static ssize_t show_saturation(struct device *cd, struct v4l2_control ctrl; ctrl.id = V4L2_CID_SATURATION; ctrl.value = 0; - if(usbvision->user) + if (usbvision->user) call_all(usbvision, core, g_ctrl, &ctrl); return sprintf(buf, "%d\n", ctrl.value); } @@ -263,7 +263,7 @@ static ssize_t show_streaming(struct device *cd, container_of(cd, struct video_device, dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%s\n", - YES_NO(usbvision->streaming==stream_on?1:0)); + YES_NO(usbvision->streaming == stream_on ? 1 : 0)); } static DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL); @@ -274,7 +274,7 @@ static ssize_t show_compression(struct device *cd, container_of(cd, struct video_device, dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%s\n", - YES_NO(usbvision->isoc_mode==ISOC_MODE_COMPRESS)); + YES_NO(usbvision->isoc_mode == ISOC_MODE_COMPRESS)); } static DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL); @@ -291,35 +291,36 @@ static DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL); static void usbvision_create_sysfs(struct video_device *vdev) { int res; + if (!vdev) return; do { res = device_create_file(&vdev->dev, &dev_attr_version); - if (res<0) + if (res < 0) break; res = device_create_file(&vdev->dev, &dev_attr_model); - if (res<0) + if (res < 0) break; res = device_create_file(&vdev->dev, &dev_attr_hue); - if (res<0) + if (res < 0) break; res = device_create_file(&vdev->dev, &dev_attr_contrast); - if (res<0) + if (res < 0) break; res = device_create_file(&vdev->dev, &dev_attr_brightness); - if (res<0) + if (res < 0) break; res = device_create_file(&vdev->dev, &dev_attr_saturation); - if (res<0) + if (res < 0) break; res = device_create_file(&vdev->dev, &dev_attr_streaming); - if (res<0) + if (res < 0) break; res = device_create_file(&vdev->dev, &dev_attr_compression); - if (res<0) + if (res < 0) break; res = device_create_file(&vdev->dev, &dev_attr_bridge); - if (res>=0) + if (res >= 0) return; } while (0); @@ -363,7 +364,7 @@ static int usbvision_v4l2_open(struct file *file) else { /* Allocate memory for the scratch ring buffer */ err_code = usbvision_scratch_alloc(usbvision); - if (isoc_mode==ISOC_MODE_COMPRESS) { + if (isoc_mode == ISOC_MODE_COMPRESS) { /* Allocate intermediate decompression buffers only if needed */ err_code = usbvision_decompress_alloc(usbvision); @@ -385,7 +386,7 @@ static int usbvision_v4l2_open(struct file *file) /* Send init sequence only once, it's large! */ if (!usbvision->initialized) { int setup_ok = 0; - setup_ok = usbvision_setup(usbvision,isoc_mode); + setup_ok = usbvision_setup(usbvision, isoc_mode); if (setup_ok) usbvision->initialized = 1; else @@ -396,7 +397,7 @@ static int usbvision_v4l2_open(struct file *file) usbvision_begin_streaming(usbvision); err_code = usbvision_init_isoc(usbvision); /* device must be initialized before isoc transfer */ - usbvision_muxsel(usbvision,0); + usbvision_muxsel(usbvision, 0); usbvision->user++; } else { if (power_on_at_open) { @@ -463,7 +464,7 @@ static int usbvision_v4l2_close(struct file *file) * */ #ifdef CONFIG_VIDEO_ADV_DEBUG -static int vidioc_g_register (struct file *file, void *priv, +static int vidioc_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { struct usb_usbvision *usbvision = video_drvdata(file); @@ -484,7 +485,7 @@ static int vidioc_g_register (struct file *file, void *priv, return 0; } -static int vidioc_s_register (struct file *file, void *priv, +static int vidioc_s_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { struct usb_usbvision *usbvision = video_drvdata(file); @@ -493,7 +494,7 @@ static int vidioc_s_register (struct file *file, void *priv, if (!v4l2_chip_match_host(®->match)) return -EINVAL; /* NT100x has a 8-bit register space */ - err_code = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); + err_code = usbvision_write_reg(usbvision, reg->reg & 0xff, reg->val); if (err_code < 0) { dev_err(&usbvision->vdev->dev, "%s: VIDIOC_DBG_S_REGISTER failed: error %d\n", @@ -504,7 +505,7 @@ static int vidioc_s_register (struct file *file, void *priv, } #endif -static int vidioc_querycap (struct file *file, void *priv, +static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *vc) { struct usb_usbvision *usbvision = video_drvdata(file); @@ -523,7 +524,7 @@ static int vidioc_querycap (struct file *file, void *priv, return 0; } -static int vidioc_enum_input (struct file *file, void *priv, +static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *vi) { struct usb_usbvision *usbvision = video_drvdata(file); @@ -531,14 +532,14 @@ static int vidioc_enum_input (struct file *file, void *priv, if (vi->index >= usbvision->video_inputs) return -EINVAL; - if (usbvision->have_tuner) { + if (usbvision->have_tuner) chan = vi->index; - } else { + else chan = vi->index + 1; /* skip Television string*/ - } + /* Determine the requested input characteristics specific for each usbvision card model */ - switch(chan) { + switch (chan) { case 0: if (usbvision_device_data[usbvision->dev_model].video_channels == 4) { strcpy(vi->name, "White Video Input"); @@ -552,20 +553,18 @@ static int vidioc_enum_input (struct file *file, void *priv, break; case 1: vi->type = V4L2_INPUT_TYPE_CAMERA; - if (usbvision_device_data[usbvision->dev_model].video_channels == 4) { + if (usbvision_device_data[usbvision->dev_model].video_channels == 4) strcpy(vi->name, "Green Video Input"); - } else { + else strcpy(vi->name, "Composite Video Input"); - } vi->std = V4L2_STD_PAL; break; case 2: vi->type = V4L2_INPUT_TYPE_CAMERA; - if (usbvision_device_data[usbvision->dev_model].video_channels == 4) { + if (usbvision_device_data[usbvision->dev_model].video_channels == 4) strcpy(vi->name, "Yellow Video Input"); - } else { + else strcpy(vi->name, "S-Video Input"); - } vi->std = V4L2_STD_PAL; break; case 3: @@ -577,7 +576,7 @@ static int vidioc_enum_input (struct file *file, void *priv, return 0; } -static int vidioc_g_input (struct file *file, void *priv, unsigned int *input) +static int vidioc_g_input(struct file *file, void *priv, unsigned int *input) { struct usb_usbvision *usbvision = video_drvdata(file); @@ -585,7 +584,7 @@ static int vidioc_g_input (struct file *file, void *priv, unsigned int *input) return 0; } -static int vidioc_s_input (struct file *file, void *priv, unsigned int input) +static int vidioc_s_input(struct file *file, void *priv, unsigned int input) { struct usb_usbvision *usbvision = video_drvdata(file); @@ -600,11 +599,11 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int input) return 0; } -static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id) { struct usb_usbvision *usbvision = video_drvdata(file); - usbvision->tvnorm_id=*id; + usbvision->tvnorm_id = *id; call_all(usbvision, core, s_std, usbvision->tvnorm_id); /* propagate the change to the decoder */ @@ -613,14 +612,14 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) return 0; } -static int vidioc_g_tuner (struct file *file, void *priv, +static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) { struct usb_usbvision *usbvision = video_drvdata(file); if (!usbvision->have_tuner || vt->index) /* Only tuner 0 */ return -EINVAL; - if(usbvision->radio) { + if (usbvision->radio) { strcpy(vt->name, "Radio"); vt->type = V4L2_TUNER_RADIO; } else { @@ -632,7 +631,7 @@ static int vidioc_g_tuner (struct file *file, void *priv, return 0; } -static int vidioc_s_tuner (struct file *file, void *priv, +static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) { struct usb_usbvision *usbvision = video_drvdata(file); @@ -646,23 +645,22 @@ static int vidioc_s_tuner (struct file *file, void *priv, return 0; } -static int vidioc_g_frequency (struct file *file, void *priv, +static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *freq) { struct usb_usbvision *usbvision = video_drvdata(file); freq->tuner = 0; /* Only one tuner */ - if(usbvision->radio) { + if (usbvision->radio) freq->type = V4L2_TUNER_RADIO; - } else { + else freq->type = V4L2_TUNER_ANALOG_TV; - } freq->frequency = usbvision->freq; return 0; } -static int vidioc_s_frequency (struct file *file, void *priv, +static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *freq) { struct usb_usbvision *usbvision = video_drvdata(file); @@ -677,30 +675,27 @@ static int vidioc_s_frequency (struct file *file, void *priv, return 0; } -static int vidioc_g_audio (struct file *file, void *priv, struct v4l2_audio *a) +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { struct usb_usbvision *usbvision = video_drvdata(file); - if(usbvision->radio) { - strcpy(a->name,"Radio"); - } else { + if (usbvision->radio) + strcpy(a->name, "Radio"); + else strcpy(a->name, "TV"); - } return 0; } -static int vidioc_s_audio (struct file *file, void *fh, +static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) { - if(a->index) { + if (a->index) return -EINVAL; - } - return 0; } -static int vidioc_queryctrl (struct file *file, void *priv, +static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *ctrl) { struct usb_usbvision *usbvision = video_drvdata(file); @@ -713,52 +708,53 @@ static int vidioc_queryctrl (struct file *file, void *priv, return 0; } -static int vidioc_g_ctrl (struct file *file, void *priv, +static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct usb_usbvision *usbvision = video_drvdata(file); - call_all(usbvision, core, g_ctrl, ctrl); + call_all(usbvision, core, g_ctrl, ctrl); return 0; } -static int vidioc_s_ctrl (struct file *file, void *priv, +static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct usb_usbvision *usbvision = video_drvdata(file); - call_all(usbvision, core, s_ctrl, ctrl); + call_all(usbvision, core, s_ctrl, ctrl); return 0; } -static int vidioc_reqbufs (struct file *file, +static int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *vr) { struct usb_usbvision *usbvision = video_drvdata(file); int ret; - RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES); + RESTRICT_TO_RANGE(vr->count, 1, USBVISION_NUMFRAMES); /* Check input validity: the user must do a VIDEO CAPTURE and MMAP method. */ if (vr->memory != V4L2_MEMORY_MMAP) return -EINVAL; - if(usbvision->streaming == stream_on) { - if ((ret = usbvision_stream_interrupt(usbvision))) + if (usbvision->streaming == stream_on) { + ret = usbvision_stream_interrupt(usbvision); + if (ret) return ret; } usbvision_frames_free(usbvision); usbvision_empty_framequeues(usbvision); - vr->count = usbvision_frames_alloc(usbvision,vr->count); + vr->count = usbvision_frames_alloc(usbvision, vr->count); usbvision->cur_frame = NULL; return 0; } -static int vidioc_querybuf (struct file *file, +static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *vb) { struct usb_usbvision *usbvision = video_drvdata(file); @@ -766,48 +762,45 @@ static int vidioc_querybuf (struct file *file, /* FIXME : must control that buffers are mapped (VIDIOC_REQBUFS has been called) */ - if(vb->index>=usbvision->num_frames) { + if (vb->index >= usbvision->num_frames) return -EINVAL; - } /* Updating the corresponding frame state */ vb->flags = 0; frame = &usbvision->frame[vb->index]; - if(frame->grabstate >= frame_state_ready) + if (frame->grabstate >= frame_state_ready) vb->flags |= V4L2_BUF_FLAG_QUEUED; - if(frame->grabstate >= frame_state_done) + if (frame->grabstate >= frame_state_done) vb->flags |= V4L2_BUF_FLAG_DONE; - if(frame->grabstate == frame_state_unused) + if (frame->grabstate == frame_state_unused) vb->flags |= V4L2_BUF_FLAG_MAPPED; vb->memory = V4L2_MEMORY_MMAP; - vb->m.offset = vb->index*PAGE_ALIGN(usbvision->max_frame_size); + vb->m.offset = vb->index * PAGE_ALIGN(usbvision->max_frame_size); vb->memory = V4L2_MEMORY_MMAP; vb->field = V4L2_FIELD_NONE; - vb->length = usbvision->curwidth* - usbvision->curheight* + vb->length = usbvision->curwidth * + usbvision->curheight * usbvision->palette.bytes_per_pixel; vb->timestamp = usbvision->frame[vb->index].timestamp; vb->sequence = usbvision->frame[vb->index].sequence; return 0; } -static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb) +static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *vb) { struct usb_usbvision *usbvision = video_drvdata(file); struct usbvision_frame *frame; unsigned long lock_flags; /* FIXME : works only on VIDEO_CAPTURE MODE, MMAP. */ - if(vb->index>=usbvision->num_frames) { + if (vb->index >= usbvision->num_frames) return -EINVAL; - } frame = &usbvision->frame[vb->index]; - if (frame->grabstate != frame_state_unused) { + if (frame->grabstate != frame_state_unused) return -EAGAIN; - } /* Mark it as ready and enqueue frame */ frame->grabstate = frame_state_ready; @@ -826,7 +819,7 @@ static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb) return 0; } -static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *vb) { struct usb_usbvision *usbvision = video_drvdata(file); int ret; @@ -882,7 +875,7 @@ static int vidioc_streamoff(struct file *file, if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - if(usbvision->streaming == stream_on) { + if (usbvision->streaming == stream_on) { usbvision_stream_interrupt(usbvision); /* Stop all video streamings */ call_all(usbvision, video, s_stream, 0); @@ -892,18 +885,17 @@ static int vidioc_streamoff(struct file *file, return 0; } -static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *vfd) { - if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) { + if (vfd->index >= USBVISION_SUPPORTED_PALETTES - 1) return -EINVAL; - } - strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc); + strcpy(vfd->description, usbvision_v4l2_format[vfd->index].desc); vfd->pixelformat = usbvision_v4l2_format[vfd->index].format; return 0; } -static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf) { struct usb_usbvision *usbvision = video_drvdata(file); @@ -911,32 +903,31 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, vf->fmt.pix.height = usbvision->curheight; vf->fmt.pix.pixelformat = usbvision->palette.format; vf->fmt.pix.bytesperline = - usbvision->curwidth*usbvision->palette.bytes_per_pixel; - vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*usbvision->curheight; + usbvision->curwidth * usbvision->palette.bytes_per_pixel; + vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline * usbvision->curheight; vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */ return 0; } -static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf) { struct usb_usbvision *usbvision = video_drvdata(file); int format_idx; /* Find requested format in available ones */ - for(format_idx=0;format_idxfmt.pix.pixelformat == + for (format_idx = 0; format_idx < USBVISION_SUPPORTED_PALETTES; format_idx++) { + if (vf->fmt.pix.pixelformat == usbvision_v4l2_format[format_idx].format) { usbvision->palette = usbvision_v4l2_format[format_idx]; break; } } /* robustness */ - if(format_idx == USBVISION_SUPPORTED_PALETTES) { + if (format_idx == USBVISION_SUPPORTED_PALETTES) return -EINVAL; - } RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH); RESTRICT_TO_RANGE(vf->fmt.pix.height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT); @@ -953,13 +944,14 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct usb_usbvision *usbvision = video_drvdata(file); int ret; - if( 0 != (ret=vidioc_try_fmt_vid_cap (file, priv, vf)) ) { + ret = vidioc_try_fmt_vid_cap(file, priv, vf); + if (ret) return ret; - } /* stop io in case it is already in progress */ - if(usbvision->streaming == stream_on) { - if ((ret = usbvision_stream_interrupt(usbvision))) + if (usbvision->streaming == stream_on) { + ret = usbvision_stream_interrupt(usbvision); + if (ret) return ret; } usbvision_frames_free(usbvision); @@ -979,8 +971,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, struct usb_usbvision *usbvision = video_drvdata(file); int noblock = file->f_flags & O_NONBLOCK; unsigned long lock_flags; - - int ret,i; + int ret, i; struct usbvision_frame *frame; PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __func__, @@ -992,15 +983,15 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, /* This entry point is compatible with the mmap routines so that a user can do either VIDIOC_QBUF/VIDIOC_DQBUF to get frames or call read on the device. */ - if(!usbvision->num_frames) { + if (!usbvision->num_frames) { /* First, allocate some frames to work with if this has not been done with VIDIOC_REQBUF */ usbvision_frames_free(usbvision); usbvision_empty_framequeues(usbvision); - usbvision_frames_alloc(usbvision,USBVISION_NUMFRAMES); + usbvision_frames_alloc(usbvision, USBVISION_NUMFRAMES); } - if(usbvision->streaming != stream_on) { + if (usbvision->streaming != stream_on) { /* no stream is running, make it running ! */ usbvision->streaming = stream_on; call_all(usbvision, video, s_stream, 1); @@ -1008,9 +999,9 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, /* Then, enqueue as many frames as possible (like a user of VIDIOC_QBUF would do) */ - for(i=0;inum_frames;i++) { + for (i = 0; i < usbvision->num_frames; i++) { frame = &usbvision->frame[i]; - if(frame->grabstate == frame_state_unused) { + if (frame->grabstate == frame_state_unused) { /* Mark it as ready and enqueue frame */ frame->grabstate = frame_state_ready; frame->scanstate = scan_state_scanning; @@ -1029,7 +1020,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, /* Then try to steal a frame (like a VIDIOC_DQBUF would do) */ if (list_empty(&(usbvision->outqueue))) { - if(noblock) + if (noblock) return -EAGAIN; ret = wait_event_interruptible @@ -1059,9 +1050,8 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, if ((count + frame->bytes_read) > (unsigned long)frame->scanlength) count = frame->scanlength - frame->bytes_read; - if (copy_to_user(buf, frame->data + frame->bytes_read, count)) { + if (copy_to_user(buf, frame->data + frame->bytes_read, count)) return -EFAULT; - } frame->bytes_read += count; PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld", @@ -1069,12 +1059,12 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, (unsigned long)count, frame->bytes_read); /* For now, forget the frame if it has not been read in one shot. */ -/* if (frame->bytes_read >= frame->scanlength) {*/ /* All data has been read */ +/* if (frame->bytes_read >= frame->scanlength) {*/ /* All data has been read */ frame->bytes_read = 0; /* Mark it as available to be used again. */ frame->grabstate = frame_state_unused; -/* } */ +/* } */ return count; } @@ -1089,9 +1079,8 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) PDEBUG(DBG_MMAP, "mmap"); - if (!USBVISION_IS_OPERATIONAL(usbvision)) { + if (!USBVISION_IS_OPERATIONAL(usbvision)) return -EFAULT; - } if (!(vma->vm_flags & VM_WRITE) || size != PAGE_ALIGN(usbvision->max_frame_size)) { @@ -1115,7 +1104,6 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) pos = usbvision->frame[i].data; while (size > 0) { - if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { PDEBUG(DBG_MMAP, "mmap: vm_insert_page failed"); return -EAGAIN; @@ -1145,9 +1133,8 @@ static int usbvision_radio_open(struct file *file) "%s: Someone tried to open an already opened USBVision Radio!\n", __func__); err_code = -EBUSY; - } - else { - if(power_on_at_open) { + } else { + if (power_on_at_open) { usbvision_reset_power_off_timer(usbvision); if (usbvision->power == 0) { usbvision_power_on(usbvision); @@ -1190,12 +1177,12 @@ static int usbvision_radio_close(struct file *file) PDEBUG(DBG_IO, ""); /* Set packet size to 0 */ - usbvision->iface_alt=0; + usbvision->iface_alt = 0; err_code = usb_set_interface(usbvision->dev, usbvision->iface, usbvision->iface_alt); usbvision_audio_off(usbvision); - usbvision->radio=0; + usbvision->radio = 0; usbvision->user--; if (power_on_at_open) { @@ -1222,7 +1209,7 @@ static const struct v4l2_file_operations usbvision_fops = { .read = usbvision_v4l2_read, .mmap = usbvision_v4l2_mmap, .unlocked_ioctl = video_ioctl2, -/* .poll = video_poll, */ +/* .poll = video_poll, */ }; static const struct v4l2_ioctl_ops usbvision_ioctl_ops = { @@ -1258,11 +1245,11 @@ static const struct v4l2_ioctl_ops usbvision_ioctl_ops = { static struct video_device usbvision_video_template = { .fops = &usbvision_fops, - .ioctl_ops = &usbvision_ioctl_ops, + .ioctl_ops = &usbvision_ioctl_ops, .name = "usbvision-video", .release = video_device_release, - .tvnorms = USBVISION_NORMS, - .current_norm = V4L2_STD_PAL + .tvnorms = USBVISION_NORMS, + .current_norm = V4L2_STD_PAL }; @@ -1292,9 +1279,9 @@ static const struct v4l2_ioctl_ops usbvision_radio_ioctl_ops = { static struct video_device usbvision_radio_template = { .fops = &usbvision_radio_fops, - .name = "usbvision-radio", + .name = "usbvision-radio", .release = video_device_release, - .ioctl_ops = &usbvision_radio_ioctl_ops, + .ioctl_ops = &usbvision_radio_ioctl_ops, .tvnorms = USBVISION_NORMS, .current_norm = V4L2_STD_PAL @@ -1315,9 +1302,8 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, } vdev = video_device_alloc(); - if (NULL == vdev) { + if (NULL == vdev) return NULL; - } *vdev = *vdev_template; vdev->lock = &usbvision->v4l2_lock; vdev->v4l2_dev = &usbvision->v4l2_dev; @@ -1333,11 +1319,10 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) if (usbvision->rdev) { PDEBUG(DBG_PROBE, "unregister %s [v4l2]", video_device_node_name(usbvision->rdev)); - if (video_is_registered(usbvision->rdev)) { + if (video_is_registered(usbvision->rdev)) video_unregister_device(usbvision->rdev); - } else { + else video_device_release(usbvision->rdev); - } usbvision->rdev = NULL; } @@ -1345,11 +1330,10 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) if (usbvision->vdev) { PDEBUG(DBG_PROBE, "unregister %s [v4l2]", video_device_node_name(usbvision->vdev)); - if (video_is_registered(usbvision->vdev)) { + if (video_is_registered(usbvision->vdev)) video_unregister_device(usbvision->vdev); - } else { + else video_device_release(usbvision->vdev); - } usbvision->vdev = NULL; } } @@ -1361,14 +1345,10 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) usbvision->vdev = usbvision_vdev_init(usbvision, &usbvision_video_template, "USBVision Video"); - if (usbvision->vdev == NULL) { + if (usbvision->vdev == NULL) goto err_exit; - } - if (video_register_device(usbvision->vdev, - VFL_TYPE_GRABBER, - video_nr)<0) { + if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr) < 0) goto err_exit; - } printk(KERN_INFO "USBVision[%d]: registered USBVision Video device %s [v4l2]\n", usbvision->nr, video_device_node_name(usbvision->vdev)); @@ -1378,14 +1358,10 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) usbvision->rdev = usbvision_vdev_init(usbvision, &usbvision_radio_template, "USBVision Radio"); - if (usbvision->rdev == NULL) { + if (usbvision->rdev == NULL) goto err_exit; - } - if (video_register_device(usbvision->rdev, - VFL_TYPE_RADIO, - radio_nr)<0) { + if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr) < 0) goto err_exit; - } printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device %s [v4l2]\n", usbvision->nr, video_device_node_name(usbvision->rdev)); } @@ -1459,9 +1435,7 @@ static void usbvision_release(struct usb_usbvision *usbvision) usbvision_remove_sysfs(usbvision->vdev); usbvision_unregister_video(usbvision); - if (usbvision->ctrl_urb) { - usb_free_urb(usbvision->ctrl_urb); - } + usb_free_urb(usbvision->ctrl_urb); v4l2_device_unregister(&usbvision->v4l2_dev); kfree(usbvision); @@ -1520,25 +1494,24 @@ static int __devinit usbvision_probe(struct usb_interface *intf, const struct usb_host_interface *interface; struct usb_usbvision *usbvision = NULL; const struct usb_endpoint_descriptor *endpoint; - int model,i; + int model, i; PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u", dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum); model = devid->driver_info; - if ( (model<0) || (model>=usbvision_device_data_size) ) { - PDEBUG(DBG_PROBE, "model out of bounds %d",model); + if (model < 0 || model >= usbvision_device_data_size) { + PDEBUG(DBG_PROBE, "model out of bounds %d", model); return -ENODEV; } printk(KERN_INFO "%s: %s found\n", __func__, usbvision_device_data[model].model_string); - if (usbvision_device_data[model].interface >= 0) { + if (usbvision_device_data[model].interface >= 0) interface = &dev->actconfig->interface[usbvision_device_data[model].interface]->altsetting[0]; - } else { + else interface = &dev->actconfig->interface[ifnum]->altsetting[0]; - } endpoint = &interface->endpoint[1].desc; if (!usb_endpoint_xfer_isoc(endpoint)) { dev_err(&intf->dev, "%s: interface %d. has non-ISO endpoint!\n", @@ -1559,33 +1532,31 @@ static int __devinit usbvision_probe(struct usb_interface *intf, return -ENOMEM; } - if (dev->descriptor.bNumConfigurations > 1) { + if (dev->descriptor.bNumConfigurations > 1) usbvision->bridge_type = BRIDGE_NT1004; - } else if (model == DAZZLE_DVC_90_REV_1_SECAM) { + else if (model == DAZZLE_DVC_90_REV_1_SECAM) usbvision->bridge_type = BRIDGE_NT1005; - } else { + else usbvision->bridge_type = BRIDGE_NT1003; - } PDEBUG(DBG_PROBE, "bridge_type %d", usbvision->bridge_type); /* compute alternate max packet sizes */ uif = dev->actconfig->interface[0]; - usbvision->num_alt=uif->num_altsetting; - PDEBUG(DBG_PROBE, "Alternate settings: %i",usbvision->num_alt); - usbvision->alt_max_pkt_size = kmalloc(32* - usbvision->num_alt,GFP_KERNEL); + usbvision->num_alt = uif->num_altsetting; + PDEBUG(DBG_PROBE, "Alternate settings: %i", usbvision->num_alt); + usbvision->alt_max_pkt_size = kmalloc(32 * usbvision->num_alt, GFP_KERNEL); if (usbvision->alt_max_pkt_size == NULL) { dev_err(&intf->dev, "usbvision: out of memory!\n"); return -ENOMEM; } - for (i = 0; i < usbvision->num_alt ; i++) { + for (i = 0; i < usbvision->num_alt; i++) { u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc. wMaxPacketSize); usbvision->alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - PDEBUG(DBG_PROBE, "Alternate setting %i, max size= %i",i, + PDEBUG(DBG_PROBE, "Alternate setting %i, max size= %i", i, usbvision->alt_max_pkt_size[i]); } @@ -1593,9 +1564,8 @@ static int __devinit usbvision_probe(struct usb_interface *intf, usbvision->nr = usbvision_nr++; usbvision->have_tuner = usbvision_device_data[model].tuner; - if (usbvision->have_tuner) { + if (usbvision->have_tuner) usbvision->tuner_type = usbvision_device_data[model].tuner_type; - } usbvision->dev_model = model; usbvision->remove_pending = 0; @@ -1689,7 +1659,7 @@ static int __init usbvision_init(void) PDEBUG(DBG_MMAP, "MMAP debugging is enabled [video]"); /* disable planar mode support unless compression enabled */ - if (isoc_mode != ISOC_MODE_COMPRESS ) { + if (isoc_mode != ISOC_MODE_COMPRESS) { /* FIXME : not the right way to set supported flag */ usbvision_v4l2_format[6].supported = 0; /* V4L2_PIX_FMT_YVU420 */ usbvision_v4l2_format[7].supported = 0; /* V4L2_PIX_FMT_YUV422P */ @@ -1706,10 +1676,10 @@ static int __init usbvision_init(void) static void __exit usbvision_exit(void) { - PDEBUG(DBG_PROBE, ""); + PDEBUG(DBG_PROBE, ""); - usb_deregister(&usbvision_driver); - PDEBUG(DBG_PROBE, "success"); + usb_deregister(&usbvision_driver); + PDEBUG(DBG_PROBE, "success"); } module_init(usbvision_init); diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h index 5141159..8074787 100644 --- a/drivers/media/video/usbvision/usbvision.h +++ b/drivers/media/video/usbvision/usbvision.h @@ -139,7 +139,7 @@ #define MAX_USB_HEIGHT 240 /* 288 */ #define MAX_FRAME_HEIGHT 240 /* 288 */ /* Streching sometimes causes crashes*/ -#define MAX_FRAME_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * MAX_BYTES_PER_PIXEL) +#define MAX_FRAME_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * MAX_BYTES_PER_PIXEL) #define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) /* bytesize of clipmask */ #define USBVISION_URB_FRAMES 32 @@ -148,7 +148,7 @@ #define USBVISION_NUMFRAMES 3 /* Maximum number of frames an application can get */ #define USBVISION_NUMSBUF 2 /* Dimensioning the USB S buffering */ -#define USBVISION_POWEROFF_TIME 3 * (HZ) /* 3 seconds */ +#define USBVISION_POWEROFF_TIME (3 * HZ) /* 3 seconds */ #define FRAMERATE_MIN 0 @@ -161,7 +161,8 @@ enum { }; /* This macro restricts an int variable to an inclusive range */ -#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); } +#define RESTRICT_TO_RANGE(v, mi, ma) \ + { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); } /* * We use macros to do YUV -> RGB conversion because this is @@ -183,18 +184,18 @@ enum { * Make sure the output values are within [0..255] range. */ #define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x))) -#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \ - int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \ - mm_y = (my) - 16; \ - mm_u = (mu) - 128; \ - mm_v = (mv) - 128; \ - mm_yc= mm_y * 76284; \ - mm_b = (mm_yc + 132252*mm_v ) >> 16; \ - mm_g = (mm_yc - 53281*mm_u - 25625*mm_v ) >> 16; \ - mm_r = (mm_yc + 104595*mm_u ) >> 16; \ - mb = LIMIT_RGB(mm_b); \ - mg = LIMIT_RGB(mm_g); \ - mr = LIMIT_RGB(mm_r); \ +#define YUV_TO_RGB_BY_THE_BOOK(my, mu, mv, mr, mg, mb) { \ + int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \ + mm_y = (my) - 16; \ + mm_u = (mu) - 128; \ + mm_v = (mv) - 128; \ + mm_yc = mm_y * 76284; \ + mm_b = (mm_yc + 132252 * mm_v) >> 16; \ + mm_g = (mm_yc - 53281 * mm_u - 25625 * mm_v) >> 16; \ + mm_r = (mm_yc + 104595 * mm_u) >> 16; \ + mb = LIMIT_RGB(mm_b); \ + mg = LIMIT_RGB(mm_g); \ + mr = LIMIT_RGB(mm_r); \ } /* Debugging aid */ @@ -202,7 +203,7 @@ enum { wait_queue_head_t wq; \ init_waitqueue_head(&wq); \ printk(KERN_INFO "Say: %s\n", what); \ - interruptible_sleep_on_timeout (&wq, HZ*3); \ + interruptible_sleep_on_timeout(&wq, HZ * 3); \ } /* @@ -265,8 +266,8 @@ struct usbvision_sbuf { struct urb *urb; }; -#define USBVISION_MAGIC_1 0x55 -#define USBVISION_MAGIC_2 0xAA +#define USBVISION_MAGIC_1 0x55 +#define USBVISION_MAGIC_2 0xAA #define USBVISION_HEADER_LENGTH 0x0c #define USBVISION_SAA7111_ADDR 0x48 #define USBVISION_SAA7113_ADDR 0x4a @@ -358,8 +359,8 @@ extern struct usb_device_id usbvision_table[]; struct usb_usbvision { struct v4l2_device v4l2_dev; - struct video_device *vdev; /* Video Device */ - struct video_device *rdev; /* Radio Device */ + struct video_device *vdev; /* Video Device */ + struct video_device *rdev; /* Radio Device */ /* i2c Declaration Section*/ struct i2c_adapter i2c_adap; @@ -401,7 +402,7 @@ struct usb_usbvision { enum stream_state streaming; /* Are we streaming Isochronous? */ int last_error; /* What calamity struck us? */ int curwidth; /* width of the frame the device is currently set to*/ - int curheight; /* height of the frame the device is currently set to*/ + int curheight; /* height of the frame the device is currently set to*/ int stretch_width; /* stretch-factor for frame width (from usb to screen)*/ int stretch_height; /* stretch-factor for frame height (from usb to screen)*/ char *fbuf; /* Videodev buffer area for mmap*/ @@ -434,7 +435,7 @@ struct usb_usbvision { /* Decompression stuff: */ unsigned char *intra_frame_buffer; /* Buffer for reference frame */ - int block_pos; /* for test only */ + int block_pos; /* for test only */ int request_intra; /* 0 = normal; 1 = intra frame is requested; */ int last_isoc_frame_num; /* check for lost isoc frames */ int isoc_packet_size; /* need to calculate used_bandwidth */ @@ -494,7 +495,7 @@ void usbvision_scratch_free(struct usb_usbvision *usbvision); int usbvision_decompress_alloc(struct usb_usbvision *usbvision); void usbvision_decompress_free(struct usb_usbvision *usbvision); -int usbvision_setup(struct usb_usbvision *usbvision,int format); +int usbvision_setup(struct usb_usbvision *usbvision, int format); int usbvision_init_isoc(struct usb_usbvision *usbvision); int usbvision_restart_isoc(struct usb_usbvision *usbvision); void usbvision_stop_isoc(struct usb_usbvision *usbvision); -- cgit v0.10.2 From 513521eaee4375a1a0da0b73c7131a165a9fe4d9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 Dec 2010 14:25:52 -0300 Subject: [media] v4l2-ctrls: use const char * const * for the menu arrays This prevents checkpatch warnings generated when defining 'static const char *foo[]' arrays. It makes sense to use const char * const * anyway since the pointers in the array are indeed const. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c index 67043c7..97d7b7e 100644 --- a/drivers/media/video/cx18/cx18-controls.c +++ b/drivers/media/video/cx18/cx18-controls.c @@ -108,7 +108,7 @@ static int cx18_try_ctrl(struct file *file, void *fh, struct v4l2_ext_control *vctrl) { struct v4l2_queryctrl qctrl; - const char **menu_items = NULL; + const char * const *menu_items = NULL; int err; qctrl.id = vctrl->id; diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c index e5c3c8d..103ef6b 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/video/cx2341x.c @@ -853,9 +853,9 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, } EXPORT_SYMBOL(cx2341x_ctrl_query); -const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id) +const char * const *cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id) { - static const char *mpeg_stream_type_without_ts[] = { + static const char * const mpeg_stream_type_without_ts[] = { "MPEG-2 Program Stream", "", "MPEG-1 System Stream", @@ -952,7 +952,7 @@ int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy, for (i = 0; i < ctrls->count; i++) { struct v4l2_ext_control *ctrl = ctrls->controls + i; struct v4l2_queryctrl qctrl; - const char **menu_items = NULL; + const char * const *menu_items = NULL; qctrl.id = ctrl->id; err = cx2341x_ctrl_query(params, &qctrl); @@ -1135,7 +1135,7 @@ EXPORT_SYMBOL(cx2341x_update); static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id) { - const char **menu = cx2341x_ctrl_get_menu(p, id); + const char * const *menu = cx2341x_ctrl_get_menu(p, id); struct v4l2_ext_control ctrl; if (menu == NULL) diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c index 55ea914..7d5a713 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c +++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c @@ -203,7 +203,7 @@ int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val, *blen = 0; LOCK_TAKE(cptr->hdw->big_lock); do { if (cptr->info->type == pvr2_ctl_enum) { - const char **names; + const char * const *names; names = cptr->info->def.type_enum.value_names; if (pvr2_ctrl_range_check(cptr,val) == 0) { if (names[val]) { @@ -367,7 +367,7 @@ static const char *boolNames[] = { static int parse_token(const char *ptr,unsigned int len, int *valptr, - const char **names,unsigned int namecnt) + const char * const *names, unsigned int namecnt) { char buf[33]; unsigned int slen; @@ -559,7 +559,7 @@ int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr, *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false"); ret = 0; } else if (cptr->info->type == pvr2_ctl_enum) { - const char **names; + const char * const *names; names = cptr->info->def.type_enum.value_names; if ((val >= 0) && (val < cptr->info->def.type_enum.count)) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index cb4057b..ac94a8b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -115,7 +115,7 @@ struct pvr2_ctl_info { } type_int; struct { /* enumerated control */ unsigned int count; /* enum value count */ - const char **value_names; /* symbol names */ + const char * const *value_names; /* symbol names */ } type_enum; struct { /* bitmask control */ unsigned int valid_bits; /* bits in use */ diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index b5eb1f3..3f0871b 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -150,7 +150,7 @@ EXPORT_SYMBOL(v4l2_prio_check); struct v4l2_queryctrl and the available menu items. Note that menu_items may be NULL, in that case it is ignored. */ int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl, - const char **menu_items) + const char * const *menu_items) { if (qctrl->flags & V4L2_CTRL_FLAG_DISABLED) return -EINVAL; @@ -199,7 +199,7 @@ EXPORT_SYMBOL(v4l2_ctrl_query_fill); If menu_items is NULL, then the menu items are retrieved using v4l2_ctrl_get_menu. */ int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl, - const char **menu_items) + const char * const *menu_items) { int i; @@ -222,7 +222,7 @@ EXPORT_SYMBOL(v4l2_ctrl_query_menu); Use this if there are 'holes' in the list of valid menu items. */ int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids) { - const char **menu_items = v4l2_ctrl_get_menu(qmenu->id); + const char * const *menu_items = v4l2_ctrl_get_menu(qmenu->id); qmenu->reserved = 0; if (menu_items == NULL || ids == NULL) diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c index 9d2502c..6c0fadc 100644 --- a/drivers/media/video/v4l2-ctrls.c +++ b/drivers/media/video/v4l2-ctrls.c @@ -38,15 +38,15 @@ struct ctrl_helper { the given control ID. The pointer array ends with a NULL pointer. An empty string signifies a menu entry that is invalid. This allows drivers to disable certain options if it is not supported. */ -const char **v4l2_ctrl_get_menu(u32 id) +const char * const *v4l2_ctrl_get_menu(u32 id) { - static const char *mpeg_audio_sampling_freq[] = { + static const char * const mpeg_audio_sampling_freq[] = { "44.1 kHz", "48 kHz", "32 kHz", NULL }; - static const char *mpeg_audio_encoding[] = { + static const char * const mpeg_audio_encoding[] = { "MPEG-1/2 Layer I", "MPEG-1/2 Layer II", "MPEG-1/2 Layer III", @@ -54,7 +54,7 @@ const char **v4l2_ctrl_get_menu(u32 id) "AC-3", NULL }; - static const char *mpeg_audio_l1_bitrate[] = { + static const char * const mpeg_audio_l1_bitrate[] = { "32 kbps", "64 kbps", "96 kbps", @@ -71,7 +71,7 @@ const char **v4l2_ctrl_get_menu(u32 id) "448 kbps", NULL }; - static const char *mpeg_audio_l2_bitrate[] = { + static const char * const mpeg_audio_l2_bitrate[] = { "32 kbps", "48 kbps", "56 kbps", @@ -88,7 +88,7 @@ const char **v4l2_ctrl_get_menu(u32 id) "384 kbps", NULL }; - static const char *mpeg_audio_l3_bitrate[] = { + static const char * const mpeg_audio_l3_bitrate[] = { "32 kbps", "40 kbps", "48 kbps", @@ -105,7 +105,7 @@ const char **v4l2_ctrl_get_menu(u32 id) "320 kbps", NULL }; - static const char *mpeg_audio_ac3_bitrate[] = { + static const char * const mpeg_audio_ac3_bitrate[] = { "32 kbps", "40 kbps", "48 kbps", @@ -127,50 +127,50 @@ const char **v4l2_ctrl_get_menu(u32 id) "640 kbps", NULL }; - static const char *mpeg_audio_mode[] = { + static const char * const mpeg_audio_mode[] = { "Stereo", "Joint Stereo", "Dual", "Mono", NULL }; - static const char *mpeg_audio_mode_extension[] = { + static const char * const mpeg_audio_mode_extension[] = { "Bound 4", "Bound 8", "Bound 12", "Bound 16", NULL }; - static const char *mpeg_audio_emphasis[] = { + static const char * const mpeg_audio_emphasis[] = { "No Emphasis", "50/15 us", "CCITT J17", NULL }; - static const char *mpeg_audio_crc[] = { + static const char * const mpeg_audio_crc[] = { "No CRC", "16-bit CRC", NULL }; - static const char *mpeg_video_encoding[] = { + static const char * const mpeg_video_encoding[] = { "MPEG-1", "MPEG-2", "MPEG-4 AVC", NULL }; - static const char *mpeg_video_aspect[] = { + static const char * const mpeg_video_aspect[] = { "1x1", "4x3", "16x9", "2.21x1", NULL }; - static const char *mpeg_video_bitrate_mode[] = { + static const char * const mpeg_video_bitrate_mode[] = { "Variable Bitrate", "Constant Bitrate", NULL }; - static const char *mpeg_stream_type[] = { + static const char * const mpeg_stream_type[] = { "MPEG-2 Program Stream", "MPEG-2 Transport Stream", "MPEG-1 System Stream", @@ -179,25 +179,25 @@ const char **v4l2_ctrl_get_menu(u32 id) "MPEG-2 SVCD-compatible Stream", NULL }; - static const char *mpeg_stream_vbi_fmt[] = { + static const char * const mpeg_stream_vbi_fmt[] = { "No VBI", "Private packet, IVTV format", NULL }; - static const char *camera_power_line_frequency[] = { + static const char * const camera_power_line_frequency[] = { "Disabled", "50 Hz", "60 Hz", NULL }; - static const char *camera_exposure_auto[] = { + static const char * const camera_exposure_auto[] = { "Auto Mode", "Manual Mode", "Shutter Priority Mode", "Aperture Priority Mode", NULL }; - static const char *colorfx[] = { + static const char * const colorfx[] = { "None", "Black & White", "Sepia", @@ -210,7 +210,7 @@ const char **v4l2_ctrl_get_menu(u32 id) "Vivid", NULL }; - static const char *tune_preemphasis[] = { + static const char * const tune_preemphasis[] = { "No preemphasis", "50 useconds", "75 useconds", @@ -952,7 +952,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, u32 id, const char *name, enum v4l2_ctrl_type type, s32 min, s32 max, u32 step, s32 def, - u32 flags, const char **qmenu, void *priv) + u32 flags, const char * const *qmenu, void *priv) { struct v4l2_ctrl *ctrl; unsigned sz_extra = 0; @@ -1019,7 +1019,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl, bool is_menu; struct v4l2_ctrl *ctrl; const char *name = cfg->name; - const char **qmenu = cfg->qmenu; + const char * const *qmenu = cfg->qmenu; enum v4l2_ctrl_type type = cfg->type; u32 flags = cfg->flags; s32 min = cfg->min; @@ -1075,7 +1075,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, u32 id, s32 max, s32 mask, s32 def) { - const char **qmenu = v4l2_ctrl_get_menu(id); + const char * const *qmenu = v4l2_ctrl_get_menu(id); const char *name; enum v4l2_ctrl_type type; s32 min; diff --git a/include/media/cx2341x.h b/include/media/cx2341x.h index 8d08ebf..9635eeb 100644 --- a/include/media/cx2341x.h +++ b/include/media/cx2341x.h @@ -95,7 +95,7 @@ int cx2341x_update(void *priv, cx2341x_mbox_func func, const struct cx2341x_mpeg_params *new); int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, struct v4l2_queryctrl *qctrl); -const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id); +const char * const *cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id); int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy, struct v4l2_ext_controls *ctrls, unsigned int cmd); void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p); diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 239125a..2d65b35 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -98,12 +98,12 @@ int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority local); /* Control helper functions */ int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl, - const char **menu_items); + const char * const *menu_items); const char *v4l2_ctrl_get_name(u32 id); -const char **v4l2_ctrl_get_menu(u32 id); +const char * const *v4l2_ctrl_get_menu(u32 id); int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def); int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, - struct v4l2_queryctrl *qctrl, const char **menu_items); + struct v4l2_queryctrl *qctrl, const char * const *menu_items); #define V4L2_CTRL_MENU_IDS_END (0xffffffff) int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids); diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index 9b7bea9..d69ab4a 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -112,7 +112,7 @@ struct v4l2_ctrl { u32 step; u32 menu_skip_mask; }; - const char **qmenu; + const char * const *qmenu; unsigned long flags; union { s32 val; @@ -202,7 +202,7 @@ struct v4l2_ctrl_config { s32 def; u32 flags; u32 menu_skip_mask; - const char **qmenu; + const char * const *qmenu; unsigned int is_private:1; unsigned int is_volatile:1; }; -- cgit v0.10.2 From 02ac04805e6a753610d7dd1716181ccbd8e366af Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 Dec 2010 14:27:05 -0300 Subject: [media] v4l2-ctrls: only check def for menu, integer and boolean controls The 'def' field is only valid for menus, integers and booleans. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c index 6c0fadc..8f81efc 100644 --- a/drivers/media/video/v4l2-ctrls.c +++ b/drivers/media/video/v4l2-ctrls.c @@ -962,13 +962,20 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, /* Sanity checks */ if (id == 0 || name == NULL || id >= V4L2_CID_PRIVATE_BASE || - def < min || def > max || max < min || + max < min || (type == V4L2_CTRL_TYPE_INTEGER && step == 0) || (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) || (type == V4L2_CTRL_TYPE_STRING && max == 0)) { handler_set_err(hdl, -ERANGE); return NULL; } + if ((type == V4L2_CTRL_TYPE_INTEGER || + type == V4L2_CTRL_TYPE_MENU || + type == V4L2_CTRL_TYPE_BOOLEAN) && + (def < min || def > max)) { + handler_set_err(hdl, -ERANGE); + return NULL; + } if (type == V4L2_CTRL_TYPE_BUTTON) flags |= V4L2_CTRL_FLAG_WRITE_ONLY; -- cgit v0.10.2 From 3ea2b673a55cee528f83653e711d09425ed4d8b6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 Dec 2010 14:28:13 -0300 Subject: [media] em28xx: fix incorrect s_ctrl error code and wrong call to res_free Calling subdevs to handle s_ctrl returned a non-zero return code even if everything went fine. Calling STREAMOFF if no STREAMON happened earlier would hit a BUG_ON in res_free. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 7be9bba..37b48a2 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1434,7 +1434,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, /* It isn't an AC97 control. Sends it to the v4l2 dev interface */ if (rc == 1) { - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); + rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); /* * In the case of non-AC97 volume controls, we still need @@ -1708,11 +1708,15 @@ static int vidioc_streamoff(struct file *file, void *priv, fh, type, fh->resources, dev->resources); if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - videobuf_streamoff(&fh->vb_vidq); - res_free(fh, EM28XX_RESOURCE_VIDEO); + if (res_check(fh, EM28XX_RESOURCE_VIDEO)) { + videobuf_streamoff(&fh->vb_vidq); + res_free(fh, EM28XX_RESOURCE_VIDEO); + } } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - videobuf_streamoff(&fh->vb_vbiq); - res_free(fh, EM28XX_RESOURCE_VBI); + if (res_check(fh, EM28XX_RESOURCE_VBI)) { + videobuf_streamoff(&fh->vb_vbiq); + res_free(fh, EM28XX_RESOURCE_VBI); + } } return 0; -- cgit v0.10.2 From 657f2271050beabe725ba101c1d840f51a41f33d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 Dec 2010 14:29:55 -0300 Subject: [media] v4l: fix handling of v4l2_input.capabilities The v4l core sets the v4l2_input.capabilities field based on the supplied v4l2_ioctl_ops. However, several drivers do a memset or memcpy of the v4l2_input struct, thus overwriting that field incorrectly. Either remove the memset (which is already done by the v4l core), or add the proper capabilities field in case of a memcpy. The same is also true for v4l2_output, but that only affected the ivtv driver. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c index ac20c5b..cdd31ca 100644 --- a/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/drivers/media/dvb/ttpci/av7110_v4l.c @@ -100,6 +100,7 @@ static struct v4l2_input inputs[4] = { .tuner = 0, /* ignored */ .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, .status = 0, + .capabilities = V4L2_IN_CAP_STD, }, { .index = 1, .name = "Television", @@ -108,6 +109,7 @@ static struct v4l2_input inputs[4] = { .tuner = 0, .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, .status = 0, + .capabilities = V4L2_IN_CAP_STD, }, { .index = 2, .name = "Video", @@ -116,6 +118,7 @@ static struct v4l2_input inputs[4] = { .tuner = 0, .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, .status = 0, + .capabilities = V4L2_IN_CAP_STD, }, { .index = 3, .name = "Y/C", @@ -124,6 +127,7 @@ static struct v4l2_input inputs[4] = { .tuner = 0, .std = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, .status = 0, + .capabilities = V4L2_IN_CAP_STD, } }; diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 97afc01..e957d76 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -1406,8 +1406,10 @@ static int budget_av_detach(struct saa7146_dev *dev) #define KNC1_INPUTS 2 static struct v4l2_input knc1_inputs[KNC1_INPUTS] = { - {0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0}, - {1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0}, + { 0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, + V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, + V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, }; static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index 52ba913..8717773 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -546,7 +546,6 @@ int cx18_get_input(struct cx18 *cx, u16 index, struct v4l2_input *input) "Component 1" }; - memset(input, 0, sizeof(*input)); if (index >= cx->nof_inputs) return -EINVAL; input->index = index; diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 796a797..644fcb8 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -1126,7 +1126,6 @@ static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) if (0 == INPUT(n)->type) return -EINVAL; - memset(i, 0, sizeof(*i)); i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; strcpy(i->name, iname[INPUT(n)->type]); diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index bb16409..a982750 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -1610,6 +1610,7 @@ et61x251_vidioc_enuminput(struct et61x251_device* cam, void __user * arg) memset(&i, 0, sizeof(i)); strcpy(i.name, "Camera"); i.type = V4L2_INPUT_TYPE_CAMERA; + i.capabilities = V4L2_IN_CAP_STD; if (copy_to_user(arg, &i, sizeof(i))) return -EFAULT; diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c index 7ae9636..cdf8b19 100644 --- a/drivers/media/video/hexium_gemini.c +++ b/drivers/media/video/hexium_gemini.c @@ -37,15 +37,15 @@ static int hexium_num; #define HEXIUM_INPUTS 9 static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = { - { 0, "CVBS 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 1, "CVBS 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 2, "CVBS 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 3, "CVBS 4", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 4, "CVBS 5", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 5, "CVBS 6", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 6, "Y/C 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 7, "Y/C 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 8, "Y/C 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { 0, "CVBS 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 1, "CVBS 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 2, "CVBS 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 3, "CVBS 4", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 4, "CVBS 5", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 5, "CVBS 6", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 6, "Y/C 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 7, "Y/C 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 8, "Y/C 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, }; #define HEXIUM_AUDIOS 0 diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c index b72d0f0..6ad7e1c 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/video/hexium_orion.c @@ -38,15 +38,15 @@ static int hexium_num; #define HEXIUM_INPUTS 9 static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = { - { 0, "CVBS 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 1, "CVBS 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 2, "CVBS 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 3, "CVBS 4", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 4, "CVBS 5", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 5, "CVBS 6", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 6, "Y/C 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 7, "Y/C 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 8, "Y/C 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { 0, "CVBS 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 1, "CVBS 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 2, "CVBS 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 3, "CVBS 4", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 4, "CVBS 5", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 5, "CVBS 6", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 6, "Y/C 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 7, "Y/C 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { 8, "Y/C 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, }; #define HEXIUM_AUDIOS 0 diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c index 87afbbe..b6f2a2b4 100644 --- a/drivers/media/video/ivtv/ivtv-cards.c +++ b/drivers/media/video/ivtv/ivtv-cards.c @@ -1313,7 +1313,6 @@ int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input) "Composite 3" }; - memset(input, 0, sizeof(*input)); if (index >= itv->nof_inputs) return -EINVAL; input->index = index; @@ -1331,7 +1330,6 @@ int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output) { const struct ivtv_card_output *card_output = itv->card->video_outputs + index; - memset(output, 0, sizeof(*output)); if (index >= itv->card->nof_outputs) return -EINVAL; output->index = index; diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 4e8fd96..e8846a0 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -59,10 +59,10 @@ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); enum { TUNER, AUX1, AUX3, AUX3_YC }; static struct v4l2_input mxb_inputs[MXB_INPUTS] = { - { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, + { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, }; /* this array holds the information, which port of the saa7146 each diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index ee4ea5f..776ba2d 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1748,7 +1748,6 @@ static int saa7134_enum_input(struct file *file, void *priv, return -EINVAL; if (NULL == card_in(dev, i->index).name) return -EINVAL; - memset(i, 0, sizeof(*i)); i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; strcpy(i->name, card_in(dev, n).name); diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index f49fbfb..84984f6 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -2189,6 +2189,7 @@ sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg) memset(&i, 0, sizeof(i)); strcpy(i.name, "Camera"); i.type = V4L2_INPUT_TYPE_CAMERA; + i.capabilities = V4L2_IN_CAP_STD; if (copy_to_user(arg, &i, sizeof(i))) return -EFAULT; diff --git a/drivers/media/video/timblogiw.c b/drivers/media/video/timblogiw.c index 700c08a..c2fcab4 100644 --- a/drivers/media/video/timblogiw.c +++ b/drivers/media/video/timblogiw.c @@ -369,7 +369,6 @@ static int timblogiw_enuminput(struct file *file, void *priv, if (inp->index != 0) return -EINVAL; - memset(inp, 0, sizeof(*inp)); inp->index = 0; strncpy(inp->name, "Timb input 1", sizeof(inp->name) - 1); diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 7e7eec4..d63e9d9 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -2954,9 +2954,6 @@ static int vino_enum_input(struct file *file, void *__fh, if (input == VINO_INPUT_NONE) return -EINVAL; - memset(i, 0, sizeof(struct v4l2_input)); - - i->index = index; i->type = V4L2_INPUT_TYPE_CAMERA; i->std = vino_inputs[input].std; strcpy(i->name, vino_inputs[input].name); diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 1b67b19..fe84f17 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -2449,11 +2449,6 @@ static int zoran_enum_input(struct file *file, void *__fh, if (inp->index >= zr->card.inputs) return -EINVAL; - else { - int id = inp->index; - memset(inp, 0, sizeof(*inp)); - inp->index = id; - } strncpy(inp->name, zr->card.input[inp->index].name, sizeof(inp->name) - 1); @@ -2503,7 +2498,6 @@ static int zoran_enum_output(struct file *file, void *__fh, if (outp->index != 0) return -EINVAL; - memset(outp, 0, sizeof(*outp)); outp->index = 0; outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY; strncpy(outp->name, "Autodetect", sizeof(outp->name)-1); diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c index 27406c3..998c33a 100644 --- a/drivers/staging/cx25821/cx25821-video.c +++ b/drivers/staging/cx25821/cx25821-video.c @@ -1272,8 +1272,6 @@ int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i) if (0 == INPUT(n)->type) return -EINVAL; - memset(i, 0, sizeof(*i)); - i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; strcpy(i->name, iname[INPUT(n)->type]); -- cgit v0.10.2 From 61ea3aa5bf309333c6655ccef825b4a765bff219 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 Dec 2010 14:38:44 -0300 Subject: [media] timblogiw: fix compile warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix 64-bit compile warning: drivers/media/video/timblogiw.c: In function ‘timblogiw_dma_filter_fn’: drivers/media/video/timblogiw.c:151: warning: cast from pointer to integer of different size drivers/media/video/timblogiw.c: In function ‘timblogiw_open’: drivers/media/video/timblogiw.c:670: warning: cast to pointer from integer of different size Signed-off-by: Hans Verkuil Cc: Richard Rojförs Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/timblogiw.c b/drivers/media/video/timblogiw.c index c2fcab4..fc611eb 100644 --- a/drivers/media/video/timblogiw.c +++ b/drivers/media/video/timblogiw.c @@ -148,7 +148,7 @@ static void timblogiw_dma_cb(void *data) static bool timblogiw_dma_filter_fn(struct dma_chan *chan, void *filter_param) { - return chan->chan_id == (int)filter_param; + return chan->chan_id == (uintptr_t)filter_param; } /* IOCTL functions */ @@ -668,7 +668,7 @@ static int timblogiw_open(struct file *file) /* find the DMA channel */ fh->chan = dma_request_channel(mask, timblogiw_dma_filter_fn, - (void *)lw->pdata.dma_channel); + (void *)(uintptr_t)lw->pdata.dma_channel); if (!fh->chan) { dev_err(&vdev->dev, "Failed to get DMA channel\n"); kfree(fh); -- cgit v0.10.2 From b22374544b981b82f7319a02e6b718fc796e9cfa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 30 Dec 2010 08:01:01 -0300 Subject: [media] bttv-input: Add a note about PV951 RC When comparing lirc-i2c and ir-kbd-i2c/bttv-input logic, a difference was noticed. As lirc-i2c will be removed soon, store the difference on a comment inside ir-kbd-i2c, in order to preserve the knowledge we have about that remote controller. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 7f48306..97793b9 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -354,6 +354,18 @@ static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) return 0; dprintk(KERN_INFO DEVNAME ": key %02x\n", b); + /* + * NOTE: + * lirc_i2c maps the pv951 code as: + * addr = 0x61D6 + * cmd = bit_reverse (b) + * So, it seems that this device uses NEC extended + * I decided to not fix the table, due to two reasons: + * 1) Without the actual device, this is only a guess; + * 2) As the addr is not reported via I2C, nor can be changed, + * the device is bound to the vendor-provided RC. + */ + *ir_key = b; *ir_raw = b; return 1; -- cgit v0.10.2 From 1c0eb0ffb0d541bf05a4b422a629fa5986799313 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 30 Dec 2010 08:02:51 -0300 Subject: [media] cx88: Add RC logic for Leadtek PVR 2000 Currently, lirc-i2c has a decoding logic for Leadtek Remote Control. Move it to cx88, as we intend to remove lirc-i2c. For now, initialize LIRC remote keytable with RC_MAP_EMPTY, as we don't know its keymap yet. It would be nice to later check if is there any file on LIRC userspace with that keytable. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 4a3bf54..06f7d1d 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -68,6 +68,9 @@ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); #define ir_dprintk(fmt, arg...) if (ir_debug) \ printk(KERN_DEBUG "%s IR: " fmt , ir->core->name , ##arg) +#define dprintk(fmt, arg...) if (ir_debug) \ + printk(KERN_DEBUG "cx88 IR: " fmt , ##arg) + /* ---------------------------------------------------------------------- */ static void cx88_ir_handle_key(struct cx88_IR *ir) @@ -527,13 +530,47 @@ void cx88_ir_irq(struct cx88_core *core) ir_raw_event_handle(ir->dev); } +static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +{ + int flags, code; + + /* poll IR chip */ + flags = i2c_smbus_read_byte_data(ir->c, 0x10); + if (flags < 0) { + dprintk("read error\n"); + return 0; + } + /* key pressed ? */ + if (0 == (flags & 0x80)) + return 0; + + /* read actual key code */ + code = i2c_smbus_read_byte_data(ir->c, 0x00); + if (code < 0) { + dprintk("read error\n"); + return 0; + } + + dprintk("IR Key/Flags: (0x%02x/0x%02x)\n", + code & 0xff, flags & 0xff); + + *ir_key = code & 0xff; + *ir_raw = code; + return 1; +} + void cx88_i2c_init_ir(struct cx88_core *core) { struct i2c_board_info info; - const unsigned short addr_list[] = { + const unsigned short default_addr_list[] = { 0x18, 0x6b, 0x71, I2C_CLIENT_END }; + const unsigned short pvr2000_addr_list[] = { + 0x18, 0x1a, + I2C_CLIENT_END + }; + const unsigned short *addr_list = default_addr_list; const unsigned short *addrp; /* Instantiate the IR receiver device, if present */ if (0 != core->i2c_rc) @@ -542,6 +579,16 @@ void cx88_i2c_init_ir(struct cx88_core *core) memset(&info, 0, sizeof(struct i2c_board_info)); strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + switch (core->boardnr) { + case CX88_BOARD_LEADTEK_PVR2000: + addr_list = pvr2000_addr_list; + core->init_data.name = "cx88 Leadtek PVR 2000 remote"; + core->init_data.type = RC_TYPE_UNKNOWN; + core->init_data.get_key = get_key_pvr2000; + core->init_data.ir_codes = RC_MAP_EMPTY; + break; + } + /* * We can't call i2c_new_probed_device() because it uses * quick writes for probing and at least some RC receiver -- cgit v0.10.2 From e1e2c57565635310209566a31a300e593f74cc22 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 30 Dec 2010 08:31:10 -0300 Subject: [media] ivtv: Add Adaptec Remote Controller lirc-i2c implements a get key logic for the Adaptec Remote Controller, at address 0x6b. The only driver that seems to have an Adaptec device is ivtv: $ git grep -i adaptec drivers/media drivers/media/video/cs53l32a.c: * cs53l32a (Adaptec AVC-2010 and AVC-2410) i2c ivtv driver. drivers/media/video/cs53l32a.c: * Audio source switching for Adaptec AVC-2410 added by Trev Jackson drivers/media/video/cs53l32a.c: /* Set cs53l32a internal register for Adaptec 2010/2410 setup */ drivers/media/video/ivtv/ivtv-cards.c:/* Adaptec VideOh! AVC-2410 card */ drivers/media/video/ivtv/ivtv-cards.c: { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ADAPTEC, 0x0093 }, drivers/media/video/ivtv/ivtv-cards.c: .name = "Adaptec VideOh! AVC-2410", drivers/media/video/ivtv/ivtv-cards.c:/* Adaptec VideOh! AVC-2010 card */ drivers/media/video/ivtv/ivtv-cards.c: { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ADAPTEC, 0x0092 }, drivers/media/video/ivtv/ivtv-cards.c: .name = "Adaptec VideOh! AVC-2010", drivers/media/video/ivtv/ivtv-cards.h:#define IVTV_CARD_AVC2410 7 /* Adaptec AVC-2410 */ drivers/media/video/ivtv/ivtv-cards.h:#define IVTV_CARD_AVC2010 8 /* Adaptec AVD-2010 (No Tuner) */ drivers/media/video/ivtv/ivtv-cards.h:#define IVTV_PCI_ID_ADAPTEC 0x9005 drivers/media/video/ivtv/ivtv-driver.c: "\t\t\t 8 = Adaptec AVC-2410\n" drivers/media/video/ivtv/ivtv-driver.c: "\t\t\t 9 = Adaptec AVC-2010\n" drivers/media/video/ivtv/ivtv-i2c.c: 0x6b, /* Adaptec IR */ There are two Adaptec cards defined there, but AVC-2010 doesn't have a remote controller. So, the logic at lirc_i2c seems to be for Adaptec AVC-2410. As we'll remove lirc_i2c from kernel, move the getkey code to ivtv driver, and use it for AVC-2410. Reviewed-by: Andy Walls Acked-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c index b6f2a2b4..145e474 100644 --- a/drivers/media/video/ivtv/ivtv-cards.c +++ b/drivers/media/video/ivtv/ivtv-cards.c @@ -405,7 +405,8 @@ static const struct ivtv_card ivtv_card_avc2410 = { .hw_audio_ctrl = IVTV_HW_MSP34XX, .hw_muxer = IVTV_HW_CS53L32A, .hw_all = IVTV_HW_MSP34XX | IVTV_HW_CS53L32A | - IVTV_HW_SAA7115 | IVTV_HW_TUNER, + IVTV_HW_SAA7115 | IVTV_HW_TUNER | + IVTV_HW_I2C_IR_RX_ADAPTEC, .video_inputs = { { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h index 78eca992..e6f5c02 100644 --- a/drivers/media/video/ivtv/ivtv-cards.h +++ b/drivers/media/video/ivtv/ivtv-cards.h @@ -111,6 +111,7 @@ #define IVTV_HW_I2C_IR_RX_HAUP_INT (1 << 18) #define IVTV_HW_Z8F0811_IR_TX_HAUP (1 << 19) #define IVTV_HW_Z8F0811_IR_RX_HAUP (1 << 20) +#define IVTV_HW_I2C_IR_RX_ADAPTEC (1 << 21) #define IVTV_HW_Z8F0811_IR_HAUP (IVTV_HW_Z8F0811_IR_RX_HAUP | \ IVTV_HW_Z8F0811_IR_TX_HAUP) @@ -120,7 +121,8 @@ #define IVTV_HW_IR_RX_ANY (IVTV_HW_I2C_IR_RX_AVER | \ IVTV_HW_I2C_IR_RX_HAUP_EXT | \ IVTV_HW_I2C_IR_RX_HAUP_INT | \ - IVTV_HW_Z8F0811_IR_RX_HAUP) + IVTV_HW_Z8F0811_IR_RX_HAUP | \ + IVTV_HW_I2C_IR_RX_ADAPTEC) #define IVTV_HW_IR_TX_ANY (IVTV_HW_Z8F0811_IR_TX_HAUP) diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index 6817092..bf0d35a 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -94,6 +94,7 @@ #define IVTV_HAUP_INT_IR_RX_I2C_ADDR 0x18 #define IVTV_Z8F0811_IR_TX_I2C_ADDR 0x70 #define IVTV_Z8F0811_IR_RX_I2C_ADDR 0x71 +#define IVTV_ADAPTEC_IR_ADDR 0x6b /* This array should match the IVTV_HW_ defines */ static const u8 hw_addrs[] = { @@ -118,6 +119,7 @@ static const u8 hw_addrs[] = { IVTV_HAUP_INT_IR_RX_I2C_ADDR, /* IVTV_HW_I2C_IR_RX_HAUP_INT */ IVTV_Z8F0811_IR_TX_I2C_ADDR, /* IVTV_HW_Z8F0811_IR_TX_HAUP */ IVTV_Z8F0811_IR_RX_I2C_ADDR, /* IVTV_HW_Z8F0811_IR_RX_HAUP */ + IVTV_ADAPTEC_IR_ADDR, /* IVTV_HW_I2C_IR_RX_ADAPTEC */ }; /* This array should match the IVTV_HW_ defines */ @@ -143,8 +145,34 @@ static const char * const hw_devicenames[] = { "ir_video", /* IVTV_HW_I2C_IR_RX_HAUP_INT */ "ir_tx_z8f0811_haup", /* IVTV_HW_Z8F0811_IR_TX_HAUP */ "ir_rx_z8f0811_haup", /* IVTV_HW_Z8F0811_IR_RX_HAUP */ + "ir_video", /* IVTV_HW_I2C_IR_RX_ADAPTEC */ }; +static int get_key_adaptec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +{ + unsigned char keybuf[4]; + + keybuf[0] = 0x00; + i2c_master_send(ir->c, keybuf, 1); + /* poll IR chip */ + if (i2c_master_recv(ir->c, keybuf, sizeof(keybuf)) != sizeof(keybuf)) { + return 0; + } + + /* key pressed ? */ + if (keybuf[2] == 0xff) + return 0; + + /* remove repeat bit */ + keybuf[2] &= 0x7f; + keybuf[3] |= 0x80; + + *ir_key = (u32) keybuf; + *ir_raw = (u32) keybuf; + + return 1; +} + static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) { struct i2c_board_info info; @@ -190,6 +218,13 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) init_data->type = RC_TYPE_RC5; init_data->name = itv->card_name; break; + case IVTV_HW_I2C_IR_RX_ADAPTEC: + init_data->get_key = get_key_adaptec; + init_data->name = itv->card_name; + /* FIXME: The protocol and RC_MAP needs to be corrected */ + init_data->ir_codes = RC_MAP_EMPTY; + init_data->type = RC_TYPE_UNKNOWN; + break; } memset(&info, 0, sizeof(struct i2c_board_info)); @@ -219,7 +254,6 @@ struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv) 0x1a, /* Hauppauge IR external - collides with WM8739 */ 0x18, /* Hauppauge IR internal */ 0x71, /* Hauppauge IR (PVR150) */ - 0x6b, /* Adaptec IR */ I2C_CLIENT_END }; -- cgit v0.10.2 From 8a6334fc91de3f58bbd3051d6f088e7f71a3becd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 30 Dec 2010 10:25:12 -0300 Subject: [media] ivtv-i2c: Don't use IR legacy mode for Zilog IR The Zilog IR entries are already handled by IR new code. So, remove its usage from the legacy IR support. Acked-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index bf0d35a..2bed430 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -253,7 +253,6 @@ struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv) const unsigned short addr_list[] = { 0x1a, /* Hauppauge IR external - collides with WM8739 */ 0x18, /* Hauppauge IR internal */ - 0x71, /* Hauppauge IR (PVR150) */ I2C_CLIENT_END }; -- cgit v0.10.2 From 41ca2b1ac269e2ed64e2562b91fa61cab0b19e7a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 30 Dec 2010 08:37:33 -0300 Subject: [media] Remove staging/lirc/lirc_i2c driver This driver duplicates the same functionality found at ir-kbd-i2c. There were a few missing key parsers that were added by the previous patches. The only thing left on lirc_i2c driver is the IR parsing for Asus TV-Box and Creative/VisionTek BreakOut-Box. Those devices use pcf8574 chip for IR. They are old video adapters with TV tuners. Their code were never merged upstream, and they are not chipped anymore. So, it is very unlikely that someone would have interests on porting them to the Linux Kernel. Due to that, let's remove lirc_i2c, as all the remaining functionality are already mapped via ir-kbd-i2c. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/lirc/Kconfig b/drivers/staging/lirc/Kconfig index be97f7b..cdaff59 100644 --- a/drivers/staging/lirc/Kconfig +++ b/drivers/staging/lirc/Kconfig @@ -18,13 +18,6 @@ config LIRC_BT829 help Driver for the IR interface on BT829-based hardware -config LIRC_I2C - tristate "I2C Based IR Receivers" - depends on LIRC && I2C - help - Driver for I2C-based IR receivers, such as those commonly - found onboard Hauppauge PVR-150/250/350 video capture cards - config LIRC_IGORPLUGUSB tristate "Igor Cesko's USB IR Receiver" depends on LIRC && USB diff --git a/drivers/staging/lirc/Makefile b/drivers/staging/lirc/Makefile index 4da1f33..94af218 100644 --- a/drivers/staging/lirc/Makefile +++ b/drivers/staging/lirc/Makefile @@ -4,7 +4,6 @@ # Each configuration option enables a list of files. obj-$(CONFIG_LIRC_BT829) += lirc_bt829.o -obj-$(CONFIG_LIRC_I2C) += lirc_i2c.o obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb.o obj-$(CONFIG_LIRC_IMON) += lirc_imon.o obj-$(CONFIG_LIRC_IT87) += lirc_it87.o diff --git a/drivers/staging/lirc/lirc_i2c.c b/drivers/staging/lirc/lirc_i2c.c deleted file mode 100644 index 6df2c0e..0000000 --- a/drivers/staging/lirc/lirc_i2c.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - * lirc_i2c.c - * - * i2c IR driver for the onboard IR port on many TV tuner cards, including: - * -Flavors of the Hauppauge PVR-150/250/350 - * -Hauppauge HVR-1300 - * -PixelView (BT878P+W/FM) - * -KNC ONE TV Station/Anubis Typhoon TView Tuner - * -Asus TV-Box and Creative/VisionTek BreakOut-Box - * -Leadtek Winfast PVR2000 - * - * Copyright (c) 2000 Gerd Knorr - * modified for PixelView (BT878P+W/FM) by - * Michal Kochanowicz - * Christoph Bartelmus - * modified for KNC ONE TV Station/Anubis Typhoon TView Tuner by - * Ulrich Mueller - * modified for Asus TV-Box and Creative/VisionTek BreakOut-Box by - * Stefan Jahn - * modified for inclusion into kernel sources by - * Jerome Brock - * modified for Leadtek Winfast PVR2000 by - * Thomas Reitmayr (treitmayr@yahoo.com) - * modified for Hauppauge HVR-1300 by - * Jan Frey (jfrey@gmx.de) - * - * parts are cut&pasted from the old lirc_haup.c driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -struct IR { - struct lirc_driver l; - struct i2c_client c; - int nextkey; - unsigned char b[3]; - unsigned char bits; - unsigned char flag; -}; - -#define DEVICE_NAME "lirc_i2c" - -/* module parameters */ -static int debug; /* debug output */ -static int minor = -1; /* minor number */ - -#define dprintk(fmt, args...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG DEVICE_NAME ": " fmt, \ - ## args); \ - } while (0) - -static int reverse(int data, int bits) -{ - int i; - int c; - - for (c = 0, i = 0; i < bits; i++) - c |= ((data & (1<c, keybuf, 1); - /* poll IR chip */ - if (i2c_master_recv(&ir->c, keybuf, sizeof(keybuf)) != sizeof(keybuf)) { - dprintk("read error\n"); - return -EIO; - } - - dprintk("key (0x%02x%02x%02x%02x)\n", - keybuf[0], keybuf[1], keybuf[2], keybuf[3]); - - /* key pressed ? */ - if (keybuf[2] == 0xff) - return -ENODATA; - - /* remove repeat bit */ - keybuf[2] &= 0x7f; - keybuf[3] |= 0x80; - - lirc_buffer_write(buf, keybuf); - return 0; -} - -static int add_to_buf_pcf8574(void *data, struct lirc_buffer *buf) -{ - struct IR *ir = data; - int rc; - unsigned char all, mask; - unsigned char key; - - /* compute all valid bits (key code + pressed/release flag) */ - all = ir->bits | ir->flag; - - /* save IR writable mask bits */ - mask = i2c_smbus_read_byte(&ir->c) & ~all; - - /* send bit mask */ - rc = i2c_smbus_write_byte(&ir->c, (0xff & all) | mask); - - /* receive scan code */ - rc = i2c_smbus_read_byte(&ir->c); - - if (rc == -1) { - dprintk("%s read error\n", ir->c.name); - return -EIO; - } - - /* drop duplicate polls */ - if (ir->b[0] == (rc & all)) - return -ENODATA; - - ir->b[0] = rc & all; - - dprintk("%s key 0x%02X %s\n", ir->c.name, rc & ir->bits, - (rc & ir->flag) ? "released" : "pressed"); - - /* ignore released buttons */ - if (rc & ir->flag) - return -ENODATA; - - /* set valid key code */ - key = rc & ir->bits; - lirc_buffer_write(buf, &key); - return 0; -} - -/* common for Hauppauge IR receivers */ -static int add_to_buf_haup_common(void *data, struct lirc_buffer *buf, - unsigned char *keybuf, int size, int offset) -{ - struct IR *ir = data; - __u16 code; - unsigned char codes[2]; - int ret; - - /* poll IR chip */ - ret = i2c_master_recv(&ir->c, keybuf, size); - if (ret == size) { - ir->b[0] = keybuf[offset]; - ir->b[1] = keybuf[offset+1]; - ir->b[2] = keybuf[offset+2]; - if (ir->b[0] != 0x00 && ir->b[1] != 0x00) - dprintk("key (0x%02x/0x%02x)\n", ir->b[0], ir->b[1]); - } else { - dprintk("read error (ret=%d)\n", ret); - /* keep last successful read buffer */ - } - - /* key pressed ? */ - if ((ir->b[0] & 0x80) == 0) - return -ENODATA; - - /* look what we have */ - code = (((__u16)ir->b[0]&0x7f)<<6) | (ir->b[1]>>2); - - codes[0] = (code >> 8) & 0xff; - codes[1] = code & 0xff; - - /* return it */ - dprintk("sending code 0x%02x%02x to lirc\n", codes[0], codes[1]); - lirc_buffer_write(buf, codes); - return 0; -} - -/* specific for the Hauppauge PVR150 IR receiver */ -static int add_to_buf_haup_pvr150(void *data, struct lirc_buffer *buf) -{ - unsigned char keybuf[6]; - /* fetch 6 bytes, first relevant is at offset 3 */ - return add_to_buf_haup_common(data, buf, keybuf, 6, 3); -} - -/* used for all Hauppauge IR receivers but the PVR150 */ -static int add_to_buf_haup(void *data, struct lirc_buffer *buf) -{ - unsigned char keybuf[3]; - /* fetch 3 bytes, first relevant is at offset 0 */ - return add_to_buf_haup_common(data, buf, keybuf, 3, 0); -} - - -static int add_to_buf_pvr2000(void *data, struct lirc_buffer *buf) -{ - struct IR *ir = data; - unsigned char key; - s32 flags; - s32 code; - - /* poll IR chip */ - flags = i2c_smbus_read_byte_data(&ir->c, 0x10); - if (-1 == flags) { - dprintk("read error\n"); - return -ENODATA; - } - /* key pressed ? */ - if (0 == (flags & 0x80)) - return -ENODATA; - - /* read actual key code */ - code = i2c_smbus_read_byte_data(&ir->c, 0x00); - if (-1 == code) { - dprintk("read error\n"); - return -ENODATA; - } - - key = code & 0xFF; - - dprintk("IR Key/Flags: (0x%02x/0x%02x)\n", key, flags & 0xFF); - - /* return it */ - lirc_buffer_write(buf, &key); - return 0; -} - -static int add_to_buf_pixelview(void *data, struct lirc_buffer *buf) -{ - struct IR *ir = data; - unsigned char key; - - /* poll IR chip */ - if (1 != i2c_master_recv(&ir->c, &key, 1)) { - dprintk("read error\n"); - return -1; - } - dprintk("key %02x\n", key); - - /* return it */ - lirc_buffer_write(buf, &key); - return 0; -} - -static int add_to_buf_pv951(void *data, struct lirc_buffer *buf) -{ - struct IR *ir = data; - unsigned char key; - unsigned char codes[4]; - - /* poll IR chip */ - if (1 != i2c_master_recv(&ir->c, &key, 1)) { - dprintk("read error\n"); - return -ENODATA; - } - /* ignore 0xaa */ - if (key == 0xaa) - return -ENODATA; - dprintk("key %02x\n", key); - - codes[0] = 0x61; - codes[1] = 0xD6; - codes[2] = reverse(key, 8); - codes[3] = (~codes[2])&0xff; - - lirc_buffer_write(buf, codes); - return 0; -} - -static int add_to_buf_knc1(void *data, struct lirc_buffer *buf) -{ - static unsigned char last_key = 0xFF; - struct IR *ir = data; - unsigned char key; - - /* poll IR chip */ - if (1 != i2c_master_recv(&ir->c, &key, 1)) { - dprintk("read error\n"); - return -ENODATA; - } - - /* - * it seems that 0xFE indicates that a button is still held - * down, while 0xFF indicates that no button is held - * down. 0xFE sequences are sometimes interrupted by 0xFF - */ - - dprintk("key %02x\n", key); - - if (key == 0xFF) - return -ENODATA; - - if (key == 0xFE) - key = last_key; - - last_key = key; - lirc_buffer_write(buf, &key); - - return 0; -} - -static int set_use_inc(void *data) -{ - struct IR *ir = data; - - dprintk("%s called\n", __func__); - - /* lock bttv in memory while /dev/lirc is in use */ - i2c_use_client(&ir->c); - - return 0; -} - -static void set_use_dec(void *data) -{ - struct IR *ir = data; - - dprintk("%s called\n", __func__); - - i2c_release_client(&ir->c); -} - -static struct lirc_driver lirc_template = { - .name = "lirc_i2c", - .set_use_inc = set_use_inc, - .set_use_dec = set_use_dec, - .dev = NULL, - .owner = THIS_MODULE, -}; - -static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id); -static int ir_remove(struct i2c_client *client); -static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg); - -static const struct i2c_device_id ir_receiver_id[] = { - /* Generic entry for any IR receiver */ - { "ir_video", 0 }, - /* IR device specific entries could be added here */ - { } -}; - -static struct i2c_driver driver = { - .driver = { - .owner = THIS_MODULE, - .name = "i2c ir driver", - }, - .probe = ir_probe, - .remove = ir_remove, - .id_table = ir_receiver_id, - .command = ir_command, -}; - -static void pcf_probe(struct i2c_client *client, struct IR *ir) -{ - int ret1, ret2, ret3, ret4; - - ret1 = i2c_smbus_write_byte(client, 0xff); - ret2 = i2c_smbus_read_byte(client); - ret3 = i2c_smbus_write_byte(client, 0x00); - ret4 = i2c_smbus_read_byte(client); - - /* in the Asus TV-Box: bit 1-0 */ - if (((ret2 & 0x03) == 0x03) && ((ret4 & 0x03) == 0x00)) { - ir->bits = (unsigned char) ~0x07; - ir->flag = 0x04; - /* in the Creative/VisionTek BreakOut-Box: bit 7-6 */ - } else if (((ret2 & 0xc0) == 0xc0) && ((ret4 & 0xc0) == 0x00)) { - ir->bits = (unsigned char) ~0xe0; - ir->flag = 0x20; - } - - return; -} - -static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct IR *ir; - struct i2c_adapter *adap = client->adapter; - unsigned short addr = client->addr; - int retval; - - ir = kzalloc(sizeof(struct IR), GFP_KERNEL); - if (!ir) - return -ENOMEM; - memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver)); - memcpy(&ir->c, client, sizeof(struct i2c_client)); - - i2c_set_clientdata(client, ir); - ir->l.data = ir; - ir->l.minor = minor; - ir->l.sample_rate = 10; - ir->l.dev = &ir->c.dev; - ir->nextkey = -1; - - switch (addr) { - case 0x64: - strlcpy(ir->c.name, "Pixelview IR", I2C_NAME_SIZE); - ir->l.code_length = 8; - ir->l.add_to_buf = add_to_buf_pixelview; - break; - case 0x4b: - strlcpy(ir->c.name, "PV951 IR", I2C_NAME_SIZE); - ir->l.code_length = 32; - ir->l.add_to_buf = add_to_buf_pv951; - break; - case 0x71: - if (adap->id == I2C_HW_B_CX2388x) - strlcpy(ir->c.name, "Hauppauge HVR1300", I2C_NAME_SIZE); - else /* bt8xx or cx2341x */ - /* - * The PVR150 IR receiver uses the same protocol as - * other Hauppauge cards, but the data flow is - * different, so we need to deal with it by its own. - */ - strlcpy(ir->c.name, "Hauppauge PVR150", I2C_NAME_SIZE); - ir->l.code_length = 13; - ir->l.add_to_buf = add_to_buf_haup_pvr150; - break; - case 0x6b: - strlcpy(ir->c.name, "Adaptec IR", I2C_NAME_SIZE); - ir->l.code_length = 32; - ir->l.add_to_buf = add_to_buf_adap; - break; - case 0x18: - case 0x1a: - if (adap->id == I2C_HW_B_CX2388x) { - strlcpy(ir->c.name, "Leadtek IR", I2C_NAME_SIZE); - ir->l.code_length = 8; - ir->l.add_to_buf = add_to_buf_pvr2000; - } else { /* bt8xx or cx2341x */ - strlcpy(ir->c.name, "Hauppauge IR", I2C_NAME_SIZE); - ir->l.code_length = 13; - ir->l.add_to_buf = add_to_buf_haup; - } - break; - case 0x30: - strlcpy(ir->c.name, "KNC ONE IR", I2C_NAME_SIZE); - ir->l.code_length = 8; - ir->l.add_to_buf = add_to_buf_knc1; - break; - case 0x21: - case 0x23: - pcf_probe(client, ir); - strlcpy(ir->c.name, "TV-Box IR", I2C_NAME_SIZE); - ir->l.code_length = 8; - ir->l.add_to_buf = add_to_buf_pcf8574; - break; - default: - /* shouldn't happen */ - printk("lirc_i2c: Huh? unknown i2c address (0x%02x)?\n", addr); - kfree(ir); - return -EINVAL; - } - printk(KERN_INFO "lirc_i2c: chip 0x%x found @ 0x%02x (%s)\n", - adap->id, addr, ir->c.name); - - retval = lirc_register_driver(&ir->l); - - if (retval < 0) { - printk(KERN_ERR "lirc_i2c: failed to register driver!\n"); - kfree(ir); - return retval; - } - - ir->l.minor = retval; - - return 0; -} - -static int ir_remove(struct i2c_client *client) -{ - struct IR *ir = i2c_get_clientdata(client); - - /* unregister device */ - lirc_unregister_driver(ir->l.minor); - - /* free memory */ - kfree(ir); - return 0; -} - -static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - /* nothing */ - return 0; -} - -static int __init lirc_i2c_init(void) -{ - i2c_add_driver(&driver); - return 0; -} - -static void __exit lirc_i2c_exit(void) -{ - i2c_del_driver(&driver); -} - -MODULE_DESCRIPTION("Infrared receiver driver for Hauppauge and " - "Pixelview cards (i2c stack)"); -MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, " - "Ulrich Mueller, Stefan Jahn, Jerome Brock"); -MODULE_LICENSE("GPL"); - -module_param(minor, int, S_IRUGO); -MODULE_PARM_DESC(minor, "Preferred minor device number"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging messages"); - -module_init(lirc_i2c_init); -module_exit(lirc_i2c_exit); -- cgit v0.10.2 From ea6c06033f01216df504b0f337a350778a3bc80e Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Tue, 28 Dec 2010 22:46:13 -0300 Subject: [media] hdpvr: Add I2C and ir-kdb-i2c registration of the Zilog Z8 IR chip Adds I2C registration of the Zilog Z8F0811 IR microcontroller for either lirc_zilog or ir-kbd-i2c to use. This is a required step in removing lirc_zilog's use of the deprecated struct i2c_adapter.id field. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index b70d6af..f7d1ee5 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c @@ -385,6 +385,11 @@ static int hdpvr_probe(struct usb_interface *interface, v4l2_err(&dev->v4l2_dev, "registering i2c adapter failed\n"); goto error; } + + /* until i2c is working properly */ + retval = 0; /* hdpvr_register_i2c_ir(dev); */ + if (retval < 0) + v4l2_err(&dev->v4l2_dev, "registering i2c IR devices failed\n"); #endif /* CONFIG_I2C */ /* let the user know what node this device is now attached to */ diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c index 409de11..24966aa 100644 --- a/drivers/media/video/hdpvr/hdpvr-i2c.c +++ b/drivers/media/video/hdpvr/hdpvr-i2c.c @@ -4,6 +4,9 @@ * * Copyright (C) 2008 Janne Grunau (j@jannau.net) * + * IR device registration code is + * Copyright (C) 2010 Andy Walls + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. @@ -22,6 +25,56 @@ #define REQTYPE_I2C_WRITE 0xb0 #define REQTYPE_I2C_WRITE_STATT 0xd0 +#define Z8F0811_IR_TX_I2C_ADDR 0x70 +#define Z8F0811_IR_RX_I2C_ADDR 0x71 + +static const u8 ir_i2c_addrs[] = { + Z8F0811_IR_TX_I2C_ADDR, + Z8F0811_IR_RX_I2C_ADDR, +}; + +static const char * const ir_devicenames[] = { + "ir_tx_z8f0811_hdpvr", + "ir_rx_z8f0811_hdpvr", +}; + +static int hdpvr_new_i2c_ir(struct hdpvr_device *dev, struct i2c_adapter *adap, + const char *type, u8 addr) +{ + struct i2c_board_info info; + struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data; + unsigned short addr_list[2] = { addr, I2C_CLIENT_END }; + + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, type, I2C_NAME_SIZE); + + /* Our default information for ir-kbd-i2c.c to use */ + switch (addr) { + case Z8F0811_IR_RX_I2C_ADDR: + init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; + init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; + init_data->type = RC_TYPE_RC5; + init_data->name = "HD PVR"; + info.platform_data = init_data; + break; + } + + return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ? + -1 : 0; +} + +int hdpvr_register_i2c_ir(struct hdpvr_device *dev) +{ + int i; + int ret = 0; + + for (i = 0; i < ARRAY_SIZE(ir_i2c_addrs); i++) + ret += hdpvr_new_i2c_ir(dev, dev->i2c_adapter, + ir_devicenames[i], ir_i2c_addrs[i]); + + return ret; +} + static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr, char *data, int len) { diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h index 5efc963..37f1e4c 100644 --- a/drivers/media/video/hdpvr/hdpvr.h +++ b/drivers/media/video/hdpvr/hdpvr.h @@ -16,6 +16,7 @@ #include #include +#include #define HDPVR_MAJOR_VERSION 0 #define HDPVR_MINOR_VERSION 2 @@ -109,6 +110,9 @@ struct hdpvr_device { /* I2C lock */ struct mutex i2c_mutex; + /* For passing data to ir-kbd-i2c */ + struct IR_i2c_init_data ir_i2c_init_data; + /* usb control transfer buffer and lock */ struct mutex usbc_mutex; u8 *usbc_buf; @@ -306,6 +310,8 @@ int hdpvr_cancel_queue(struct hdpvr_device *dev); /* i2c adapter registration */ int hdpvr_register_i2c_adapter(struct hdpvr_device *dev); +int hdpvr_register_i2c_ir(struct hdpvr_device *dev); + /*========================================================================*/ /* buffer management */ int hdpvr_free_buffers(struct hdpvr_device *dev); -- cgit v0.10.2 From a9cd591e29b6b50e1212de7b7a86ccd270f5c2a6 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Tue, 28 Dec 2010 22:47:46 -0300 Subject: [media] ir-kbd-i2c: Add HD PVR IR Rx support to ir-kbd-i2c Add HD PVR IR Rx support to ir-kbd-i2c Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index dd54c3d..c87b6bc 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -449,6 +449,7 @@ static const struct i2c_device_id ir_kbd_id[] = { { "ir_video", 0 }, /* IR device specific entries should be added here */ { "ir_rx_z8f0811_haup", 0 }, + { "ir_rx_z8f0811_hdpvr", 0 }, { } }; -- cgit v0.10.2 From d7c7235695ef9cbbdc20bdeb8554dbf10f576ca1 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Tue, 28 Dec 2010 22:49:50 -0300 Subject: [media] lirc_zilog: Remove use of deprecated struct i2c_adapter.id field Remove use of deprecated struct i2c_adapter.id field. In the process, perform different detection of the HD PVR's Z8 IR microcontroller versus the other Hauppauge cards with the Z8 IR microcontroller. Also added a comment about probe() function behavior that needs to be fixed. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/lirc/lirc_zilog.c b/drivers/staging/lirc/lirc_zilog.c index 52be6de..ad29bb1 100644 --- a/drivers/staging/lirc/lirc_zilog.c +++ b/drivers/staging/lirc/lirc_zilog.c @@ -66,6 +66,7 @@ struct IR { /* Device info */ struct mutex ir_lock; int open; + bool is_hdpvr; /* RX device */ struct i2c_client c_rx; @@ -206,16 +207,12 @@ static int add_to_buf(struct IR *ir) } /* key pressed ? */ -#ifdef I2C_HW_B_HDPVR - if (ir->c_rx.adapter->id == I2C_HW_B_HDPVR) { + if (ir->is_hdpvr) { if (got_data && (keybuf[0] == 0x80)) return 0; else if (got_data && (keybuf[0] == 0x00)) return -ENODATA; } else if ((ir->b[0] & 0x80) == 0) -#else - if ((ir->b[0] & 0x80) == 0) -#endif return got_data ? 0 : -ENODATA; /* look what we have */ @@ -841,15 +838,15 @@ static int send_code(struct IR *ir, unsigned int code, unsigned int key) return ret < 0 ? ret : -EFAULT; } -#ifdef I2C_HW_B_HDPVR /* * The sleep bits aren't necessary on the HD PVR, and in fact, the * last i2c_master_recv always fails with a -5, so for now, we're * going to skip this whole mess and say we're done on the HD PVR */ - if (ir->c_rx.adapter->id == I2C_HW_B_HDPVR) - goto done; -#endif + if (ir->is_hdpvr) { + dprintk("sent code %u, key %u\n", code, key); + return 0; + } /* * This bit NAKs until the device is ready, so we retry it @@ -1111,12 +1108,14 @@ static int ir_remove(struct i2c_client *client); static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id); static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg); +#define ID_FLAG_TX 0x01 +#define ID_FLAG_HDPVR 0x02 + static const struct i2c_device_id ir_transceiver_id[] = { - /* Generic entry for any IR transceiver */ - { "ir_video", 0 }, - /* IR device specific entries should be added here */ - { "ir_tx_z8f0811_haup", 0 }, - { "ir_rx_z8f0811_haup", 0 }, + { "ir_tx_z8f0811_haup", ID_FLAG_TX }, + { "ir_rx_z8f0811_haup", 0 }, + { "ir_tx_z8f0811_hdpvr", ID_FLAG_HDPVR | ID_FLAG_TX }, + { "ir_rx_z8f0811_hdpvr", ID_FLAG_HDPVR }, { } }; @@ -1196,10 +1195,25 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) int ret; int have_rx = 0, have_tx = 0; - dprintk("%s: adapter id=0x%x, client addr=0x%02x\n", - __func__, adap->id, client->addr); + dprintk("%s: adapter name (%s) nr %d, i2c_device_id name (%s), " + "client addr=0x%02x\n", + __func__, adap->name, adap->nr, id->name, client->addr); /* + * FIXME - This probe function probes both the Tx and Rx + * addresses of the IR microcontroller. + * + * However, the I2C subsystem is passing along one I2C client at a + * time, based on matches to the ir_transceiver_id[] table above. + * The expectation is that each i2c_client address will be probed + * individually by drivers so the I2C subsystem can mark all client + * addresses as claimed or not. + * + * This probe routine causes only one of the client addresses, TX or RX, + * to be claimed. This will cause a problem if the I2C subsystem is + * subsequently triggered to probe unclaimed clients again. + */ + /* * The external IR receiver is at i2c address 0x71. * The IR transmitter is at 0x70. */ @@ -1241,6 +1255,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) mutex_init(&ir->ir_lock); mutex_init(&ir->buf_lock); ir->need_boot = 1; + ir->is_hdpvr = (id->driver_data & ID_FLAG_HDPVR) ? true : false; memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver)); ir->l.minor = -1; -- cgit v0.10.2 From 6a23a520c07ba556ea2317b1f72f3d2eb002f991 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 30 Dec 2010 09:05:12 -0300 Subject: [media] cx88: Remove the obsolete i2c_adapter.id field Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index f53836b..a1fe0ab 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -146,7 +146,6 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) core->i2c_adap.dev.parent = &pci->dev; strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name)); core->i2c_adap.owner = THIS_MODULE; - core->i2c_adap.id = I2C_HW_B_CX2388x; core->i2c_algo.udelay = i2c_udelay; core->i2c_algo.data = core; i2c_set_adapdata(&core->i2c_adap, &core->v4l2_dev); diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c index ec5476d..d77f8ec 100644 --- a/drivers/media/video/cx88/cx88-vp3054-i2c.c +++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c @@ -125,7 +125,6 @@ int vp3054_i2c_probe(struct cx8802_dev *dev) strlcpy(vp3054_i2c->adap.name, core->name, sizeof(vp3054_i2c->adap.name)); vp3054_i2c->adap.owner = THIS_MODULE; - vp3054_i2c->adap.id = I2C_HW_B_CX2388x; vp3054_i2c->algo.data = dev; i2c_set_adapdata(&vp3054_i2c->adap, dev); vp3054_i2c->adap.algo_data = &vp3054_i2c->algo; -- cgit v0.10.2 From abfd013b665d21f57bc4b2e455b23c4cece0df9f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 30 Dec 2010 09:51:19 -0300 Subject: [media] staging/lirc: Update lirc TODO files Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/lirc/TODO.lirc_i2c b/drivers/staging/lirc/TODO.lirc_i2c deleted file mode 100644 index 1f0a6ff..0000000 --- a/drivers/staging/lirc/TODO.lirc_i2c +++ /dev/null @@ -1,3 +0,0 @@ -lirc_i2c provides support for some drivers that have already a RC -driver under drivers/media/video. It should be integrated into those -drivers, in special with drivers/media/video/ir-kbd-i2c.c. diff --git a/drivers/staging/lirc/TODO.lirc_zilog b/drivers/staging/lirc/TODO.lirc_zilog new file mode 100644 index 0000000..6aa312d --- /dev/null +++ b/drivers/staging/lirc/TODO.lirc_zilog @@ -0,0 +1,13 @@ +The binding between hdpvr and lirc_zilog is currently disabled, +due to an OOPS reported a few years ago when both the hdpvr and cx18 +drivers were loaded in his system. More details can be seen at: + http://www.mail-archive.com/linux-media@vger.kernel.org/msg09163.html +More tests need to be done, in order to fix the reported issue. + +There's a conflict between ir-kbd-i2c: Both provide support for RX events. +Such conflict needs to be fixed, before moving it out of staging. + +The way I2C probe works, it will try to register the driver twice, one +for RX and another for TX. The logic needs to be fixed to avoid such +issue. + -- cgit v0.10.2 From 9804ed9e840c461f88b290dea43173e3eed37102 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 30 Dec 2010 11:58:37 -0300 Subject: [media] ivtv-i2c: Fix two warnings Fix two gcc warnings: drivers/media/video/ivtv/ivtv-i2c.c:170: warning: cast from pointer to integer of different size drivers/media/video/ivtv/ivtv-i2c.c:171: warning: cast from pointer to integer of different size $ gcc --version gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-48) They seem bogus, but, as the original code also has problems with LE/BE, just change its implementation to be clear. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index 2bed430..e103b8f 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -167,8 +167,8 @@ static int get_key_adaptec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) keybuf[2] &= 0x7f; keybuf[3] |= 0x80; - *ir_key = (u32) keybuf; - *ir_raw = (u32) keybuf; + *ir_key = keybuf[3] | keybuf[2] << 8 | keybuf[1] << 16 |keybuf[0] << 24; + *ir_raw = *ir_key; return 1; } -- cgit v0.10.2 From f7b74f76a3a5bcad4d2e8db76834253a63977545 Mon Sep 17 00:00:00 2001 From: David Cohen Date: Wed, 8 Dec 2010 09:13:58 -0300 Subject: [media] ov9640: use macro to request OmniVision OV9640 sensor private data This cleanup patch creates macro to request OmniVision OV9640 private data, which increases readability. Signed-off-by: David Cohen Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c index 99e9e1d..c6d8e8a 100644 --- a/drivers/media/video/ov9640.c +++ b/drivers/media/video/ov9640.c @@ -31,6 +31,8 @@ #include "ov9640.h" +#define to_ov9640_sensor(sd) container_of(sd, struct ov9640_priv, subdev) + /* default register setup */ static const struct ov9640_reg ov9640_regs_dflt[] = { { OV9640_COM5, OV9640_COM5_SYSCLK | OV9640_COM5_LONGEXP }, @@ -308,9 +310,7 @@ static unsigned long ov9640_query_bus_param(struct soc_camera_device *icd) /* Get status of additional camera capabilities */ static int ov9640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov9640_priv *priv = container_of(i2c_get_clientdata(client), - struct ov9640_priv, subdev); + struct ov9640_priv *priv = to_ov9640_sensor(sd); switch (ctrl->id) { case V4L2_CID_VFLIP: @@ -327,8 +327,7 @@ static int ov9640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int ov9640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov9640_priv *priv = container_of(i2c_get_clientdata(client), - struct ov9640_priv, subdev); + struct ov9640_priv *priv = to_ov9640_sensor(sd); int ret = 0; @@ -360,9 +359,7 @@ static int ov9640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int ov9640_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *id) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov9640_priv *priv = container_of(i2c_get_clientdata(client), - struct ov9640_priv, subdev); + struct ov9640_priv *priv = to_ov9640_sensor(sd); id->ident = priv->model; id->revision = priv->revision; -- cgit v0.10.2 From 63c9718c1a4595d51f5b70ed4aed6cee5aea875b Mon Sep 17 00:00:00 2001 From: David Cohen Date: Wed, 8 Dec 2010 09:13:59 -0300 Subject: [media] ov9640: fix OmniVision OV9640 sensor driver's priv data retrieving OmniVision OV9640 driver wasn't requesting properly its private data on I2C remove and video_probe functions. It was retrieving the V4L2 subdev struct address instead of priv struct's one. This patch fixes such problem. Signed-off-by: David Cohen Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c index c6d8e8a..53d88a2 100644 --- a/drivers/media/video/ov9640.c +++ b/drivers/media/video/ov9640.c @@ -651,7 +651,8 @@ static int ov9640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) static int ov9640_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { - struct ov9640_priv *priv = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov9640_priv *priv = to_ov9640_sensor(sd); u8 pid, ver, midh, midl; const char *devname; int ret = 0; @@ -788,7 +789,8 @@ static int ov9640_probe(struct i2c_client *client, static int ov9640_remove(struct i2c_client *client) { - struct ov9640_priv *priv = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov9640_priv *priv = to_ov9640_sensor(sd); kfree(priv); return 0; -- cgit v0.10.2 From c85bb69af09988f728aca825c11267c9d06ba32e Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 30 Dec 2010 08:37:06 -0300 Subject: [media] v4l: ov772x: simplify pointer dereference Use a more direct way to obtain a pointer to struct ov772x_priv, where the subdevice is available. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index a84b770..48895ef 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c @@ -600,7 +600,7 @@ static int ov772x_reset(struct i2c_client *client) static int ov772x_s_stream(struct v4l2_subdev *sd, int enable) { struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov772x_priv *priv = to_ov772x(client); + struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); if (!enable) { ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); @@ -645,8 +645,7 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) static int ov772x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov772x_priv *priv = to_ov772x(client); + struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); switch (ctrl->id) { case V4L2_CID_VFLIP: @@ -665,7 +664,7 @@ static int ov772x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov772x_priv *priv = to_ov772x(client); + struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); int ret = 0; u8 val; @@ -715,8 +714,7 @@ static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int ov772x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *id) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov772x_priv *priv = to_ov772x(client); + struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); id->ident = priv->model; id->revision = 0; @@ -955,7 +953,7 @@ static int ov772x_g_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov772x_priv *priv = to_ov772x(client); + struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); if (!priv->win || !priv->cfmt) { u32 width = VGA_WIDTH, height = VGA_HEIGHT; @@ -978,7 +976,7 @@ static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov772x_priv *priv = to_ov772x(client); + struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); int ret = ov772x_set_params(client, &mf->width, &mf->height, mf->code); @@ -991,8 +989,7 @@ static int ov772x_s_fmt(struct v4l2_subdev *sd, static int ov772x_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov772x_priv *priv = to_ov772x(client); + struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev); const struct ov772x_win_size *win; int i; -- cgit v0.10.2 From b6a633c18ba83c0c8e96759a31d356bfb77e2b5f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Sat, 25 Dec 2010 17:40:26 -0300 Subject: [media] v4l: soc-camera: switch to .unlocked_ioctl Use the V4L mutex infrastructure in soc-camera core and drivers and switch to .unlocked_ioctl. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c index 5e486a8..bc0c23a 100644 --- a/drivers/media/video/mx1_camera.c +++ b/drivers/media/video/mx1_camera.c @@ -382,10 +382,9 @@ static void mx1_camera_init_videobuf(struct videobuf_queue *q, struct mx1_camera_dev *pcdev = ici->priv; videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, icd->dev.parent, - &pcdev->lock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_NONE, - sizeof(struct mx1_buffer), icd, NULL); + &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_NONE, + sizeof(struct mx1_buffer), icd, &icd->video_lock); } static int mclk_get_divisor(struct mx1_camera_dev *pcdev) diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c index 13565cb..4eab1c6 100644 --- a/drivers/media/video/mx2_camera.c +++ b/drivers/media/video/mx2_camera.c @@ -683,7 +683,8 @@ static void mx2_camera_init_videobuf(struct videobuf_queue *q, videobuf_queue_dma_contig_init(q, &mx2_videobuf_ops, pcdev->dev, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_NONE, sizeof(struct mx2_buffer), icd, NULL); + V4L2_FIELD_NONE, sizeof(struct mx2_buffer), + icd, &icd->video_lock); } #define MX2_BUS_FLAGS (SOCAM_DATAWIDTH_8 | \ diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index 330d42e..b9cb4a4 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c @@ -443,7 +443,7 @@ static void mx3_camera_init_videobuf(struct videobuf_queue *q, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, sizeof(struct mx3_camera_buffer), icd, - NULL); + &icd->video_lock); } /* First part of ipu_csi_init_interface() */ diff --git a/drivers/media/video/omap1_camera.c b/drivers/media/video/omap1_camera.c index cbfd07f..0a2fb2b 100644 --- a/drivers/media/video/omap1_camera.c +++ b/drivers/media/video/omap1_camera.c @@ -1365,12 +1365,12 @@ static void omap1_cam_init_videobuf(struct videobuf_queue *q, videobuf_queue_dma_contig_init(q, &omap1_videobuf_ops, icd->dev.parent, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, - sizeof(struct omap1_cam_buf), icd, NULL); + sizeof(struct omap1_cam_buf), icd, &icd->video_lock); else videobuf_queue_sg_init(q, &omap1_videobuf_ops, icd->dev.parent, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, - sizeof(struct omap1_cam_buf), icd, NULL); + sizeof(struct omap1_cam_buf), icd, &icd->video_lock); /* use videobuf mode (auto)selected with the module parameter */ pcdev->vb_mode = sg_mode ? OMAP1_CAM_DMA_SG : OMAP1_CAM_DMA_CONTIG; diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index c143ed0..0268677 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -852,7 +852,7 @@ static void pxa_camera_init_videobuf(struct videobuf_queue *q, */ videobuf_queue_sg_init(q, &pxa_videobuf_ops, NULL, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, - sizeof(struct pxa_buffer), icd, NULL); + sizeof(struct pxa_buffer), icd, &icd->video_lock); } static u32 mclk_get_divisor(struct platform_device *pdev, diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 2486520..954222b 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -1786,7 +1786,7 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q, V4L2_BUF_TYPE_VIDEO_CAPTURE, pcdev->field, sizeof(struct sh_mobile_ceu_buffer), - icd, NULL); + icd, &icd->video_lock); } static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd, diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 052bd6d..aba4ce9 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -352,12 +352,6 @@ static int soc_camera_open(struct file *file) return -EINVAL; } - /* - * Protect against icd->ops->remove() until we module_get() both - * drivers. - */ - mutex_lock(&icd->video_lock); - icd->use_count++; /* Now we really have to activate the camera */ @@ -412,8 +406,6 @@ static int soc_camera_open(struct file *file) file->private_data = icd; dev_dbg(&icd->dev, "camera device open\n"); - mutex_unlock(&icd->video_lock); - return 0; /* @@ -429,7 +421,6 @@ eiciadd: icl->power(icd->pdev, 0); epower: icd->use_count--; - mutex_unlock(&icd->video_lock); module_put(ici->ops->owner); return ret; @@ -440,7 +431,6 @@ static int soc_camera_close(struct file *file) struct soc_camera_device *icd = file->private_data; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - mutex_lock(&icd->video_lock); icd->use_count--; if (!icd->use_count) { struct soc_camera_link *icl = to_soc_camera_link(icd); @@ -457,8 +447,6 @@ static int soc_camera_close(struct file *file) if (icd->streamer == file) icd->streamer = NULL; - mutex_unlock(&icd->video_lock); - module_put(ici->ops->owner); dev_dbg(&icd->dev, "camera device close\n"); @@ -517,7 +505,7 @@ static struct v4l2_file_operations soc_camera_fops = { .owner = THIS_MODULE, .open = soc_camera_open, .release = soc_camera_close, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, .read = soc_camera_read, .mmap = soc_camera_mmap, .poll = soc_camera_poll, @@ -534,12 +522,9 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, if (icd->streamer && icd->streamer != file) return -EBUSY; - mutex_lock(&icd->vb_vidq.vb_lock); - if (icd->vb_vidq.bufs[0]) { dev_err(&icd->dev, "S_FMT denied: queue initialised\n"); - ret = -EBUSY; - goto unlock; + return -EBUSY; } ret = soc_camera_set_fmt(icd, f); @@ -547,9 +532,6 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, if (!ret && !icd->streamer) icd->streamer = file; -unlock: - mutex_unlock(&icd->vb_vidq.vb_lock); - return ret; } @@ -622,15 +604,11 @@ static int soc_camera_streamon(struct file *file, void *priv, if (icd->streamer != file) return -EBUSY; - mutex_lock(&icd->video_lock); - v4l2_subdev_call(sd, video, s_stream, 1); /* This calls buf_queue from host driver's videobuf_queue_ops */ ret = videobuf_streamon(&icd->vb_vidq); - mutex_unlock(&icd->video_lock); - return ret; } @@ -648,8 +626,6 @@ static int soc_camera_streamoff(struct file *file, void *priv, if (icd->streamer != file) return -EBUSY; - mutex_lock(&icd->video_lock); - /* * This calls buf_release from host driver's videobuf_queue_ops for all * remaining buffers. When the last buffer is freed, stop capture @@ -658,8 +634,6 @@ static int soc_camera_streamoff(struct file *file, void *priv, v4l2_subdev_call(sd, video, s_stream, 0); - mutex_unlock(&icd->video_lock); - return 0; } @@ -748,9 +722,7 @@ static int soc_camera_g_crop(struct file *file, void *fh, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); int ret; - mutex_lock(&icd->vb_vidq.vb_lock); ret = ici->ops->get_crop(icd, a); - mutex_unlock(&icd->vb_vidq.vb_lock); return ret; } @@ -775,9 +747,6 @@ static int soc_camera_s_crop(struct file *file, void *fh, dev_dbg(&icd->dev, "S_CROP(%ux%u@%u:%u)\n", rect->width, rect->height, rect->left, rect->top); - /* Cropping is allowed during a running capture, guard consistency */ - mutex_lock(&icd->vb_vidq.vb_lock); - /* If get_crop fails, we'll let host and / or client drivers decide */ ret = ici->ops->get_crop(icd, ¤t_crop); @@ -795,8 +764,6 @@ static int soc_camera_s_crop(struct file *file, void *fh, ret = ici->ops->set_crop(icd, a); } - mutex_unlock(&icd->vb_vidq.vb_lock); - return ret; } @@ -998,7 +965,13 @@ static int soc_camera_probe(struct device *dev) icd->field = V4L2_FIELD_ANY; - /* ..._video_start() will create a device node, so we have to protect */ + icd->vdev->lock = &icd->video_lock; + + /* + * ..._video_start() will create a device node, video_register_device() + * itself is protected against concurrent open() calls, but we also have + * to protect our data. + */ mutex_lock(&icd->video_lock); ret = soc_camera_video_start(icd); @@ -1063,10 +1036,8 @@ static int soc_camera_remove(struct device *dev) BUG_ON(!dev->parent); if (vdev) { - mutex_lock(&icd->video_lock); video_unregister_device(vdev); icd->vdev = NULL; - mutex_unlock(&icd->video_lock); } if (icl->board_info) { -- cgit v0.10.2 From 3153ac9c6208892ee237caccdbe2290f8247e236 Mon Sep 17 00:00:00 2001 From: Alberto Panizzo Date: Thu, 2 Dec 2010 11:53:28 -0300 Subject: [media] V4L2: Add a v4l2-subdev (soc-camera) driver for OmniVision OV2640 sensor Signed-off-by: Alberto Panizzo Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 78b8c5d..eb875af 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -794,6 +794,12 @@ config SOC_CAMERA_PLATFORM help This is a generic SoC camera platform driver, useful for testing +config SOC_CAMERA_OV2640 + tristate "ov2640 camera support" + depends on SOC_CAMERA && I2C + help + This is a ov2640 camera driver + config SOC_CAMERA_OV6650 tristate "ov6650 sensor support" depends on SOC_CAMERA && I2C diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 98825e7..81e38cb 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -75,6 +75,7 @@ obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o obj-$(CONFIG_SOC_CAMERA_MT9T112) += mt9t112.o obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o +obj-$(CONFIG_SOC_CAMERA_OV2640) += ov2640.o obj-$(CONFIG_SOC_CAMERA_OV6650) += ov6650.o obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o obj-$(CONFIG_SOC_CAMERA_OV9640) += ov9640.o diff --git a/drivers/media/video/ov2640.c b/drivers/media/video/ov2640.c new file mode 100644 index 0000000..0cea0cf --- /dev/null +++ b/drivers/media/video/ov2640.c @@ -0,0 +1,1205 @@ +/* + * ov2640 Camera Driver + * + * Copyright (C) 2010 Alberto Panizzo + * + * Based on ov772x, ov9640 drivers and previous non merged implementations. + * + * Copyright 2005-2009 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2006, OmniVision + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VAL_SET(x, mask, rshift, lshift) \ + ((((x) >> rshift) & mask) << lshift) +/* + * DSP registers + * register offset for BANK_SEL == BANK_SEL_DSP + */ +#define R_BYPASS 0x05 /* Bypass DSP */ +#define R_BYPASS_DSP_BYPAS 0x01 /* Bypass DSP, sensor out directly */ +#define R_BYPASS_USE_DSP 0x00 /* Use the internal DSP */ +#define QS 0x44 /* Quantization Scale Factor */ +#define CTRLI 0x50 +#define CTRLI_LP_DP 0x80 +#define CTRLI_ROUND 0x40 +#define CTRLI_V_DIV_SET(x) VAL_SET(x, 0x3, 0, 3) +#define CTRLI_H_DIV_SET(x) VAL_SET(x, 0x3, 0, 0) +#define HSIZE 0x51 /* H_SIZE[7:0] (real/4) */ +#define HSIZE_SET(x) VAL_SET(x, 0xFF, 2, 0) +#define VSIZE 0x52 /* V_SIZE[7:0] (real/4) */ +#define VSIZE_SET(x) VAL_SET(x, 0xFF, 2, 0) +#define XOFFL 0x53 /* OFFSET_X[7:0] */ +#define XOFFL_SET(x) VAL_SET(x, 0xFF, 0, 0) +#define YOFFL 0x54 /* OFFSET_Y[7:0] */ +#define YOFFL_SET(x) VAL_SET(x, 0xFF, 0, 0) +#define VHYX 0x55 /* Offset and size completion */ +#define VHYX_VSIZE_SET(x) VAL_SET(x, 0x1, (8+2), 7) +#define VHYX_HSIZE_SET(x) VAL_SET(x, 0x1, (8+2), 3) +#define VHYX_YOFF_SET(x) VAL_SET(x, 0x3, 8, 4) +#define VHYX_XOFF_SET(x) VAL_SET(x, 0x3, 8, 0) +#define DPRP 0x56 +#define TEST 0x57 /* Horizontal size completion */ +#define TEST_HSIZE_SET(x) VAL_SET(x, 0x1, (9+2), 7) +#define ZMOW 0x5A /* Zoom: Out Width OUTW[7:0] (real/4) */ +#define ZMOW_OUTW_SET(x) VAL_SET(x, 0xFF, 2, 0) +#define ZMOH 0x5B /* Zoom: Out Height OUTH[7:0] (real/4) */ +#define ZMOH_OUTH_SET(x) VAL_SET(x, 0xFF, 2, 0) +#define ZMHH 0x5C /* Zoom: Speed and H&W completion */ +#define ZMHH_ZSPEED_SET(x) VAL_SET(x, 0x0F, 0, 4) +#define ZMHH_OUTH_SET(x) VAL_SET(x, 0x1, (8+2), 2) +#define ZMHH_OUTW_SET(x) VAL_SET(x, 0x3, (8+2), 0) +#define BPADDR 0x7C /* SDE Indirect Register Access: Address */ +#define BPDATA 0x7D /* SDE Indirect Register Access: Data */ +#define CTRL2 0x86 /* DSP Module enable 2 */ +#define CTRL2_DCW_EN 0x20 +#define CTRL2_SDE_EN 0x10 +#define CTRL2_UV_ADJ_EN 0x08 +#define CTRL2_UV_AVG_EN 0x04 +#define CTRL2_CMX_EN 0x01 +#define CTRL3 0x87 /* DSP Module enable 3 */ +#define CTRL3_BPC_EN 0x80 +#define CTRL3_WPC_EN 0x40 +#define SIZEL 0x8C /* Image Size Completion */ +#define SIZEL_HSIZE8_11_SET(x) VAL_SET(x, 0x1, 11, 6) +#define SIZEL_HSIZE8_SET(x) VAL_SET(x, 0x7, 0, 3) +#define SIZEL_VSIZE8_SET(x) VAL_SET(x, 0x7, 0, 0) +#define HSIZE8 0xC0 /* Image Horizontal Size HSIZE[10:3] */ +#define HSIZE8_SET(x) VAL_SET(x, 0xFF, 3, 0) +#define VSIZE8 0xC1 /* Image Vertical Size VSIZE[10:3] */ +#define VSIZE8_SET(x) VAL_SET(x, 0xFF, 3, 0) +#define CTRL0 0xC2 /* DSP Module enable 0 */ +#define CTRL0_AEC_EN 0x80 +#define CTRL0_AEC_SEL 0x40 +#define CTRL0_STAT_SEL 0x20 +#define CTRL0_VFIRST 0x10 +#define CTRL0_YUV422 0x08 +#define CTRL0_YUV_EN 0x04 +#define CTRL0_RGB_EN 0x02 +#define CTRL0_RAW_EN 0x01 +#define CTRL1 0xC3 /* DSP Module enable 1 */ +#define CTRL1_CIP 0x80 +#define CTRL1_DMY 0x40 +#define CTRL1_RAW_GMA 0x20 +#define CTRL1_DG 0x10 +#define CTRL1_AWB 0x08 +#define CTRL1_AWB_GAIN 0x04 +#define CTRL1_LENC 0x02 +#define CTRL1_PRE 0x01 +#define R_DVP_SP 0xD3 /* DVP output speed control */ +#define R_DVP_SP_AUTO_MODE 0x80 +#define R_DVP_SP_DVP_MASK 0x3F /* DVP PCLK = sysclk (48)/[6:0] (YUV0); + * = sysclk (48)/(2*[6:0]) (RAW);*/ +#define IMAGE_MODE 0xDA /* Image Output Format Select */ +#define IMAGE_MODE_Y8_DVP_EN 0x40 +#define IMAGE_MODE_JPEG_EN 0x10 +#define IMAGE_MODE_YUV422 0x00 +#define IMAGE_MODE_RAW10 0x04 /* (DVP) */ +#define IMAGE_MODE_RGB565 0x08 +#define IMAGE_MODE_HREF_VSYNC 0x02 /* HREF timing select in DVP JPEG output + * mode (0 for HREF is same as sensor) */ +#define IMAGE_MODE_LBYTE_FIRST 0x01 /* Byte swap enable for DVP + * 1: Low byte first UYVY (C2[4] =0) + * VYUY (C2[4] =1) + * 0: High byte first YUYV (C2[4]=0) + * YVYU (C2[4] = 1) */ +#define RESET 0xE0 /* Reset */ +#define RESET_MICROC 0x40 +#define RESET_SCCB 0x20 +#define RESET_JPEG 0x10 +#define RESET_DVP 0x04 +#define RESET_IPU 0x02 +#define RESET_CIF 0x01 +#define REGED 0xED /* Register ED */ +#define REGED_CLK_OUT_DIS 0x10 +#define MS_SP 0xF0 /* SCCB Master Speed */ +#define SS_ID 0xF7 /* SCCB Slave ID */ +#define SS_CTRL 0xF8 /* SCCB Slave Control */ +#define SS_CTRL_ADD_AUTO_INC 0x20 +#define SS_CTRL_EN 0x08 +#define SS_CTRL_DELAY_CLK 0x04 +#define SS_CTRL_ACC_EN 0x02 +#define SS_CTRL_SEN_PASS_THR 0x01 +#define MC_BIST 0xF9 /* Microcontroller misc register */ +#define MC_BIST_RESET 0x80 /* Microcontroller Reset */ +#define MC_BIST_BOOT_ROM_SEL 0x40 +#define MC_BIST_12KB_SEL 0x20 +#define MC_BIST_12KB_MASK 0x30 +#define MC_BIST_512KB_SEL 0x08 +#define MC_BIST_512KB_MASK 0x0C +#define MC_BIST_BUSY_BIT_R 0x02 +#define MC_BIST_MC_RES_ONE_SH_W 0x02 +#define MC_BIST_LAUNCH 0x01 +#define BANK_SEL 0xFF /* Register Bank Select */ +#define BANK_SEL_DSP 0x00 +#define BANK_SEL_SENS 0x01 + +/* + * Sensor registers + * register offset for BANK_SEL == BANK_SEL_SENS + */ +#define GAIN 0x00 /* AGC - Gain control gain setting */ +#define COM1 0x03 /* Common control 1 */ +#define COM1_1_DUMMY_FR 0x40 +#define COM1_3_DUMMY_FR 0x80 +#define COM1_7_DUMMY_FR 0xC0 +#define COM1_VWIN_LSB_UXGA 0x0F +#define COM1_VWIN_LSB_SVGA 0x0A +#define COM1_VWIN_LSB_CIF 0x06 +#define REG04 0x04 /* Register 04 */ +#define REG04_DEF 0x20 /* Always set */ +#define REG04_HFLIP_IMG 0x80 /* Horizontal mirror image ON/OFF */ +#define REG04_VFLIP_IMG 0x40 /* Vertical flip image ON/OFF */ +#define REG04_VREF_EN 0x10 +#define REG04_HREF_EN 0x08 +#define REG04_AEC_SET(x) VAL_SET(x, 0x3, 0, 0) +#define REG08 0x08 /* Frame Exposure One-pin Control Pre-charge Row Num */ +#define COM2 0x09 /* Common control 2 */ +#define COM2_SOFT_SLEEP_MODE 0x10 /* Soft sleep mode */ + /* Output drive capability */ +#define COM2_OCAP_Nx_SET(N) (((N) - 1) & 0x03) /* N = [1x .. 4x] */ +#define PID 0x0A /* Product ID Number MSB */ +#define VER 0x0B /* Product ID Number LSB */ +#define COM3 0x0C /* Common control 3 */ +#define COM3_BAND_50H 0x04 /* 0 For Banding at 60H */ +#define COM3_BAND_AUTO 0x02 /* Auto Banding */ +#define COM3_SING_FR_SNAPSH 0x01 /* 0 For enable live video output after the + * snapshot sequence*/ +#define AEC 0x10 /* AEC[9:2] Exposure Value */ +#define CLKRC 0x11 /* Internal clock */ +#define CLKRC_EN 0x80 +#define CLKRC_DIV_SET(x) (((x) - 1) & 0x1F) /* CLK = XVCLK/(x) */ +#define COM7 0x12 /* Common control 7 */ +#define COM7_SRST 0x80 /* Initiates system reset. All registers are + * set to factory default values after which + * the chip resumes normal operation */ +#define COM7_RES_UXGA 0x00 /* Resolution selectors for UXGA */ +#define COM7_RES_SVGA 0x40 /* SVGA */ +#define COM7_RES_CIF 0x20 /* CIF */ +#define COM7_ZOOM_EN 0x04 /* Enable Zoom mode */ +#define COM7_COLOR_BAR_TEST 0x02 /* Enable Color Bar Test Pattern */ +#define COM8 0x13 /* Common control 8 */ +#define COM8_DEF 0xC0 /* Banding filter ON/OFF */ +#define COM8_BNDF_EN 0x20 /* Banding filter ON/OFF */ +#define COM8_AGC_EN 0x04 /* AGC Auto/Manual control selection */ +#define COM8_AEC_EN 0x01 /* Auto/Manual Exposure control */ +#define COM9 0x14 /* Common control 9 + * Automatic gain ceiling - maximum AGC value [7:5]*/ +#define COM9_AGC_GAIN_2x 0x00 /* 000 : 2x */ +#define COM9_AGC_GAIN_4x 0x20 /* 001 : 4x */ +#define COM9_AGC_GAIN_8x 0x40 /* 010 : 8x */ +#define COM9_AGC_GAIN_16x 0x60 /* 011 : 16x */ +#define COM9_AGC_GAIN_32x 0x80 /* 100 : 32x */ +#define COM9_AGC_GAIN_64x 0xA0 /* 101 : 64x */ +#define COM9_AGC_GAIN_128x 0xC0 /* 110 : 128x */ +#define COM10 0x15 /* Common control 10 */ +#define COM10_PCLK_HREF 0x20 /* PCLK output qualified by HREF */ +#define COM10_PCLK_RISE 0x10 /* Data is updated at the rising edge of + * PCLK (user can latch data at the next + * falling edge of PCLK). + * 0 otherwise. */ +#define COM10_HREF_INV 0x08 /* Invert HREF polarity: + * HREF negative for valid data*/ +#define COM10_VSINC_INV 0x02 /* Invert VSYNC polarity */ +#define HSTART 0x17 /* Horizontal Window start MSB 8 bit */ +#define HEND 0x18 /* Horizontal Window end MSB 8 bit */ +#define VSTART 0x19 /* Vertical Window start MSB 8 bit */ +#define VEND 0x1A /* Vertical Window end MSB 8 bit */ +#define MIDH 0x1C /* Manufacturer ID byte - high */ +#define MIDL 0x1D /* Manufacturer ID byte - low */ +#define AEW 0x24 /* AGC/AEC - Stable operating region (upper limit) */ +#define AEB 0x25 /* AGC/AEC - Stable operating region (lower limit) */ +#define VV 0x26 /* AGC/AEC Fast mode operating region */ +#define VV_HIGH_TH_SET(x) VAL_SET(x, 0xF, 0, 4) +#define VV_LOW_TH_SET(x) VAL_SET(x, 0xF, 0, 0) +#define REG2A 0x2A /* Dummy pixel insert MSB */ +#define FRARL 0x2B /* Dummy pixel insert LSB */ +#define ADDVFL 0x2D /* LSB of insert dummy lines in Vertical direction */ +#define ADDVFH 0x2E /* MSB of insert dummy lines in Vertical direction */ +#define YAVG 0x2F /* Y/G Channel Average value */ +#define REG32 0x32 /* Common Control 32 */ +#define REG32_PCLK_DIV_2 0x80 /* PCLK freq divided by 2 */ +#define REG32_PCLK_DIV_4 0xC0 /* PCLK freq divided by 4 */ +#define ARCOM2 0x34 /* Zoom: Horizontal start point */ +#define REG45 0x45 /* Register 45 */ +#define FLL 0x46 /* Frame Length Adjustment LSBs */ +#define FLH 0x47 /* Frame Length Adjustment MSBs */ +#define COM19 0x48 /* Zoom: Vertical start point */ +#define ZOOMS 0x49 /* Zoom: Vertical start point */ +#define COM22 0x4B /* Flash light control */ +#define COM25 0x4E /* For Banding operations */ +#define BD50 0x4F /* 50Hz Banding AEC 8 LSBs */ +#define BD60 0x50 /* 60Hz Banding AEC 8 LSBs */ +#define REG5D 0x5D /* AVGsel[7:0], 16-zone average weight option */ +#define REG5E 0x5E /* AVGsel[15:8], 16-zone average weight option */ +#define REG5F 0x5F /* AVGsel[23:16], 16-zone average weight option */ +#define REG60 0x60 /* AVGsel[31:24], 16-zone average weight option */ +#define HISTO_LOW 0x61 /* Histogram Algorithm Low Level */ +#define HISTO_HIGH 0x62 /* Histogram Algorithm High Level */ + +/* + * ID + */ +#define MANUFACTURER_ID 0x7FA2 +#define PID_OV2640 0x2642 +#define VERSION(pid, ver) ((pid << 8) | (ver & 0xFF)) + +/* + * Struct + */ +struct regval_list { + u8 reg_num; + u8 value; +}; + +/* Supported resolutions */ +enum ov2640_width { + W_QCIF = 176, + W_QVGA = 320, + W_CIF = 352, + W_VGA = 640, + W_SVGA = 800, + W_XGA = 1024, + W_SXGA = 1280, + W_UXGA = 1600, +}; + +enum ov2640_height { + H_QCIF = 144, + H_QVGA = 240, + H_CIF = 288, + H_VGA = 480, + H_SVGA = 600, + H_XGA = 768, + H_SXGA = 1024, + H_UXGA = 1200, +}; + +struct ov2640_win_size { + char *name; + enum ov2640_width width; + enum ov2640_height height; + const struct regval_list *regs; +}; + + +struct ov2640_priv { + struct v4l2_subdev subdev; + struct ov2640_camera_info *info; + enum v4l2_mbus_pixelcode cfmt_code; + const struct ov2640_win_size *win; + int model; + u16 flag_vflip:1; + u16 flag_hflip:1; +}; + +/* + * Registers settings + */ + +#define ENDMARKER { 0xff, 0xff } + +static const struct regval_list ov2640_init_regs[] = { + { BANK_SEL, BANK_SEL_DSP }, + { 0x2c, 0xff }, + { 0x2e, 0xdf }, + { BANK_SEL, BANK_SEL_SENS }, + { 0x3c, 0x32 }, + { CLKRC, CLKRC_DIV_SET(1) }, + { COM2, COM2_OCAP_Nx_SET(3) }, + { REG04, REG04_DEF | REG04_HREF_EN }, + { COM8, COM8_DEF | COM8_BNDF_EN | COM8_AGC_EN | COM8_AEC_EN }, + { COM9, COM9_AGC_GAIN_8x | 0x08}, + { 0x2c, 0x0c }, + { 0x33, 0x78 }, + { 0x3a, 0x33 }, + { 0x3b, 0xfb }, + { 0x3e, 0x00 }, + { 0x43, 0x11 }, + { 0x16, 0x10 }, + { 0x39, 0x02 }, + { 0x35, 0x88 }, + { 0x22, 0x0a }, + { 0x37, 0x40 }, + { 0x23, 0x00 }, + { ARCOM2, 0xa0 }, + { 0x06, 0x02 }, + { 0x06, 0x88 }, + { 0x07, 0xc0 }, + { 0x0d, 0xb7 }, + { 0x0e, 0x01 }, + { 0x4c, 0x00 }, + { 0x4a, 0x81 }, + { 0x21, 0x99 }, + { AEW, 0x40 }, + { AEB, 0x38 }, + { VV, VV_HIGH_TH_SET(0x08) | VV_LOW_TH_SET(0x02) }, + { 0x5c, 0x00 }, + { 0x63, 0x00 }, + { FLL, 0x22 }, + { COM3, 0x38 | COM3_BAND_AUTO }, + { REG5D, 0x55 }, + { REG5E, 0x7d }, + { REG5F, 0x7d }, + { REG60, 0x55 }, + { HISTO_LOW, 0x70 }, + { HISTO_HIGH, 0x80 }, + { 0x7c, 0x05 }, + { 0x20, 0x80 }, + { 0x28, 0x30 }, + { 0x6c, 0x00 }, + { 0x6d, 0x80 }, + { 0x6e, 0x00 }, + { 0x70, 0x02 }, + { 0x71, 0x94 }, + { 0x73, 0xc1 }, + { 0x3d, 0x34 }, + { COM7, COM7_RES_UXGA | COM7_ZOOM_EN }, + { 0x5a, 0x57 }, + { BD50, 0xbb }, + { BD60, 0x9c }, + { BANK_SEL, BANK_SEL_DSP }, + { 0xe5, 0x7f }, + { MC_BIST, MC_BIST_RESET | MC_BIST_BOOT_ROM_SEL }, + { 0x41, 0x24 }, + { RESET, RESET_JPEG | RESET_DVP }, + { 0x76, 0xff }, + { 0x33, 0xa0 }, + { 0x42, 0x20 }, + { 0x43, 0x18 }, + { 0x4c, 0x00 }, + { CTRL3, CTRL3_BPC_EN | CTRL3_WPC_EN | 0x10 }, + { 0x88, 0x3f }, + { 0xd7, 0x03 }, + { 0xd9, 0x10 }, + { R_DVP_SP , R_DVP_SP_AUTO_MODE | 0x2 }, + { 0xc8, 0x08 }, + { 0xc9, 0x80 }, + { BPADDR, 0x00 }, + { BPDATA, 0x00 }, + { BPADDR, 0x03 }, + { BPDATA, 0x48 }, + { BPDATA, 0x48 }, + { BPADDR, 0x08 }, + { BPDATA, 0x20 }, + { BPDATA, 0x10 }, + { BPDATA, 0x0e }, + { 0x90, 0x00 }, + { 0x91, 0x0e }, + { 0x91, 0x1a }, + { 0x91, 0x31 }, + { 0x91, 0x5a }, + { 0x91, 0x69 }, + { 0x91, 0x75 }, + { 0x91, 0x7e }, + { 0x91, 0x88 }, + { 0x91, 0x8f }, + { 0x91, 0x96 }, + { 0x91, 0xa3 }, + { 0x91, 0xaf }, + { 0x91, 0xc4 }, + { 0x91, 0xd7 }, + { 0x91, 0xe8 }, + { 0x91, 0x20 }, + { 0x92, 0x00 }, + { 0x93, 0x06 }, + { 0x93, 0xe3 }, + { 0x93, 0x03 }, + { 0x93, 0x03 }, + { 0x93, 0x00 }, + { 0x93, 0x02 }, + { 0x93, 0x00 }, + { 0x93, 0x00 }, + { 0x93, 0x00 }, + { 0x93, 0x00 }, + { 0x93, 0x00 }, + { 0x93, 0x00 }, + { 0x93, 0x00 }, + { 0x96, 0x00 }, + { 0x97, 0x08 }, + { 0x97, 0x19 }, + { 0x97, 0x02 }, + { 0x97, 0x0c }, + { 0x97, 0x24 }, + { 0x97, 0x30 }, + { 0x97, 0x28 }, + { 0x97, 0x26 }, + { 0x97, 0x02 }, + { 0x97, 0x98 }, + { 0x97, 0x80 }, + { 0x97, 0x00 }, + { 0x97, 0x00 }, + { 0xa4, 0x00 }, + { 0xa8, 0x00 }, + { 0xc5, 0x11 }, + { 0xc6, 0x51 }, + { 0xbf, 0x80 }, + { 0xc7, 0x10 }, + { 0xb6, 0x66 }, + { 0xb8, 0xA5 }, + { 0xb7, 0x64 }, + { 0xb9, 0x7C }, + { 0xb3, 0xaf }, + { 0xb4, 0x97 }, + { 0xb5, 0xFF }, + { 0xb0, 0xC5 }, + { 0xb1, 0x94 }, + { 0xb2, 0x0f }, + { 0xc4, 0x5c }, + { 0xa6, 0x00 }, + { 0xa7, 0x20 }, + { 0xa7, 0xd8 }, + { 0xa7, 0x1b }, + { 0xa7, 0x31 }, + { 0xa7, 0x00 }, + { 0xa7, 0x18 }, + { 0xa7, 0x20 }, + { 0xa7, 0xd8 }, + { 0xa7, 0x19 }, + { 0xa7, 0x31 }, + { 0xa7, 0x00 }, + { 0xa7, 0x18 }, + { 0xa7, 0x20 }, + { 0xa7, 0xd8 }, + { 0xa7, 0x19 }, + { 0xa7, 0x31 }, + { 0xa7, 0x00 }, + { 0xa7, 0x18 }, + { 0x7f, 0x00 }, + { 0xe5, 0x1f }, + { 0xe1, 0x77 }, + { 0xdd, 0x7f }, + { CTRL0, CTRL0_YUV422 | CTRL0_YUV_EN | CTRL0_RGB_EN }, + ENDMARKER, +}; + +/* + * Register settings for window size + * The preamble, setup the internal DSP to input an UXGA (1600x1200) image. + * Then the different zooming configurations will setup the output image size. + */ +static const struct regval_list ov2640_size_change_preamble_regs[] = { + { BANK_SEL, BANK_SEL_DSP }, + { RESET, RESET_DVP }, + { HSIZE8, HSIZE8_SET(W_UXGA) }, + { VSIZE8, VSIZE8_SET(H_UXGA) }, + { CTRL2, CTRL2_DCW_EN | CTRL2_SDE_EN | + CTRL2_UV_AVG_EN | CTRL2_CMX_EN | CTRL2_UV_ADJ_EN }, + { HSIZE, HSIZE_SET(W_UXGA) }, + { VSIZE, VSIZE_SET(H_UXGA) }, + { XOFFL, XOFFL_SET(0) }, + { YOFFL, YOFFL_SET(0) }, + { VHYX, VHYX_HSIZE_SET(W_UXGA) | VHYX_VSIZE_SET(H_UXGA) | + VHYX_XOFF_SET(0) | VHYX_YOFF_SET(0)}, + { TEST, TEST_HSIZE_SET(W_UXGA) }, + ENDMARKER, +}; + +#define PER_SIZE_REG_SEQ(x, y, v_div, h_div, pclk_div) \ + { CTRLI, CTRLI_LP_DP | CTRLI_V_DIV_SET(v_div) | \ + CTRLI_H_DIV_SET(h_div)}, \ + { ZMOW, ZMOW_OUTW_SET(x) }, \ + { ZMOH, ZMOH_OUTH_SET(y) }, \ + { ZMHH, ZMHH_OUTW_SET(x) | ZMHH_OUTH_SET(y) }, \ + { R_DVP_SP, pclk_div }, \ + { RESET, 0x00} + +static const struct regval_list ov2640_qcif_regs[] = { + PER_SIZE_REG_SEQ(W_QCIF, H_QCIF, 3, 3, 4), + ENDMARKER, +}; + +static const struct regval_list ov2640_qvga_regs[] = { + PER_SIZE_REG_SEQ(W_QVGA, H_QVGA, 2, 2, 4), + ENDMARKER, +}; + +static const struct regval_list ov2640_cif_regs[] = { + PER_SIZE_REG_SEQ(W_CIF, H_CIF, 2, 2, 8), + ENDMARKER, +}; + +static const struct regval_list ov2640_vga_regs[] = { + PER_SIZE_REG_SEQ(W_VGA, H_VGA, 0, 0, 2), + ENDMARKER, +}; + +static const struct regval_list ov2640_svga_regs[] = { + PER_SIZE_REG_SEQ(W_SVGA, H_SVGA, 1, 1, 2), + ENDMARKER, +}; + +static const struct regval_list ov2640_xga_regs[] = { + PER_SIZE_REG_SEQ(W_XGA, H_XGA, 0, 0, 2), + { CTRLI, 0x00}, + ENDMARKER, +}; + +static const struct regval_list ov2640_sxga_regs[] = { + PER_SIZE_REG_SEQ(W_SXGA, H_SXGA, 0, 0, 2), + { CTRLI, 0x00}, + { R_DVP_SP, 2 | R_DVP_SP_AUTO_MODE }, + ENDMARKER, +}; + +static const struct regval_list ov2640_uxga_regs[] = { + PER_SIZE_REG_SEQ(W_UXGA, H_UXGA, 0, 0, 0), + { CTRLI, 0x00}, + { R_DVP_SP, 0 | R_DVP_SP_AUTO_MODE }, + ENDMARKER, +}; + +#define OV2640_SIZE(n, w, h, r) \ + {.name = n, .width = w , .height = h, .regs = r } + +static const struct ov2640_win_size ov2640_supported_win_sizes[] = { + OV2640_SIZE("QCIF", W_QCIF, H_QCIF, ov2640_qcif_regs), + OV2640_SIZE("QVGA", W_QVGA, H_QVGA, ov2640_qvga_regs), + OV2640_SIZE("CIF", W_CIF, H_CIF, ov2640_cif_regs), + OV2640_SIZE("VGA", W_VGA, H_VGA, ov2640_vga_regs), + OV2640_SIZE("SVGA", W_SVGA, H_SVGA, ov2640_svga_regs), + OV2640_SIZE("XGA", W_XGA, H_XGA, ov2640_xga_regs), + OV2640_SIZE("SXGA", W_SXGA, H_SXGA, ov2640_sxga_regs), + OV2640_SIZE("UXGA", W_UXGA, H_UXGA, ov2640_uxga_regs), +}; + +/* + * Register settings for pixel formats + */ +static const struct regval_list ov2640_format_change_preamble_regs[] = { + { BANK_SEL, BANK_SEL_DSP }, + { R_BYPASS, R_BYPASS_USE_DSP }, + ENDMARKER, +}; + +static const struct regval_list ov2640_yuv422_regs[] = { + { IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_YUV422 }, + { 0xD7, 0x01 }, + { 0x33, 0xa0 }, + { 0xe1, 0x67 }, + { RESET, 0x00 }, + { R_BYPASS, R_BYPASS_USE_DSP }, + ENDMARKER, +}; + +static const struct regval_list ov2640_rgb565_regs[] = { + { IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_RGB565 }, + { 0xd7, 0x03 }, + { RESET, 0x00 }, + { R_BYPASS, R_BYPASS_USE_DSP }, + ENDMARKER, +}; + +static enum v4l2_mbus_pixelcode ov2640_codes[] = { + V4L2_MBUS_FMT_UYVY8_2X8, + V4L2_MBUS_FMT_RGB565_2X8_LE, +}; + +/* + * Supported controls + */ +static const struct v4l2_queryctrl ov2640_controls[] = { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Vertically", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flip Horizontally", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, +}; + +/* + * General functions + */ +static struct ov2640_priv *to_ov2640(const struct i2c_client *client) +{ + return container_of(i2c_get_clientdata(client), struct ov2640_priv, + subdev); +} + +static int ov2640_write_array(struct i2c_client *client, + const struct regval_list *vals) +{ + int ret; + + while ((vals->reg_num != 0xff) || (vals->value != 0xff)) { + ret = i2c_smbus_write_byte_data(client, + vals->reg_num, vals->value); + dev_vdbg(&client->dev, "array: 0x%02x, 0x%02x", + vals->reg_num, vals->value); + + if (ret < 0) + return ret; + vals++; + } + return 0; +} + +static int ov2640_mask_set(struct i2c_client *client, + u8 reg, u8 mask, u8 set) +{ + s32 val = i2c_smbus_read_byte_data(client, reg); + if (val < 0) + return val; + + val &= ~mask; + val |= set & mask; + + dev_vdbg(&client->dev, "masks: 0x%02x, 0x%02x", reg, val); + + return i2c_smbus_write_byte_data(client, reg, val); +} + +static int ov2640_reset(struct i2c_client *client) +{ + int ret; + const struct regval_list reset_seq[] = { + {BANK_SEL, BANK_SEL_SENS}, + {COM7, COM7_SRST}, + ENDMARKER, + }; + + ret = ov2640_write_array(client, reset_seq); + if (ret) + goto err; + + msleep(5); +err: + dev_dbg(&client->dev, "%s: (ret %d)", __func__, ret); + return ret; +} + +/* + * soc_camera_ops functions + */ +static int ov2640_s_stream(struct v4l2_subdev *sd, int enable) +{ + return 0; +} + +static int ov2640_set_bus_param(struct soc_camera_device *icd, + unsigned long flags) +{ + struct soc_camera_link *icl = to_soc_camera_link(icd); + unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK; + + /* Only one width bit may be set */ + if (!is_power_of_2(width_flag)) + return -EINVAL; + + if (icl->set_bus_param) + return icl->set_bus_param(icl, width_flag); + + /* + * Without board specific bus width settings we support only the + * sensors native bus width witch are tested working + */ + if (width_flag & (SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8)) + return 0; + + return 0; +} + +static unsigned long ov2640_query_bus_param(struct soc_camera_device *icd) +{ + struct soc_camera_link *icl = to_soc_camera_link(icd); + unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | + SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | + SOCAM_DATA_ACTIVE_HIGH; + + if (icl->query_bus_param) + flags |= icl->query_bus_param(icl) & SOCAM_DATAWIDTH_MASK; + else + flags |= SOCAM_DATAWIDTH_10; + + return soc_camera_apply_sensor_flags(icl, flags); +} + +static int ov2640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ov2640_priv *priv = to_ov2640(client); + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + ctrl->value = priv->flag_vflip; + break; + case V4L2_CID_HFLIP: + ctrl->value = priv->flag_hflip; + break; + } + return 0; +} + +static int ov2640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ov2640_priv *priv = to_ov2640(client); + int ret = 0; + u8 val; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + val = ctrl->value ? REG04_VFLIP_IMG : 0x00; + priv->flag_vflip = ctrl->value ? 1 : 0; + ret = ov2640_mask_set(client, REG04, REG04_VFLIP_IMG, val); + break; + case V4L2_CID_HFLIP: + val = ctrl->value ? REG04_HFLIP_IMG : 0x00; + priv->flag_hflip = ctrl->value ? 1 : 0; + ret = ov2640_mask_set(client, REG04, REG04_HFLIP_IMG, val); + break; + } + + return ret; +} + +static int ov2640_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ov2640_priv *priv = to_ov2640(client); + + id->ident = priv->model; + id->revision = 0; + + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int ov2640_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + + reg->size = 1; + if (reg->reg > 0xff) + return -EINVAL; + + ret = i2c_smbus_read_byte_data(client, reg->reg); + if (ret < 0) + return ret; + + reg->val = ret; + + return 0; +} + +static int ov2640_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (reg->reg > 0xff || + reg->val > 0xff) + return -EINVAL; + + return i2c_smbus_write_byte_data(client, reg->reg, reg->val); +} +#endif + +/* Select the nearest higher resolution for capture */ +static const struct ov2640_win_size *ov2640_select_win(u32 *width, u32 *height) +{ + int i, default_size = ARRAY_SIZE(ov2640_supported_win_sizes) - 1; + + for (i = 0; i < ARRAY_SIZE(ov2640_supported_win_sizes); i++) { + if (ov2640_supported_win_sizes[i].width >= *width && + ov2640_supported_win_sizes[i].height >= *height) { + *width = ov2640_supported_win_sizes[i].width; + *height = ov2640_supported_win_sizes[i].height; + return &ov2640_supported_win_sizes[i]; + } + } + + *width = ov2640_supported_win_sizes[default_size].width; + *height = ov2640_supported_win_sizes[default_size].height; + return &ov2640_supported_win_sizes[default_size]; +} + +static int ov2640_set_params(struct i2c_client *client, u32 *width, u32 *height, + enum v4l2_mbus_pixelcode code) +{ + struct ov2640_priv *priv = to_ov2640(client); + const struct regval_list *selected_cfmt_regs; + int ret; + + /* select win */ + priv->win = ov2640_select_win(width, height); + + /* select format */ + priv->cfmt_code = 0; + switch (code) { + case V4L2_MBUS_FMT_RGB565_2X8_LE: + dev_dbg(&client->dev, "%s: Selected cfmt RGB565", __func__); + selected_cfmt_regs = ov2640_rgb565_regs; + break; + default: + case V4L2_MBUS_FMT_UYVY8_2X8: + dev_dbg(&client->dev, "%s: Selected cfmt YUV422", __func__); + selected_cfmt_regs = ov2640_yuv422_regs; + } + + /* reset hardware */ + ov2640_reset(client); + + /* initialize the sensor with default data */ + dev_dbg(&client->dev, "%s: Init default", __func__); + ret = ov2640_write_array(client, ov2640_init_regs); + if (ret < 0) + goto err; + + /* select preamble */ + dev_dbg(&client->dev, "%s: Set size to %s", __func__, priv->win->name); + ret = ov2640_write_array(client, ov2640_size_change_preamble_regs); + if (ret < 0) + goto err; + + /* set size win */ + ret = ov2640_write_array(client, priv->win->regs); + if (ret < 0) + goto err; + + /* cfmt preamble */ + dev_dbg(&client->dev, "%s: Set cfmt", __func__); + ret = ov2640_write_array(client, ov2640_format_change_preamble_regs); + if (ret < 0) + goto err; + + /* set cfmt */ + ret = ov2640_write_array(client, selected_cfmt_regs); + if (ret < 0) + goto err; + + priv->cfmt_code = code; + *width = priv->win->width; + *height = priv->win->height; + + return 0; + +err: + dev_err(&client->dev, "%s: Error %d", __func__, ret); + ov2640_reset(client); + priv->win = NULL; + + return ret; +} + +static int ov2640_g_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ov2640_priv *priv = to_ov2640(client); + + if (!priv->win) { + u32 width = W_SVGA, height = H_SVGA; + int ret = ov2640_set_params(client, &width, &height, + V4L2_MBUS_FMT_UYVY8_2X8); + if (ret < 0) + return ret; + } + + mf->width = priv->win->width; + mf->height = priv->win->height; + mf->code = priv->cfmt_code; + + switch (mf->code) { + case V4L2_MBUS_FMT_RGB565_2X8_LE: + mf->colorspace = V4L2_COLORSPACE_SRGB; + break; + default: + case V4L2_MBUS_FMT_UYVY8_2X8: + mf->colorspace = V4L2_COLORSPACE_JPEG; + } + mf->field = V4L2_FIELD_NONE; + + return 0; +} + +static int ov2640_s_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + + + switch (mf->code) { + case V4L2_MBUS_FMT_RGB565_2X8_LE: + mf->colorspace = V4L2_COLORSPACE_SRGB; + break; + default: + mf->code = V4L2_MBUS_FMT_UYVY8_2X8; + case V4L2_MBUS_FMT_UYVY8_2X8: + mf->colorspace = V4L2_COLORSPACE_JPEG; + } + + ret = ov2640_set_params(client, &mf->width, &mf->height, mf->code); + + return ret; +} + +static int ov2640_try_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) +{ + const struct ov2640_win_size *win; + + /* + * select suitable win + */ + win = ov2640_select_win(&mf->width, &mf->height); + + mf->field = V4L2_FIELD_NONE; + + switch (mf->code) { + case V4L2_MBUS_FMT_RGB565_2X8_LE: + mf->colorspace = V4L2_COLORSPACE_SRGB; + break; + default: + mf->code = V4L2_MBUS_FMT_UYVY8_2X8; + case V4L2_MBUS_FMT_UYVY8_2X8: + mf->colorspace = V4L2_COLORSPACE_JPEG; + } + + return 0; +} + +static int ov2640_enum_fmt(struct v4l2_subdev *sd, unsigned int index, + enum v4l2_mbus_pixelcode *code) +{ + if (index >= ARRAY_SIZE(ov2640_codes)) + return -EINVAL; + + *code = ov2640_codes[index]; + return 0; +} + +static int ov2640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +{ + a->c.left = 0; + a->c.top = 0; + a->c.width = W_UXGA; + a->c.height = H_UXGA; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + return 0; +} + +static int ov2640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + a->bounds.left = 0; + a->bounds.top = 0; + a->bounds.width = W_UXGA; + a->bounds.height = H_UXGA; + a->defrect = a->bounds; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int ov2640_video_probe(struct soc_camera_device *icd, + struct i2c_client *client) +{ + struct ov2640_priv *priv = to_ov2640(client); + u8 pid, ver, midh, midl; + const char *devname; + int ret; + + /* + * we must have a parent by now. And it cannot be a wrong one. + * So this entire test is completely redundant. + */ + if (!icd->dev.parent || + to_soc_camera_host(icd->dev.parent)->nr != icd->iface) { + dev_err(&client->dev, "Parent missing or invalid!\n"); + ret = -ENODEV; + goto err; + } + + /* + * check and show product ID and manufacturer ID + */ + i2c_smbus_write_byte_data(client, BANK_SEL, BANK_SEL_SENS); + pid = i2c_smbus_read_byte_data(client, PID); + ver = i2c_smbus_read_byte_data(client, VER); + midh = i2c_smbus_read_byte_data(client, MIDH); + midl = i2c_smbus_read_byte_data(client, MIDL); + + switch (VERSION(pid, ver)) { + case PID_OV2640: + devname = "ov2640"; + priv->model = V4L2_IDENT_OV2640; + break; + default: + dev_err(&client->dev, + "Product ID error %x:%x\n", pid, ver); + ret = -ENODEV; + goto err; + } + + dev_info(&client->dev, + "%s Product ID %0x:%0x Manufacturer ID %x:%x\n", + devname, pid, ver, midh, midl); + + return 0; + +err: + return ret; +} + +static struct soc_camera_ops ov2640_ops = { + .set_bus_param = ov2640_set_bus_param, + .query_bus_param = ov2640_query_bus_param, + .controls = ov2640_controls, + .num_controls = ARRAY_SIZE(ov2640_controls), +}; + +static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = { + .g_ctrl = ov2640_g_ctrl, + .s_ctrl = ov2640_s_ctrl, + .g_chip_ident = ov2640_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = ov2640_g_register, + .s_register = ov2640_s_register, +#endif +}; + +static struct v4l2_subdev_video_ops ov2640_subdev_video_ops = { + .s_stream = ov2640_s_stream, + .g_mbus_fmt = ov2640_g_fmt, + .s_mbus_fmt = ov2640_s_fmt, + .try_mbus_fmt = ov2640_try_fmt, + .cropcap = ov2640_cropcap, + .g_crop = ov2640_g_crop, + .enum_mbus_fmt = ov2640_enum_fmt, +}; + +static struct v4l2_subdev_ops ov2640_subdev_ops = { + .core = &ov2640_subdev_core_ops, + .video = &ov2640_subdev_video_ops, +}; + +/* + * i2c_driver functions + */ +static int ov2640_probe(struct i2c_client *client, + const struct i2c_device_id *did) +{ + struct ov2640_priv *priv; + struct soc_camera_device *icd = client->dev.platform_data; + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct soc_camera_link *icl; + int ret; + + if (!icd) { + dev_err(&adapter->dev, "OV2640: missing soc-camera data!\n"); + return -EINVAL; + } + + icl = to_soc_camera_link(icd); + if (!icl) { + dev_err(&adapter->dev, + "OV2640: Missing platform_data for driver\n"); + return -EINVAL; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&adapter->dev, + "OV2640: I2C-Adapter doesn't support SMBUS\n"); + return -EIO; + } + + priv = kzalloc(sizeof(struct ov2640_priv), GFP_KERNEL); + if (!priv) { + dev_err(&adapter->dev, + "Failed to allocate memory for private data!\n"); + return -ENOMEM; + } + + priv->info = icl->priv; + + v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops); + + icd->ops = &ov2640_ops; + + ret = ov2640_video_probe(icd, client); + if (ret) { + icd->ops = NULL; + kfree(priv); + } else { + dev_info(&adapter->dev, "OV2640 Probed\n"); + } + + return ret; +} + +static int ov2640_remove(struct i2c_client *client) +{ + struct ov2640_priv *priv = to_ov2640(client); + struct soc_camera_device *icd = client->dev.platform_data; + + icd->ops = NULL; + kfree(priv); + return 0; +} + +static const struct i2c_device_id ov2640_id[] = { + { "ov2640", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ov2640_id); + +static struct i2c_driver ov2640_i2c_driver = { + .driver = { + .name = "ov2640", + }, + .probe = ov2640_probe, + .remove = ov2640_remove, + .id_table = ov2640_id, +}; + +/* + * Module functions + */ +static int __init ov2640_module_init(void) +{ + return i2c_add_driver(&ov2640_i2c_driver); +} + +static void __exit ov2640_module_exit(void) +{ + i2c_del_driver(&ov2640_i2c_driver); +} + +module_init(ov2640_module_init); +module_exit(ov2640_module_exit); + +MODULE_DESCRIPTION("SoC Camera driver for Omni Vision 2640 sensor"); +MODULE_AUTHOR("Alberto Panizzo"); +MODULE_LICENSE("GPL v2"); diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 51e89f2..44fe44e 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -74,6 +74,7 @@ enum { V4L2_IDENT_SOI968 = 256, V4L2_IDENT_OV9640 = 257, V4L2_IDENT_OV6650 = 258, + V4L2_IDENT_OV2640 = 259, /* module saa7146: reserved range 300-309 */ V4L2_IDENT_SAA7146 = 300, -- cgit v0.10.2 From 96e442c1b2ef2ba9476e5da2607ba666ce09664d Mon Sep 17 00:00:00 2001 From: Alberto Panizzo Date: Thu, 2 Dec 2010 07:43:37 -0300 Subject: [media] soc_camera: Add the ability to bind regulators to soc_camedra devices In certain machines, camera devices are supplied directly by a number of regulators. This patch add the ability to drive these regulators directly by the soc_camera driver. Signed-off-by: Alberto Panizzo Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index aba4ce9..a66811b 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,51 @@ static LIST_HEAD(hosts); static LIST_HEAD(devices); static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ +static int soc_camera_power_set(struct soc_camera_device *icd, + struct soc_camera_link *icl, + int power_on) +{ + int ret; + + if (power_on) { + ret = regulator_bulk_enable(icl->num_regulators, + icl->regulators); + if (ret < 0) { + dev_err(&icd->dev, "Cannot enable regulators\n"); + return ret; + } + + if (icl->power) + ret = icl->power(icd->pdev, power_on); + if (ret < 0) { + dev_err(&icd->dev, + "Platform failed to power-on the camera.\n"); + + regulator_bulk_disable(icl->num_regulators, + icl->regulators); + return ret; + } + } else { + ret = 0; + if (icl->power) + ret = icl->power(icd->pdev, 0); + if (ret < 0) { + dev_err(&icd->dev, + "Platform failed to power-off the camera.\n"); + return ret; + } + + ret = regulator_bulk_disable(icl->num_regulators, + icl->regulators); + if (ret < 0) { + dev_err(&icd->dev, "Cannot disable regulators\n"); + return ret; + } + } + + return 0; +} + const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( struct soc_camera_device *icd, unsigned int fourcc) { @@ -369,11 +415,9 @@ static int soc_camera_open(struct file *file) }, }; - if (icl->power) { - ret = icl->power(icd->pdev, 1); - if (ret < 0) - goto epower; - } + ret = soc_camera_power_set(icd, icl, 1); + if (ret < 0) + goto epower; /* The camera could have been already on, try to reset */ if (icl->reset) @@ -417,8 +461,7 @@ esfmt: eresume: ici->ops->remove(icd); eiciadd: - if (icl->power) - icl->power(icd->pdev, 0); + soc_camera_power_set(icd, icl, 0); epower: icd->use_count--; module_put(ici->ops->owner); @@ -440,8 +483,7 @@ static int soc_camera_close(struct file *file) ici->ops->remove(icd); - if (icl->power) - icl->power(icd->pdev, 0); + soc_camera_power_set(icd, icl, 0); } if (icd->streamer == file) @@ -908,14 +950,14 @@ static int soc_camera_probe(struct device *dev) dev_info(dev, "Probing %s\n", dev_name(dev)); - if (icl->power) { - ret = icl->power(icd->pdev, 1); - if (ret < 0) { - dev_err(dev, - "Platform failed to power-on the camera.\n"); - goto epower; - } - } + ret = regulator_bulk_get(icd->pdev, icl->num_regulators, + icl->regulators); + if (ret < 0) + goto ereg; + + ret = soc_camera_power_set(icd, icl, 1); + if (ret < 0) + goto epower; /* The camera could have been already on, try to reset */ if (icl->reset) @@ -994,8 +1036,7 @@ static int soc_camera_probe(struct device *dev) ici->ops->remove(icd); - if (icl->power) - icl->power(icd->pdev, 0); + soc_camera_power_set(icd, icl, 0); mutex_unlock(&icd->video_lock); @@ -1017,9 +1058,10 @@ eadddev: evdc: ici->ops->remove(icd); eadd: - if (icl->power) - icl->power(icd->pdev, 0); + soc_camera_power_set(icd, icl, 0); epower: + regulator_bulk_free(icl->num_regulators, icl->regulators); +ereg: return ret; } @@ -1052,6 +1094,8 @@ static int soc_camera_remove(struct device *dev) } soc_camera_free_user_formats(icd); + regulator_bulk_free(icl->num_regulators, icl->regulators); + return 0; } diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 86e3631..9386db8 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -97,6 +97,7 @@ struct soc_camera_host_ops { #define SOCAM_SENSOR_INVERT_DATA (1 << 4) struct i2c_board_info; +struct regulator_bulk_data; struct soc_camera_link { /* Camera bus id, used to match a camera and a bus */ @@ -108,6 +109,10 @@ struct soc_camera_link { const char *module_name; void *priv; + /* Optional regulators that have to be managed on power on/off events */ + struct regulator_bulk_data *regulators; + int num_regulators; + /* * For non-I2C devices platform platform has to provide methods to * add a device to the system and to remove -- cgit v0.10.2 From 798cf3144f8b7466533cf738740478e472677a01 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 30 Dec 2010 15:23:38 -0300 Subject: [media] staging: usbvideo/vicam depends on USB Fix build errors by adding "depends on USB": ERROR: "usb_register_driver" [drivers/staging/usbvideo/vicam.ko] undefined! ERROR: "usb_bulk_msg" [drivers/staging/usbvideo/vicam.ko] undefined! ERROR: "usb_control_msg" [drivers/staging/usbvideo/vicam.ko] undefined! ERROR: "usb_deregister" [drivers/staging/usbvideo/vicam.ko] undefined! ERROR: "usb_get_dev" [drivers/staging/usbvideo/usbvideo.ko] undefined! ERROR: "usb_put_dev" [drivers/staging/usbvideo/usbvideo.ko] undefined! ERROR: "usb_free_urb" [drivers/staging/usbvideo/usbvideo.ko] undefined! ERROR: "usb_submit_urb" [drivers/staging/usbvideo/usbvideo.ko] undefined! ERROR: "usb_set_interface" [drivers/staging/usbvideo/usbvideo.ko] undefined! ERROR: "usb_kill_urb" [drivers/staging/usbvideo/usbvideo.ko] undefined! ERROR: "usb_register_driver" [drivers/staging/usbvideo/usbvideo.ko] undefined! ERROR: "usb_deregister" [drivers/staging/usbvideo/usbvideo.ko] undefined! ERROR: "usb_alloc_urb" [drivers/staging/usbvideo/usbvideo.ko] undefined! Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/usbvideo/Kconfig b/drivers/staging/usbvideo/Kconfig index d9fc867..566d659 100644 --- a/drivers/staging/usbvideo/Kconfig +++ b/drivers/staging/usbvideo/Kconfig @@ -3,7 +3,7 @@ config VIDEO_USBVIDEO config USB_VICAM tristate "USB 3com HomeConnect (aka vicam) support (DEPRECATED)" - depends on VIDEO_DEV && VIDEO_V4L2_COMMON + depends on VIDEO_DEV && VIDEO_V4L2_COMMON && USB select VIDEO_USBVIDEO ---help--- Say Y here if you have 3com homeconnect camera (vicam). -- cgit v0.10.2 From ef98a2c0f2856f6b2aa87fd32d5b192afaeae518 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 30 Dec 2010 15:23:41 -0300 Subject: [media] staging: se401 depends on USB Fix build errors by adding "depends on USB": ERROR: "usb_register_driver" [drivers/staging/se401/se401.ko] undefined! ERROR: "usb_alloc_urb" [drivers/staging/se401/se401.ko] undefined! ERROR: "usb_submit_urb" [drivers/staging/se401/se401.ko] undefined! ERROR: "usb_control_msg" [drivers/staging/se401/se401.ko] undefined! ERROR: "usb_free_urb" [drivers/staging/se401/se401.ko] undefined! ERROR: "usb_kill_urb" [drivers/staging/se401/se401.ko] undefined! ERROR: "usb_deregister" [drivers/staging/se401/se401.ko] undefined! Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/se401/Kconfig b/drivers/staging/se401/Kconfig index ee7313e..b7f8222 100644 --- a/drivers/staging/se401/Kconfig +++ b/drivers/staging/se401/Kconfig @@ -1,6 +1,6 @@ config USB_SE401 tristate "USB SE401 Camera support (DEPRECATED)" - depends on VIDEO_DEV && VIDEO_V4L2_COMMON + depends on VIDEO_DEV && VIDEO_V4L2_COMMON && USB ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. See -- cgit v0.10.2 From 21d33014108671cc6b02feda088f32bf26ce532d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20Bia=C5=82o=C5=84czyk?= Date: Wed, 29 Dec 2010 19:48:43 -0300 Subject: [media] ir-nec-decoder: fix repeat key issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixing the problem with NEC protocol and repeating keys under the following circumstances. The problem occurs when there is a repeat code without properly decoded scancode. This leads to repeat the wrong (last decoded) scancode. An example from real life: I am pressing volume down, then several minutes later i am pressing volume up, but the real scancode is wrongly decoded and only a repeat event is emitted, so as a result volume is going down while i am holding volume up button. The patch fixes above problem using rc_keyup timeout (as pointed by Mauro). It just prevents key repeats if they appear after rc_keyup. Signed-off-by: Mariusz BiaÅ‚oÅ„czyk Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c index 5d15c31..7b58b4a 100644 --- a/drivers/media/rc/ir-nec-decoder.c +++ b/drivers/media/rc/ir-nec-decoder.c @@ -88,9 +88,13 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) data->state = STATE_BIT_PULSE; return 0; } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) { - rc_repeat(dev); - IR_dprintk(1, "Repeat last key\n"); - data->state = STATE_TRAILER_PULSE; + if (!dev->keypressed) { + IR_dprintk(1, "Discarding last key repeat: event after key up\n"); + } else { + rc_repeat(dev); + IR_dprintk(1, "Repeat last key\n"); + data->state = STATE_TRAILER_PULSE; + } return 0; } -- cgit v0.10.2 From ebce9a3331f4dd1f39856dc4b79f539eb25f7f64 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Fri, 31 Dec 2010 02:04:38 -0300 Subject: [media] cx23885, cimax2.c: Fix case of two CAM insertion irq For example boot up with two CAM inserted. Signed-off-by: Abylay Ospan Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx23885/cimax2.c b/drivers/media/video/cx23885/cimax2.c index c95e7bc..209b971 100644 --- a/drivers/media/video/cx23885/cimax2.c +++ b/drivers/media/video/cx23885/cimax2.c @@ -368,7 +368,7 @@ static void netup_read_ci_status(struct work_struct *work) DVB_CA_EN50221_POLL_CAM_READY; else state->status = 0; - }; + } } /* CI irq handler */ @@ -377,16 +377,24 @@ int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status) struct cx23885_tsport *port = NULL; struct netup_ci_state *state = NULL; - if (pci_status & PCI_MSK_GPIO0) - port = &dev->ts1; - else if (pci_status & PCI_MSK_GPIO1) - port = &dev->ts2; - else /* who calls ? */ + ci_dbg_print("%s:\n", __func__); + + if (0 == (pci_status & (PCI_MSK_GPIO0 | PCI_MSK_GPIO1))) return 0; - state = port->port_priv; + if (pci_status & PCI_MSK_GPIO0) { + port = &dev->ts1; + state = port->port_priv; + schedule_work(&state->work); + ci_dbg_print("%s: Wakeup CI0\n", __func__); + } - schedule_work(&state->work); + if (pci_status & PCI_MSK_GPIO1) { + port = &dev->ts2; + state = port->port_priv; + schedule_work(&state->work); + ci_dbg_print("%s: Wakeup CI1\n", __func__); + } return 1; } -- cgit v0.10.2 From 9d1da730ee17e712c25c0b1e51653048f92d2385 Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Sun, 26 Dec 2010 10:23:58 -0300 Subject: [media] DVB: IR support for TechnoTrend CT-3650 Based on Waling Dijkstra's discovery that the IR works the same as on the TT-1500, this patch has been rewritten to fit with the rc_core infrastructure. Signed-off-by: David Henningsson Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c index a6de489..0d4709f 100644 --- a/drivers/media/dvb/dvb-usb/ttusb2.c +++ b/drivers/media/dvb/dvb-usb/ttusb2.c @@ -43,6 +43,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); struct ttusb2_state { u8 id; + u16 last_rc_key; }; static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd, @@ -128,6 +129,33 @@ static struct i2c_algorithm ttusb2_i2c_algo = { .functionality = ttusb2_i2c_func, }; +/* command to poll IR receiver (copied from pctv452e.c) */ +#define CMD_GET_IR_CODE 0x1b + +/* IR */ +static int tt3650_rc_query(struct dvb_usb_device *d) +{ + int ret; + u8 rx[9]; /* A CMD_GET_IR_CODE reply is 9 bytes long */ + struct ttusb2_state *st = d->priv; + ret = ttusb2_msg(d, CMD_GET_IR_CODE, NULL, 0, rx, sizeof(rx)); + if (ret != 0) + return ret; + + if (rx[8] & 0x01) { + /* got a "press" event */ + st->last_rc_key = (rx[3] << 8) | rx[2]; + deb_info("%s: cmd=0x%02x sys=0x%02x\n", __func__, rx[2], rx[3]); + rc_keydown(d->rc_dev, st->last_rc_key, 0); + } else if (st->last_rc_key) { + rc_keyup(d->rc_dev); + st->last_rc_key = 0; + } + + return 0; +} + + /* Callbacks for DVB USB */ static int ttusb2_identify_state (struct usb_device *udev, struct dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, @@ -345,6 +373,13 @@ static struct dvb_usb_device_properties ttusb2_properties_ct3650 = { .size_of_priv = sizeof(struct ttusb2_state), + .rc.core = { + .rc_interval = 150, /* Less than IR_KEYPRESS_TIMEOUT */ + .rc_codes = RC_MAP_TT_1500, + .rc_query = tt3650_rc_query, + .allowed_protos = RC_TYPE_UNKNOWN, + }, + .num_adapters = 1, .adapter = { { -- cgit v0.10.2 From 4f77b86c665ff6a167edfdf152ebfa997783fa17 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 31 Dec 2010 12:25:32 -0300 Subject: [media] ngene: fix compile warning drivers/media/dvb/ngene/ngene-core.c: In function 'ngene_start': drivers/media/dvb/ngene/ngene-core.c:1308:16: warning: unused variable 'flags' Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index be71f91..dc073bd 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c @@ -1304,7 +1304,6 @@ static void ngene_stop(struct ngene *dev) static int ngene_start(struct ngene *dev) { int stat; - unsigned long flags; int i; pci_set_master(dev->pci_dev); @@ -1337,6 +1336,8 @@ static int ngene_start(struct ngene *dev) #ifdef CONFIG_PCI_MSI /* enable MSI if kernel and card support it */ if (pci_msi_enabled() && dev->card_info->msi_supported) { + unsigned long flags; + ngwritel(0, NGENE_INT_ENABLE); free_irq(dev->pci_dev->irq, dev); stat = pci_enable_msi(dev->pci_dev); -- cgit v0.10.2 From 0c8fc77e481a3bfc243336085a3fe1fc71f9c1fb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 31 Dec 2010 12:26:53 -0300 Subject: [media] tda18218: fix compile warning drivers/media/common/tuners/tda18218.c: In function 'tda18218_wr_regs': drivers/media/common/tuners/tda18218.c:58:5: warning: 'ret' may be used uninitialized in this function Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/tuners/tda18218.c b/drivers/media/common/tuners/tda18218.c index 8da1fde..aacfe23 100644 --- a/drivers/media/common/tuners/tda18218.c +++ b/drivers/media/common/tuners/tda18218.c @@ -28,7 +28,7 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); /* write multiple registers */ static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len) { - int ret; + int ret = 0; u8 buf[1+len], quotient, remainder, i, msg_len, msg_len_max; struct i2c_msg msg[1] = { { -- cgit v0.10.2 From 1a5e5af0d2111fdc39c6f2275ed2a9e2e6dd69e2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 31 Dec 2010 12:30:56 -0300 Subject: [media] zoran: fix compiler warning drivers/media/video/zoran/zoran_driver.c: In function 'zoran_dqbuf': drivers/media/video/zoran/zoran_driver.c:2197:21: warning: 'bs.frame' may be used uninitialized in this function Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index fe84f17..7c3921d 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -2216,6 +2216,7 @@ static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) res = -EAGAIN; goto dqbuf_unlock_and_return; } + bs.frame = 0; /* suppress compiler warning */ res = jpg_sync(fh, &bs); if (res) goto dqbuf_unlock_and_return; -- cgit v0.10.2 From 36f54ff67bc78c6d8dc4a90ac257165e05fdd8da Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 31 Dec 2010 12:34:32 -0300 Subject: [media] v4l2-compat-ioctl32: fix compile warning drivers/media/video/v4l2-compat-ioctl32.c: In function 'get_v4l2_format32': drivers/media/video/v4l2-compat-ioctl32.c:169:2: warning: case value '0' not in enumerated type 'enum v4l2_buf_type' drivers/media/video/v4l2-compat-ioctl32.c: In function 'put_v4l2_format32': drivers/media/video/v4l2-compat-ioctl32.c:200:2: warning: case value '0' not in enumerated type 'enum v4l2_buf_type' Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index 65e6f13..dc82eb8 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -165,8 +165,6 @@ static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user if (copy_from_user(kp, up, sizeof(kp->fmt.raw_data))) return -EFAULT; return 0; - case 0: - return -EINVAL; default: printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", kp->type); @@ -196,8 +194,6 @@ static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user if (copy_to_user(up, kp, sizeof(up->fmt.raw_data))) return -EFAULT; return 0; - case 0: - return -EINVAL; default: printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", kp->type); -- cgit v0.10.2 From a7862aa90ffd1113bc2898ae6be2e4861b1f76cc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 5 Jan 2011 12:31:15 -0300 Subject: [media] cx25821: Fix compilation breakage due to BKL dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/staging/cx25821/cx25821-video.c: In function ‘video_open’: drivers/staging/cx25821/cx25821-video.c:817:8: error: implicit declaration of function ‘lock_kernel’ drivers/staging/cx25821/cx25821-video.c:834:9: error: implicit declaration of function ‘unlock_kernel’ This patch just adds a header with BKL function. It should be enough to avoid compilation breakage, but, as BKL will be removed, we need to properly fix it on a latter patch. Reported-by: Randy Dunlap Reported-by: Anca Emanuel Cc: Palash Bandyopadhyay Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c index 998c33a..0d8d756 100644 --- a/drivers/staging/cx25821/cx25821-video.c +++ b/drivers/staging/cx25821/cx25821-video.c @@ -27,6 +27,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include "cx25821-video.h" +#include MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); MODULE_AUTHOR("Hiep Huynh "); -- cgit v0.10.2 From e3c92215198cb6aa00ad38db2780faa6b72e0a3f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 6 Jan 2011 08:16:04 -0200 Subject: [media] radio-aimslab.c: Fix gcc 4.5+ bug gcc 4.5+ doesn't properly evaluate some inlined expressions. A previous patch were proposed by Andrew Morton using noinline. However, the entire inlined function is bogus, so let's just remove it and be happy. Reported-by: Andrew Morton Cc: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index 05e832f..6cc5d13 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -31,7 +31,6 @@ #include /* Modules */ #include /* Initdata */ #include /* request_region */ -#include /* udelay */ #include /* kernel radio structs */ #include /* for KERNEL_VERSION MACRO */ #include /* outb, outb_p */ @@ -71,27 +70,17 @@ static struct rtrack rtrack_card; /* local things */ -static void sleep_delay(long n) -{ - /* Sleep nicely for 'n' uS */ - int d = n / msecs_to_jiffies(1000); - if (!d) - udelay(n); - else - msleep(jiffies_to_msecs(d)); -} - static void rt_decvol(struct rtrack *rt) { outb(0x58, rt->io); /* volume down + sigstr + on */ - sleep_delay(100000); + msleep(100); outb(0xd8, rt->io); /* volume steady + sigstr + on */ } static void rt_incvol(struct rtrack *rt) { outb(0x98, rt->io); /* volume up + sigstr + on */ - sleep_delay(100000); + msleep(100); outb(0xd8, rt->io); /* volume steady + sigstr + on */ } @@ -120,7 +109,7 @@ static int rt_setvol(struct rtrack *rt, int vol) if (vol == 0) { /* volume = 0 means mute the card */ outb(0x48, rt->io); /* volume down but still "on" */ - sleep_delay(2000000); /* make sure it's totally down */ + msleep(2000); /* make sure it's totally down */ outb(0xd0, rt->io); /* volume steady, off */ rt->curvol = 0; /* track the volume state! */ mutex_unlock(&rt->lock); @@ -155,7 +144,7 @@ static void send_0_byte(struct rtrack *rt) outb_p(128+64+16+8+ 1, rt->io); /* on + wr-enable + data low */ outb_p(128+64+16+8+2+1, rt->io); /* clock */ } - sleep_delay(1000); + msleep(1); } static void send_1_byte(struct rtrack *rt) @@ -169,7 +158,7 @@ static void send_1_byte(struct rtrack *rt) outb_p(128+64+16+8+4+2+1, rt->io); /* clock */ } - sleep_delay(1000); + msleep(1); } static int rt_setfreq(struct rtrack *rt, unsigned long freq) @@ -420,7 +409,7 @@ static int __init rtrack_init(void) /* this ensures that the volume is all the way down */ outb(0x48, rt->io); /* volume down but still "on" */ - sleep_delay(2000000); /* make sure it's totally down */ + msleep(2000); /* make sure it's totally down */ outb(0xc0, rt->io); /* steady volume, mute card */ if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { -- cgit v0.10.2