From d30a3fe89635324397c9cf5802f18f11a49ace17 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 5 Dec 2009 01:19:47 -0300 Subject: V4L/DVB (13543): ir-common: Associate a table with a given protocol type While here, convert the protocol types into an enum and define 0 as unknown. Signed-off-by: Mauro Carvalho Chehab diff --git a/include/media/ir-common.h b/include/media/ir-common.h index e41a99e..28d1b9c 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -32,9 +32,13 @@ extern int media_ir_debug; /* media_ir_debug level (0,1,2) */ #define IR_dprintk(level, fmt, arg...) if (media_ir_debug >= level) \ printk(KERN_DEBUG "%s: " fmt , __func__, ## arg) -#define IR_TYPE_RC5 1 -#define IR_TYPE_PD 2 /* Pulse distance encoded IR */ -#define IR_TYPE_OTHER 99 +enum ir_type { + IR_TYPE_UNKNOWN = 0, + IR_TYPE_RC5 = 1, + IR_TYPE_PD = 2, /* Pulse distance encoded IR */ + IR_TYPE_NEC = 3, + IR_TYPE_OTHER = 99, +}; struct ir_scancode { u16 scancode; @@ -44,6 +48,7 @@ struct ir_scancode { struct ir_scancode_table { struct ir_scancode *scan; int size; + enum ir_type ir_type; spinlock_t lock; }; -- cgit v0.10.2 From 4039ff28a501cf6b9fc2b6a2c2b28476d7fa14cd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 5 Dec 2009 01:20:54 -0300 Subject: V4L/DVB (13544): ir-keymaps: mark the new rc5 hauppauge with IR_TYPE_RC5 While here, move the table to a better place inside the file Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index 328c973..abb5c73 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -1847,76 +1847,6 @@ struct ir_scancode_table ir_codes_hauppauge_new_table = { }; EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new_table); -/* - * 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 ir_codes_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) */ -}; - -struct ir_scancode_table ir_codes_rc5_hauppauge_new_table = { - .scan = ir_codes_rc5_hauppauge_new, - .size = ARRAY_SIZE(ir_codes_rc5_hauppauge_new), -}; -EXPORT_SYMBOL_GPL(ir_codes_rc5_hauppauge_new_table); - static struct ir_scancode ir_codes_npgtech[] = { { 0x1d, KEY_SWITCHVIDEOMODE }, /* switch inputs */ { 0x2a, KEY_FRONT }, @@ -3314,3 +3244,79 @@ struct ir_scancode_table ir_codes_gadmei_rm008z_table = { }; EXPORT_SYMBOL_GPL(ir_codes_gadmei_rm008z_table); +/************************************************************* + * COMPLETE SCANCODE TABLES + * Instead of just a partial scancode, the tables bellow + * contains the complete scancode and the receiver protocol + *************************************************************/ + +/* + * 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 ir_codes_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) */ +}; + +struct ir_scancode_table ir_codes_rc5_hauppauge_new_table = { + .scan = ir_codes_rc5_hauppauge_new, + .size = ARRAY_SIZE(ir_codes_rc5_hauppauge_new), + .ir_type = IR_TYPE_RC5, +}; +EXPORT_SYMBOL_GPL(ir_codes_rc5_hauppauge_new_table); -- cgit v0.10.2 From 1bad429e81f9a9ffa01c4158e6d1b1a3e06d9886 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 5 Dec 2009 08:27:49 -0300 Subject: V4L/DVB (13545): em28xx: properly select IR protocol based on the IR table Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 3f86d36..4f61e05 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -216,7 +216,7 @@ int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val) * sets only some bits (specified by bitmask) of a register, by first reading * the actual value */ -static int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, +int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, u8 bitmask) { int oldval; diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index d96ec7c..3f5cf02 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -337,19 +337,28 @@ int em28xx_ir_init(struct em28xx *dev) goto err_out_free; ir->input = input_dev; + ir_config = EM2874_IR_RC5; + + /* Adjust xclk based o IR table for RC5/NEC tables */ + if (dev->board.ir_codes->ir_type == IR_TYPE_RC5) { + dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; + ir->full_code = 1; + } else if (dev->board.ir_codes->ir_type == IR_TYPE_NEC) { + dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; + ir_config = EM2874_IR_NEC; + ir->full_code = 1; + } + em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, + EM28XX_XCLK_IR_RC5_MODE); /* Setup the proper handler based on the chip */ switch (dev->chip_id) { case CHIP_ID_EM2860: case CHIP_ID_EM2883: - if (dev->model == EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950) - ir->full_code = 1; ir->get_key = default_polling_getkey; break; case CHIP_ID_EM2874: ir->get_key = em2874_polling_getkey; - /* For now we only support RC5, so enable it */ - ir_config = EM2874_IR_RC5; em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1); break; default: diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 441df64..4897783 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -643,6 +643,8 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, int len); int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len); int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val); +int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, + u8 bitmask); int em28xx_read_ac97(struct em28xx *dev, u8 reg); int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val); -- cgit v0.10.2 From cda4303f555316930a219cd7c03a1925526145f0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 5 Dec 2009 09:34:21 -0300 Subject: V4L/DVB (13546): ir-keymaps: Add table for Terratec Cinergy XS FM This IR uses NEC protocol, with address=0x14. This keymap is similar to the existing Terratec Cinergy XS, except that: - it contains the full address/command code; - the Music button were mapped as KEY_RADIO; - some keycodes from the previous entry were wrong, IMHO. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index abb5c73..9bbe6b1 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -3320,3 +3320,76 @@ struct ir_scancode_table ir_codes_rc5_hauppauge_new_table = { .ir_type = IR_TYPE_RC5, }; EXPORT_SYMBOL_GPL(ir_codes_rc5_hauppauge_new_table); + +/* Terratec Cinergy Hybrid T USB XS FM + Mauro Carvalho Chehab + */ +static struct ir_scancode ir_codes_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}, +}; +struct ir_scancode_table ir_codes_nec_terratec_cinergy_xs_table = { + .scan = ir_codes_nec_terratec_cinergy_xs, + .size = ARRAY_SIZE(ir_codes_nec_terratec_cinergy_xs), + .ir_type = IR_TYPE_NEC, +}; +EXPORT_SYMBOL_GPL(ir_codes_nec_terratec_cinergy_xs_table); + diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 28d1b9c..45bf5cf 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -200,4 +200,5 @@ extern struct ir_scancode_table ir_codes_evga_indtube_table; extern struct ir_scancode_table ir_codes_terratec_cinergy_xs_table; extern struct ir_scancode_table ir_codes_videomate_s350_table; extern struct ir_scancode_table ir_codes_gadmei_rm008z_table; +extern struct ir_scancode_table ir_codes_nec_terratec_cinergy_xs_table; #endif -- cgit v0.10.2 From a3a9e287daa1f299e318161b790b1c5902b1d869 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 27 Nov 2009 04:33:25 -0300 Subject: V4L/DVB (13547): radio: add trivial checks on the tuner and type args. Many radio drivers did not check the tuner and type field correctly for g/s_frequency. These checks have now been added. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index 35edee0..5bf4985 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -268,6 +268,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct rtrack *rt = video_drvdata(file); + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; rt_setfreq(rt, f->frequency); return 0; } @@ -277,6 +279,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct rtrack *rt = video_drvdata(file); + if (f->tuner != 0) + return -EINVAL; f->type = V4L2_TUNER_RADIO; f->frequency = rt->curfreq; return 0; diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index 8daf809e..c223113 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c @@ -254,6 +254,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct aztech *az = video_drvdata(file); + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; az_setfreq(az, f->frequency); return 0; } @@ -263,6 +265,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct aztech *az = video_drvdata(file); + if (f->tuner != 0) + return -EINVAL; f->type = V4L2_TUNER_RADIO; f->frequency = az->curfreq; return 0; diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c index c6cf116..000f4d3 100644 --- a/drivers/media/radio/radio-gemtek-pci.c +++ b/drivers/media/radio/radio-gemtek-pci.c @@ -240,6 +240,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct gemtek_pci *card = video_drvdata(file); + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; if (f->frequency < GEMTEK_PCI_RANGE_LOW || f->frequency > GEMTEK_PCI_RANGE_HIGH) return -EINVAL; @@ -253,6 +255,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct gemtek_pci *card = video_drvdata(file); + if (f->tuner != 0) + return -EINVAL; f->type = V4L2_TUNER_RADIO; f->frequency = card->current_frequency; return 0; diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c index 64d737c..f8213b7 100644 --- a/drivers/media/radio/radio-maestro.c +++ b/drivers/media/radio/radio-maestro.c @@ -200,6 +200,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct maestro *dev = video_drvdata(file); + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) return -EINVAL; mutex_lock(&dev->lock); @@ -213,6 +215,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct maestro *dev = video_drvdata(file); + if (f->tuner != 0) + return -EINVAL; f->type = V4L2_TUNER_RADIO; mutex_lock(&dev->lock); f->frequency = BITS2FREQ(radio_bits_get(dev)); diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 3da51fe..44b4dbe 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -262,6 +262,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct maxiradio *dev = video_drvdata(file); + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) { dprintk(dev, 1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n", f->frequency / 16000, @@ -285,6 +287,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct maxiradio *dev = video_drvdata(file); + if (f->tuner != 0) + return -EINVAL; f->type = V4L2_TUNER_RADIO; f->frequency = dev->freq; diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 949f605..02a9cef 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -374,6 +374,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct amradio_device *radio = file->private_data; + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; return amradio_setfreq(radio, f->frequency); } @@ -383,6 +385,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct amradio_device *radio = file->private_data; + if (f->tuner != 0) + return -EINVAL; f->type = V4L2_TUNER_RADIO; f->frequency = radio->curfreq; diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c index 9cb193f..a79296a 100644 --- a/drivers/media/radio/radio-rtrack2.c +++ b/drivers/media/radio/radio-rtrack2.c @@ -167,6 +167,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct rtrack2 *rt = video_drvdata(file); + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; rt_setfreq(rt, f->frequency); return 0; } @@ -176,6 +178,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct rtrack2 *rt = video_drvdata(file); + if (f->tuner != 0) + return -EINVAL; f->type = V4L2_TUNER_RADIO; f->frequency = rt->curfreq; return 0; diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 49c4aab..93990b7 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -168,6 +168,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct fmi *fmi = video_drvdata(file); + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; if (f->frequency < RSF16_MINFREQ || f->frequency > RSF16_MAXFREQ) return -EINVAL; @@ -182,6 +184,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct fmi *fmi = video_drvdata(file); + if (f->tuner != 0) + return -EINVAL; f->type = V4L2_TUNER_RADIO; f->frequency = fmi->curfreq; return 0; diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index a11414f..52c7bbb 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -251,6 +251,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct fmr2 *fmr2 = video_drvdata(file); + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; if (f->frequency < RSF16_MINFREQ || f->frequency > RSF16_MAXFREQ) return -EINVAL; @@ -272,6 +274,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct fmr2 *fmr2 = video_drvdata(file); + if (f->tuner != 0) + return -EINVAL; f->type = V4L2_TUNER_RADIO; f->frequency = fmr2->curfreq; return 0; diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 3cd76dd..730ffd9 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -349,7 +349,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct tea5764_device *radio = video_drvdata(file); - if (f->tuner != 0) + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) return -EINVAL; if (f->frequency == 0) { /* We special case this as a power down control. */ @@ -370,6 +370,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct tea5764_device *radio = video_drvdata(file); struct tea5764_regs *r = &radio->regs; + if (f->tuner != 0) + return -EINVAL; tea5764_i2c_read(radio); memset(f, 0, sizeof(f)); f->type = V4L2_TUNER_RADIO; diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c index 699db9a..fc1c860 100644 --- a/drivers/media/radio/radio-terratec.c +++ b/drivers/media/radio/radio-terratec.c @@ -240,6 +240,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct terratec *tt = video_drvdata(file); + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; tt_setfreq(tt, f->frequency); return 0; } @@ -249,6 +251,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct terratec *tt = video_drvdata(file); + if (f->tuner != 0) + return -EINVAL; f->type = V4L2_TUNER_RADIO; f->frequency = tt->curfreq; return 0; diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c index 6f9ecc3..9d6dcf8 100644 --- a/drivers/media/radio/radio-trust.c +++ b/drivers/media/radio/radio-trust.c @@ -239,6 +239,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct trust *tr = video_drvdata(file); + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; tr_setfreq(tr, f->frequency); return 0; } @@ -248,6 +250,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct trust *tr = video_drvdata(file); + if (f->tuner != 0) + return -EINVAL; f->type = V4L2_TUNER_RADIO; f->frequency = tr->curfreq; return 0; diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index 3a98f13..0343928 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c @@ -207,6 +207,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct typhoon *dev = video_drvdata(file); + if (f->tuner != 0) + return -EINVAL; f->type = V4L2_TUNER_RADIO; f->frequency = dev->curfreq; return 0; @@ -217,6 +219,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct typhoon *dev = video_drvdata(file); + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; dev->curfreq = f->frequency; typhoon_setfreq(dev, dev->curfreq); return 0; diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index 80e98b6..f31eab9 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c @@ -266,6 +266,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, { struct zoltrix *zol = video_drvdata(file); + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; if (zol_setfreq(zol, f->frequency) != 0) return -EINVAL; return 0; @@ -276,6 +278,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct zoltrix *zol = video_drvdata(file); + if (f->tuner != 0) + return -EINVAL; f->type = V4L2_TUNER_RADIO; f->frequency = zol->curfreq; return 0; -- cgit v0.10.2 From eac8ea536aded07004bde917f05a2329902c64b0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 27 Nov 2009 13:56:50 -0300 Subject: V4L/DVB (13549): v4l: Add video_device_node_name function Many drivers access the device number (video_device::v4l2_devnode::num) in order to print the video device node name. Add and use a helper function to retrieve the video_device node name. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index b806eda..74d677c 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -561,6 +561,8 @@ video_device helper functions There are a few useful helper functions: +- file/video_device private data + You can set/get driver private data in the video_device struct using: void *video_get_drvdata(struct video_device *vdev); @@ -575,8 +577,7 @@ struct video_device *video_devdata(struct file *file); returns the video_device belonging to the file struct. -The final helper function combines video_get_drvdata with -video_devdata: +The video_drvdata function combines video_get_drvdata with video_devdata: void *video_drvdata(struct file *file); @@ -584,6 +585,17 @@ You can go from a video_device struct to the v4l2_device struct using: struct v4l2_device *v4l2_dev = vdev->v4l2_dev; +- Device node name + +The video_device node kernel name can be retrieved using + +const char *video_device_node_name(struct video_device *vdev); + +The name is used as a hint by userspace tools such as udev. The function +should be used where possible instead of accessing the video_device::num and +video_device::minor fields. + + video buffer helper functions ----------------------------- diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 500cbe9..aa3e0f9 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -551,8 +551,8 @@ static int __video_register_device(struct video_device *vdev, int type, int nr, vdev->dev.release = v4l2_device_release; if (nr != -1 && nr != vdev->num && warn_if_nr_in_use) - printk(KERN_WARNING "%s: requested %s%d, got %s%d\n", - __func__, name_base, nr, name_base, vdev->num); + printk(KERN_WARNING "%s: requested %s%d, got %s\n", __func__, + name_base, nr, video_device_node_name(vdev)); /* Part 5: Activate this minor. The char device can now be used. */ mutex_lock(&videodev_lock); diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 73c9867..9135f57 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -141,6 +141,11 @@ static inline void *video_drvdata(struct file *file) return video_get_drvdata(video_devdata(file)); } +static inline const char *video_device_node_name(struct video_device *vdev) +{ + return dev_name(&vdev->dev); +} + static inline int video_is_unregistered(struct video_device *vdev) { return test_bit(V4L2_FL_UNREGISTERED, &vdev->flags); -- cgit v0.10.2 From 38c7c036036c6260606a2a833aaad3794ca22499 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 27 Nov 2009 13:57:15 -0300 Subject: V4L/DVB (13550): v4l: Use the new video_device_node_name function Fix all device drivers to use the new video_device_node_name function. This also strips kernel log messages from the "/dev/" prefix, has the device node location is a userspace policy decision unknown to the kernel. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index 620f655..f279a64 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -543,15 +543,13 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, return err; } - if( VFL_TYPE_GRABBER == type ) { + if (VFL_TYPE_GRABBER == type) vv->video_minor = vfd->minor; - INFO(("%s: registered device video%d [v4l2]\n", - dev->name, vfd->num)); - } else { + else vv->vbi_minor = vfd->minor; - INFO(("%s: registered device vbi%d [v4l2]\n", - dev->name, vfd->num)); - } + + INFO(("%s: registered device %s [v4l2]\n", + dev->name, video_device_node_name(vfd))); *vid = vfd; return 0; diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index d137bac..0ec807d 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -860,8 +860,8 @@ static int __init ar_init(void) goto out_dev; } - printk("video%d: Found M64278 VGA (IRQ %d, Freq %dMHz).\n", - ar->vdev->num, M32R_IRQ_INT3, freq); + printk("%s: Found M64278 VGA (IRQ %d, Freq %dMHz).\n", + video_device_node_name(ar->vdev), M32R_IRQ_INT3, freq); return 0; diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index a672401..d576183 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -4244,8 +4244,8 @@ static int __devinit bttv_register_video(struct bttv *btv) if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER, video_nr[btv->c.nr]) < 0) goto err; - printk(KERN_INFO "bttv%d: registered device video%d\n", - btv->c.nr, btv->video_dev->num); + printk(KERN_INFO "bttv%d: registered device %s\n", + btv->c.nr, video_device_node_name(btv->video_dev)); if (device_create_file(&btv->video_dev->dev, &dev_attr_card)<0) { printk(KERN_ERR "bttv%d: device_create_file 'card' " @@ -4261,8 +4261,8 @@ static int __devinit bttv_register_video(struct bttv *btv) if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI, vbi_nr[btv->c.nr]) < 0) goto err; - printk(KERN_INFO "bttv%d: registered device vbi%d\n", - btv->c.nr, btv->vbi_dev->num); + printk(KERN_INFO "bttv%d: registered device %s\n", + btv->c.nr, video_device_node_name(btv->vbi_dev)); if (!btv->has_radio) return 0; @@ -4273,8 +4273,8 @@ static int __devinit bttv_register_video(struct bttv *btv) if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO, radio_nr[btv->c.nr]) < 0) goto err; - printk(KERN_INFO "bttv%d: registered device radio%d\n", - btv->c.nr, btv->radio_dev->num); + printk(KERN_INFO "bttv%d: registered device %s\n", + btv->c.nr, video_device_node_name(btv->radio_dev)); /* all done */ return 0; diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 85cf177..e2cbeba 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -809,8 +809,8 @@ static int init_cqcam(struct parport *port) return -ENODEV; } - printk(KERN_INFO "video%d: Colour QuickCam found on %s\n", - qcam->vdev.num, qcam->pport->name); + printk(KERN_INFO "%s: Colour QuickCam found on %s\n", + video_device_node_name(&qcam->vdev), qcam->pport->name); qcams[num_cams++] = qcam; diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index 2377313..d6f2653 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -1342,15 +1342,13 @@ out: static void create_proc_cpia_cam(struct cam_data *cam) { - char name[5 + 1 + 10 + 1]; struct proc_dir_entry *ent; if (!cpia_proc_root || !cam) return; - snprintf(name, sizeof(name), "video%d", cam->vdev.num); - - ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root); + ent = create_proc_entry(video_device_node_name(&cam->vdev), + S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root); if (!ent) return; @@ -1368,13 +1366,10 @@ static void create_proc_cpia_cam(struct cam_data *cam) static void destroy_proc_cpia_cam(struct cam_data *cam) { - char name[5 + 1 + 10 + 1]; - if (!cam || !cam->proc_entry) return; - snprintf(name, sizeof(name), "video%d", cam->vdev.num); - remove_proc_entry(name, cpia_proc_root); + remove_proc_entry(video_device_node_name(&cam->vdev), cpia_proc_root); cam->proc_entry = NULL; } @@ -3999,7 +3994,7 @@ void cpia_unregister_camera(struct cam_data *cam) } #ifdef CONFIG_PROC_FS - DBG("destroying /proc/cpia/video%d\n", cam->vdev.num); + DBG("destroying /proc/cpia/%s\n", video_device_node_name(&cam->vdev)); destroy_proc_cpia_cam(cam); #endif if (!cam->open_count) { diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 0b4a8f3..f8952af 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -1967,9 +1967,9 @@ void cpia2_unregister_camera(struct camera_data *cam) if (!cam->open_count) { video_unregister_device(cam->vdev); } else { - LOG("/dev/video%d removed while open, " - "deferring video_unregister_device\n", - cam->vdev->num); + LOG("%s removed while open, deferring " + "video_unregister_device\n", + video_device_node_name(cam->vdev)); } } diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index c398651..987a930 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -219,6 +219,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type) { struct cx18_stream *s = &cx->streams[type]; int vfl_type = cx18_stream_info[type].vfl_type; + const char *name; int num, ret; /* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something? @@ -258,31 +259,30 @@ static int cx18_reg_dev(struct cx18 *cx, int type) s->video_dev = NULL; return ret; } - num = s->video_dev->num; + + name = video_device_node_name(s->video_dev); switch (vfl_type) { case VFL_TYPE_GRABBER: - CX18_INFO("Registered device video%d for %s " - "(%d x %d.%02d kB)\n", - num, s->name, cx->stream_buffers[type], + CX18_INFO("Registered device %s for %s (%d x %d.%02d kB)\n", + name, s->name, cx->stream_buffers[type], cx->stream_buf_size[type] / 1024, (cx->stream_buf_size[type] * 100 / 1024) % 100); break; case VFL_TYPE_RADIO: - CX18_INFO("Registered device radio%d for %s\n", - num, s->name); + CX18_INFO("Registered device %s for %s\n", name, s->name); break; case VFL_TYPE_VBI: if (cx->stream_buffers[type]) - CX18_INFO("Registered device vbi%d for %s " + CX18_INFO("Registered device %s for %s " "(%d x %d bytes)\n", - num, s->name, cx->stream_buffers[type], + name, s->name, cx->stream_buffers[type], cx->stream_buf_size[type]); else - CX18_INFO("Registered device vbi%d for %s\n", - num, s->name); + CX18_INFO("Registered device %s for %s\n", + name, s->name); break; } diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 319c459..ff534fe 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c @@ -856,8 +856,9 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) if (dev->users) { cx231xx_warn - ("device /dev/video%d is open! Deregistration and memory " - "deallocation are deferred on close.\n", dev->vdev->num); + ("device %s is open! Deregistration and memory " + "deallocation are deferred on close.\n", + video_device_node_name(dev->vdev)); dev->state |= DEV_MISCONFIGURED; cx231xx_uninit_isoc(dev); diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index d095aa0..1c7f84e 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c @@ -2027,8 +2027,8 @@ void cx231xx_release_analog_resources(struct cx231xx *dev) dev->radio_dev = NULL; } if (dev->vbi_dev) { - cx231xx_info("V4L2 device /dev/vbi%d deregistered\n", - dev->vbi_dev->num); + cx231xx_info("V4L2 device %s deregistered\n", + video_device_node_name(dev->vbi_dev)); if (-1 != dev->vbi_dev->minor) video_unregister_device(dev->vbi_dev); else @@ -2036,8 +2036,8 @@ void cx231xx_release_analog_resources(struct cx231xx *dev) dev->vbi_dev = NULL; } if (dev->vdev) { - cx231xx_info("V4L2 device /dev/video%d deregistered\n", - dev->vdev->num); + cx231xx_info("V4L2 device %s deregistered\n", + video_device_node_name(dev->vdev)); if (-1 != dev->vdev->minor) video_unregister_device(dev->vdev); else @@ -2374,8 +2374,8 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) return ret; } - cx231xx_info("%s/0: registered device video%d [v4l2]\n", - dev->name, dev->vdev->num); + cx231xx_info("%s/0: registered device %s [v4l2]\n", + dev->name, video_device_node_name(dev->vdev)); /* Initialize VBI template */ memcpy(&cx231xx_vbi_template, &cx231xx_video_template, @@ -2393,8 +2393,8 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) return ret; } - cx231xx_info("%s/0: registered device vbi%d\n", - dev->name, dev->vbi_dev->num); + cx231xx_info("%s/0: registered device %s\n", + dev->name, video_device_node_name(dev->vbi_dev)); if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) { dev->radio_dev = cx231xx_vdev_init(dev, &cx231xx_radio_template, @@ -2409,12 +2409,13 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) cx231xx_errdev("can't register radio device\n"); return ret; } - cx231xx_info("Registered radio device as /dev/radio%d\n", - dev->radio_dev->num); + cx231xx_info("Registered radio device as %s\n", + video_device_node_name(dev->radio_dev)); } - cx231xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", - dev->vdev->num, dev->vbi_dev->num); + cx231xx_info("V4L2 device registered as %s and %s\n", + video_device_node_name(dev->vdev), + video_device_node_name(dev->vbi_dev)); return 0; } diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 0eed852..8084e13 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c @@ -1810,8 +1810,8 @@ int cx23885_417_register(struct cx23885_dev *dev) return err; } - printk(KERN_INFO "%s: registered device video%d [mpeg]\n", - dev->name, dev->v4l_device->num); + printk(KERN_INFO "%s: registered device %s [mpeg]\n", + dev->name, video_device_node_name(dev->v4l_device)); return 0; } diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 8b372b4..5570383 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -1532,8 +1532,8 @@ int cx23885_video_register(struct cx23885_dev *dev) dev->name); goto fail_unreg; } - printk(KERN_INFO "%s/0: registered device video%d [v4l2]\n", - dev->name, dev->video_dev->num); + printk(KERN_INFO "%s/0: registered device %s [v4l2]\n", + dev->name, video_device_node_name(dev->video_dev)); /* initial device configuration */ mutex_lock(&dev->lock); cx23885_set_tvnorm(dev, dev->tvnorm); diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index fbdc1cd..9f02715 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1296,8 +1296,8 @@ static int blackbird_register_video(struct cx8802_dev *dev) dev->core->name); return err; } - printk(KERN_INFO "%s/2: registered device video%d [mpeg]\n", - dev->core->name, dev->mpeg_dev->num); + printk(KERN_INFO "%s/2: registered device %s [mpeg]\n", + dev->core->name, video_device_node_name(dev->mpeg_dev)); return 0; } diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index d7e8fce..55063a7 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1916,8 +1916,8 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, core->name); goto fail_unreg; } - printk(KERN_INFO "%s/0: registered device video%d [v4l2]\n", - core->name, dev->video_dev->num); + printk(KERN_INFO "%s/0: registered device %s [v4l2]\n", + core->name, video_device_node_name(dev->video_dev)); dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi"); err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, @@ -1927,8 +1927,8 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, core->name); goto fail_unreg; } - printk(KERN_INFO "%s/0: registered device vbi%d\n", - core->name, dev->vbi_dev->num); + printk(KERN_INFO "%s/0: registered device %s\n", + core->name, video_device_node_name(dev->vbi_dev)); if (core->board.radio.type == CX88_RADIO) { dev->radio_dev = cx88_vdev_init(core,dev->pci, @@ -1940,8 +1940,8 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, core->name); goto fail_unreg; } - printk(KERN_INFO "%s/0: registered device radio%d\n", - core->name, dev->radio_dev->num); + printk(KERN_INFO "%s/0: registered device %s\n", + core->name, video_device_node_name(dev->radio_dev)); } /* everything worked */ diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 82da205..4ace709 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -2923,9 +2923,9 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) if (dev->users) { em28xx_warn - ("device /dev/video%d is open! Deregistration and memory " + ("device %s is open! Deregistration and memory " "deallocation are deferred on close.\n", - dev->vdev->num); + video_device_node_name(dev->vdev)); dev->state |= DEV_MISCONFIGURED; em28xx_uninit_isoc(dev); diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 7ad6537..5cc4fff 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -2167,8 +2167,8 @@ void em28xx_release_analog_resources(struct em28xx *dev) dev->radio_dev = NULL; } if (dev->vbi_dev) { - em28xx_info("V4L2 device /dev/vbi%d deregistered\n", - dev->vbi_dev->num); + em28xx_info("V4L2 device %s deregistered\n", + video_device_node_name(dev->vbi_dev)); if (-1 != dev->vbi_dev->minor) video_unregister_device(dev->vbi_dev); else @@ -2176,8 +2176,8 @@ void em28xx_release_analog_resources(struct em28xx *dev) dev->vbi_dev = NULL; } if (dev->vdev) { - em28xx_info("V4L2 device /dev/video%d deregistered\n", - dev->vdev->num); + em28xx_info("V4L2 device %s deregistered\n", + video_device_node_name(dev->vdev)); if (-1 != dev->vdev->minor) video_unregister_device(dev->vdev); else @@ -2540,16 +2540,16 @@ int em28xx_register_analog_devices(struct em28xx *dev) em28xx_errdev("can't register radio device\n"); return ret; } - em28xx_info("Registered radio device as /dev/radio%d\n", - dev->radio_dev->num); + em28xx_info("Registered radio device as %s\n", + video_device_node_name(dev->radio_dev)); } - em28xx_info("V4L2 video device registered as /dev/video%d\n", - dev->vdev->num); + em28xx_info("V4L2 video device registered as %s\n", + video_device_node_name(dev->vdev)); if (dev->vbi_dev) - em28xx_info("V4L2 VBI device registered as /dev/vbi%d\n", - dev->vbi_dev->num); + em28xx_info("V4L2 VBI device registered as %s\n", + video_device_node_name(dev->vbi_dev)); return 0; } diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index 88987a5..f561a1c 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -587,8 +587,8 @@ static int et61x251_stream_interrupt(struct et61x251_device* cam) else if (cam->stream != STREAM_OFF) { cam->state |= DEV_MISCONFIGURED; DBG(1, "URB timeout reached. The camera is misconfigured. To " - "use it, close and open /dev/video%d again.", - cam->v4ldev->num); + "use it, close and open %s again.", + video_device_node_name(cam->v4ldev)); return -EIO; } @@ -1195,7 +1195,8 @@ static void et61x251_release_resources(struct kref *kref) cam = container_of(kref, struct et61x251_device, kref); - DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->num); + DBG(2, "V4L2 device %s deregistered", + video_device_node_name(cam->v4ldev)); video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); usb_put_dev(cam->usbdev); @@ -1236,8 +1237,8 @@ static int et61x251_open(struct file *filp) } if (cam->users) { - DBG(2, "Device /dev/video%d is already in use", - cam->v4ldev->num); + DBG(2, "Device %s is already in use", + video_device_node_name(cam->v4ldev)); DBG(3, "Simultaneous opens are not supported"); if ((filp->f_flags & O_NONBLOCK) || (filp->f_flags & O_NDELAY)) { @@ -1280,7 +1281,8 @@ static int et61x251_open(struct file *filp) cam->frame_count = 0; et61x251_empty_framequeues(cam); - DBG(3, "Video device /dev/video%d is open", cam->v4ldev->num); + DBG(3, "Video device %s is open", + video_device_node_name(cam->v4ldev)); out: mutex_unlock(&cam->open_mutex); @@ -1304,7 +1306,8 @@ static int et61x251_release(struct file *filp) cam->users--; wake_up_interruptible_nr(&cam->wait_open, 1); - DBG(3, "Video device /dev/video%d closed", cam->v4ldev->num); + DBG(3, "Video device %s closed", + video_device_node_name(cam->v4ldev)); kref_put(&cam->kref, et61x251_release_resources); @@ -1846,8 +1849,8 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) if (err) { /* atomic, no rollback in ioctl() */ cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->num); + "use the camera, close and open %s again.", + video_device_node_name(cam->v4ldev)); return -EIO; } @@ -1859,8 +1862,8 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) nbuffers != et61x251_request_buffers(cam, nbuffers, cam->io)) { cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->num); + "use the camera, close and open %s again.", + video_device_node_name(cam->v4ldev)); return -ENOMEM; } @@ -2069,8 +2072,8 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, if (err) { /* atomic, no rollback in ioctl() */ cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->num); + "use the camera, close and open %s again.", + video_device_node_name(cam->v4ldev)); return -EIO; } @@ -2081,8 +2084,8 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, nbuffers != et61x251_request_buffers(cam, nbuffers, cam->io)) { cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->num); + "use the camera, close and open %s again.", + video_device_node_name(cam->v4ldev)); return -ENOMEM; } @@ -2130,7 +2133,7 @@ et61x251_vidioc_s_jpegcomp(struct et61x251_device* cam, void __user * arg) cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " "problems. To use the camera, close and open " - "/dev/video%d again.", cam->v4ldev->num); + "%s again.", video_device_node_name(cam->v4ldev)); return -EIO; } @@ -2603,7 +2606,8 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) goto fail; } - DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->num); + DBG(2, "V4L2 device registered as %s", + video_device_node_name(cam->v4ldev)); cam->module_param.force_munmap = force_munmap[dev_nr]; cam->module_param.frame_timeout = frame_timeout[dev_nr]; @@ -2654,9 +2658,9 @@ static void et61x251_usb_disconnect(struct usb_interface* intf) DBG(2, "Disconnecting %s...", cam->v4ldev->name); if (cam->users) { - DBG(2, "Device /dev/video%d is open! Deregistration and " - "memory deallocation are deferred.", - cam->v4ldev->num); + DBG(2, "Device %s is open! Deregistration and memory " + "deallocation are deferred.", + video_device_node_name(cam->v4ldev)); cam->state |= DEV_MISCONFIGURED; et61x251_stop_transfer(cam); cam->state |= DEV_DISCONNECTED; diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c index a695e0a..bd3c21a 100644 --- a/drivers/media/video/gspca/gl860/gl860.c +++ b/drivers/media/video/gspca/gl860/gl860.c @@ -534,8 +534,8 @@ static int sd_probe(struct usb_interface *intf, gspca_dev = usb_get_intfdata(intf); PDEBUG(D_PROBE, - "Camera is now controlling video device /dev/video%d", - gspca_dev->vdev.minor); + "Camera is now controlling video device %s", + video_device_node_name(&gspca_dev->vdev)); } return ret; diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 4076f8e..6af4f23 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -987,7 +987,8 @@ static void gspca_release(struct video_device *vfd) { struct gspca_dev *gspca_dev = container_of(vfd, struct gspca_dev, vdev); - PDEBUG(D_PROBE, "/dev/video%d released", gspca_dev->vdev.num); + PDEBUG(D_PROBE, "%s released", + video_device_node_name(&gspca_dev->vdev)); kfree(gspca_dev->usb_buf); kfree(gspca_dev); @@ -2073,7 +2074,7 @@ int gspca_dev_probe(struct usb_interface *intf, } usb_set_intfdata(intf, gspca_dev); - PDEBUG(D_PROBE, "/dev/video%d created", gspca_dev->vdev.num); + PDEBUG(D_PROBE, "%s created", video_device_node_name(&gspca_dev->vdev)); return 0; out: kfree(gspca_dev->usb_buf); @@ -2092,7 +2093,8 @@ void gspca_disconnect(struct usb_interface *intf) { struct gspca_dev *gspca_dev = usb_get_intfdata(intf); - PDEBUG(D_PROBE, "/dev/video%d disconnect", gspca_dev->vdev.num); + PDEBUG(D_PROBE, "%s disconnect", + video_device_node_name(&gspca_dev->vdev)); mutex_lock(&gspca_dev->usb_lock); gspca_dev->present = 0; diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index 1c9bc94..e280eb1 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c @@ -376,8 +376,8 @@ static int hdpvr_probe(struct usb_interface *interface, usb_set_intfdata(interface, dev); /* let the user know what node this device is now attached to */ - v4l2_info(&dev->v4l2_dev, "device now attached to /dev/video%d\n", - dev->video_dev->minor); + v4l2_info(&dev->v4l2_dev, "device now attached to %s\n", + video_device_node_name(dev->video_dev)); return 0; error: @@ -391,13 +391,10 @@ error: static void hdpvr_disconnect(struct usb_interface *interface) { struct hdpvr_device *dev; - int minor; dev = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); - minor = dev->video_dev->minor; - /* prevent more I/O from starting and stop any ongoing */ mutex_lock(&dev->io_mutex); dev->status = STATUS_DISCONNECTED; @@ -425,7 +422,8 @@ static void hdpvr_disconnect(struct usb_interface *interface) atomic_dec(&dev_nr); - v4l2_info(&dev->v4l2_dev, "device /dev/video%d disconnected\n", minor); + v4l2_info(&dev->v4l2_dev, "device %s disconnected\n", + video_device_node_name(dev->video_dev)); v4l2_device_unregister(&dev->v4l2_dev); kfree(dev->usbc_buf); diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 67699e3..e12c602 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -245,6 +245,7 @@ static int ivtv_reg_dev(struct ivtv *itv, int type) { struct ivtv_stream *s = &itv->streams[type]; int vfl_type = ivtv_stream_info[type].vfl_type; + const char *name; int num; if (s->vdev == NULL) @@ -268,24 +269,24 @@ static int ivtv_reg_dev(struct ivtv *itv, int type) s->vdev = NULL; return -ENOMEM; } - num = s->vdev->num; + name = video_device_node_name(s->vdev); switch (vfl_type) { case VFL_TYPE_GRABBER: - IVTV_INFO("Registered device video%d for %s (%d kB)\n", - num, s->name, itv->options.kilobytes[type]); + IVTV_INFO("Registered device %s for %s (%d kB)\n", + name, s->name, itv->options.kilobytes[type]); break; case VFL_TYPE_RADIO: - IVTV_INFO("Registered device radio%d for %s\n", - num, s->name); + IVTV_INFO("Registered device %s for %s\n", + name, s->name); break; case VFL_TYPE_VBI: if (itv->options.kilobytes[type]) - IVTV_INFO("Registered device vbi%d for %s (%d kB)\n", - num, s->name, itv->options.kilobytes[type]); + IVTV_INFO("Registered device %s for %s (%d kB)\n", + name, s->name, itv->options.kilobytes[type]); else - IVTV_INFO("Registered device vbi%d for %s\n", - num, s->name); + IVTV_INFO("Registered device %s for %s\n", + name, s->name); break; } return 0; diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index 5fc4ac0..e2f137b 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c @@ -1678,7 +1678,8 @@ static int omap24xxcam_device_register(struct v4l2_int_device *s) omap24xxcam_poweron_reset(cam); - dev_info(cam->dev, "registered device video%d\n", vfd->minor); + dev_info(cam->dev, "registered device %s\n", + video_device_node_name(vfd)); return 0; diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 6aa48e0..cc8ddb2 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -151,17 +151,6 @@ static struct v4l2_format pvr_format [] = { }; -static const char *get_v4l_name(int v4l_type) -{ - switch (v4l_type) { - case VFL_TYPE_GRABBER: return "video"; - case VFL_TYPE_RADIO: return "radio"; - case VFL_TYPE_VBI: return "vbi"; - default: return "?"; - } -} - - /* * pvr_ioctl() * @@ -891,10 +880,8 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) { - int num = dip->devbase.num; struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw; enum pvr2_config cfg = dip->config; - int v4l_type = dip->v4l_type; pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1); @@ -906,8 +893,8 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) are gone. */ video_unregister_device(&dip->devbase); - printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n", - get_v4l_name(v4l_type), num, + printk(KERN_INFO "pvrusb2: unregistered device %s [%s]\n", + video_device_node_name(&dip->devbase), pvr2_config_get_name(cfg)); } @@ -1317,8 +1304,8 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, ": Failed to register pvrusb2 v4l device\n"); } - printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n", - get_v4l_name(dip->v4l_type), dip->devbase.num, + printk(KERN_INFO "pvrusb2: registered device %s [%s]\n", + video_device_node_name(&dip->devbase), pvr2_config_get_name(dip->config)); pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw, diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 89b620f..819cf4e 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -1807,7 +1807,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id goto err_video_release; } - PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->num); + PWC_INFO("Registered as %s.\n", video_device_node_name(pdev->vdev)); /* occupy slot */ if (hint < MAX_DEV_HINTS) diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 0ba7f5a..c07f072 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -1046,8 +1046,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, dev->name); goto fail4; } - printk(KERN_INFO "%s: registered device video%d [v4l2]\n", - dev->name, dev->video_dev->num); + printk(KERN_INFO "%s: registered device %s [v4l2]\n", + dev->name, video_device_node_name(dev->video_dev)); dev->vbi_dev = vdev_init(dev, &saa7134_video_template, "vbi"); @@ -1055,8 +1055,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, vbi_nr[dev->nr]); if (err < 0) goto fail4; - printk(KERN_INFO "%s: registered device vbi%d\n", - dev->name, dev->vbi_dev->num); + printk(KERN_INFO "%s: registered device %s\n", + dev->name, video_device_node_name(dev->vbi_dev)); if (card_has_radio(dev)) { dev->radio_dev = vdev_init(dev,&saa7134_radio_template,"radio"); @@ -1064,8 +1064,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, radio_nr[dev->nr]); if (err < 0) goto fail4; - printk(KERN_INFO "%s: registered device radio%d\n", - dev->name, dev->radio_dev->num); + printk(KERN_INFO "%s: registered device %s\n", + dev->name, video_device_node_name(dev->radio_dev)); } /* everything worked */ diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 296788c..abc1d0b 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -540,8 +540,8 @@ static int empress_init(struct saa7134_dev *dev) dev->empress_dev = NULL; return err; } - printk(KERN_INFO "%s: registered device video%d [mpeg]\n", - dev->name, dev->empress_dev->num); + printk(KERN_INFO "%s: registered device %s [mpeg]\n", + dev->name, video_device_node_name(dev->empress_dev)); videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops, &dev->pci->dev, &dev->slock, diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c index 85ffc2c..41d0166 100644 --- a/drivers/media/video/se401.c +++ b/drivers/media/video/se401.c @@ -1428,8 +1428,8 @@ static int se401_probe(struct usb_interface *intf, err("video_register_device failed"); return -EIO; } - dev_info(&intf->dev, "registered new video device: video%d\n", - se401->vdev.num); + dev_info(&intf->dev, "registered new video device: %s\n", + video_device_node_name(&se401->vdev)); usb_set_intfdata(intf, se401); return 0; diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 4a7711c..4cf41a8 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -1007,8 +1007,8 @@ static int sn9c102_stream_interrupt(struct sn9c102_device* cam) else if (cam->stream != STREAM_OFF) { cam->state |= DEV_MISCONFIGURED; DBG(1, "URB timeout reached. The camera is misconfigured. " - "To use it, close and open /dev/video%d again.", - cam->v4ldev->num); + "To use it, close and open %s again.", + video_device_node_name(cam->v4ldev)); return -EIO; } @@ -1734,7 +1734,8 @@ static void sn9c102_release_resources(struct kref *kref) cam = container_of(kref, struct sn9c102_device, kref); - DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->num); + DBG(2, "V4L2 device %s deregistered", + video_device_node_name(cam->v4ldev)); video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); usb_put_dev(cam->usbdev); @@ -1791,8 +1792,8 @@ static int sn9c102_open(struct file *filp) } if (cam->users) { - DBG(2, "Device /dev/video%d is already in use", - cam->v4ldev->num); + DBG(2, "Device %s is already in use", + video_device_node_name(cam->v4ldev)); DBG(3, "Simultaneous opens are not supported"); /* open() must follow the open flags and should block @@ -1845,7 +1846,7 @@ static int sn9c102_open(struct file *filp) cam->frame_count = 0; sn9c102_empty_framequeues(cam); - DBG(3, "Video device /dev/video%d is open", cam->v4ldev->num); + DBG(3, "Video device %s is open", video_device_node_name(cam->v4ldev)); out: mutex_unlock(&cam->open_mutex); @@ -1870,7 +1871,7 @@ static int sn9c102_release(struct file *filp) cam->users--; wake_up_interruptible_nr(&cam->wait_open, 1); - DBG(3, "Video device /dev/video%d closed", cam->v4ldev->num); + DBG(3, "Video device %s closed", video_device_node_name(cam->v4ldev)); kref_put(&cam->kref, sn9c102_release_resources); @@ -2433,8 +2434,8 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg) if (err) { /* atomic, no rollback in ioctl() */ cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->num); + "use the camera, close and open %s again.", + video_device_node_name(cam->v4ldev)); return -EIO; } @@ -2446,8 +2447,8 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg) nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) { cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->num); + "use the camera, close and open %s again.", + video_device_node_name(cam->v4ldev)); return -ENOMEM; } @@ -2690,8 +2691,8 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, if (err) { /* atomic, no rollback in ioctl() */ cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->num); + "use the camera, close and open %s again.", + video_device_node_name(cam->v4ldev)); return -EIO; } @@ -2702,8 +2703,8 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) { cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->num); + "use the camera, close and open %s again.", + video_device_node_name(cam->v4ldev)); return -ENOMEM; } @@ -2748,9 +2749,9 @@ sn9c102_vidioc_s_jpegcomp(struct sn9c102_device* cam, void __user * arg) err += sn9c102_set_compression(cam, &jc); if (err) { /* atomic, no rollback in ioctl() */ cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " - "problems. To use the camera, close and open " - "/dev/video%d again.", cam->v4ldev->num); + DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware problems. " + "To use the camera, close and open %s again.", + video_device_node_name(cam->v4ldev)); return -EIO; } @@ -3346,7 +3347,8 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) goto fail; } - DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->num); + DBG(2, "V4L2 device registered as %s", + video_device_node_name(cam->v4ldev)); video_set_drvdata(cam->v4ldev, cam); cam->module_param.force_munmap = force_munmap[dev_nr]; @@ -3398,9 +3400,9 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf) DBG(2, "Disconnecting %s...", cam->v4ldev->name); if (cam->users) { - DBG(2, "Device /dev/video%d is open! Deregistration and " - "memory deallocation are deferred.", - cam->v4ldev->num); + DBG(2, "Device %s is open! Deregistration and memory " + "deallocation are deferred.", + video_device_node_name(cam->v4ldev)); cam->state |= DEV_MISCONFIGURED; sn9c102_stop_transfer(cam); cam->state |= DEV_DISCONNECTED; diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index 6b41865..6590b92 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c @@ -1327,8 +1327,8 @@ static int stk_register_video_device(struct stk_camera *dev) if (err) STK_ERROR("v4l registration failed\n"); else - STK_INFO("Syntek USB2.0 Camera is now controlling video device" - " /dev/video%d\n", dev->vdev.num); + STK_INFO("Syntek USB2.0 Camera is now controlling device %s\n", + video_device_node_name(&dev->vdev)); return err; } @@ -1418,8 +1418,8 @@ static void stk_camera_disconnect(struct usb_interface *interface) wake_up_interruptible(&dev->wait_frame); stk_remove_sysfs_files(&dev->vdev); - STK_INFO("Syntek USB2.0 Camera release resources " - "video device /dev/video%d\n", dev->vdev.num); + STK_INFO("Syntek USB2.0 Camera release resources device %s\n", + video_device_node_name(&dev->vdev)); video_unregister_device(&dev->vdev); } diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index 6a91714..b542222 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c @@ -1467,8 +1467,8 @@ static int stv680_probe (struct usb_interface *intf, const struct usb_device_id retval = -EIO; goto error_vdev; } - PDEBUG(0, "STV(i): registered new video device: video%d", - stv680->vdev->num); + PDEBUG(0, "STV(i): registered new video device: %s", + video_device_node_name(stv680->vdev)); usb_set_intfdata (intf, stv680); retval = stv680_create_sysfs_files(stv680->vdev); diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c index dea8b32..5ac37c6 100644 --- a/drivers/media/video/usbvideo/usbvideo.c +++ b/drivers/media/video/usbvideo/usbvideo.c @@ -1053,9 +1053,9 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd) "%s: video_register_device() successful\n", __func__); } - dev_info(&uvd->dev->dev, "%s on /dev/video%d: canvas=%s videosize=%s\n", + dev_info(&uvd->dev->dev, "%s on %s: canvas=%s videosize=%s\n", (uvd->handle != NULL) ? uvd->handle->drvName : "???", - uvd->vdev.num, tmp2, tmp1); + video_device_node_name(&uvd->vdev), tmp2, tmp1); usb_get_dev(uvd->dev); return 0; diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c index 45fce39..b75143e 100644 --- a/drivers/media/video/usbvideo/vicam.c +++ b/drivers/media/video/usbvideo/vicam.c @@ -873,8 +873,8 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id) return -EIO; } - printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n", - cam->vdev.num); + printk(KERN_INFO "ViCam webcam driver now controlling device %s\n", + video_device_node_name(&cam->vdev)); usb_set_intfdata (intf, cam); diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index c07b0ac..639c339 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -1416,8 +1416,8 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) { // vbi Device: if (usbvision->vbi) { - PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]", - usbvision->vbi->num); + PDEBUG(DBG_PROBE, "unregister %s [v4l2]", + video_device_node_name(usbvision->vbi)); if (usbvision->vbi->minor != -1) { video_unregister_device(usbvision->vbi); } else { @@ -1428,8 +1428,8 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) // Radio Device: if (usbvision->rdev) { - PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]", - usbvision->rdev->num); + PDEBUG(DBG_PROBE, "unregister %s [v4l2]", + video_device_node_name(usbvision->rdev)); if (usbvision->rdev->minor != -1) { video_unregister_device(usbvision->rdev); } else { @@ -1440,8 +1440,8 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) // Video Device: if (usbvision->vdev) { - PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]", - usbvision->vdev->num); + PDEBUG(DBG_PROBE, "unregister %s [v4l2]", + video_device_node_name(usbvision->vdev)); if (usbvision->vdev->minor != -1) { video_unregister_device(usbvision->vdev); } else { @@ -1466,8 +1466,8 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) video_nr)<0) { goto err_exit; } - printk(KERN_INFO "USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]\n", - usbvision->nr, usbvision->vdev->num); + printk(KERN_INFO "USBVision[%d]: registered USBVision Video device %s [v4l2]\n", + usbvision->nr, video_device_node_name(usbvision->vdev)); // Radio Device: if (usbvision_device_data[usbvision->DevModel].Radio) { @@ -1483,8 +1483,8 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) radio_nr)<0) { goto err_exit; } - printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]\n", - usbvision->nr, usbvision->rdev->num); + printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device %s [v4l2]\n", + usbvision->nr, video_device_node_name(usbvision->rdev)); } // vbi Device: if (usbvision_device_data[usbvision->DevModel].vbi) { @@ -1499,8 +1499,8 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) vbi_nr)<0) { goto err_exit; } - printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)\n", - usbvision->nr, usbvision->vbi->num); + printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device %s [v4l2] (Not Working Yet!)\n", + usbvision->nr, video_device_node_name(usbvision->vbi)); } // all done return 0; diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 7705fc6..48f5a62 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -1148,7 +1148,8 @@ static int vivi_open(struct file *file) return -EBUSY; } - dprintk(dev, 1, "open /dev/video%d type=%s users=%d\n", dev->vfd->num, + dprintk(dev, 1, "open %s type=%s users=%d\n", + video_device_node_name(dev->vfd), v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users); /* allocate + initialize per filehandle data */ @@ -1317,8 +1318,8 @@ static int vivi_release(void) list_del(list); dev = list_entry(list, struct vivi_dev, vivi_devlist); - v4l2_info(&dev->v4l2_dev, "unregistering /dev/video%d\n", - dev->vfd->num); + v4l2_info(&dev->v4l2_dev, "unregistering %s\n", + video_device_node_name(dev->vfd)); video_unregister_device(dev->vfd); v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); @@ -1379,8 +1380,8 @@ static int __init vivi_create_instance(int inst) video_nr++; dev->vfd = vfd; - v4l2_info(&dev->v4l2_dev, "V4L2 device registered as /dev/video%d\n", - vfd->num); + v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n", + video_device_node_name(vfd)); return 0; rel_vdev: diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index 37fcdc4..695ad2f 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c @@ -2323,9 +2323,9 @@ static int w9968cf_sensor_init(struct w9968cf_device* cam) error: cam->sensor_initialized = 0; cam->sensor = CC_UNKNOWN; - DBG(1, "Image sensor initialization failed for %s (/dev/video%d). " + DBG(1, "Image sensor initialization failed for %s (%s). " "Try to detach and attach this device again", - symbolic(camlist, cam->id), cam->v4ldev->num) + symbolic(camlist, cam->id), video_device_node_name(cam->v4ldev)) return err; } @@ -2571,7 +2571,8 @@ static void w9968cf_release_resources(struct w9968cf_device* cam) { mutex_lock(&w9968cf_devlist_mutex); - DBG(2, "V4L device deregistered: /dev/video%d", cam->v4ldev->num) + DBG(2, "V4L device deregistered: %s", + video_device_node_name(cam->v4ldev)) video_unregister_device(cam->v4ldev); list_del(&cam->v4llist); @@ -2605,17 +2606,19 @@ static int w9968cf_open(struct file *filp) if (cam->sensor == CC_UNKNOWN) { DBG(2, "No supported image sensor has been detected by the " - "'ovcamchip' module for the %s (/dev/video%d). Make " - "sure it is loaded *before* (re)connecting the camera.", - symbolic(camlist, cam->id), cam->v4ldev->num) + "'ovcamchip' module for the %s (%s). Make sure " + "it is loaded *before* (re)connecting the camera.", + symbolic(camlist, cam->id), + video_device_node_name(cam->v4ldev)) mutex_unlock(&cam->dev_mutex); up_read(&w9968cf_disconnect); return -ENODEV; } if (cam->users) { - DBG(2, "%s (/dev/video%d) has been already occupied by '%s'", - symbolic(camlist, cam->id), cam->v4ldev->num, cam->command) + DBG(2, "%s (%s) has been already occupied by '%s'", + symbolic(camlist, cam->id), + video_device_node_name(cam->v4ldev), cam->command) if ((filp->f_flags & O_NONBLOCK)||(filp->f_flags & O_NDELAY)) { mutex_unlock(&cam->dev_mutex); up_read(&w9968cf_disconnect); @@ -2636,8 +2639,8 @@ static int w9968cf_open(struct file *filp) mutex_lock(&cam->dev_mutex); } - DBG(5, "Opening '%s', /dev/video%d ...", - symbolic(camlist, cam->id), cam->v4ldev->num) + DBG(5, "Opening '%s', %s ...", + symbolic(camlist, cam->id), video_device_node_name(cam->v4ldev)) cam->streaming = 0; cam->misconfigured = 0; @@ -3501,7 +3504,8 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) goto fail; } - DBG(2, "V4L device registered as /dev/video%d", cam->v4ldev->num) + DBG(2, "V4L device registered as %s", + video_device_node_name(cam->v4ldev)) /* Set some basic constants */ w9968cf_configure_camera(cam, udev, mod_id, dev_nr); @@ -3557,10 +3561,10 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf) wake_up_interruptible_all(&cam->open); if (cam->users) { - DBG(2, "The device is open (/dev/video%d)! " + DBG(2, "The device is open (%s)! " "Process name: %s. Deregistration and memory " "deallocation are deferred on close.", - cam->v4ldev->num, cam->command) + video_device_node_name(cam->v4ldev), cam->command) cam->misconfigured = 1; w9968cf_stop_transfer(cam); wake_up_interruptible(&cam->wait_queue); diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 312a713..524eb75 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c @@ -538,8 +538,8 @@ static int zc0301_stream_interrupt(struct zc0301_device* cam) else if (cam->stream != STREAM_OFF) { cam->state |= DEV_MISCONFIGURED; DBG(1, "URB timeout reached. The camera is misconfigured. To " - "use it, close and open /dev/video%d again.", - cam->v4ldev->num); + "use it, close and open %s again.", + video_device_node_name(cam->v4ldev)); return -EIO; } @@ -640,7 +640,8 @@ static void zc0301_release_resources(struct kref *kref) { struct zc0301_device *cam = container_of(kref, struct zc0301_device, kref); - DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->num); + DBG(2, "V4L2 device %s deregistered", + video_device_node_name(cam->v4ldev)); video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); usb_put_dev(cam->usbdev); @@ -679,7 +680,8 @@ static int zc0301_open(struct file *filp) } if (cam->users) { - DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->num); + DBG(2, "Device %s is busy...", + video_device_node_name(cam->v4ldev)); DBG(3, "Simultaneous opens are not supported"); if ((filp->f_flags & O_NONBLOCK) || (filp->f_flags & O_NDELAY)) { @@ -722,7 +724,8 @@ static int zc0301_open(struct file *filp) cam->frame_count = 0; zc0301_empty_framequeues(cam); - DBG(3, "Video device /dev/video%d is open", cam->v4ldev->num); + DBG(3, "Video device %s is open", + video_device_node_name(cam->v4ldev)); out: mutex_unlock(&cam->open_mutex); @@ -746,7 +749,8 @@ static int zc0301_release(struct file *filp) cam->users--; wake_up_interruptible_nr(&cam->wait_open, 1); - DBG(3, "Video device /dev/video%d closed", cam->v4ldev->num); + DBG(3, "Video device %s closed", + video_device_node_name(cam->v4ldev)); kref_put(&cam->kref, zc0301_release_resources); @@ -1276,8 +1280,8 @@ zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg) if (err) { /* atomic, no rollback in ioctl() */ cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->num); + "use the camera, close and open %s again.", + video_device_node_name(cam->v4ldev)); return -EIO; } @@ -1289,8 +1293,8 @@ zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg) nbuffers != zc0301_request_buffers(cam, nbuffers, cam->io)) { cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->num); + "use the camera, close and open %s again.", + video_device_node_name(cam->v4ldev)); return -ENOMEM; } @@ -1471,8 +1475,8 @@ zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd, if (err) { /* atomic, no rollback in ioctl() */ cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->num); + "use the camera, close and open %s again.", + video_device_node_name(cam->v4ldev)); return -EIO; } @@ -1483,8 +1487,8 @@ zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd, nbuffers != zc0301_request_buffers(cam, nbuffers, cam->io)) { cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " - "use the camera, close and open /dev/video%d again.", - cam->v4ldev->num); + "use the camera, close and open %s again.", + video_device_node_name(cam->v4ldev)); return -ENOMEM; } @@ -1530,8 +1534,8 @@ zc0301_vidioc_s_jpegcomp(struct zc0301_device* cam, void __user * arg) if (err) { /* atomic, no rollback in ioctl() */ cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " - "problems. To use the camera, close and open " - "/dev/video%d again.", cam->v4ldev->num); + "problems. To use the camera, close and open %s again.", + video_device_node_name(cam->v4ldev)); return -EIO; } @@ -2003,7 +2007,8 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) goto fail; } - DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->num); + DBG(2, "V4L2 device registered as %s", + video_device_node_name(cam->v4ldev)); cam->module_param.force_munmap = force_munmap[dev_nr]; cam->module_param.frame_timeout = frame_timeout[dev_nr]; @@ -2040,9 +2045,9 @@ static void zc0301_usb_disconnect(struct usb_interface* intf) DBG(2, "Disconnecting %s...", cam->v4ldev->name); if (cam->users) { - DBG(2, "Device /dev/video%d is open! Deregistration and " + DBG(2, "Device %s is open! Deregistration and " "memory deallocation are deferred.", - cam->v4ldev->num); + video_device_node_name(cam->v4ldev)); cam->state |= DEV_MISCONFIGURED; zc0301_stop_transfer(cam); cam->state |= DEV_DISCONNECTED; diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 2ef110b..69ea6df 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c @@ -1635,8 +1635,8 @@ static int zr364xx_probe(struct usb_interface *intf, spin_lock_init(&cam->slock); - dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n", - cam->vdev->num); + dev_info(&udev->dev, DRIVER_DESC " controlling device %s\n", + video_device_node_name(cam->vdev)); return 0; } diff --git a/drivers/staging/go7007/go7007-v4l2.c b/drivers/staging/go7007/go7007-v4l2.c index b18d8e2..fe73975 100644 --- a/drivers/staging/go7007/go7007-v4l2.c +++ b/drivers/staging/go7007/go7007-v4l2.c @@ -1817,8 +1817,8 @@ int go7007_v4l2_init(struct go7007 *go) } video_set_drvdata(go->video_dev, go); ++go->ref_count; - printk(KERN_INFO "%s: registered device video%d [v4l2]\n", - go->video_dev->name, go->video_dev->num); + printk(KERN_INFO "%s: registered device %s [v4l2]\n", + go->video_dev->name, video_device_node_name(go->video_dev)); return 0; } -- cgit v0.10.2 From 0fda5d4420fe1d6a19189386b6bc6532c97a7e0e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 27 Nov 2009 13:57:18 -0300 Subject: V4L/DVB (13551): v4l: Remove video_device::num usage from device drivers Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index c19f51d..0613922 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c @@ -215,8 +215,8 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision) memcpy(&usbvision->i2c_adap, &i2c_adap_template, sizeof(struct i2c_adapter)); - sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name), - " #%d", usbvision->vdev->num); + 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); usbvision->i2c_adap.dev.parent = &usbvision->dev->dev; diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 48f5a62..93e0a25 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -1373,9 +1373,6 @@ static int __init vivi_create_instance(int inst) /* Now that everything is fine, let's add it to device list */ list_add_tail(&dev->vivi_devlist, &vivi_devlist); - snprintf(vfd->name, sizeof(vfd->name), "%s (%i)", - vivi_template.name, vfd->num); - if (video_nr >= 0) video_nr++; diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index 695ad2f..3af6d6b 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c @@ -2877,8 +2877,7 @@ static long w9968cf_v4l_ioctl(struct file *filp, .minwidth = cam->minwidth, .minheight = cam->minheight, }; - sprintf(cap.name, "W996[87]CF USB Camera #%d", - cam->v4ldev->num); + sprintf(cap.name, "W996[87]CF USB Camera"); cap.maxwidth = (cam->upscaling && w9968cf_vpp) ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth) : cam->maxwidth; -- cgit v0.10.2 From 957b4aa9f786cf04585a690a2e4c3dc867ce80e9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 27 Nov 2009 13:57:22 -0300 Subject: V4L/DVB (13552): v4l: Replace video_is_unregistered with video_is_registered Replace the video_is_unregistered function by a video_is_registered function. The V4L2_FL_UNREGISTERED flag is replaced by a V4L2_FL_REGISTERED flag. This change makes the video_is_registered function return coherent results when called on an initialize but not yet registered video_device instance. The function can now be used instead of checking video_device::minor. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index b5439ca..fdd7820 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c @@ -523,7 +523,7 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) mutex_lock(&dev->io_mutex); - if (video_is_unregistered(dev->video_dev)) { + if (!video_is_registered(dev->video_dev)) { mutex_unlock(&dev->io_mutex); return -EIO; } diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index aa3e0f9..7090699 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -189,7 +189,7 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf, if (!vdev->fops->read) return -EINVAL; - if (video_is_unregistered(vdev)) + if (!video_is_registered(vdev)) return -EIO; return vdev->fops->read(filp, buf, sz, off); } @@ -201,7 +201,7 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf, if (!vdev->fops->write) return -EINVAL; - if (video_is_unregistered(vdev)) + if (!video_is_registered(vdev)) return -EIO; return vdev->fops->write(filp, buf, sz, off); } @@ -210,7 +210,7 @@ static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll) { struct video_device *vdev = video_devdata(filp); - if (!vdev->fops->poll || video_is_unregistered(vdev)) + if (!vdev->fops->poll || !video_is_registered(vdev)) return DEFAULT_POLLMASK; return vdev->fops->poll(filp, poll); } @@ -250,7 +250,7 @@ static unsigned long v4l2_get_unmapped_area(struct file *filp, if (!vdev->fops->get_unmapped_area) return -ENOSYS; - if (video_is_unregistered(vdev)) + if (!video_is_registered(vdev)) return -ENODEV; return vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags); } @@ -260,8 +260,7 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) { struct video_device *vdev = video_devdata(filp); - if (!vdev->fops->mmap || - video_is_unregistered(vdev)) + if (!vdev->fops->mmap || !video_is_registered(vdev)) return -ENODEV; return vdev->fops->mmap(filp, vm); } @@ -277,7 +276,7 @@ static int v4l2_open(struct inode *inode, struct file *filp) vdev = video_devdata(filp); /* return ENODEV if the video device has been removed already or if it is not registered anymore. */ - if (vdev == NULL || video_is_unregistered(vdev)) { + if (vdev == NULL || !video_is_registered(vdev)) { mutex_unlock(&videodev_lock); return -ENODEV; } @@ -555,6 +554,7 @@ static int __video_register_device(struct video_device *vdev, int type, int nr, name_base, nr, video_device_node_name(vdev)); /* Part 5: Activate this minor. The char device can now be used. */ + set_bit(V4L2_FL_REGISTERED, &vdev->flags); mutex_lock(&videodev_lock); video_device[vdev->minor] = vdev; mutex_unlock(&videodev_lock); @@ -593,11 +593,11 @@ EXPORT_SYMBOL(video_register_device_no_warn); void video_unregister_device(struct video_device *vdev) { /* Check if vdev was ever registered at all */ - if (!vdev || vdev->minor < 0) + if (!vdev || !video_is_registered(vdev)) return; mutex_lock(&videodev_lock); - set_bit(V4L2_FL_UNREGISTERED, &vdev->flags); + clear_bit(V4L2_FL_REGISTERED, &vdev->flags); mutex_unlock(&videodev_lock); device_unregister(&vdev->dev); } diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 9135f57..2dee938 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -28,10 +28,10 @@ struct v4l2_ioctl_callbacks; struct video_device; struct v4l2_device; -/* Flag to mark the video_device struct as unregistered. - Drivers can set this flag if they want to block all future - device access. It is set by video_unregister_device. */ -#define V4L2_FL_UNREGISTERED (0) +/* Flag to mark the video_device struct as registered. + Drivers can clear this flag if they want to block all future + device access. It is cleared by video_unregister_device. */ +#define V4L2_FL_REGISTERED (0) struct v4l2_file_operations { struct module *owner; @@ -96,9 +96,7 @@ struct video_device /* Register video devices. Note that if video_register_device fails, the release() callback of the video_device structure is *not* called, so the caller is responsible for freeing any data. Usually that means that - you call video_device_release() on failure. - - Also note that vdev->minor is set to -1 if the registration failed. */ + you call video_device_release() on failure. */ int __must_check video_register_device(struct video_device *vdev, int type, int nr); /* Same as video_register_device, but no warning is issued if the desired @@ -106,7 +104,7 @@ int __must_check video_register_device(struct video_device *vdev, int type, int int __must_check video_register_device_no_warn(struct video_device *vdev, int type, int nr); /* Unregister video devices. Will do nothing if vdev == NULL or - vdev->minor < 0. */ + video_is_registered() returns false. */ void video_unregister_device(struct video_device *vdev); /* helper functions to alloc/release struct video_device, the @@ -146,9 +144,9 @@ static inline const char *video_device_node_name(struct video_device *vdev) return dev_name(&vdev->dev); } -static inline int video_is_unregistered(struct video_device *vdev) +static inline int video_is_registered(struct video_device *vdev) { - return test_bit(V4L2_FL_UNREGISTERED, &vdev->flags); + return test_bit(V4L2_FL_REGISTERED, &vdev->flags); } #endif /* _V4L2_DEV_H */ -- cgit v0.10.2 From f0813b4c9f7ffbeaddcba1c08a1812f7ff30e1b7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 27 Nov 2009 13:57:30 -0300 Subject: V4L/DVB (13553): v4l: Use the video_is_registered function in device drivers Fix all device drivers to use the video_is_registered function instead of checking video_device::minor. Signed-off-by: Laurent Pinchart 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 d576183..a233691 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -4208,21 +4208,21 @@ static struct video_device *vdev_init(struct bttv *btv, static void bttv_unregister_video(struct bttv *btv) { if (btv->video_dev) { - if (-1 != btv->video_dev->minor) + if (video_is_registered(btv->video_dev)) video_unregister_device(btv->video_dev); else video_device_release(btv->video_dev); btv->video_dev = NULL; } if (btv->vbi_dev) { - if (-1 != btv->vbi_dev->minor) + if (video_is_registered(btv->vbi_dev)) video_unregister_device(btv->vbi_dev); else video_device_release(btv->vbi_dev); btv->vbi_dev = NULL; } if (btv->radio_dev) { - if (-1 != btv->radio_dev->minor) + if (video_is_registered(btv->radio_dev)) video_unregister_device(btv->radio_dev); else video_device_release(btv->radio_dev); diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index 1c7f84e..71e152d 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c @@ -2020,7 +2020,7 @@ void cx231xx_release_analog_resources(struct cx231xx *dev) /*FIXME: I2C IR should be disconnected */ if (dev->radio_dev) { - if (-1 != dev->radio_dev->minor) + if (video_is_registered(dev->radio_dev)) video_unregister_device(dev->radio_dev); else video_device_release(dev->radio_dev); @@ -2029,7 +2029,7 @@ void cx231xx_release_analog_resources(struct cx231xx *dev) if (dev->vbi_dev) { cx231xx_info("V4L2 device %s deregistered\n", video_device_node_name(dev->vbi_dev)); - if (-1 != dev->vbi_dev->minor) + if (video_is_registered(dev->vbi_dev)) video_unregister_device(dev->vbi_dev); else video_device_release(dev->vbi_dev); @@ -2038,7 +2038,7 @@ void cx231xx_release_analog_resources(struct cx231xx *dev) if (dev->vdev) { cx231xx_info("V4L2 device %s deregistered\n", video_device_node_name(dev->vdev)); - if (-1 != dev->vdev->minor) + if (video_is_registered(dev->vdev)) video_unregister_device(dev->vdev); else video_device_release(dev->vdev); diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 8084e13..a7bfe7c 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c @@ -1746,7 +1746,7 @@ void cx23885_417_unregister(struct cx23885_dev *dev) dprintk(1, "%s()\n", __func__); if (dev->v4l_device) { - if (-1 != dev->v4l_device->minor) + if (video_is_registered(dev->v4l_device)) video_unregister_device(dev->v4l_device); else video_device_release(dev->v4l_device); diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 5570383..fd98121 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -1461,7 +1461,7 @@ void cx23885_video_unregister(struct cx23885_dev *dev) cx_clear(PCI_INT_MSK, 1); if (dev->video_dev) { - if (-1 != dev->video_dev->minor) + if (video_is_registered(dev->video_dev)) video_unregister_device(dev->video_dev); else video_device_release(dev->video_dev); diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 9f02715..5186f87 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1276,7 +1276,7 @@ static int cx8802_blackbird_advise_release(struct cx8802_driver *drv) static void blackbird_unregister_video(struct cx8802_dev *dev) { if (dev->mpeg_dev) { - if (-1 != dev->mpeg_dev->minor) + if (video_is_registered(dev->mpeg_dev)) video_unregister_device(dev->mpeg_dev); else video_device_release(dev->mpeg_dev); diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 55063a7..0259ac6 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1778,21 +1778,21 @@ static struct video_device cx8800_radio_template = { static void cx8800_unregister_video(struct cx8800_dev *dev) { if (dev->radio_dev) { - if (-1 != dev->radio_dev->minor) + if (video_is_registered(dev->radio_dev)) video_unregister_device(dev->radio_dev); else video_device_release(dev->radio_dev); dev->radio_dev = NULL; } if (dev->vbi_dev) { - if (-1 != dev->vbi_dev->minor) + if (video_is_registered(dev->vbi_dev)) video_unregister_device(dev->vbi_dev); else video_device_release(dev->vbi_dev); dev->vbi_dev = NULL; } if (dev->video_dev) { - if (-1 != dev->video_dev->minor) + if (video_is_registered(dev->video_dev)) video_unregister_device(dev->video_dev); else video_device_release(dev->video_dev); diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index c3916a4..1e85794 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -2071,7 +2071,7 @@ probe_out_video_unregister: probe_out_v4l2_unregister: v4l2_device_unregister(&vpfe_dev->v4l2_dev); probe_out_video_release: - if (vpfe_dev->video_dev->minor == -1) + if (!video_is_registered(vpfe_dev->video_dev)) video_device_release(vpfe_dev->video_dev); probe_out_release_irq: free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 5cc4fff..9a8ff32 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -2160,7 +2160,7 @@ void em28xx_release_analog_resources(struct em28xx *dev) /*FIXME: I2C IR should be disconnected */ if (dev->radio_dev) { - if (-1 != dev->radio_dev->minor) + if (video_is_registered(dev->radio_dev)) video_unregister_device(dev->radio_dev); else video_device_release(dev->radio_dev); @@ -2169,7 +2169,7 @@ void em28xx_release_analog_resources(struct em28xx *dev) if (dev->vbi_dev) { em28xx_info("V4L2 device %s deregistered\n", video_device_node_name(dev->vbi_dev)); - if (-1 != dev->vbi_dev->minor) + if (video_is_registered(dev->vbi_dev)) video_unregister_device(dev->vbi_dev); else video_device_release(dev->vbi_dev); @@ -2178,7 +2178,7 @@ void em28xx_release_analog_resources(struct em28xx *dev) if (dev->vdev) { em28xx_info("V4L2 device %s deregistered\n", video_device_node_name(dev->vdev)); - if (-1 != dev->vdev->minor) + if (video_is_registered(dev->vdev)) video_unregister_device(dev->vdev); else video_device_release(dev->vdev); diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index e2f137b..34eb965 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c @@ -1696,7 +1696,7 @@ static void omap24xxcam_device_unregister(struct v4l2_int_device *s) omap24xxcam_sensor_exit(cam); if (cam->vfd) { - if (cam->vfd->minor == -1) { + if (!video_is_registered(cam->vfd)) { /* * The device was never registered, so release the * video_device struct directly. diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index 0bc2cf5..b636160 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -5884,7 +5884,7 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) error: if (ov->vdev) { - if (-1 == ov->vdev->minor) + if (!video_is_registered(ov->vdev)) video_device_release(ov->vdev); else video_unregister_device(ov->vdev); diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 41765f3..4201abc 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -1880,7 +1880,7 @@ static void s2255_exit_v4l(struct s2255_dev *dev) int i; for (i = 0; i < MAX_CHANNELS; i++) { - if (-1 != dev->vdev[i]->minor) { + if (video_is_registered(dev->vdev[i])) { video_unregister_device(dev->vdev[i]); printk(KERN_INFO "s2255 unregistered\n"); } else { diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index c07f072..b910df9 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -803,21 +803,21 @@ static struct video_device *vdev_init(struct saa7134_dev *dev, static void saa7134_unregister_video(struct saa7134_dev *dev) { if (dev->video_dev) { - if (-1 != dev->video_dev->minor) + if (video_is_registered(dev->video_dev)) video_unregister_device(dev->video_dev); else video_device_release(dev->video_dev); dev->video_dev = NULL; } if (dev->vbi_dev) { - if (-1 != dev->vbi_dev->minor) + if (video_is_registered(dev->vbi_dev)) video_unregister_device(dev->vbi_dev); else video_device_release(dev->vbi_dev); dev->vbi_dev = NULL; } if (dev->radio_dev) { - if (-1 != dev->radio_dev->minor) + if (video_is_registered(dev->radio_dev)) video_unregister_device(dev->radio_dev); else video_device_release(dev->radio_dev); diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index eaada39..c890905 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c @@ -2134,7 +2134,7 @@ static void stradis_release_saa(struct pci_dev *pdev) free_irq(saa->irq, saa); if (saa->saa7146_mem) iounmap(saa->saa7146_mem); - if (saa->video_dev.minor != -1) + if (video_is_registered(&saa->video_dev)) video_unregister_device(&saa->video_dev); } diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 639c339..e89b855 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -1418,7 +1418,7 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) if (usbvision->vbi) { PDEBUG(DBG_PROBE, "unregister %s [v4l2]", video_device_node_name(usbvision->vbi)); - if (usbvision->vbi->minor != -1) { + if (video_is_registered(usbvision->vbi)) { video_unregister_device(usbvision->vbi); } else { video_device_release(usbvision->vbi); @@ -1430,7 +1430,7 @@ 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 (usbvision->rdev->minor != -1) { + if (video_is_registered(usbvision->rdev)) { video_unregister_device(usbvision->rdev); } else { video_device_release(usbvision->rdev); @@ -1442,7 +1442,7 @@ 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 (usbvision->vdev->minor != -1) { + if (video_is_registered(usbvision->vdev)) { video_unregister_device(usbvision->vdev); } else { video_device_release(usbvision->vdev); diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c index 8834bc8..156e332 100644 --- a/drivers/staging/cx25821/cx25821-video.c +++ b/drivers/staging/cx25821/cx25821-video.c @@ -424,7 +424,7 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) void cx25821_videoioctl_unregister(struct cx25821_dev *dev) { if (dev->ioctl_dev) { - if (dev->ioctl_dev->minor != -1) + if (video_is_registered(dev->ioctl_dev)) video_unregister_device(dev->ioctl_dev); else video_device_release(dev->ioctl_dev); @@ -438,7 +438,7 @@ void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num) cx_clear(PCI_INT_MSK, 1); if (dev->video_dev[chan_num]) { - if (-1 != dev->video_dev[chan_num]->minor) + if (video_is_registered(dev->video_dev[chan_num])) video_unregister_device(dev->video_dev[chan_num]); else video_device_release(dev->video_dev[chan_num]); -- cgit v0.10.2 From 63b0d5ad20365edf8baf96cdbb8e7faf62501286 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 10 Dec 2009 11:44:04 -0200 Subject: V4L/DVB (13554a): v4l: Use the video_drvdata function in drivers Fix all device drivers to use the video_drvdata function instead of maintaining a local list of minor to private data mappings. Call video_set_drvdata to register the driver private pointer when not already done. Where applicable, the local list of mappings is completely removed when it becomes unused. [mchehab.redhat.com: removed tm6000 changes as tm6000 is not ready yet for submission even on staging] Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index f279a64..2d9fc243 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -195,42 +195,24 @@ void saa7146_buffer_timeout(unsigned long data) static int fops_open(struct file *file) { unsigned int minor = video_devdata(file)->minor; - struct saa7146_dev *h = NULL, *dev = NULL; - struct list_head *list; + struct video_device *vdev = video_devdata(file); + struct saa7146_dev *dev = video_drvdata(file); struct saa7146_fh *fh = NULL; int result = 0; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + enum v4l2_buf_type type; DEB_EE(("file:%p, minor:%d\n", file, minor)); if (mutex_lock_interruptible(&saa7146_devices_lock)) return -ERESTARTSYS; - list_for_each(list,&saa7146_devices) { - h = list_entry(list, struct saa7146_dev, item); - if( NULL == h->vv_data ) { - DEB_D(("device %p has not registered video devices.\n",h)); - continue; - } - DEB_D(("trying: %p @ major %d,%d\n",h,h->vv_data->video_minor,h->vv_data->vbi_minor)); - - if (h->vv_data->video_minor == minor) { - dev = h; - } - if (h->vv_data->vbi_minor == minor) { - type = V4L2_BUF_TYPE_VBI_CAPTURE; - dev = h; - } - } - if (NULL == dev) { - DEB_S(("no such video device.\n")); - result = -ENODEV; - goto out; - } - DEB_D(("using: %p\n",dev)); + type = vdev->vfl_type == VFL_TYPE_GRABBER + ? V4L2_BUF_TYPE_VIDEO_CAPTURE + : V4L2_BUF_TYPE_VBI_CAPTURE; + /* check if an extension is registered */ if( NULL == dev->ext ) { DEB_S(("no extension registered for this device.\n")); diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 1485aee..13a8a1d 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -40,7 +40,6 @@ #include "au0828.h" #include "au0828-reg.h" -static LIST_HEAD(au0828_devlist); static DEFINE_MUTEX(au0828_sysfs_lock); #define AU0828_VERSION_CODE KERNEL_VERSION(0, 0, 1) @@ -693,10 +692,8 @@ void au0828_analog_unregister(struct au0828_dev *dev) dprintk(1, "au0828_release_resources called\n"); mutex_lock(&au0828_sysfs_lock); - if (dev->vdev) { - list_del(&dev->au0828list); + if (dev->vdev) video_unregister_device(dev->vdev); - } if (dev->vbi_dev) video_unregister_device(dev->vbi_dev); @@ -737,29 +734,15 @@ static void res_free(struct au0828_fh *fh) static int au0828_v4l2_open(struct file *filp) { - int minor = video_devdata(filp)->minor; int ret = 0; - struct au0828_dev *h, *dev = NULL; + struct au0828_dev *dev = video_drvdata(filp); struct au0828_fh *fh; - int type = 0; - struct list_head *list; - - list_for_each(list, &au0828_devlist) { - h = list_entry(list, struct au0828_dev, au0828list); - if (h->vdev->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } + int type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + #ifdef VBI_IS_WORKING - if (h->vbi_dev->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VBI_CAPTURE; - } + if (video_devdata(filp)->vfl_type == VFL_TYPE_GRABBER) + type = V4L2_BUF_TYPE_VBI_CAPTURE; #endif - } - - if (NULL == dev) - return -ENODEV; fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL); if (NULL == fh) { @@ -1676,25 +1659,23 @@ int au0828_analog_register(struct au0828_dev *dev, strcpy(dev->vbi_dev->name, "au0828a vbi"); #endif - list_add_tail(&dev->au0828list, &au0828_devlist); - /* Register the v4l2 device */ + video_set_drvdata(dev->vdev, dev); retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1); if (retval != 0) { dprintk(1, "unable to register video device (error = %d).\n", retval); - list_del(&dev->au0828list); video_device_release(dev->vdev); return -ENODEV; } #ifdef VBI_IS_WORKING /* Register the vbi device */ + video_set_drvdata(dev->vbi_dev, dev); retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1); if (retval != 0) { dprintk(1, "unable to register vbi device (error = %d).\n", retval); - list_del(&dev->au0828list); video_device_release(dev->vbi_dev); video_device_release(dev->vdev); return -ENODEV; diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index b977915..207f32d 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -192,7 +192,6 @@ struct au0828_dev { struct au0828_dvb dvb; /* Analog */ - struct list_head au0828list; struct v4l2_device v4l2_dev; int users; unsigned int stream_on:1; /* Locks streams */ diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c index 0d333e6..4a60dfb 100644 --- a/drivers/media/video/cx231xx/cx231xx-core.c +++ b/drivers/media/video/cx231xx/cx231xx-core.c @@ -66,32 +66,6 @@ MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); static LIST_HEAD(cx231xx_devlist); static DEFINE_MUTEX(cx231xx_devlist_mutex); -struct cx231xx *cx231xx_get_device(int minor, - enum v4l2_buf_type *fh_type, int *has_radio) -{ - struct cx231xx *h, *dev = NULL; - - *fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - *has_radio = 0; - - mutex_lock(&cx231xx_devlist_mutex); - list_for_each_entry(h, &cx231xx_devlist, devlist) { - if (h->vdev->minor == minor) - dev = h; - if (h->vbi_dev->minor == minor) { - dev = h; - *fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; - } - if (h->radio_dev && h->radio_dev->minor == minor) { - dev = h; - *has_radio = 1; - } - } - mutex_unlock(&cx231xx_devlist_mutex); - - return dev; -} - /* * cx231xx_realease_resources() * unregisters the v4l2,i2c and usb devices diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index 71e152d..3fc7a6f 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c @@ -1918,13 +1918,22 @@ static int cx231xx_v4l2_open(struct file *filp) { int minor = video_devdata(filp)->minor; int errCode = 0, radio = 0; - struct cx231xx *dev = NULL; + struct video_device *vdev = video_devdata(filp); + struct cx231xx *dev = video_drvdata(filp); struct cx231xx_fh *fh; enum v4l2_buf_type fh_type = 0; - dev = cx231xx_get_device(minor, &fh_type, &radio); - if (NULL == dev) - return -ENODEV; + switch (vdev->vfl_type) { + case VFL_TYPE_GRABBER: + fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + break; + case VFL_TYPE_VBI: + fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; + break; + case VFL_TYPE_RADIO: + radio = 1; + break; + } mutex_lock(&dev->lock); @@ -2326,6 +2335,7 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); + video_set_drvdata(vfd, dev); return vfd; } diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h index 64e2ddd..17d4d1a 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/video/cx231xx/cx231xx.h @@ -689,8 +689,6 @@ void cx231xx_release_analog_resources(struct cx231xx *dev); int cx231xx_register_analog_devices(struct cx231xx *dev); void cx231xx_remove_from_devlist(struct cx231xx *dev); void cx231xx_add_into_devlist(struct cx231xx *dev); -struct cx231xx *cx231xx_get_device(int minor, - enum v4l2_buf_type *fh_type, int *has_radio); void cx231xx_init_extension(struct cx231xx *dev); void cx231xx_close_extension(struct cx231xx *dev); diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index a7bfe7c..272c60a 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c @@ -1568,28 +1568,11 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int mpeg_open(struct file *file) { - int minor = video_devdata(file)->minor; - struct cx23885_dev *h, *dev = NULL; - struct list_head *list; + struct cx23885_dev *dev = video_drvdata(file); struct cx23885_fh *fh; dprintk(2, "%s()\n", __func__); - lock_kernel(); - list_for_each(list, &cx23885_devlist) { - h = list_entry(list, struct cx23885_dev, devlist); - if (h->v4l_device && - h->v4l_device->minor == minor) { - dev = h; - break; - } - } - - if (dev == NULL) { - unlock_kernel(); - return -ENODEV; - } - /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) { @@ -1597,6 +1580,8 @@ static int mpeg_open(struct file *file) return -ENOMEM; } + lock_kernel(); + file->private_data = fh; fh->dev = dev; @@ -1803,6 +1788,7 @@ int cx23885_417_register(struct cx23885_dev *dev) /* Allocate and initialize V4L video device */ dev->v4l_device = cx23885_video_dev_alloc(tsport, dev->pci, &cx23885_mpeg_template, "mpeg"); + video_set_drvdata(dev->v4l_device, dev); err = video_register_device(dev->v4l_device, VFL_TYPE_GRABBER, -1); if (err < 0) { diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 04b12d2..0dde57e 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -55,9 +55,6 @@ MODULE_PARM_DESC(card, "card type"); static unsigned int cx23885_devcount; -static DEFINE_MUTEX(devlist); -LIST_HEAD(cx23885_devlist); - #define NO_SYNC_LINE (-1U) /* FIXME, these allocations will change when @@ -785,10 +782,6 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) dev->nr = cx23885_devcount++; sprintf(dev->name, "cx23885[%d]", dev->nr); - mutex_lock(&devlist); - list_add_tail(&dev->devlist, &cx23885_devlist); - mutex_unlock(&devlist); - /* Configure the internal memory */ if (dev->pci->device == 0x8880) { /* Could be 887 or 888, assume a default */ @@ -2008,10 +2001,6 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev) /* unregister stuff */ free_irq(pci_dev->irq, dev); - mutex_lock(&devlist); - list_del(&dev->devlist); - mutex_unlock(&devlist); - cx23885_dev_unregister(dev); v4l2_device_unregister(v4l2_dev); kfree(dev); diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index fd98121..e10f28c 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -323,6 +323,7 @@ static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev, vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, cx23885_boards[dev->board].name); + video_set_drvdata(vfd, dev); return vfd; } @@ -717,34 +718,22 @@ static int get_resource(struct cx23885_fh *fh) static int video_open(struct file *file) { int minor = video_devdata(file)->minor; - struct cx23885_dev *h, *dev = NULL; + struct video_device *vdev = video_devdata(file); + struct cx23885_dev *dev = video_drvdata(file); struct cx23885_fh *fh; - struct list_head *list; enum v4l2_buf_type type = 0; int radio = 0; - lock_kernel(); - list_for_each(list, &cx23885_devlist) { - h = list_entry(list, struct cx23885_dev, devlist); - if (h->video_dev && - h->video_dev->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - if (h->vbi_dev && - h->vbi_dev->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VBI_CAPTURE; - } - if (h->radio_dev && - h->radio_dev->minor == minor) { - radio = 1; - dev = h; - } - } - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; + switch (vdev->vfl_type) { + case VFL_TYPE_GRABBER: + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + break; + case VFL_TYPE_VBI: + type = V4L2_BUF_TYPE_VBI_CAPTURE; + break; + case VFL_TYPE_RADIO: + radio = 1; + break; } dprintk(1, "open minor=%d radio=%d type=%s\n", @@ -752,10 +741,11 @@ static int video_open(struct file *file) /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); + if (NULL == fh) return -ENOMEM; - } + + lock_kernel(); + file->private_data = fh; fh->dev = dev; fh->radio = radio; diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index fa74476..08b3f6b 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -303,7 +303,6 @@ struct cx23885_tsport { }; struct cx23885_dev { - struct list_head devlist; atomic_t refcount; struct v4l2_device v4l2_dev; @@ -399,8 +398,6 @@ static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev) extern struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw); -extern struct list_head cx23885_devlist; - #define SRAM_CH01 0 /* Video A */ #define SRAM_CH02 1 /* VBI A */ #define SRAM_CH03 2 /* Video B */ diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 5186f87..f0ef941 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1049,20 +1049,14 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) static int mpeg_open(struct file *file) { int minor = video_devdata(file)->minor; - struct cx8802_dev *dev = NULL; + struct cx8802_dev *dev = video_drvdata(file); struct cx8802_fh *fh; struct cx8802_driver *drv = NULL; int err; - lock_kernel(); - dev = cx8802_get_device(minor); - dprintk( 1, "%s\n", __func__); - if (dev == NULL) { - unlock_kernel(); - return -ENODEV; - } + lock_kernel(); /* Make sure we can acquire the hardware */ drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); @@ -1129,10 +1123,6 @@ static int mpeg_release(struct file *file) kfree(fh); /* Make sure we release the hardware */ - dev = cx8802_get_device(video_devdata(file)->minor); - if (dev == NULL) - return -ENODEV; - drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); if (drv) drv->request_release(drv); @@ -1290,6 +1280,7 @@ static int blackbird_register_video(struct cx8802_dev *dev) dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci, &cx8802_mpeg_template,"mpeg"); + video_set_drvdata(dev->mpeg_dev, dev); err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1); if (err < 0) { printk(KERN_INFO "%s/2: can't register mpeg device\n", diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index de9ff0f..bb51048 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -580,21 +580,6 @@ static int cx8802_resume_common(struct pci_dev *pci_dev) return 0; } -#if defined(CONFIG_VIDEO_CX88_BLACKBIRD) || \ - defined(CONFIG_VIDEO_CX88_BLACKBIRD_MODULE) -struct cx8802_dev *cx8802_get_device(int minor) -{ - struct cx8802_dev *dev; - - list_for_each_entry(dev, &cx8802_devlist, devlist) - if (dev->mpeg_dev && dev->mpeg_dev->minor == minor) - return dev; - - return NULL; -} -EXPORT_SYMBOL(cx8802_get_device); -#endif - struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype) { struct cx8802_driver *d; diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 0259ac6..7583991 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -75,10 +75,6 @@ MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes"); #define dprintk(level,fmt, arg...) if (video_debug >= level) \ printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg) -/* ------------------------------------------------------------------ */ - -static LIST_HEAD(cx8800_devlist); - /* ------------------------------------------------------------------- */ /* static data */ @@ -754,33 +750,27 @@ static int get_ressource(struct cx8800_fh *fh) static int video_open(struct file *file) { int minor = video_devdata(file)->minor; - struct cx8800_dev *h,*dev = NULL; + struct video_device *vdev = video_devdata(file); + struct cx8800_dev *dev = video_drvdata(file); struct cx88_core *core; struct cx8800_fh *fh; enum v4l2_buf_type type = 0; int radio = 0; - lock_kernel(); - list_for_each_entry(h, &cx8800_devlist, devlist) { - if (h->video_dev->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - if (h->vbi_dev->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VBI_CAPTURE; - } - if (h->radio_dev && - h->radio_dev->minor == minor) { - radio = 1; - dev = h; - } - } - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; + switch (vdev->vfl_type) { + case VFL_TYPE_GRABBER: + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + break; + case VFL_TYPE_VBI: + type = V4L2_BUF_TYPE_VBI_CAPTURE; + break; + case VFL_TYPE_RADIO: + radio = 1; + break; } + lock_kernel(); + core = dev->core; dprintk(1,"open minor=%d radio=%d type=%s\n", @@ -1909,6 +1899,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, /* register v4l devices */ dev->video_dev = cx88_vdev_init(core,dev->pci, &cx8800_video_template,"video"); + video_set_drvdata(dev->video_dev, dev); err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, video_nr[core->nr]); if (err < 0) { @@ -1920,6 +1911,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, core->name, video_device_node_name(dev->video_dev)); dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi"); + video_set_drvdata(dev->vbi_dev, dev); err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, vbi_nr[core->nr]); if (err < 0) { @@ -1933,6 +1925,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, if (core->board.radio.type == CX88_RADIO) { dev->radio_dev = cx88_vdev_init(core,dev->pci, &cx8800_radio_template,"radio"); + video_set_drvdata(dev->radio_dev, dev); err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO, radio_nr[core->nr]); if (err < 0) { @@ -1945,7 +1938,6 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, } /* everything worked */ - list_add_tail(&dev->devlist,&cx8800_devlist); pci_set_drvdata(pci_dev,dev); /* initial device configuration */ @@ -2001,7 +1993,6 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev) /* free memory */ btcx_riscmem_free(dev->pci,&dev->vidq.stopper); - list_del(&dev->devlist); cx88_core_put(core,dev->pci); kfree(dev); } diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index e1c5217..b1499bf 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -423,7 +423,6 @@ struct cx8800_suspend_state { struct cx8800_dev { struct cx88_core *core; - struct list_head devlist; spinlock_t slock; /* various device info */ @@ -670,7 +669,6 @@ int cx88_audio_thread(void *data); int cx8802_register_driver(struct cx8802_driver *drv); int cx8802_unregister_driver(struct cx8802_driver *drv); -struct cx8802_dev *cx8802_get_device(int minor); struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype); /* ----------------------------------------------------------- */ diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 4ace709..e7a68e2 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -2653,7 +2653,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, INIT_LIST_HEAD(&dev->vbiq.active); INIT_LIST_HEAD(&dev->vbiq.queued); - if (dev->board.has_msp34xx) { /* Send a reset to other chips via gpio */ errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7); diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 4f61e05..b311d45 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -1136,34 +1136,6 @@ void em28xx_wake_i2c(struct em28xx *dev) static LIST_HEAD(em28xx_devlist); static DEFINE_MUTEX(em28xx_devlist_mutex); -struct em28xx *em28xx_get_device(int minor, - enum v4l2_buf_type *fh_type, - int *has_radio) -{ - struct em28xx *h, *dev = NULL; - - *fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - *has_radio = 0; - - mutex_lock(&em28xx_devlist_mutex); - list_for_each_entry(h, &em28xx_devlist, devlist) { - if (h->vdev->minor == minor) - dev = h; - if (h->vbi_dev && h->vbi_dev->minor == minor) { - dev = h; - *fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; - } - if (h->radio_dev && - h->radio_dev->minor == minor) { - dev = h; - *has_radio = 1; - } - } - mutex_unlock(&em28xx_devlist_mutex); - - return dev; -} - /* * em28xx_realease_resources() * unregisters the v4l2,i2c and usb devices diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 9a8ff32..dd9bbe8 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -2082,16 +2082,24 @@ static int radio_queryctrl(struct file *file, void *priv, static int em28xx_v4l2_open(struct file *filp) { int minor = video_devdata(filp)->minor; - int errCode = 0, radio; - struct em28xx *dev; - enum v4l2_buf_type fh_type; + int errCode = 0, radio = 0; + struct video_device *vdev = video_devdata(filp); + struct em28xx *dev = video_drvdata(filp); + enum v4l2_buf_type fh_type = 0; struct em28xx_fh *fh; enum v4l2_field field; - dev = em28xx_get_device(minor, &fh_type, &radio); - - if (NULL == dev) - return -ENODEV; + switch (vdev->vfl_type) { + case VFL_TYPE_GRABBER: + fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + break; + case VFL_TYPE_VBI: + fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; + break; + case VFL_TYPE_RADIO: + radio = 1; + break; + } mutex_lock(&dev->lock); @@ -2459,6 +2467,7 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); + video_set_drvdata(vfd, dev); return vfd; } diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 4897783..80d9b4f 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -668,9 +668,6 @@ int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); void em28xx_wake_i2c(struct em28xx *dev); void em28xx_remove_from_devlist(struct em28xx *dev); void em28xx_add_into_devlist(struct em28xx *dev); -struct em28xx *em28xx_get_device(int minor, - enum v4l2_buf_type *fh_type, - int *has_radio); int em28xx_register_extension(struct em28xx_ops *dev); void em28xx_unregister_extension(struct em28xx_ops *dev); void em28xx_init_extension(struct em28xx *dev); diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 4201abc..0a77108 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -233,7 +233,6 @@ struct s2255_dev { struct s2255_dmaqueue vidq[MAX_CHANNELS]; struct video_device *vdev[MAX_CHANNELS]; - struct list_head s2255_devlist; struct timer_list timer; struct s2255_fw *fw_data; struct s2255_pipeinfo pipes[MAX_PIPE_BUFFERS]; @@ -313,8 +312,6 @@ struct s2255_fh { /* Channels on box are in reverse order */ static unsigned long G_chnmap[MAX_CHANNELS] = {3, 2, 1, 0}; -static LIST_HEAD(s2255_devlist); - static int debug; static int *s2255_debug = &debug; @@ -1534,31 +1531,22 @@ static int vidioc_s_parm(struct file *file, void *priv, static int s2255_open(struct file *file) { int minor = video_devdata(file)->minor; - struct s2255_dev *h, *dev = NULL; + struct video_device *vdev = video_devdata(file); + struct s2255_dev *dev = video_drvdata(file); struct s2255_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; int i = 0; int cur_channel = -1; int state; dprintk(1, "s2255: open called (minor=%d)\n", minor); lock_kernel(); - list_for_each(list, &s2255_devlist) { - h = list_entry(list, struct s2255_dev, s2255_devlist); - for (i = 0; i < MAX_CHANNELS; i++) { - if (h->vdev[i]->minor == minor) { - cur_channel = i; - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - } - } - if ((NULL == dev) || (cur_channel == -1)) { - unlock_kernel(); - printk(KERN_INFO "s2255: openv4l no dev\n"); - return -ENODEV; + for (i = 0; i < MAX_CHANNELS; i++) { + if (dev->vdev[i] == vdev) { + cur_channel = i; + break; + } } if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_DISCONNECTING) { @@ -1699,7 +1687,6 @@ static unsigned int s2255_poll(struct file *file, static void s2255_destroy(struct kref *kref) { struct s2255_dev *dev = to_s2255_dev(kref); - struct list_head *list; int i; if (!dev) { printk(KERN_ERR "s2255drv: kref problem\n"); @@ -1733,10 +1720,6 @@ static void s2255_destroy(struct kref *kref) usb_put_dev(dev->udev); dprintk(1, "%s", __func__); - while (!list_empty(&s2255_devlist)) { - list = s2255_devlist.next; - list_del(list); - } mutex_unlock(&dev->open_lock); kfree(dev); } @@ -1843,7 +1826,6 @@ static int s2255_probe_v4l(struct s2255_dev *dev) int cur_nr = video_nr; /* initialize all video 4 linux */ - list_add_tail(&dev->s2255_devlist, &s2255_devlist); /* register 4 video devices */ for (i = 0; i < MAX_CHANNELS; i++) { INIT_LIST_HEAD(&dev->vidq[i].active); @@ -1853,6 +1835,7 @@ static int s2255_probe_v4l(struct s2255_dev *dev) dev->vdev[i] = video_device_alloc(); memcpy(dev->vdev[i], &template, sizeof(struct video_device)); dev->vdev[i]->parent = &dev->interface->dev; + video_set_drvdata(dev->vdev[i], dev); if (video_nr == -1) ret = video_register_device(dev->vdev[i], VFL_TYPE_GRABBER, diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index b910df9..9f85e91 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -797,6 +797,7 @@ static struct video_device *vdev_init(struct saa7134_dev *dev, vfd->debug = video_debug; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, saa7134_boards[dev->board].name); + video_set_drvdata(vfd, dev); return vfd; } diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index abc1d0b..1de27af 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -87,17 +87,9 @@ static int ts_init_encoder(struct saa7134_dev* dev) static int ts_open(struct file *file) { int minor = video_devdata(file)->minor; - struct saa7134_dev *dev; + struct saa7134_dev *dev = video_drvdata(file); int err; - lock_kernel(); - list_for_each_entry(dev, &saa7134_devlist, devlist) - if (dev->empress_dev && dev->empress_dev->minor == minor) - goto found; - unlock_kernel(); - return -ENODEV; - found: - dprintk("open minor=%d\n",minor); err = -EBUSY; if (!mutex_trylock(&dev->empress_tsq.vb_lock)) @@ -531,6 +523,7 @@ static int empress_init(struct saa7134_dev *dev) INIT_WORK(&dev->empress_workqueue, empress_signal_update); + video_set_drvdata(dev->empress_dev, dev); err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER, empress_nr[dev->nr]); if (err < 0) { diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 35f8daa..bcca5a4 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1327,29 +1327,23 @@ static int saa7134_resource(struct saa7134_fh *fh) static int video_open(struct file *file) { int minor = video_devdata(file)->minor; - struct saa7134_dev *dev; + struct video_device *vdev = video_devdata(file); + struct saa7134_dev *dev = video_drvdata(file); struct saa7134_fh *fh; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + enum v4l2_buf_type type = 0; int radio = 0; - mutex_lock(&saa7134_devlist_lock); - list_for_each_entry(dev, &saa7134_devlist, devlist) { - if (dev->video_dev && (dev->video_dev->minor == minor)) - goto found; - if (dev->radio_dev && (dev->radio_dev->minor == minor)) { - radio = 1; - goto found; - } - if (dev->vbi_dev && (dev->vbi_dev->minor == minor)) { - type = V4L2_BUF_TYPE_VBI_CAPTURE; - goto found; - } + switch (vdev->vfl_type) { + case VFL_TYPE_GRABBER: + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + break; + case VFL_TYPE_VBI: + type = V4L2_BUF_TYPE_VBI_CAPTURE; + break; + case VFL_TYPE_RADIO: + radio = 1; + break; } - mutex_unlock(&saa7134_devlist_lock); - return -ENODEV; - -found: - mutex_unlock(&saa7134_devlist_lock); dprintk("open minor=%d radio=%d type=%s\n",minor,radio, v4l2_type_names[type]); diff --git a/drivers/staging/cx25821/cx25821-audups11.c b/drivers/staging/cx25821/cx25821-audups11.c index f78b891..e1364d1 100644 --- a/drivers/staging/cx25821/cx25821-audups11.c +++ b/drivers/staging/cx25821/cx25821-audups11.c @@ -95,35 +95,18 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; + struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; - - lock_kernel(); - list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH11] - && h->video_dev[SRAM_CH11]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - } - - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); + if (NULL == fh) return -ENOMEM; - } + + lock_kernel(); file->private_data = fh; fh->dev = dev; diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c index 156e332..c0c99c0 100644 --- a/drivers/staging/cx25821/cx25821-video.c +++ b/drivers/staging/cx25821/cx25821-video.c @@ -189,6 +189,7 @@ struct video_device *cx25821_vdev_init(struct cx25821_dev *dev, vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, cx25821_boards[dev->board].name); + video_set_drvdata(vfd, dev); return vfd; } diff --git a/drivers/staging/cx25821/cx25821-video0.c b/drivers/staging/cx25821/cx25821-video0.c index 950fac1..eb0fe81 100644 --- a/drivers/staging/cx25821/cx25821-video0.c +++ b/drivers/staging/cx25821/cx25821-video0.c @@ -95,36 +95,19 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; + struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; u32 pix_format; - lock_kernel(); - list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH00] - && h->video_dev[SRAM_CH00]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - } - - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); + if (NULL == fh) return -ENOMEM; - } + + lock_kernel(); file->private_data = fh; fh->dev = dev; diff --git a/drivers/staging/cx25821/cx25821-video1.c b/drivers/staging/cx25821/cx25821-video1.c index a4dddc68..96ec238 100644 --- a/drivers/staging/cx25821/cx25821-video1.c +++ b/drivers/staging/cx25821/cx25821-video1.c @@ -95,36 +95,19 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; + struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; u32 pix_format; - lock_kernel(); - list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH01] - && h->video_dev[SRAM_CH01]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - } - - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); + if (NULL == fh) return -ENOMEM; - } + + lock_kernel(); file->private_data = fh; fh->dev = dev; diff --git a/drivers/staging/cx25821/cx25821-video2.c b/drivers/staging/cx25821/cx25821-video2.c index 8e04e25..e659603 100644 --- a/drivers/staging/cx25821/cx25821-video2.c +++ b/drivers/staging/cx25821/cx25821-video2.c @@ -95,36 +95,20 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; + struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; u32 pix_format; - lock_kernel(); - list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH02] - && h->video_dev[SRAM_CH02]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - } - - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); + if (NULL == fh) return -ENOMEM; - } + + lock_kernel(); + file->private_data = fh; fh->dev = dev; fh->type = type; diff --git a/drivers/staging/cx25821/cx25821-video3.c b/drivers/staging/cx25821/cx25821-video3.c index 8801a8e..873f0f8 100644 --- a/drivers/staging/cx25821/cx25821-video3.c +++ b/drivers/staging/cx25821/cx25821-video3.c @@ -95,36 +95,20 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; + struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; u32 pix_format; - lock_kernel(); - list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH03] - && h->video_dev[SRAM_CH03]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - } - - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); + if (NULL == fh) return -ENOMEM; - } + + lock_kernel(); + file->private_data = fh; fh->dev = dev; fh->type = type; diff --git a/drivers/staging/cx25821/cx25821-video4.c b/drivers/staging/cx25821/cx25821-video4.c index ab0d747..c00e3f8 100644 --- a/drivers/staging/cx25821/cx25821-video4.c +++ b/drivers/staging/cx25821/cx25821-video4.c @@ -95,36 +95,20 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; + struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; u32 pix_format; - lock_kernel(); - list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH04] - && h->video_dev[SRAM_CH04]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - } - - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); + if (NULL == fh) return -ENOMEM; - } + + lock_kernel(); + file->private_data = fh; fh->dev = dev; fh->type = type; diff --git a/drivers/staging/cx25821/cx25821-video5.c b/drivers/staging/cx25821/cx25821-video5.c index 7ef0b97..06396b8 100644 --- a/drivers/staging/cx25821/cx25821-video5.c +++ b/drivers/staging/cx25821/cx25821-video5.c @@ -95,36 +95,20 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; + struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; u32 pix_format; - lock_kernel(); - list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH05] - && h->video_dev[SRAM_CH05]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - } - - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); + if (NULL == fh) return -ENOMEM; - } + + lock_kernel(); + file->private_data = fh; fh->dev = dev; fh->type = type; diff --git a/drivers/staging/cx25821/cx25821-video6.c b/drivers/staging/cx25821/cx25821-video6.c index 3c41b49..c5410c1 100644 --- a/drivers/staging/cx25821/cx25821-video6.c +++ b/drivers/staging/cx25821/cx25821-video6.c @@ -95,36 +95,20 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; + struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; u32 pix_format; - lock_kernel(); - list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH06] - && h->video_dev[SRAM_CH06]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - } - - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); + if (NULL == fh) return -ENOMEM; - } + + lock_kernel(); + file->private_data = fh; fh->dev = dev; fh->type = type; diff --git a/drivers/staging/cx25821/cx25821-video7.c b/drivers/staging/cx25821/cx25821-video7.c index 625c9b7..274977e 100644 --- a/drivers/staging/cx25821/cx25821-video7.c +++ b/drivers/staging/cx25821/cx25821-video7.c @@ -94,36 +94,20 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; + struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; u32 pix_format; - lock_kernel(); - list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH07] - && h->video_dev[SRAM_CH07]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - } - - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); + if (NULL == fh) return -ENOMEM; - } + + lock_kernel(); + file->private_data = fh; fh->dev = dev; fh->type = type; diff --git a/drivers/staging/cx25821/cx25821-videoioctl.c b/drivers/staging/cx25821/cx25821-videoioctl.c index 2a312ce..42ea8bf 100644 --- a/drivers/staging/cx25821/cx25821-videoioctl.c +++ b/drivers/staging/cx25821/cx25821-videoioctl.c @@ -95,35 +95,19 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; + struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; u32 pix_format; - lock_kernel(); - list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->ioctl_dev && h->ioctl_dev->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - } - - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); + if (NULL == fh) return -ENOMEM; - } + + lock_kernel(); file->private_data = fh; fh->dev = dev; diff --git a/drivers/staging/cx25821/cx25821-vidups10.c b/drivers/staging/cx25821/cx25821-vidups10.c index 77b63b0..4e0033f 100644 --- a/drivers/staging/cx25821/cx25821-vidups10.c +++ b/drivers/staging/cx25821/cx25821-vidups10.c @@ -95,35 +95,18 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; + struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; - - lock_kernel(); - list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH10] - && h->video_dev[SRAM_CH10]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - } - - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); + if (NULL == fh) return -ENOMEM; - } + + lock_kernel(); file->private_data = fh; fh->dev = dev; diff --git a/drivers/staging/cx25821/cx25821-vidups9.c b/drivers/staging/cx25821/cx25821-vidups9.c index 75c8c1e..67fc082 100644 --- a/drivers/staging/cx25821/cx25821-vidups9.c +++ b/drivers/staging/cx25821/cx25821-vidups9.c @@ -95,35 +95,18 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; + struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; - - lock_kernel(); - list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH09] - && h->video_dev[SRAM_CH09]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - } - - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); + if (NULL == fh) return -ENOMEM; - } + + lock_kernel(); file->private_data = fh; fh->dev = dev; -- cgit v0.10.2 From 50462eb065e12f45851a9959a90d46b758944552 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 10 Dec 2009 11:47:13 -0200 Subject: V4L/DVB (13555): v4l: Use video_device_node_name() instead of the minor number Instead of using the minor number in kernel log messages, use the device node name as returned by the video_device_node_name() function. This makes debug, informational and error messages easier to understand for end users. [mchehab.redhat.com: removed tm6000 changes as tm6000 is not ready yet for submission even on staging] Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index 2d9fc243..3c11cff 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -194,7 +194,6 @@ void saa7146_buffer_timeout(unsigned long data) static int fops_open(struct file *file) { - unsigned int minor = video_devdata(file)->minor; struct video_device *vdev = video_devdata(file); struct saa7146_dev *dev = video_drvdata(file); struct saa7146_fh *fh = NULL; @@ -202,7 +201,7 @@ static int fops_open(struct file *file) enum v4l2_buf_type type; - DEB_EE(("file:%p, minor:%d\n", file, minor)); + DEB_EE(("file:%p, dev:%s\n", file, video_device_node_name(vdev))); if (mutex_lock_interruptible(&saa7146_devices_lock)) return -ERESTARTSYS; diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index a233691..dcad2f7 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -3207,11 +3207,12 @@ err: static int bttv_open(struct file *file) { int minor = video_devdata(file)->minor; + struct video_device *vdev = video_devdata(file); struct bttv *btv = video_drvdata(file); struct bttv_fh *fh; enum v4l2_buf_type type = 0; - dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor); + dprintk(KERN_DEBUG "bttv: open dev=%s\n", video_device_node_name(vdev)); lock_kernel(); if (btv->video_dev->minor == minor) { @@ -3409,10 +3410,11 @@ static struct video_device bttv_video_template = { static int radio_open(struct file *file) { int minor = video_devdata(file)->minor; + struct video_device *vdev = video_devdata(file); struct bttv *btv = video_drvdata(file); struct bttv_fh *fh; - dprintk("bttv: open minor=%d\n",minor); + dprintk("bttv: open dev=%s\n", video_device_node_name(vdev)); lock_kernel(); WARN_ON(btv->radio_dev && btv->radio_dev->minor != minor); diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 4e278db..c0885c6 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c @@ -758,8 +758,8 @@ int cx18_v4l2_open(struct file *filp) mutex_lock(&cx->serialize_lock); if (cx18_init_on_first_open(cx)) { - CX18_ERR("Failed to initialize on minor %d\n", - video_dev->minor); + CX18_ERR("Failed to initialize on %s\n", + video_device_node_name(video_dev)); mutex_unlock(&cx->serialize_lock); return -ENXIO; } diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index 3fc7a6f..552dff5 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c @@ -1916,7 +1916,6 @@ static int radio_queryctrl(struct file *file, void *priv, */ static int cx231xx_v4l2_open(struct file *filp) { - int minor = video_devdata(filp)->minor; int errCode = 0, radio = 0; struct video_device *vdev = video_devdata(filp); struct cx231xx *dev = video_drvdata(filp); @@ -1937,8 +1936,9 @@ static int cx231xx_v4l2_open(struct file *filp) mutex_lock(&dev->lock); - cx231xx_videodbg("open minor=%d type=%s users=%d\n", - minor, v4l2_type_names[fh_type], dev->users); + cx231xx_videodbg("open dev=%s type=%s users=%d\n", + video_device_node_name(vdev), v4l2_type_names[fh_type], + dev->users); #if 0 errCode = cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index e10f28c..e8ca8bb 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -717,7 +717,6 @@ static int get_resource(struct cx23885_fh *fh) static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; struct video_device *vdev = video_devdata(file); struct cx23885_dev *dev = video_drvdata(file); struct cx23885_fh *fh; @@ -736,8 +735,8 @@ static int video_open(struct file *file) break; } - dprintk(1, "open minor=%d radio=%d type=%s\n", - minor, radio, v4l2_type_names[type]); + dprintk(1, "open dev=%s radio=%d type=%s\n", + video_device_node_name(vdev), radio, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index f0ef941..03e592e 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1048,7 +1048,7 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) static int mpeg_open(struct file *file) { - int minor = video_devdata(file)->minor; + struct video_device *vdev = video_devdata(file); struct cx8802_dev *dev = video_drvdata(file); struct cx8802_fh *fh; struct cx8802_driver *drv = NULL; @@ -1075,7 +1075,7 @@ static int mpeg_open(struct file *file) unlock_kernel(); return -EINVAL; } - dprintk(1,"open minor=%d\n",minor); + dprintk(1, "open dev=%s\n", video_device_node_name(vdev)); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh),GFP_KERNEL); diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 7583991..0013cb4 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -749,7 +749,6 @@ static int get_ressource(struct cx8800_fh *fh) static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; struct video_device *vdev = video_devdata(file); struct cx8800_dev *dev = video_drvdata(file); struct cx88_core *core; @@ -773,8 +772,8 @@ static int video_open(struct file *file) core = dev->core; - dprintk(1,"open minor=%d radio=%d type=%s\n", - minor,radio,v4l2_type_names[type]); + dprintk(1, "open dev=%s radio=%d type=%s\n", + video_device_node_name(vdev), radio, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh),GFP_KERNEL); diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index dd9bbe8..0408727b 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -2081,7 +2081,6 @@ static int radio_queryctrl(struct file *file, void *priv, */ static int em28xx_v4l2_open(struct file *filp) { - int minor = video_devdata(filp)->minor; int errCode = 0, radio = 0; struct video_device *vdev = video_devdata(filp); struct em28xx *dev = video_drvdata(filp); @@ -2103,8 +2102,9 @@ static int em28xx_v4l2_open(struct file *filp) mutex_lock(&dev->lock); - em28xx_videodbg("open minor=%d type=%s users=%d\n", - minor, v4l2_type_names[fh_type], dev->users); + em28xx_videodbg("open dev=%s type=%s users=%d\n", + video_device_node_name(vdev), v4l2_type_names[fh_type], + dev->users); fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index e707ef3..babcabd 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -985,8 +985,8 @@ int ivtv_v4l2_open(struct file *filp) mutex_lock(&itv->serialize_lock); if (ivtv_init_on_first_open(itv)) { - IVTV_ERR("Failed to initialize on minor %d\n", - vdev->minor); + IVTV_ERR("Failed to initialize on device %s\n", + video_device_node_name(vdev)); mutex_unlock(&itv->serialize_lock); return -ENXIO; } diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index b636160..939ae8b 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -5867,8 +5867,8 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) ov511_devused |= 1 << nr; ov->nr = nr; - dev_info(&intf->dev, "Device at %s registered to minor %d\n", - ov->usb_path, ov->vdev->minor); + dev_info(&intf->dev, "Device at %s registered to %s\n", + ov->usb_path, video_device_node_name(ov->vdev)); usb_set_intfdata(intf, ov); if (ov_create_sysfs(ov->vdev)) { diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 0a77108..f6a4929 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -1530,7 +1530,6 @@ static int vidioc_s_parm(struct file *file, void *priv, } static int s2255_open(struct file *file) { - int minor = video_devdata(file)->minor; struct video_device *vdev = video_devdata(file); struct s2255_dev *dev = video_drvdata(file); struct s2255_fh *fh; @@ -1538,7 +1537,9 @@ static int s2255_open(struct file *file) int i = 0; int cur_channel = -1; int state; - dprintk(1, "s2255: open called (minor=%d)\n", minor); + + dprintk(1, "s2255: open called (dev=%s)\n", + video_device_node_name(vdev)); lock_kernel(); @@ -1650,8 +1651,9 @@ static int s2255_open(struct file *file) for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++) qctl_regs[i] = s2255_qctrl[i].default_value; - dprintk(1, "s2255drv: open minor=%d type=%s users=%d\n", - minor, v4l2_type_names[type], dev->users[cur_channel]); + dprintk(1, "s2255drv: open dev=%s type=%s users=%d\n", + video_device_node_name(vdev), v4l2_type_names[type], + dev->users[cur_channel]); dprintk(2, "s2255drv: open: fh=0x%08lx, dev=0x%08lx, vidq=0x%08lx\n", (unsigned long)fh, (unsigned long)dev, (unsigned long)&dev->vidq[cur_channel]); @@ -1728,7 +1730,8 @@ static int s2255_close(struct file *file) { struct s2255_fh *fh = file->private_data; struct s2255_dev *dev = fh->dev; - int minor = video_devdata(file)->minor; + struct video_device *vdev = video_devdata(file); + if (!dev) return -ENODEV; @@ -1748,8 +1751,8 @@ static int s2255_close(struct file *file) mutex_unlock(&dev->open_lock); kref_put(&dev->kref, s2255_destroy); - dprintk(1, "s2255: close called (minor=%d, users=%d)\n", - minor, dev->users[fh->channel]); + dprintk(1, "s2255: close called (dev=%s, users=%d)\n", + video_device_node_name(vdev), dev->users[fh->channel]); kfree(fh); return 0; } diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 1de27af..df56241 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -86,11 +86,11 @@ static int ts_init_encoder(struct saa7134_dev* dev) static int ts_open(struct file *file) { - int minor = video_devdata(file)->minor; + struct video_device *vdev = video_devdata(file); struct saa7134_dev *dev = video_drvdata(file); int err; - dprintk("open minor=%d\n",minor); + dprintk("open dev=%s\n", video_device_node_name(vdev)); err = -EBUSY; if (!mutex_trylock(&dev->empress_tsq.vb_lock)) goto done; diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index bcca5a4..9d26b1bd 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1326,7 +1326,6 @@ static int saa7134_resource(struct saa7134_fh *fh) static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; struct video_device *vdev = video_devdata(file); struct saa7134_dev *dev = video_drvdata(file); struct saa7134_fh *fh; @@ -1345,8 +1344,8 @@ static int video_open(struct file *file) break; } - dprintk("open minor=%d radio=%d type=%s\n",minor,radio, - v4l2_type_names[type]); + dprintk("open dev=%s radio=%d type=%s\n", video_device_node_name(vdev), + radio, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh),GFP_KERNEL); diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 93e0a25..ce197e4 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -1222,8 +1222,7 @@ static int vivi_close(struct file *file) struct vivi_fh *fh = file->private_data; struct vivi_dev *dev = fh->dev; struct vivi_dmaqueue *vidq = &dev->vidq; - - int minor = video_devdata(file)->minor; + struct video_device *vdev = video_devdata(file); vivi_stop_thread(vidq); videobuf_stop(&fh->vb_vidq); @@ -1235,8 +1234,8 @@ static int vivi_close(struct file *file) dev->users--; mutex_unlock(&dev->mutex); - dprintk(dev, 1, "close called (minor=%d, users=%d)\n", - minor, dev->users); + dprintk(dev, 1, "close called (dev=%s, users=%d)\n", + video_device_node_name(vdev), dev->users); return 0; } diff --git a/drivers/staging/cx25821/cx25821-audups11.c b/drivers/staging/cx25821/cx25821-audups11.c index e1364d1..a2fcbf0 100644 --- a/drivers/staging/cx25821/cx25821-audups11.c +++ b/drivers/staging/cx25821/cx25821-audups11.c @@ -94,12 +94,13 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; + struct video_device *vdev = video_devdata(file); struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open dev=%s type=%s\n", video_device_node_name(vdev), + v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); diff --git a/drivers/staging/cx25821/cx25821-video0.c b/drivers/staging/cx25821/cx25821-video0.c index eb0fe81..9a47420 100644 --- a/drivers/staging/cx25821/cx25821-video0.c +++ b/drivers/staging/cx25821/cx25821-video0.c @@ -94,13 +94,14 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; + struct video_device *vdev = video_devdata(file); struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; u32 pix_format; - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open dev=%s type=%s\n", video_device_node_name(vdev), + v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); diff --git a/drivers/staging/cx25821/cx25821-video1.c b/drivers/staging/cx25821/cx25821-video1.c index 96ec238..fc9c118 100644 --- a/drivers/staging/cx25821/cx25821-video1.c +++ b/drivers/staging/cx25821/cx25821-video1.c @@ -94,13 +94,14 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; + struct video_device *vdev = video_devdata(file); struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; u32 pix_format; - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open dev=%s type=%s\n", video_device_node_name(vdev), + v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); diff --git a/drivers/staging/cx25821/cx25821-video2.c b/drivers/staging/cx25821/cx25821-video2.c index e659603..7466829 100644 --- a/drivers/staging/cx25821/cx25821-video2.c +++ b/drivers/staging/cx25821/cx25821-video2.c @@ -94,13 +94,14 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; + struct video_device *vdev = video_devdata(file); struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; u32 pix_format; - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open dev=%s type=%s\n", video_device_node_name(vdev), + v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); diff --git a/drivers/staging/cx25821/cx25821-video3.c b/drivers/staging/cx25821/cx25821-video3.c index 873f0f8..0806e40 100644 --- a/drivers/staging/cx25821/cx25821-video3.c +++ b/drivers/staging/cx25821/cx25821-video3.c @@ -94,13 +94,14 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; + struct video_device *vdev = video_devdata(file); struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; u32 pix_format; - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open dev=%s type=%s\n", video_device_node_name(vdev), + v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); diff --git a/drivers/staging/cx25821/cx25821-video4.c b/drivers/staging/cx25821/cx25821-video4.c index c00e3f8..f44e1d4 100644 --- a/drivers/staging/cx25821/cx25821-video4.c +++ b/drivers/staging/cx25821/cx25821-video4.c @@ -94,13 +94,14 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; + struct video_device *vdev = video_devdata(file); struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; u32 pix_format; - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open dev=%s type=%s\n", video_device_node_name(vdev), + v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); diff --git a/drivers/staging/cx25821/cx25821-video5.c b/drivers/staging/cx25821/cx25821-video5.c index 06396b8..85028ea 100644 --- a/drivers/staging/cx25821/cx25821-video5.c +++ b/drivers/staging/cx25821/cx25821-video5.c @@ -94,13 +94,14 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; + struct video_device *vdev = video_devdata(file); struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; u32 pix_format; - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open dev=%s type=%s\n", video_device_node_name(vdev), + v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); diff --git a/drivers/staging/cx25821/cx25821-video6.c b/drivers/staging/cx25821/cx25821-video6.c index c5410c1..27afa03 100644 --- a/drivers/staging/cx25821/cx25821-video6.c +++ b/drivers/staging/cx25821/cx25821-video6.c @@ -94,13 +94,14 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; + struct video_device *vdev = video_devdata(file); struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; u32 pix_format; - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open dev=%s type=%s\n", video_device_node_name(vdev), + v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); diff --git a/drivers/staging/cx25821/cx25821-video7.c b/drivers/staging/cx25821/cx25821-video7.c index 274977e..055a7ef 100644 --- a/drivers/staging/cx25821/cx25821-video7.c +++ b/drivers/staging/cx25821/cx25821-video7.c @@ -93,13 +93,14 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; + struct video_device *vdev = video_devdata(file); struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; u32 pix_format; - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open dev=%s type=%s\n", video_device_node_name(vdev), + v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); diff --git a/drivers/staging/cx25821/cx25821-videoioctl.c b/drivers/staging/cx25821/cx25821-videoioctl.c index 42ea8bf..ae33355 100644 --- a/drivers/staging/cx25821/cx25821-videoioctl.c +++ b/drivers/staging/cx25821/cx25821-videoioctl.c @@ -94,13 +94,14 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; + struct video_device *vdev = video_devdata(file); struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; u32 pix_format; - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open dev=%s type=%s\n", video_device_node_name(vdev), + v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); diff --git a/drivers/staging/cx25821/cx25821-vidups10.c b/drivers/staging/cx25821/cx25821-vidups10.c index 4e0033f..97db6cd 100644 --- a/drivers/staging/cx25821/cx25821-vidups10.c +++ b/drivers/staging/cx25821/cx25821-vidups10.c @@ -94,12 +94,13 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; + struct video_device *vdev = video_devdata(file); struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open dev=%s type=%s\n", video_device_node_name(vdev), + v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); diff --git a/drivers/staging/cx25821/cx25821-vidups9.c b/drivers/staging/cx25821/cx25821-vidups9.c index 67fc082..d06054f 100644 --- a/drivers/staging/cx25821/cx25821-vidups9.c +++ b/drivers/staging/cx25821/cx25821-vidups9.c @@ -94,12 +94,13 @@ static struct videobuf_queue_ops cx25821_video_qops = { static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; + struct video_device *vdev = video_devdata(file); struct cx25821_dev *dev = video_drvdata(file); struct cx25821_fh *fh; enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open dev=%s type=%s\n", video_device_node_name(vdev), + v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); -- cgit v0.10.2 From 46b21094cee16bc7e531d7d6cd66fb5ea05065d4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 10 Dec 2009 11:51:38 -0200 Subject: V4L/DVB (13556): v4l: Remove unneeded video_device::minor assignments Now that the video_device registration is tested using video_is_registered(), drivers don't need to initialize the video_device::minor field to -1 anymore. Remove those unneeded assignments. [mchehab.redhat.com: removed tm6000 changes as tm6000 is not ready yet for submission even on staging] Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 0ec807d..a356d6b 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -767,7 +767,6 @@ static struct video_device ar_template = { .name = "Colour AR VGA", .fops = &ar_fops, .release = ar_release, - .minor = -1, }; #define ALIGN4(x) ((((int)(x)) & 0x3) == 0) diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 13a8a1d..dc67bc4 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -1570,7 +1570,6 @@ static const struct video_device au0828_video_template = { .fops = &au0828_v4l_fops, .release = video_device_release, .ioctl_ops = &video_ioctl_ops, - .minor = -1, .tvnorms = V4L2_STD_NTSC_M, .current_norm = V4L2_STD_NTSC_M, }; diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index dcad2f7..410260a 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -3398,7 +3398,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = { static struct video_device bttv_video_template = { .fops = &bttv_fops, - .minor = -1, .ioctl_ops = &bttv_ioctl_ops, .tvnorms = BTTV_NORMS, .current_norm = V4L2_STD_PAL, @@ -3642,7 +3641,6 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { static struct video_device radio_template = { .fops = &radio_fops, - .minor = -1, .ioctl_ops = &radio_ioctl_ops, }; diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 10230cb..7bb9c1e 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -1723,7 +1723,6 @@ static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = { static struct video_device cafe_v4l_template = { .name = "cafe", - .minor = -1, /* Get one dynamically */ .tvnorms = V4L2_STD_NTSC_M, .current_norm = V4L2_STD_NTSC_M, /* make mplayer happy */ diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index f8952af..30d39b1 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -1926,7 +1926,6 @@ static const struct v4l2_file_operations fops_template = { static struct video_device cpia2_template = { /* I could not find any place for the old .initialize initializer?? */ .name= "CPiA2 Camera", - .minor= -1, .fops= &fops_template, .release= video_device_release, }; diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index 552dff5..d4f546f 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c @@ -2277,7 +2277,6 @@ static const struct video_device cx231xx_video_template = { .fops = &cx231xx_v4l_fops, .release = video_device_release, .ioctl_ops = &video_ioctl_ops, - .minor = -1, .tvnorms = V4L2_STD_ALL, .current_norm = V4L2_STD_PAL, }; @@ -2312,7 +2311,6 @@ static struct video_device cx231xx_radio_template = { .name = "cx231xx-radio", .fops = &radio_fops, .ioctl_ops = &radio_ioctl_ops, - .minor = -1, }; /******************************** usb interface ******************************/ @@ -2328,7 +2326,6 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, return NULL; *vfd = *template; - vfd->minor = -1; vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; vfd->debug = video_debug; diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 272c60a..88c0d24 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c @@ -1721,7 +1721,6 @@ static struct video_device cx23885_mpeg_template = { .name = "cx23885", .fops = &mpeg_fops, .ioctl_ops = &mpeg_ioctl_ops, - .minor = -1, .tvnorms = CX23885_NORMS, .current_norm = V4L2_STD_NTSC_M, }; diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index e8ca8bb..8934d61 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -318,7 +318,6 @@ static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev, if (NULL == vfd) return NULL; *vfd = *template; - vfd->minor = -1; vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", @@ -1430,7 +1429,6 @@ static struct video_device cx23885_vbi_template; static struct video_device cx23885_video_template = { .name = "cx23885-video", .fops = &video_fops, - .minor = -1, .ioctl_ops = &video_ioctl_ops, .tvnorms = CX23885_NORMS, .current_norm = V4L2_STD_NTSC_M, diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 03e592e..6fe30e6 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1210,7 +1210,6 @@ static struct video_device cx8802_mpeg_template = { .name = "cx8802", .fops = &mpeg_fops, .ioctl_ops = &mpeg_ioctl_ops, - .minor = -1, .tvnorms = CX88_NORMS, .current_norm = V4L2_STD_NTSC_M, }; diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 0013cb4..48c450f 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1722,7 +1722,6 @@ static struct video_device cx8800_vbi_template; static struct video_device cx8800_video_template = { .name = "cx8800-video", .fops = &video_fops, - .minor = -1, .ioctl_ops = &video_ioctl_ops, .tvnorms = CX88_NORMS, .current_norm = V4L2_STD_NTSC_M, @@ -1758,7 +1757,6 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { static struct video_device cx8800_radio_template = { .name = "cx8800-radio", .fops = &radio_fops, - .minor = -1, .ioctl_ops = &radio_ioctl_ops, }; diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 1e85794..f2d3c9b 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -1967,7 +1967,6 @@ static __init int vpfe_probe(struct platform_device *pdev) vfd->release = video_device_release; vfd->fops = &vpfe_fops; vfd->ioctl_ops = &vpfe_ioctl_ops; - vfd->minor = -1; vfd->tvnorms = 0; vfd->current_norm = V4L2_STD_PAL; vfd->v4l2_dev = &vpfe_dev->v4l2_dev; diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c index d14cfb2..dfddef7 100644 --- a/drivers/media/video/davinci/vpif_display.c +++ b/drivers/media/video/davinci/vpif_display.c @@ -1347,7 +1347,6 @@ static const struct v4l2_file_operations vpif_fops = { static struct video_device vpif_video_template = { .name = "vpif", .fops = &vpif_fops, - .minor = -1, .ioctl_ops = &vpif_ioctl_ops, .tvnorms = DM646X_V4L2_STD, .current_norm = V4L2_STD_625_50, diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 0408727b..849b18c 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -2405,8 +2405,6 @@ static const struct video_device em28xx_video_template = { .release = video_device_release, .ioctl_ops = &video_ioctl_ops, - .minor = -1, - .tvnorms = V4L2_STD_ALL, .current_norm = V4L2_STD_PAL, }; @@ -2441,7 +2439,6 @@ static struct video_device em28xx_radio_template = { .name = "em28xx-radio", .fops = &radio_fops, .ioctl_ops = &radio_ioctl_ops, - .minor = -1, }; /******************************** usb interface ******************************/ @@ -2459,7 +2456,6 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, return NULL; *vfd = *template; - vfd->minor = -1; vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; vfd->debug = video_debug; diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index f561a1c..e6c23d50 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -2587,7 +2587,6 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) strcpy(cam->v4ldev->name, "ET61X[12]51 PC Camera"); cam->v4ldev->fops = &et61x251_fops; - cam->v4ldev->minor = video_nr[dev_nr]; cam->v4ldev->release = video_device_release; cam->v4ldev->parent = &udev->dev; video_set_drvdata(cam->v4ldev, cam); diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 6af4f23..9724e65 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -1989,7 +1989,6 @@ static struct video_device gspca_template = { .fops = &dev_fops, .ioctl_ops = &dev_ioctl_ops, .release = gspca_release, - .minor = -1, }; /* diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 01e1eef..6ffa64c 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -1681,7 +1681,6 @@ static struct video_device meye_template = { .fops = &meye_fops, .ioctl_ops = &meye_ioctl_ops, .release = video_device_release, - .minor = -1, }; #ifdef CONFIG_PM diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index 34eb965..71e08be 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c @@ -1660,7 +1660,6 @@ static int omap24xxcam_device_register(struct v4l2_int_device *s) strlcpy(vfd->name, CAM_NAME, sizeof(vfd->name)); vfd->fops = &omap24xxcam_fops; - vfd->minor = -1; vfd->ioctl_ops = &omap24xxcam_ioctl_fops; omap24xxcam_hwinit(cam); @@ -1671,7 +1670,6 @@ static int omap24xxcam_device_register(struct v4l2_int_device *s) if (video_register_device(vfd, VFL_TYPE_GRABBER, video_nr) < 0) { dev_err(cam->dev, "could not register V4L device\n"); - vfd->minor = -1; rval = -EBUSY; goto err; } diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index 939ae8b..c71865d 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -4674,7 +4674,6 @@ static struct video_device vdev_template = { .name = "OV511 USB Camera", .fops = &ov511_fops, .release = video_device_release, - .minor = -1, }; /**************************************************************************** diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 819cf4e..d0e2b57 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -169,7 +169,6 @@ static struct video_device pwc_template = { .name = "Philips Webcam", /* Filled in later */ .release = video_device_release, .fops = &pwc_fops, - .minor = -1, }; /***************************************************************************/ diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index f6a4929..fb742f1 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -1816,7 +1816,6 @@ static struct video_device template = { .name = "s2255v", .fops = &s2255_fops_v4l, .ioctl_ops = &s2255_ioctl_ops, - .minor = -1, .release = video_device_release, .tvnorms = S2255_NORMS, .current_norm = V4L2_STD_NTSC_M, diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index b624a4c..5ab6a0f 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c @@ -1036,7 +1036,6 @@ static struct video_device saa_template = .name = "saa5246a", .fops = &saa_fops, .release = video_device_release, - .minor = -1, }; static int saa5246a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index df56241..7dfecfc 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -481,7 +481,6 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = { static struct video_device saa7134_empress_template = { .name = "saa7134-empress", .fops = &ts_fops, - .minor = -1, .ioctl_ops = &ts_ioctl_ops, .tvnorms = SAA7134_NORMS, diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 9d26b1bd..cb73264 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -2495,7 +2495,6 @@ struct video_device saa7134_video_template = { .name = "saa7134-video", .fops = &video_fops, .ioctl_ops = &video_ioctl_ops, - .minor = -1, .tvnorms = SAA7134_NORMS, .current_norm = V4L2_STD_PAL, }; @@ -2504,7 +2503,6 @@ struct video_device saa7134_radio_template = { .name = "saa7134-radio", .fops = &radio_fops, .ioctl_ops = &radio_ioctl_ops, - .minor = -1, }; int saa7134_video_init1(struct saa7134_dev *dev) diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 4cf41a8..cbf8087 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -3329,7 +3329,6 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) strcpy(cam->v4ldev->name, "SN9C1xx PC Camera"); cam->v4ldev->fops = &sn9c102_fops; - cam->v4ldev->minor = video_nr[dev_nr]; cam->v4ldev->release = video_device_release; cam->v4ldev->parent = &udev->dev; diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 95fdeb2..804c675 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -1268,7 +1268,6 @@ static int video_dev_create(struct soc_camera_device *icd) vdev->fops = &soc_camera_fops; vdev->ioctl_ops = &soc_camera_ioctl_ops; vdev->release = video_device_release; - vdev->minor = -1; vdev->tvnorms = V4L2_STD_UNKNOWN; icd->vdev = vdev; @@ -1291,8 +1290,7 @@ static int soc_camera_video_start(struct soc_camera_device *icd) !icd->ops->set_bus_param) return -EINVAL; - ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, - icd->vdev->minor); + ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, -1); if (ret < 0) { dev_err(&icd->dev, "video_register_device failed: %d\n", ret); return ret; diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index 6590b92..f07a0f6 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c @@ -1307,7 +1307,6 @@ static void stk_v4l_dev_release(struct video_device *vd) static struct video_device stk_v4l_data = { .name = "stkwebcam", - .minor = -1, .tvnorms = V4L2_STD_UNKNOWN, .current_norm = V4L2_STD_UNKNOWN, .fops = &v4l_stk_fops, diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index c890905..a057824 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c @@ -1921,7 +1921,6 @@ static const struct v4l2_file_operations saa_fops = { static struct video_device saa_template = { .name = "SAA7146A", .fops = &saa_fops, - .minor = -1, .release = video_device_release_empty, }; @@ -1972,7 +1971,6 @@ static int __devinit configure_saa7146(struct pci_dev *pdev, int num) saa->id = pdev->device; saa->irq = pdev->irq; - saa->video_dev.minor = -1; saa->saa7146_adr = pci_resource_start(pdev, 0); pci_read_config_byte(pdev, PCI_CLASS_REVISION, &saa->revision); diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index b542222..5938ad8 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c @@ -1405,7 +1405,6 @@ static struct video_device stv680_template = { .name = "STV0680 USB camera", .fops = &stv680_fops, .release = video_device_release, - .minor = -1, }; static int stv680_probe (struct usb_interface *intf, const struct usb_device_id *id) diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c index b75143e..6030410 100644 --- a/drivers/media/video/usbvideo/vicam.c +++ b/drivers/media/video/usbvideo/vicam.c @@ -796,7 +796,6 @@ static const struct v4l2_file_operations vicam_fops = { static struct video_device vicam_template = { .name = "ViCam-based USB Camera", .fops = &vicam_fops, - .minor = -1, .release = video_device_release_empty, }; diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index e89b855..1054546 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -1328,7 +1328,6 @@ static struct video_device usbvision_video_template = { .ioctl_ops = &usbvision_ioctl_ops, .name = "usbvision-video", .release = video_device_release, - .minor = -1, .tvnorms = USBVISION_NORMS, .current_norm = V4L2_STD_PAL }; @@ -1362,7 +1361,6 @@ static struct video_device usbvision_radio_template = { .fops = &usbvision_radio_fops, .name = "usbvision-radio", .release = video_device_release, - .minor = -1, .ioctl_ops = &usbvision_radio_ioctl_ops, .tvnorms = USBVISION_NORMS, @@ -1382,7 +1380,6 @@ static struct video_device usbvision_vbi_template= .fops = &usbvision_vbi_fops, .release = video_device_release, .name = "usbvision-vbi", - .minor = -1, }; @@ -1404,7 +1401,6 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, return NULL; } *vdev = *vdev_template; -// vdev->minor = -1; vdev->v4l2_dev = &usbvision->v4l2_dev; snprintf(vdev->name, sizeof(vdev->name), "%s", name); video_set_drvdata(vdev, usbvision); diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index c31bc50..391cccc 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -1651,7 +1651,6 @@ static int uvc_register_video(struct uvc_device *dev, * get another one. */ vdev->parent = &dev->intf->dev; - vdev->minor = -1; vdev->fops = &uvc_fops; vdev->release = uvc_release; strlcpy(vdev->name, dev->name, sizeof vdev->name); diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index b034a81..a15d1e7 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -4068,7 +4068,6 @@ static struct video_device vdev_template = { .fops = &vino_fops, .ioctl_ops = &vino_ioctl_ops, .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, - .minor = -1, }; static void vino_module_cleanup(int stage) diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index ce197e4..37632a0 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -1296,7 +1296,6 @@ static struct video_device vivi_template = { .name = "vivi", .fops = &vivi_fops, .ioctl_ops = &vivi_ioctl_ops, - .minor = -1, .release = video_device_release, .tvnorms = V4L2_STD_525_60, diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index 3af6d6b..d807eea 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c @@ -3487,7 +3487,6 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) strcpy(cam->v4ldev->name, symbolic(camlist, mod_id)); cam->v4ldev->fops = &w9968cf_fops; - cam->v4ldev->minor = video_nr[dev_nr]; cam->v4ldev->release = video_device_release; video_set_drvdata(cam->v4ldev, cam); cam->v4ldev->v4l2_dev = &cam->v4l2_dev; diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 524eb75..e44e4b5 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c @@ -1988,7 +1988,6 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) strcpy(cam->v4ldev->name, "ZC0301[P] PC Camera"); cam->v4ldev->fops = &zc0301_fops; - cam->v4ldev->minor = video_nr[dev_nr]; cam->v4ldev->release = video_device_release; cam->v4ldev->parent = &udev->dev; video_set_drvdata(cam->v4ldev, cam); diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index e9f72ca..2ddffed 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -3387,6 +3387,5 @@ struct video_device zoran_template __devinitdata = { .ioctl_ops = &zoran_ioctl_ops, .release = &zoran_vdev_release, .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, - .minor = -1 }; diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 69ea6df..f0eae83 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c @@ -1455,7 +1455,6 @@ static struct video_device zr364xx_template = { .fops = &zr364xx_fops, .ioctl_ops = &zr364xx_ioctl_ops, .release = video_device_release, - .minor = -1, }; diff --git a/drivers/staging/cx25821/cx25821-audups11.c b/drivers/staging/cx25821/cx25821-audups11.c index a2fcbf0..89c8fe2 100644 --- a/drivers/staging/cx25821/cx25821-audups11.c +++ b/drivers/staging/cx25821/cx25821-audups11.c @@ -411,7 +411,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { struct video_device cx25821_video_template11 = { .name = "cx25821-audioupstream", .fops = &video_fops, - .minor = -1, .ioctl_ops = &video_ioctl_ops, .tvnorms = CX25821_NORMS, .current_norm = V4L2_STD_NTSC_M, diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c index c0c99c0..c7c14c7 100644 --- a/drivers/staging/cx25821/cx25821-video.c +++ b/drivers/staging/cx25821/cx25821-video.c @@ -184,7 +184,6 @@ struct video_device *cx25821_vdev_init(struct cx25821_dev *dev, if (NULL == vfd) return NULL; *vfd = *template; - vfd->minor = -1; vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, diff --git a/drivers/staging/cx25821/cx25821-video0.c b/drivers/staging/cx25821/cx25821-video0.c index 9a47420..ad7a691 100644 --- a/drivers/staging/cx25821/cx25821-video0.c +++ b/drivers/staging/cx25821/cx25821-video0.c @@ -428,7 +428,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { struct video_device cx25821_video_template0 = { .name = "cx25821-video", .fops = &video_fops, - .minor = -1, .ioctl_ops = &video_ioctl_ops, .tvnorms = CX25821_NORMS, .current_norm = V4L2_STD_NTSC_M, diff --git a/drivers/staging/cx25821/cx25821-video1.c b/drivers/staging/cx25821/cx25821-video1.c index fc9c118..e3f3c4a 100644 --- a/drivers/staging/cx25821/cx25821-video1.c +++ b/drivers/staging/cx25821/cx25821-video1.c @@ -428,7 +428,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { struct video_device cx25821_video_template1 = { .name = "cx25821-video", .fops = &video_fops, - .minor = -1, .ioctl_ops = &video_ioctl_ops, .tvnorms = CX25821_NORMS, .current_norm = V4L2_STD_NTSC_M, diff --git a/drivers/staging/cx25821/cx25821-video2.c b/drivers/staging/cx25821/cx25821-video2.c index 7466829..36fb855 100644 --- a/drivers/staging/cx25821/cx25821-video2.c +++ b/drivers/staging/cx25821/cx25821-video2.c @@ -430,7 +430,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { struct video_device cx25821_video_template2 = { .name = "cx25821-video", .fops = &video_fops, - .minor = -1, .ioctl_ops = &video_ioctl_ops, .tvnorms = CX25821_NORMS, .current_norm = V4L2_STD_NTSC_M, diff --git a/drivers/staging/cx25821/cx25821-video3.c b/drivers/staging/cx25821/cx25821-video3.c index 0806e40..1e0f10a 100644 --- a/drivers/staging/cx25821/cx25821-video3.c +++ b/drivers/staging/cx25821/cx25821-video3.c @@ -429,7 +429,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { struct video_device cx25821_video_template3 = { .name = "cx25821-video", .fops = &video_fops, - .minor = -1, .ioctl_ops = &video_ioctl_ops, .tvnorms = CX25821_NORMS, .current_norm = V4L2_STD_NTSC_M, diff --git a/drivers/staging/cx25821/cx25821-video4.c b/drivers/staging/cx25821/cx25821-video4.c index f44e1d4..0cbe7a7 100644 --- a/drivers/staging/cx25821/cx25821-video4.c +++ b/drivers/staging/cx25821/cx25821-video4.c @@ -428,7 +428,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { struct video_device cx25821_video_template4 = { .name = "cx25821-video", .fops = &video_fops, - .minor = -1, .ioctl_ops = &video_ioctl_ops, .tvnorms = CX25821_NORMS, .current_norm = V4L2_STD_NTSC_M, diff --git a/drivers/staging/cx25821/cx25821-video5.c b/drivers/staging/cx25821/cx25821-video5.c index 85028ea..5dc08ad 100644 --- a/drivers/staging/cx25821/cx25821-video5.c +++ b/drivers/staging/cx25821/cx25821-video5.c @@ -428,7 +428,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { struct video_device cx25821_video_template5 = { .name = "cx25821-video", .fops = &video_fops, - .minor = -1, .ioctl_ops = &video_ioctl_ops, .tvnorms = CX25821_NORMS, .current_norm = V4L2_STD_NTSC_M, diff --git a/drivers/staging/cx25821/cx25821-video6.c b/drivers/staging/cx25821/cx25821-video6.c index 27afa03..2938ad3 100644 --- a/drivers/staging/cx25821/cx25821-video6.c +++ b/drivers/staging/cx25821/cx25821-video6.c @@ -428,7 +428,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { struct video_device cx25821_video_template6 = { .name = "cx25821-video", .fops = &video_fops, - .minor = -1, .ioctl_ops = &video_ioctl_ops, .tvnorms = CX25821_NORMS, .current_norm = V4L2_STD_NTSC_M, diff --git a/drivers/staging/cx25821/cx25821-video7.c b/drivers/staging/cx25821/cx25821-video7.c index 055a7ef..458e525 100644 --- a/drivers/staging/cx25821/cx25821-video7.c +++ b/drivers/staging/cx25821/cx25821-video7.c @@ -427,7 +427,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { struct video_device cx25821_video_template7 = { .name = "cx25821-video", .fops = &video_fops, - .minor = -1, .ioctl_ops = &video_ioctl_ops, .tvnorms = CX25821_NORMS, .current_norm = V4L2_STD_NTSC_M, diff --git a/drivers/staging/cx25821/cx25821-videoioctl.c b/drivers/staging/cx25821/cx25821-videoioctl.c index ae33355..1da52b5 100644 --- a/drivers/staging/cx25821/cx25821-videoioctl.c +++ b/drivers/staging/cx25821/cx25821-videoioctl.c @@ -474,7 +474,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { struct video_device cx25821_videoioctl_template = { .name = "cx25821-videoioctl", .fops = &video_fops, - .minor = -1, .ioctl_ops = &video_ioctl_ops, .tvnorms = CX25821_NORMS, .current_norm = V4L2_STD_NTSC_M, diff --git a/drivers/staging/cx25821/cx25821-vidups10.c b/drivers/staging/cx25821/cx25821-vidups10.c index 97db6cd..b76d9f6 100644 --- a/drivers/staging/cx25821/cx25821-vidups10.c +++ b/drivers/staging/cx25821/cx25821-vidups10.c @@ -412,7 +412,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { struct video_device cx25821_video_template10 = { .name = "cx25821-upstream10", .fops = &video_fops, - .minor = -1, .ioctl_ops = &video_ioctl_ops, .tvnorms = CX25821_NORMS, .current_norm = V4L2_STD_NTSC_M, diff --git a/drivers/staging/cx25821/cx25821-vidups9.c b/drivers/staging/cx25821/cx25821-vidups9.c index d06054f..1580da3 100644 --- a/drivers/staging/cx25821/cx25821-vidups9.c +++ b/drivers/staging/cx25821/cx25821-vidups9.c @@ -410,7 +410,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { struct video_device cx25821_video_template9 = { .name = "cx25821-upstream9", .fops = &video_fops, - .minor = -1, .ioctl_ops = &video_ioctl_ops, .tvnorms = CX25821_NORMS, .current_norm = V4L2_STD_NTSC_M, diff --git a/drivers/staging/go7007/go7007-v4l2.c b/drivers/staging/go7007/go7007-v4l2.c index fe73975..3af7924 100644 --- a/drivers/staging/go7007/go7007-v4l2.c +++ b/drivers/staging/go7007/go7007-v4l2.c @@ -1787,7 +1787,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { static struct video_device go7007_template = { .name = "go7007", .fops = &go7007_fops, - .minor = -1, .release = go7007_vfl_release, .ioctl_ops = &video_ioctl_ops, .tvnorms = V4L2_STD_ALL, -- cgit v0.10.2 From 327ae59757f2e56fd3fc2b11acbd0a7c4070f4e8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 27 Nov 2009 13:57:55 -0300 Subject: V4L/DVB (13557): v4l: Remove unneeded video_device::minor usage in drivers The video_device::minor field is used where it shouldn't, either to - test for error conditions that can't happen anymore with the current v4l-dvb core, - store the value in a driver private field that isn't used anymore, - check the video device type where video_device::vfl_type should be used, or - create the name of a kernel thread that should get a stable name. Remove or fix those use cases. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index 3c11cff..7364b96 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -1,7 +1,5 @@ #include -#define BOARD_CAN_DO_VBI(dev) (dev->revision != 0 && dev->vv_data->vbi_minor != -1) - /****************************************************************************/ /* resource management functions, shamelessly stolen from saa7134 driver */ @@ -455,9 +453,6 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) configuration data) */ dev->ext_vv_data = ext_vv; - vv->video_minor = -1; - vv->vbi_minor = -1; - vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle); if( NULL == vv->d_clipping.cpu_addr ) { ERR(("out of memory. aborting.\n")); @@ -496,7 +491,6 @@ EXPORT_SYMBOL_GPL(saa7146_vv_release); int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, char *name, int type) { - struct saa7146_vv *vv = dev->vv_data; struct video_device *vfd; int err; int i; @@ -524,11 +518,6 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, return err; } - if (VFL_TYPE_GRABBER == type) - vv->video_minor = vfd->minor; - else - vv->vbi_minor = vfd->minor; - INFO(("%s: registered device %s [v4l2]\n", dev->name, video_device_node_name(vfd))); @@ -539,16 +528,8 @@ EXPORT_SYMBOL_GPL(saa7146_register_device); int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev) { - struct saa7146_vv *vv = dev->vv_data; - DEB_EE(("dev:%p\n",dev)); - if ((*vid)->vfl_type == VFL_TYPE_GRABBER) { - vv->video_minor = -1; - } else { - vv->vbi_minor = -1; - } - video_unregister_device(*vid); *vid = NULL; diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 730ffd9..1d357b7 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -460,12 +460,8 @@ static int vidioc_s_audio(struct file *file, void *priv, static int tea5764_open(struct file *file) { /* Currently we support only one device */ - int minor = video_devdata(file)->minor; struct tea5764_device *radio = video_drvdata(file); - if (radio->videodev->minor != minor) - return -ENODEV; - mutex_lock(&radio->mutex); /* Only exclusive access */ if (radio->users) { diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 410260a..3182a40 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -3206,7 +3206,6 @@ err: static int bttv_open(struct file *file) { - int minor = video_devdata(file)->minor; struct video_device *vdev = video_devdata(file); struct bttv *btv = video_drvdata(file); struct bttv_fh *fh; @@ -3214,17 +3213,17 @@ static int bttv_open(struct file *file) dprintk(KERN_DEBUG "bttv: open dev=%s\n", video_device_node_name(vdev)); - lock_kernel(); - if (btv->video_dev->minor == minor) { + if (vdev->vfl_type == VFL_TYPE_GRABBER) { type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } else if (btv->vbi_dev->minor == minor) { + } else if (vdev->vfl_type == VFL_TYPE_VBI) { type = V4L2_BUF_TYPE_VBI_CAPTURE; } else { WARN_ON(1); - unlock_kernel(); return -ENODEV; } + lock_kernel(); + dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n", btv->c.nr,v4l2_type_names[type]); @@ -3408,7 +3407,6 @@ static struct video_device bttv_video_template = { static int radio_open(struct file *file) { - int minor = video_devdata(file)->minor; struct video_device *vdev = video_devdata(file); struct bttv *btv = video_drvdata(file); struct bttv_fh *fh; @@ -3416,11 +3414,6 @@ static int radio_open(struct file *file) dprintk("bttv: open dev=%s\n", video_device_node_name(vdev)); lock_kernel(); - WARN_ON(btv->radio_dev && btv->radio_dev->minor != minor); - if (!btv->radio_dev || btv->radio_dev->minor != minor) { - unlock_kernel(); - return -ENODEV; - } dprintk("bttv%d: open called (radio)\n",btv->c.nr); diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index b1944a7..a3d8f46 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -1476,8 +1476,9 @@ static int sn9c20x_input_init(struct gspca_dev *gspca_dev) if (input_register_device(sd->input_dev)) return -EINVAL; - sd->input_task = kthread_run(input_kthread, gspca_dev, "sn9c20x/%d", - gspca_dev->vdev.minor); + sd->input_task = kthread_run(input_kthread, gspca_dev, "sn9c20x/%s-%s", + gspca_dev->dev->bus->bus_name, + gspca_dev->dev->devpath); if (IS_ERR(sd->input_task)) return -EINVAL; diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index 71e08be..7400eac 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c @@ -1450,12 +1450,11 @@ static int omap24xxcam_mmap(struct file *file, struct vm_area_struct *vma) static int omap24xxcam_open(struct file *file) { - int minor = video_devdata(file)->minor; struct omap24xxcam_device *cam = omap24xxcam.priv; struct omap24xxcam_fh *fh; struct v4l2_format format; - if (!cam || !cam->vfd || (cam->vfd->minor != minor)) + if (!cam || !cam->vfd) return -ENODEV; fh = kzalloc(sizeof(*fh), GFP_KERNEL); diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h index eed5fcc..4aeff96 100644 --- a/include/media/saa7146_vv.h +++ b/include/media/saa7146_vv.h @@ -108,8 +108,6 @@ struct saa7146_fh { struct saa7146_vv { - int vbi_minor; - /* vbi capture */ struct saa7146_dmaqueue vbi_q; /* vbi workaround interrupt queue */ @@ -117,8 +115,6 @@ struct saa7146_vv int vbi_fieldcount; struct saa7146_fh *vbi_streaming; - int video_minor; - int video_status; struct saa7146_fh *video_fh; -- cgit v0.10.2 From fe2b6032513099b82cd19ef8da5050f02a18d3ec Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 26 Nov 2009 14:28:48 -0300 Subject: V4L/DVB (13559): gspca - pac7302: Some webcams are upside-down by default. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index 74accee..b4049c0 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -90,6 +90,9 @@ struct sd { unsigned char autogain; __u8 hflip; __u8 vflip; + u8 flags; +#define FL_HFLIP 0x01 /* mirrored by default */ +#define FL_VFLIP 0x02 /* vertical flipped by default */ u8 sof_read; u8 autogain_ignore_frames; @@ -552,6 +555,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->autogain = AUTOGAIN_DEF; sd->hflip = HFLIP_DEF; sd->vflip = VFLIP_DEF; + sd->flags = id->driver_info; return 0; } @@ -708,10 +712,17 @@ static int sethvflip(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int ret; - __u8 data; + u8 data, hflip, vflip; + + hflip = sd->hflip; + if (sd->flags & FL_HFLIP) + hflip = !hflip; + vflip = sd->vflip; + if (sd->flags & FL_VFLIP) + vflip = !vflip; ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ - data = (sd->hflip ? 0x08 : 0x00) | (sd->vflip ? 0x04 : 0x00); + data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00); if (0 <= ret) ret = reg_w(gspca_dev, 0x21, data); /* load registers to sensor (Bit 0, auto clear) */ @@ -1222,8 +1233,8 @@ static __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x06f8, 0x3009)}, {USB_DEVICE(0x093a, 0x2620)}, {USB_DEVICE(0x093a, 0x2621)}, - {USB_DEVICE(0x093a, 0x2622)}, - {USB_DEVICE(0x093a, 0x2624)}, + {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP}, + {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP}, {USB_DEVICE(0x093a, 0x2626)}, {USB_DEVICE(0x093a, 0x2628)}, {USB_DEVICE(0x093a, 0x2629)}, -- cgit v0.10.2 From d50e257ee8d1a16ca91f9286120f222d34853c49 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 26 Nov 2009 15:36:40 -0300 Subject: V4L/DVB (13560): gspca - main: Cleanup source. Signed-off-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 9724e65..92ed4d9 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -304,7 +304,6 @@ void gspca_frame_add(struct gspca_dev *gspca_dev, j = gspca_dev->fr_queue[i]; gspca_dev->cur_frame = &gspca_dev->frame[j]; } - return; } EXPORT_SYMBOL(gspca_frame_add); @@ -321,7 +320,7 @@ static int gspca_is_compressed(__u32 format) return 0; } -static void *rvmalloc(unsigned long size) +static void *rvmalloc(long size) { void *mem; unsigned long adr; @@ -329,7 +328,7 @@ static void *rvmalloc(unsigned long size) mem = vmalloc_32(size); if (mem != NULL) { adr = (unsigned long) mem; - while ((long) size > 0) { + while (size > 0) { SetPageReserved(vmalloc_to_page((void *) adr)); adr += PAGE_SIZE; size -= PAGE_SIZE; @@ -1614,7 +1613,7 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) size -= PAGE_SIZE; } - vma->vm_ops = (struct vm_operations_struct *) &gspca_vm_ops; + vma->vm_ops = &gspca_vm_ops; vma->vm_private_data = frame; gspca_vm_open(vma); ret = 0; -- cgit v0.10.2 From 747c710098101fb2f2766171c5fc069289b56ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=83=C2=A1rton=20N=C3=83=C2=A9meth?= Date: Sun, 29 Nov 2009 08:25:20 -0300 Subject: V4L/DVB (13561): gspca - main: Remove unnecessary set to alternate 0. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calling gspca_set_alt0() in gspca_dev_probe() is not needed as gspca_set_alt0() will do nothing because gspca_dev->alt is always zero at that time. Signed-off-by: Márton Németh Signed-off-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 92ed4d9..0a99a21 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -2048,9 +2048,6 @@ int gspca_dev_probe(struct usb_interface *intf, ret = sd_desc->init(gspca_dev); if (ret < 0) goto out; - ret = gspca_set_alt0(gspca_dev); - if (ret < 0) - goto out; gspca_set_default_mode(gspca_dev); mutex_init(&gspca_dev->usb_lock); -- cgit v0.10.2 From 116dc5c50aff62064bfcceaa15abf44e9277578a Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 1 Dec 2009 07:20:34 -0300 Subject: V4L/DVB (13562): gspca - doc: Update webcam list. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 319d983..1800a62 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -12,6 +12,7 @@ m5602 0402:5602 ALi Video Camera Controller spca501 040a:0002 Kodak DVC-325 spca500 040a:0300 Kodak EZ200 zc3xx 041e:041e Creative WebCam Live! +ov519 041e:4003 Video Blaster WebCam Go Plus spca500 041e:400a Creative PC-CAM 300 sunplus 041e:400b Creative PC-CAM 600 sunplus 041e:4012 PC-Cam350 @@ -168,10 +169,14 @@ sunplus 055f:c650 Mustek MDC5500Z zc3xx 055f:d003 Mustek WCam300A zc3xx 055f:d004 Mustek WCam300 AN conex 0572:0041 Creative Notebook cx11646 +ov519 05a9:0511 Video Blaster WebCam 3/WebCam Plus, D-Link USB Digital Video Camera +ov519 05a9:0518 Creative WebCam ov519 05a9:0519 OV519 Microphone ov519 05a9:0530 OmniVision +ov519 05a9:2800 OmniVision SuperCAM ov519 05a9:4519 Webcam Classic ov519 05a9:8519 OmniVision +ov519 05a9:a511 D-Link USB Digital Video Camera ov519 05a9:a518 D-Link DSB-C310 Webcam sunplus 05da:1018 Digital Dream Enigma 1.3 stk014 05e1:0893 Syntek DV4000 @@ -187,7 +192,7 @@ ov534 06f8:3002 Hercules Blog Webcam ov534 06f8:3003 Hercules Dualpix HD Weblog sonixj 06f8:3004 Hercules Classic Silver sonixj 06f8:3008 Hercules Deluxe Optical Glass -pac7311 06f8:3009 Hercules Classic Link +pac7302 06f8:3009 Hercules Classic Link spca508 0733:0110 ViewQuest VQ110 spca501 0733:0401 Intel Create and Share spca501 0733:0402 ViewQuest M318B @@ -199,6 +204,7 @@ sunplus 0733:2221 Mercury Digital Pro 3.1p sunplus 0733:3261 Concord 3045 spca536a sunplus 0733:3281 Cyberpix S550V spca506 0734:043b 3DeMon USB Capture aka +ov519 0813:0002 Dual Mode USB Camera Plus spca500 084d:0003 D-Link DSC-350 spca500 08ca:0103 Aiptek PocketDV sunplus 08ca:0104 Aiptek PocketDVII 1.3 @@ -236,15 +242,15 @@ pac7311 093a:2603 Philips SPC 500 NC pac7311 093a:2608 Trust WB-3300p pac7311 093a:260e Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350 pac7311 093a:260f SnakeCam -pac7311 093a:2620 Apollo AC-905 -pac7311 093a:2621 PAC731x -pac7311 093a:2622 Genius Eye 312 -pac7311 093a:2624 PAC7302 -pac7311 093a:2626 Labtec 2200 -pac7311 093a:2628 Genius iLook 300 -pac7311 093a:2629 Genious iSlim 300 -pac7311 093a:262a Webcam 300k -pac7311 093a:262c Philips SPC 230 NC +pac7302 093a:2620 Apollo AC-905 +pac7302 093a:2621 PAC731x +pac7302 093a:2622 Genius Eye 312 +pac7302 093a:2624 PAC7302 +pac7302 093a:2626 Labtec 2200 +pac7302 093a:2628 Genius iLook 300 +pac7302 093a:2629 Genious iSlim 300 +pac7302 093a:262a Webcam 300k +pac7302 093a:262c Philips SPC 230 NC jeilinj 0979:0280 Sakar 57379 zc3xx 0ac8:0302 Z-star Vimicro zc0302 vc032x 0ac8:0321 Vimicro generic vc0321 @@ -259,6 +265,7 @@ vc032x 0ac8:c002 Sony embedded vimicro vc032x 0ac8:c301 Samsung Q1 Ultra Premium spca508 0af9:0010 Hama USB Sightcam 100 spca508 0af9:0011 Hama USB Sightcam 100 +ov519 0b62:0059 iBOT2 Webcam sonixb 0c45:6001 Genius VideoCAM NB sonixb 0c45:6005 Microdia Sweex Mini Webcam sonixb 0c45:6007 Sonix sn9c101 + Tas5110D @@ -318,8 +325,10 @@ sn9c20x 0c45:62b3 PC Camera (SN9C202 + OV9655) sn9c20x 0c45:62bb PC Camera (SN9C202 + OV7660) sn9c20x 0c45:62bc PC Camera (SN9C202 + HV7131R) sunplus 0d64:0303 Sunplus FashionCam DXG +ov519 0e96:c001 TRUST 380 USB2 SPACEC@M etoms 102c:6151 Qcam Sangha CIF etoms 102c:6251 Qcam xxxxxx VGA +ov519 1046:9967 W9967CF/W9968CF WebCam IC, Video Blaster WebCam Go zc3xx 10fd:0128 Typhoon Webshot II USB 300k 0x0128 spca561 10fd:7e50 FlyCam Usb 100 zc3xx 10fd:8050 Typhoon Webshot II USB 300k @@ -332,7 +341,12 @@ spca501 1776:501c Arowana 300K CMOS Camera 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 sq905c +sq905c 2770:905c DualCamera +sq905 2770:9120 Argus Digital Camera DC1512 +sq905c 2770:913d sq905c spca500 2899:012c Toptro Industrial +ov519 8020:ef04 ov519 spca508 8086:0110 Intel Easy PC Camera spca500 8086:0630 Intel Pocket PC Camera spca506 99fa:8988 Grandtec V.cap -- cgit v0.10.2 From 7bd330b44eb92b8e5ae265ab447cd317290c7aee Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 2 Dec 2009 06:06:03 -0300 Subject: V4L/DVB (13563): gspca - zc3xx: Bad sensor probe of the webcam 0ac8:305b. - probe the webcam (probe sequence from ms-win trace) - update tax5130c init sequences from ms-win newer driver - update tas5130c sequences from ms-win trace - add some comments in the probe code Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 69e5dc4..1d525c4 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -5345,9 +5345,6 @@ static const struct usb_action tas5130cxx_InitialScale[] = { /* 320x240 */ {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN}, - {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, @@ -5364,27 +5361,27 @@ static const struct usb_action tas5130cxx_InitialScale[] = { /* 320x240 */ {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x95, ZC3XX_R18D_YTARGET}, + {0xa0, 0x70, ZC3XX_R18D_YTARGET}, {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, {0xa0, 0x00, 0x01ad}, {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, + {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN}, + {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL}, {} }; static const struct usb_action tas5130cxx_Initial[] = { /* 640x480 */ {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, + {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT}, {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING}, {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN}, - {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL}, {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, @@ -5400,13 +5397,15 @@ static const struct usb_action tas5130cxx_Initial[] = { /* 640x480 */ {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x95, ZC3XX_R18D_YTARGET}, + {0xa0, 0x70, ZC3XX_R18D_YTARGET}, {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, {0xa0, 0x00, 0x01ad}, {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, + {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN}, + {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL}, {} }; static const struct usb_action tas5130cxx_50HZ[] = { @@ -6424,11 +6423,11 @@ static int vga_2wr_probe(struct gspca_dev *gspca_dev) if (retword != 0) return 0x0e; /* PAS202BCB */ - start_2wr_probe(dev, 0x02); /* ?? */ + start_2wr_probe(dev, 0x02); /* TAS5130C */ i2c_write(gspca_dev, 0x01, 0xaa, 0x00); retword = i2c_read(gspca_dev, 0x01); if (retword != 0) - return 0x02; /* ?? */ + return 0x02; /* TAS5130C */ ov_check: reg_r(gspca_dev, 0x0010); /* ?? */ reg_r(gspca_dev, 0x0010); @@ -6505,6 +6504,8 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) reg_r(gspca_dev, 0x0010); /* value 0x4001 is meaningless */ if (retword != 0x4001) { + if ((retword & 0xff00) == 0x6400) + return 0x02; /* TAS5130C */ for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) { if (chipset_revision_sensor[i].revision == retword) { sd->chip_revision = retword; @@ -6515,7 +6516,7 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) } } - reg_w(dev, 0x01, 0x0000); /* check ?? */ + reg_w(dev, 0x01, 0x0000); /* check PB0330 */ reg_w(dev, 0x01, 0x0001); reg_w(dev, 0xdd, 0x008b); reg_w(dev, 0x0a, 0x0010); @@ -6524,7 +6525,7 @@ 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 0a ?"); - return 0x0a; /* ?? */ + return 0x0a; /* PB0330 */ } reg_w(dev, 0x01, 0x0000); @@ -6673,6 +6674,10 @@ static int sd_config(struct gspca_dev *gspca_dev, PDEBUG(D_PROBE, "Find Sensor HV7131B"); sd->sensor = SENSOR_HV7131B; break; + case 0x02: + PDEBUG(D_PROBE, "Sensor TAS5130C"); + sd->sensor = SENSOR_TAS5130CXX; + break; case 0x04: PDEBUG(D_PROBE, "Find Sensor CS2102"); sd->sensor = SENSOR_CS2102; @@ -6866,11 +6871,14 @@ static int sd_start(struct gspca_dev *gspca_dev) case SENSOR_GC0305: case SENSOR_OV7620: case SENSOR_PO2030: + case SENSOR_TAS5130CXX: case SENSOR_TAS5130C_VF0250: /* msleep(100); * ?? */ reg_r(gspca_dev, 0x0002); /* --> 0x40 */ reg_w(dev, 0x09, 0x01ad); /* (from win traces) */ reg_w(dev, 0x15, 0x01ae); + if (sd->sensor == SENSOR_TAS5130CXX) + break; reg_w(dev, 0x0d, 0x003a); reg_w(dev, 0x02, 0x003b); reg_w(dev, 0x00, 0x0038); @@ -6887,6 +6895,7 @@ static int sd_start(struct gspca_dev *gspca_dev) break; case SENSOR_PAS202B: case SENSOR_GC0305: + case SENSOR_TAS5130CXX: reg_r(gspca_dev, 0x0008); /* fall thru */ case SENSOR_PO2030: @@ -6910,6 +6919,7 @@ static int sd_start(struct gspca_dev *gspca_dev) switch (sd->sensor) { case SENSOR_OV7620: case SENSOR_PAS202B: + case SENSOR_TAS5130CXX: reg_r(gspca_dev, 0x0180); /* from win */ reg_w(dev, 0x00, 0x0180); break; @@ -6928,6 +6938,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w(dev, 0x40, 0x0117); break; case SENSOR_GC0305: + case SENSOR_TAS5130CXX: reg_w(dev, 0x09, 0x01ad); /* (from win traces) */ reg_w(dev, 0x15, 0x01ae); /* fall thru */ @@ -7220,7 +7231,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0ac8, 0x0302), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x0ac8, 0x301b)}, {USB_DEVICE(0x0ac8, 0x303b)}, - {USB_DEVICE(0x0ac8, 0x305b), .driver_info = SENSOR_TAS5130C_VF0250}, + {USB_DEVICE(0x0ac8, 0x305b)}, {USB_DEVICE(0x0ac8, 0x307b)}, {USB_DEVICE(0x10fd, 0x0128)}, {USB_DEVICE(0x10fd, 0x804d)}, -- cgit v0.10.2 From 28ffe77fe2faea6658870818fd0593f1a03cc018 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Wed, 2 Dec 2009 06:18:46 -0300 Subject: V4L/DVB (13564): gspca - main: Implement vidioc_enum_frameintervals. Some drivers support multiple frameintervals (framerates), make gspca able to enumerate them. Signed-off-by: Antonio Ospite Signed-off-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 0a99a21..e6e8df4 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -982,6 +982,34 @@ static int vidioc_enum_framesizes(struct file *file, void *priv, return -EINVAL; } +static int vidioc_enum_frameintervals(struct file *filp, void *priv, + struct v4l2_frmivalenum *fival) +{ + struct gspca_dev *gspca_dev = priv; + int mode = wxh_to_mode(gspca_dev, fival->width, fival->height); + __u32 i; + + if (gspca_dev->cam.mode_framerates == NULL || + gspca_dev->cam.mode_framerates[mode].nrates == 0) + return -EINVAL; + + if (fival->pixel_format != + gspca_dev->cam.cam_mode[mode].pixelformat) + return -EINVAL; + + for (i = 0; i < gspca_dev->cam.mode_framerates[mode].nrates; i++) { + if (fival->index == i) { + fival->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fival->discrete.numerator = 1; + fival->discrete.denominator = + gspca_dev->cam.mode_framerates[mode].rates[i]; + return 0; + } + } + + return -EINVAL; +} + static void gspca_release(struct video_device *vfd) { struct gspca_dev *gspca_dev = container_of(vfd, struct gspca_dev, vdev); @@ -1973,6 +2001,7 @@ static const struct v4l2_ioctl_ops dev_ioctl_ops = { .vidioc_g_parm = vidioc_g_parm, .vidioc_s_parm = vidioc_s_parm, .vidioc_enum_framesizes = vidioc_enum_framesizes, + .vidioc_enum_frameintervals = vidioc_enum_frameintervals, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 1816173..a55c0a04 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -45,11 +45,20 @@ extern int gspca_debug; /* image transfers */ #define MAX_NURBS 4 /* max number of URBs */ + +/* used to list framerates supported by a camera mode (resolution) */ +struct framerates { + int *rates; + int nrates; +}; + /* device information - set at probe time */ struct cam { int bulk_size; /* buffer size when image transfer by bulk */ const struct v4l2_pix_format *cam_mode; /* size nmodes */ char nmodes; + const struct framerates *mode_framerates; /* must have size nmode, + * just like cam_mode */ __u8 bulk_nurbs; /* number of URBs in bulk mode * - cannot be > MAX_NURBS * - when 0 and bulk_size != 0 means -- cgit v0.10.2 From c4322bfca8907109689eb6b244258bf52277f7dc Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 2 Dec 2009 07:04:35 -0300 Subject: V4L/DVB (13565): gspca - pac7302: One more webcam is upside-down by default. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index b4049c0..e128514 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -1237,7 +1237,7 @@ static __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP}, {USB_DEVICE(0x093a, 0x2626)}, {USB_DEVICE(0x093a, 0x2628)}, - {USB_DEVICE(0x093a, 0x2629)}, + {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP}, {USB_DEVICE(0x093a, 0x262a)}, {USB_DEVICE(0x093a, 0x262c)}, {} -- cgit v0.10.2 From 8c4ebae45f8fa189746656a71d8a0ed21d569344 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 2 Dec 2009 07:14:33 -0300 Subject: V4L/DVB (13566): gspca - main: New variable usb_err for USB exchanges. Signed-off-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 e6e8df4..95a8b84 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -767,6 +767,7 @@ static int vidioc_g_register(struct file *file, 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_register(gspca_dev, reg); else @@ -790,6 +791,7 @@ static int vidioc_s_register(struct file *file, 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_register(gspca_dev, reg); else @@ -811,6 +813,7 @@ static int vidioc_g_chip_ident(struct file *file, 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_chip_ident(gspca_dev, chip); else @@ -1081,6 +1084,7 @@ static int dev_close(struct file *file) if (gspca_dev->capt_file == file) { if (gspca_dev->streaming) { mutex_lock(&gspca_dev->usb_lock); + gspca_dev->usb_err = 0; gspca_stream_off(gspca_dev); mutex_unlock(&gspca_dev->usb_lock); } @@ -1200,6 +1204,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value); if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; + gspca_dev->usb_err = 0; if (gspca_dev->present) ret = ctrls->set(gspca_dev, ctrl->value); else @@ -1221,6 +1226,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; + gspca_dev->usb_err = 0; if (gspca_dev->present) ret = ctrls->get(gspca_dev, &ctrl->value); else @@ -1335,6 +1341,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, /* stop streaming */ if (gspca_dev->streaming) { mutex_lock(&gspca_dev->usb_lock); + gspca_dev->usb_err = 0; gspca_stream_off(gspca_dev); mutex_unlock(&gspca_dev->usb_lock); } @@ -1426,6 +1433,7 @@ static int vidioc_streamoff(struct file *file, void *priv, ret = -ERESTARTSYS; goto out; } + gspca_dev->usb_err = 0; gspca_stream_off(gspca_dev); mutex_unlock(&gspca_dev->usb_lock); @@ -1451,6 +1459,7 @@ static int vidioc_g_jpegcomp(struct file *file, void *priv, return -EINVAL; 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_jcomp(gspca_dev, jpegcomp); else @@ -1469,6 +1478,7 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv, return -EINVAL; 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_jcomp(gspca_dev, jpegcomp); else @@ -1489,6 +1499,7 @@ 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); @@ -1518,6 +1529,7 @@ 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); @@ -1689,6 +1701,7 @@ static int frame_wait(struct gspca_dev *gspca_dev, if (gspca_dev->sd_desc->dq_callback) { mutex_lock(&gspca_dev->usb_lock); + gspca_dev->usb_err = 0; if (gspca_dev->present) gspca_dev->sd_desc->dq_callback(gspca_dev); mutex_unlock(&gspca_dev->usb_lock); diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index a55c0a04..59c7941d 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -180,6 +180,7 @@ struct gspca_dev { struct mutex usb_lock; /* usb exchange protection */ struct mutex read_lock; /* read protection */ struct mutex queue_lock; /* ISOC queue protection */ + int usb_err; /* USB error - protected by usb_lock */ #ifdef CONFIG_PM char frozen; /* suspend - resume */ #endif -- cgit v0.10.2 From ecb776868624751dd86e69c3e6704af35890f953 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 2 Dec 2009 14:39:53 -0300 Subject: V4L/DVB (13567): gspca - sunplus/stk014: Propagate errors to higher level. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 8e23320..2e29355 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c @@ -126,12 +126,14 @@ static const struct v4l2_pix_format vga_mode[] = { }; /* -- read a register -- */ -static int reg_r(struct gspca_dev *gspca_dev, +static u8 reg_r(struct gspca_dev *gspca_dev, __u16 index) { struct usb_device *dev = gspca_dev->dev; int ret; + if (gspca_dev->usb_err < 0) + return 0; ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x00, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, @@ -141,18 +143,21 @@ static int reg_r(struct gspca_dev *gspca_dev, 500); if (ret < 0) { PDEBUG(D_ERR, "reg_r err %d", ret); - return ret; + gspca_dev->usb_err = ret; + return 0; } return gspca_dev->usb_buf[0]; } /* -- write a register -- */ -static int reg_w(struct gspca_dev *gspca_dev, +static void reg_w(struct gspca_dev *gspca_dev, __u16 index, __u16 value) { struct usb_device *dev = gspca_dev->dev; int ret; + if (gspca_dev->usb_err < 0) + return; ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x01, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, @@ -161,13 +166,14 @@ static int reg_w(struct gspca_dev *gspca_dev, NULL, 0, 500); - if (ret < 0) + if (ret < 0) { PDEBUG(D_ERR, "reg_w err %d", ret); - return ret; + gspca_dev->usb_err = ret; + } } /* -- get a bulk value (4 bytes) -- */ -static int rcv_val(struct gspca_dev *gspca_dev, +static void rcv_val(struct gspca_dev *gspca_dev, int ads) { struct usb_device *dev = gspca_dev->dev; @@ -182,17 +188,22 @@ static int rcv_val(struct gspca_dev *gspca_dev, reg_w(gspca_dev, 0x63a, 0); reg_w(gspca_dev, 0x63b, 0); reg_w(gspca_dev, 0x630, 5); + if (gspca_dev->usb_err < 0) + return; ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, 0x05), gspca_dev->usb_buf, 4, /* length */ &alen, 500); /* timeout in milliseconds */ - return ret; + if (ret < 0) { + PDEBUG(D_ERR, "rcv_val err %d", ret); + gspca_dev->usb_err = ret; + } } /* -- send a bulk value -- */ -static int snd_val(struct gspca_dev *gspca_dev, +static void snd_val(struct gspca_dev *gspca_dev, int ads, unsigned int val) { @@ -201,16 +212,9 @@ static int snd_val(struct gspca_dev *gspca_dev, __u8 seq = 0; if (ads == 0x003f08) { - ret = reg_r(gspca_dev, 0x0704); - if (ret < 0) - goto ko; - ret = reg_r(gspca_dev, 0x0705); - if (ret < 0) - goto ko; - seq = ret; /* keep the sequence number */ - ret = reg_r(gspca_dev, 0x0650); - if (ret < 0) - goto ko; + reg_r(gspca_dev, 0x0704); + seq = reg_r(gspca_dev, 0x0705); + reg_r(gspca_dev, 0x0650); reg_w(gspca_dev, 0x654, seq); } else { reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff); @@ -223,6 +227,8 @@ static int snd_val(struct gspca_dev *gspca_dev, reg_w(gspca_dev, 0x65a, 0); reg_w(gspca_dev, 0x65b, 0); reg_w(gspca_dev, 0x650, 5); + if (gspca_dev->usb_err < 0) + return; gspca_dev->usb_buf[0] = val >> 24; gspca_dev->usb_buf[1] = val >> 16; gspca_dev->usb_buf[2] = val >> 8; @@ -233,24 +239,23 @@ static int snd_val(struct gspca_dev *gspca_dev, 4, &alen, 500); /* timeout in milliseconds */ - if (ret < 0) - goto ko; - if (ads == 0x003f08) { - seq += 4; - seq &= 0x3f; - reg_w(gspca_dev, 0x705, seq); + if (ret < 0) { + PDEBUG(D_ERR, "snd_val err %d", ret); + gspca_dev->usb_err = ret; + } else { + if (ads == 0x003f08) { + seq += 4; + seq &= 0x3f; + reg_w(gspca_dev, 0x705, seq); + } } - return ret; -ko: - PDEBUG(D_ERR, "snd_val err %d", ret); - return ret; } /* set a camera parameter */ -static int set_par(struct gspca_dev *gspca_dev, +static void set_par(struct gspca_dev *gspca_dev, int parval) { - return snd_val(gspca_dev, 0x003f08, parval); + snd_val(gspca_dev, 0x003f08, parval); } static void setbrightness(struct gspca_dev *gspca_dev) @@ -311,18 +316,18 @@ static int sd_config(struct gspca_dev *gspca_dev, /* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { - int ret; + u8 ret; /* check if the device responds */ usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); ret = reg_r(gspca_dev, 0x0740); - if (ret < 0) - return ret; - if (ret != 0xff) { - PDEBUG(D_ERR|D_STREAM, "init reg: 0x%02x", ret); - return -1; + if (gspca_dev->usb_err >= 0) { + if (ret != 0xff) { + PDEBUG(D_ERR|D_STREAM, "init reg: 0x%02x", ret); + gspca_dev->usb_err = -EIO; + } } - return 0; + return gspca_dev->usb_err; } /* -- start the camera -- */ @@ -357,15 +362,12 @@ static int sd_start(struct gspca_dev *gspca_dev) if (ret < 0) { PDEBUG(D_ERR|D_STREAM, "set intf %d %d failed", gspca_dev->iface, gspca_dev->alt); + gspca_dev->usb_err = ret; goto out; } - ret = reg_r(gspca_dev, 0x0630); - if (ret < 0) - goto out; + reg_r(gspca_dev, 0x0630); rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */ - ret = reg_r(gspca_dev, 0x0650); - if (ret < 0) - goto out; + reg_r(gspca_dev, 0x0650); snd_val(gspca_dev, 0x000020, 0xffffffff); reg_w(gspca_dev, 0x0620, 0); reg_w(gspca_dev, 0x0630, 0); @@ -384,11 +386,11 @@ static int sd_start(struct gspca_dev *gspca_dev) /* start the video flow */ set_par(gspca_dev, 0x01000000); set_par(gspca_dev, 0x01000000); - PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt); - return 0; + if (gspca_dev->usb_err >= 0) + PDEBUG(D_STREAM, "camera started alt: 0x%02x", + gspca_dev->alt); out: - PDEBUG(D_ERR|D_STREAM, "camera start err %d", ret); - return ret; + return gspca_dev->usb_err; } static void sd_stopN(struct gspca_dev *gspca_dev) @@ -456,7 +458,7 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) sd->brightness = val; if (gspca_dev->streaming) setbrightness(gspca_dev); - return 0; + return gspca_dev->usb_err; } static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) @@ -474,7 +476,7 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) sd->contrast = val; if (gspca_dev->streaming) setcontrast(gspca_dev); - return 0; + return gspca_dev->usb_err; } static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) @@ -492,7 +494,7 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) sd->colors = val; if (gspca_dev->streaming) setcolors(gspca_dev); - return 0; + return gspca_dev->usb_err; } static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) @@ -510,7 +512,7 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) sd->lightfreq = val; if (gspca_dev->streaming) setfreq(gspca_dev); - return 0; + return gspca_dev->usb_err; } static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) @@ -552,7 +554,7 @@ static int sd_set_jcomp(struct gspca_dev *gspca_dev, sd->quality = jcomp->quality; if (gspca_dev->streaming) jpeg_set_qual(sd->jpeg_hdr, sd->quality); - return 0; + return gspca_dev->usb_err; } static int sd_get_jcomp(struct gspca_dev *gspca_dev, diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index 72bf3b4..716df6b 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c @@ -460,13 +460,17 @@ static void reg_r(struct gspca_dev *gspca_dev, u16 index, u16 len) { + int ret; + #ifdef GSPCA_DEBUG if (len > USB_BUF_SZ) { err("reg_r: buffer overflow"); return; } #endif - usb_control_msg(gspca_dev->dev, + if (gspca_dev->usb_err < 0) + return; + ret = usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, @@ -474,6 +478,10 @@ static void reg_r(struct gspca_dev *gspca_dev, index, len ? gspca_dev->usb_buf : NULL, len, 500); + if (ret < 0) { + PDEBUG(D_ERR, "reg_r err %d", ret); + gspca_dev->usb_err = ret; + } } /* write one byte */ @@ -483,40 +491,55 @@ static void reg_w_1(struct gspca_dev *gspca_dev, u16 index, u16 byte) { + int ret; + + if (gspca_dev->usb_err < 0) + return; gspca_dev->usb_buf[0] = byte; - usb_control_msg(gspca_dev->dev, + ret = usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, gspca_dev->usb_buf, 1, 500); + if (ret < 0) { + PDEBUG(D_ERR, "reg_w_1 err %d", ret); + gspca_dev->usb_err = ret; + } } /* write req / index / value */ -static int reg_w_riv(struct usb_device *dev, +static void reg_w_riv(struct gspca_dev *gspca_dev, u8 req, u16 index, u16 value) { + struct usb_device *dev = gspca_dev->dev; int ret; + if (gspca_dev->usb_err < 0) + return; ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, NULL, 0, 500); - PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d", - req, index, value, ret); - if (ret < 0) - PDEBUG(D_ERR, "reg write: error %d", ret); - return ret; + if (ret < 0) { + PDEBUG(D_ERR, "reg_w_riv err %d", ret); + gspca_dev->usb_err = ret; + return; + } + PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x", + req, index, value); } /* read 1 byte */ -static int reg_r_1(struct gspca_dev *gspca_dev, +static u8 reg_r_1(struct gspca_dev *gspca_dev, u16 value) /* wValue */ { int ret; + if (gspca_dev->usb_err < 0) + return 0; ret = usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), 0x20, /* request */ @@ -527,19 +550,22 @@ static int reg_r_1(struct gspca_dev *gspca_dev, 500); /* timeout */ if (ret < 0) { PDEBUG(D_ERR, "reg_r_1 err %d", ret); + gspca_dev->usb_err = ret; return 0; } return gspca_dev->usb_buf[0]; } -/* read 1 or 2 bytes - returns < 0 if error */ -static int reg_r_12(struct gspca_dev *gspca_dev, +/* read 1 or 2 bytes */ +static u16 reg_r_12(struct gspca_dev *gspca_dev, u8 req, /* bRequest */ u16 index, /* wIndex */ u16 length) /* wLength (1 or 2 only) */ { int ret; + if (gspca_dev->usb_err < 0) + return 0; gspca_dev->usb_buf[1] = 0; ret = usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), @@ -550,62 +576,44 @@ static int reg_r_12(struct gspca_dev *gspca_dev, gspca_dev->usb_buf, length, 500); if (ret < 0) { - PDEBUG(D_ERR, "reg_read err %d", ret); - return -1; + PDEBUG(D_ERR, "reg_r_12 err %d", ret); + gspca_dev->usb_err = ret; + return 0; } return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0]; } -static int write_vector(struct gspca_dev *gspca_dev, +static void write_vector(struct gspca_dev *gspca_dev, const struct cmd *data, int ncmds) { - struct usb_device *dev = gspca_dev->dev; - int ret; - while (--ncmds >= 0) { - ret = reg_w_riv(dev, data->req, data->idx, data->val); - if (ret < 0) { - PDEBUG(D_ERR, - "Register write failed for 0x%02x, 0x%04x, 0x%04x", - data->req, data->val, data->idx); - return ret; - } + reg_w_riv(gspca_dev, data->req, data->idx, data->val); data++; } - return 0; } -static int spca50x_setup_qtable(struct gspca_dev *gspca_dev, - const u8 qtable[2][64]) +static void setup_qtable(struct gspca_dev *gspca_dev, + const u8 qtable[2][64]) { - struct usb_device *dev = gspca_dev->dev; - int i, err; + int i; /* loop over y components */ - for (i = 0; i < 64; i++) { - err = reg_w_riv(dev, 0x00, 0x2800 + i, qtable[0][i]); - if (err < 0) - return err; - } + for (i = 0; i < 64; i++) + reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]); /* loop over c components */ - for (i = 0; i < 64; i++) { - err = reg_w_riv(dev, 0x00, 0x2840 + i, qtable[1][i]); - if (err < 0) - return err; - } - return 0; + for (i = 0; i < 64; i++) + reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]); } static void spca504_acknowledged_command(struct gspca_dev *gspca_dev, u8 req, u16 idx, u16 val) { - struct usb_device *dev = gspca_dev->dev; - int notdone; + u16 notdone; - reg_w_riv(dev, req, idx, val); + reg_w_riv(gspca_dev, req, idx, val); notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1); - reg_w_riv(dev, req, idx, val); + reg_w_riv(gspca_dev, req, idx, val); PDEBUG(D_FRAM, "before wait 0x%04x", notdone); @@ -616,23 +624,22 @@ static void spca504_acknowledged_command(struct gspca_dev *gspca_dev, static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, u8 req, - u16 idx, u16 val, u8 stat, u8 count) + u16 idx, u16 val, u16 endcode, u8 count) { - struct usb_device *dev = gspca_dev->dev; - int status; - u8 endcode; + u16 status; - reg_w_riv(dev, req, idx, val); + reg_w_riv(gspca_dev, req, idx, val); status = reg_r_12(gspca_dev, 0x01, 0x0001, 1); - endcode = stat; - PDEBUG(D_FRAM, "Status 0x%x Need 0x%04x", status, stat); + if (gspca_dev->usb_err < 0) + return; + PDEBUG(D_FRAM, "Status 0x%04x Need 0x%04x", status, endcode); if (!count) return; count = 200; while (--count > 0) { msleep(10); /* gsmart mini2 write a each wait setting 1 ms is enough */ -/* reg_w_riv(dev, req, idx, val); */ +/* reg_w_riv(gspca_dev, req, idx, val); */ status = reg_r_12(gspca_dev, 0x01, 0x0001, 1); if (status == endcode) { PDEBUG(D_FRAM, "status 0x%04x after wait %d", @@ -642,7 +649,7 @@ static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, } } -static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev) +static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev) { int count = 10; @@ -652,7 +659,6 @@ static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev) break; msleep(10); } - return gspca_dev->usb_buf[0]; } static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev) @@ -686,28 +692,26 @@ static void spca50x_GetFirmware(struct gspca_dev *gspca_dev) static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; u8 Size; - int rc; Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; switch (sd->bridge) { case BRIDGE_SPCA533: - reg_w_riv(dev, 0x31, 0, 0); + reg_w_riv(gspca_dev, 0x31, 0, 0); spca504B_WaitCmdStatus(gspca_dev); - rc = spca504B_PollingDataReady(gspca_dev); + spca504B_PollingDataReady(gspca_dev); spca50x_GetFirmware(gspca_dev); reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */ reg_r(gspca_dev, 0x24, 8, 1); reg_w_1(gspca_dev, 0x25, 0, 4, Size); reg_r(gspca_dev, 0x25, 4, 1); /* size */ - rc = spca504B_PollingDataReady(gspca_dev); + spca504B_PollingDataReady(gspca_dev); /* Init the cam width height with some values get on init ? */ - reg_w_riv(dev, 0x31, 0, 0x04); + reg_w_riv(gspca_dev, 0x31, 0, 0x04); spca504B_WaitCmdStatus(gspca_dev); - rc = spca504B_PollingDataReady(gspca_dev); + spca504B_PollingDataReady(gspca_dev); break; default: /* case BRIDGE_SPCA504B: */ @@ -716,7 +720,7 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) reg_r(gspca_dev, 0x25, 4, 1); /* size */ reg_w_1(gspca_dev, 0x27, 0, 0, 6); reg_r(gspca_dev, 0x27, 0, 1); /* type */ - rc = spca504B_PollingDataReady(gspca_dev); + spca504B_PollingDataReady(gspca_dev); break; case BRIDGE_SPCA504: Size += 3; @@ -733,8 +737,8 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) break; case BRIDGE_SPCA504C: /* capture mode */ - reg_w_riv(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00); - reg_w_riv(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f)); + reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00); + reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f)); break; } } @@ -762,37 +766,33 @@ static void spca504B_setQtable(struct gspca_dev *gspca_dev) static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; u16 reg; reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7; - reg_w_riv(dev, 0x00, reg, sd->brightness); + reg_w_riv(gspca_dev, 0x00, reg, sd->brightness); } static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; u16 reg; reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8; - reg_w_riv(dev, 0x00, reg, sd->contrast); + reg_w_riv(gspca_dev, 0x00, reg, sd->contrast); } static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; u16 reg; reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae; - reg_w_riv(dev, 0x00, reg, sd->colors); + reg_w_riv(gspca_dev, 0x00, reg, sd->colors); } static void init_ctl_reg(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; int pollreg = 1; setbrightness(gspca_dev); @@ -807,14 +807,14 @@ static void init_ctl_reg(struct gspca_dev *gspca_dev) default: /* case BRIDGE_SPCA533: */ /* case BRIDGE_SPCA504B: */ - reg_w_riv(dev, 0, 0x00, 0x21ad); /* hue */ - reg_w_riv(dev, 0, 0x01, 0x21ac); /* sat/hue */ - reg_w_riv(dev, 0, 0x00, 0x21a3); /* gamma */ + reg_w_riv(gspca_dev, 0, 0x00, 0x21ad); /* hue */ + reg_w_riv(gspca_dev, 0, 0x01, 0x21ac); /* sat/hue */ + reg_w_riv(gspca_dev, 0, 0x00, 0x21a3); /* gamma */ break; case BRIDGE_SPCA536: - reg_w_riv(dev, 0, 0x40, 0x20f5); - reg_w_riv(dev, 0, 0x01, 0x20f4); - reg_w_riv(dev, 0, 0x00, 0x2089); + reg_w_riv(gspca_dev, 0, 0x40, 0x20f5); + reg_w_riv(gspca_dev, 0, 0x01, 0x20f4); + reg_w_riv(gspca_dev, 0, 0x00, 0x2089); break; } if (pollreg) @@ -881,18 +881,17 @@ static int sd_config(struct gspca_dev *gspca_dev, static int sd_init(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; - int i, err_code; + int i; u8 info[6]; switch (sd->bridge) { case BRIDGE_SPCA504B: - reg_w_riv(dev, 0x1d, 0x00, 0); - reg_w_riv(dev, 0, 0x01, 0x2306); - reg_w_riv(dev, 0, 0x00, 0x0d04); - reg_w_riv(dev, 0, 0x00, 0x2000); - reg_w_riv(dev, 0, 0x13, 0x2301); - reg_w_riv(dev, 0, 0x00, 0x2306); + reg_w_riv(gspca_dev, 0x1d, 0x00, 0); + reg_w_riv(gspca_dev, 0, 0x01, 0x2306); + reg_w_riv(gspca_dev, 0, 0x00, 0x0d04); + reg_w_riv(gspca_dev, 0, 0x00, 0x2000); + reg_w_riv(gspca_dev, 0, 0x13, 0x2301); + reg_w_riv(gspca_dev, 0, 0x00, 0x2306); /* fall thru */ case BRIDGE_SPCA533: spca504B_PollingDataReady(gspca_dev); @@ -904,13 +903,13 @@ static int sd_init(struct gspca_dev *gspca_dev) reg_w_1(gspca_dev, 0x24, 0, 0, 0); reg_r(gspca_dev, 0x24, 0, 1); spca504B_PollingDataReady(gspca_dev); - reg_w_riv(dev, 0x34, 0, 0); + reg_w_riv(gspca_dev, 0x34, 0, 0); spca504B_WaitCmdStatus(gspca_dev); break; case BRIDGE_SPCA504C: /* pccam600 */ PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)"); - reg_w_riv(dev, 0xe0, 0x0000, 0x0000); - reg_w_riv(dev, 0xe0, 0x0000, 0x0001); /* reset */ + reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000); + reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */ spca504_wait_status(gspca_dev); if (sd->subtype == LogitechClickSmart420) write_vector(gspca_dev, @@ -919,12 +918,7 @@ static int sd_init(struct gspca_dev *gspca_dev) else write_vector(gspca_dev, spca504_pccam600_open_data, ARRAY_SIZE(spca504_pccam600_open_data)); - err_code = spca50x_setup_qtable(gspca_dev, - qtable_creative_pccam); - if (err_code < 0) { - PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed"); - return err_code; - } + setup_qtable(gspca_dev, qtable_creative_pccam); break; default: /* case BRIDGE_SPCA504: */ @@ -958,29 +952,24 @@ static int sd_init(struct gspca_dev *gspca_dev) 6, 0, 0x86, 1); */ /* spca504A_acknowledged_command (gspca_dev, 0x24, 0, 0, 0x9D, 1); */ - reg_w_riv(dev, 0x00, 0x270c, 0x05); /* L92 sno1t.txt */ - reg_w_riv(dev, 0x00, 0x2310, 0x05); + reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05); + /* L92 sno1t.txt */ + reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05); spca504A_acknowledged_command(gspca_dev, 0x01, 0x0f, 0, 0xff, 0); } /* setup qtable */ - reg_w_riv(dev, 0, 0x2000, 0); - reg_w_riv(dev, 0, 0x2883, 1); - err_code = spca50x_setup_qtable(gspca_dev, - qtable_spca504_default); - if (err_code < 0) { - PDEBUG(D_ERR, "spca50x_setup_qtable failed"); - return err_code; - } + reg_w_riv(gspca_dev, 0, 0x2000, 0); + reg_w_riv(gspca_dev, 0, 0x2883, 1); + setup_qtable(gspca_dev, qtable_spca504_default); break; } - return 0; + return gspca_dev->usb_err; } static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; int enable; int i; u8 info[6]; @@ -1005,13 +994,13 @@ static int sd_start(struct gspca_dev *gspca_dev) case MegapixV4: case LogitechClickSmart820: case MegaImageVI: - reg_w_riv(dev, 0xf0, 0, 0); + reg_w_riv(gspca_dev, 0xf0, 0, 0); spca504B_WaitCmdStatus(gspca_dev); reg_r(gspca_dev, 0xf0, 4, 0); spca504B_WaitCmdStatus(gspca_dev); break; default: - reg_w_riv(dev, 0x31, 0, 0x04); + reg_w_riv(gspca_dev, 0x31, 0, 0x04); spca504B_WaitCmdStatus(gspca_dev); spca504B_PollingDataReady(gspca_dev); break; @@ -1048,8 +1037,9 @@ static int sd_start(struct gspca_dev *gspca_dev) spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); } spca504B_SetSizeType(gspca_dev); - reg_w_riv(dev, 0x00, 0x270c, 0x05); /* L92 sno1t.txt */ - reg_w_riv(dev, 0x00, 0x2310, 0x05); + reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05); + /* L92 sno1t.txt */ + reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05); break; case BRIDGE_SPCA504C: if (sd->subtype == LogitechClickSmart420) { @@ -1061,36 +1051,37 @@ static int sd_start(struct gspca_dev *gspca_dev) ARRAY_SIZE(spca504_pccam600_init_data)); } enable = (sd->autogain ? 0x04 : 0x01); - reg_w_riv(dev, 0x0c, 0x0000, enable); /* auto exposure */ - reg_w_riv(dev, 0xb0, 0x0000, enable); /* auto whiteness */ + reg_w_riv(gspca_dev, 0x0c, 0x0000, enable); + /* auto exposure */ + reg_w_riv(gspca_dev, 0xb0, 0x0000, enable); + /* auto whiteness */ /* set default exposure compensation and whiteness balance */ - reg_w_riv(dev, 0x30, 0x0001, 800); /* ~ 20 fps */ - reg_w_riv(dev, 0x30, 0x0002, 1600); + reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */ + reg_w_riv(gspca_dev, 0x30, 0x0002, 1600); spca504B_SetSizeType(gspca_dev); break; } init_ctl_reg(gspca_dev); - return 0; + return gspca_dev->usb_err; } static void sd_stopN(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; switch (sd->bridge) { default: /* case BRIDGE_SPCA533: */ /* case BRIDGE_SPCA536: */ /* case BRIDGE_SPCA504B: */ - reg_w_riv(dev, 0x31, 0, 0); + reg_w_riv(gspca_dev, 0x31, 0, 0); spca504B_WaitCmdStatus(gspca_dev); spca504B_PollingDataReady(gspca_dev); break; case BRIDGE_SPCA504: case BRIDGE_SPCA504C: - reg_w_riv(dev, 0x00, 0x2000, 0x0000); + reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000); if (sd->subtype == AiptekMiniPenCam13) { /* spca504a aiptek */ @@ -1102,7 +1093,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) 0x0f, 0x00, 0xff, 1); } else { spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); - reg_w_riv(dev, 0x01, 0x000f, 0x0000); + reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000); } break; } @@ -1216,7 +1207,7 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) sd->brightness = val; if (gspca_dev->streaming) setbrightness(gspca_dev); - return 0; + return gspca_dev->usb_err; } static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) @@ -1234,7 +1225,7 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) sd->contrast = val; if (gspca_dev->streaming) setcontrast(gspca_dev); - return 0; + return gspca_dev->usb_err; } static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) @@ -1252,7 +1243,7 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) sd->colors = val; if (gspca_dev->streaming) setcolors(gspca_dev); - return 0; + return gspca_dev->usb_err; } static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) @@ -1292,7 +1283,7 @@ static int sd_set_jcomp(struct gspca_dev *gspca_dev, sd->quality = jcomp->quality; if (gspca_dev->streaming) jpeg_set_qual(sd->jpeg_hdr, sd->quality); - return 0; + return gspca_dev->usb_err; } static int sd_get_jcomp(struct gspca_dev *gspca_dev, -- cgit v0.10.2 From 20d15a200d34cfb7141fb4558895d7d5233db84b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 30 Nov 2009 18:22:10 -0300 Subject: V4L/DVB (13569): smsusb: add autodetection support for five additional Hauppauge USB IDs Add support for five new Hauppauge Device USB IDs: 2040:b980 2040:b990 2040:c010 2040:c080 2040:c090 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c index 8f88a58..6b03dbf 100644 --- a/drivers/media/dvb/siano/smsusb.c +++ b/drivers/media/dvb/siano/smsusb.c @@ -533,8 +533,18 @@ struct usb_device_id smsusb_id_table[] = { .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, { USB_DEVICE(0x2040, 0xb910), .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0xb980), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0xb990), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, { USB_DEVICE(0x2040, 0xc000), .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0xc010), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0xc080), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0xc090), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, { } /* Terminating entry */ }; -- cgit v0.10.2 From b6456c0cfe9d94e6d2bf684e6e6c031fc0b10031 Mon Sep 17 00:00:00 2001 From: Muralidharan Karicheri Date: Thu, 19 Nov 2009 12:00:31 -0300 Subject: V4L/DVB (13571): v4l: Adding Digital Video Timings APIs This adds the above APIs to the v4l2 core. This is based on version v1.2 of the RFC titled "V4L - Support for video timings at the input/output interface" Following new ioctls are added:- - VIDIOC_ENUM_DV_PRESETS - VIDIOC_S_DV_PRESET - VIDIOC_G_DV_PRESET - VIDIOC_QUERY_DV_PRESET - VIDIOC_S_DV_TIMINGS - VIDIOC_G_DV_TIMINGS Please refer to the RFC for the details. This code was tested using vpfe capture driver on TI's DM365. Following is the test configuration used :- Blu-Ray HD DVD source -> TVP7002 -> DM365 (VPFE) ->DDR A draft version of the TVP7002 driver (currently being reviewed in the mailing list) was used that supports V4L2_DV_1080I60 & V4L2_DV_720P60 presets. A loopback video capture application was used for testing these APIs. This calls following IOCTLS :- - verify the new v4l2_input capabilities flag added - Enumerate available presets using VIDIOC_ENUM_DV_PRESETS - Set one of the supported preset using VIDIOC_S_DV_PRESET - Get current preset using VIDIOC_G_DV_PRESET - Detect current preset using VIDIOC_QUERY_DV_PRESET - Using stub functions in tvp7002, verify VIDIOC_S_DV_TIMINGS and VIDIOC_G_DV_TIMINGS ioctls are received at the sub device. - Tested on 64bit platform by Hans Verkuil Signed-off-by: Muralidharan Karicheri Signed-off-by: Hans Verkuil Reviewed-by: Randy Dunlap 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 997975d..c4150bd 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -1077,6 +1077,12 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) case VIDIOC_DBG_G_REGISTER: case VIDIOC_DBG_G_CHIP_IDENT: case VIDIOC_S_HW_FREQ_SEEK: + case VIDIOC_ENUM_DV_PRESETS: + case VIDIOC_S_DV_PRESET: + case VIDIOC_G_DV_PRESET: + case VIDIOC_QUERY_DV_PRESET: + case VIDIOC_S_DV_TIMINGS: + case VIDIOC_G_DV_TIMINGS: ret = do_video_ioctl(file, cmd, arg); break; diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 30cc3347..4b11257 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -284,6 +284,12 @@ static const char *v4l2_ioctls[] = { [_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT", [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK", #endif + [_IOC_NR(VIDIOC_ENUM_DV_PRESETS)] = "VIDIOC_ENUM_DV_PRESETS", + [_IOC_NR(VIDIOC_S_DV_PRESET)] = "VIDIOC_S_DV_PRESET", + [_IOC_NR(VIDIOC_G_DV_PRESET)] = "VIDIOC_G_DV_PRESET", + [_IOC_NR(VIDIOC_QUERY_DV_PRESET)] = "VIDIOC_QUERY_DV_PRESET", + [_IOC_NR(VIDIOC_S_DV_TIMINGS)] = "VIDIOC_S_DV_TIMINGS", + [_IOC_NR(VIDIOC_G_DV_TIMINGS)] = "VIDIOC_G_DV_TIMINGS", }; #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) @@ -1135,6 +1141,19 @@ static long __video_do_ioctl(struct file *file, { struct v4l2_input *p = arg; + /* + * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS & + * CAP_STD here based on ioctl handler provided by the + * driver. If the driver doesn't support these + * for a specific input, it must override these flags. + */ + if (ops->vidioc_s_std) + p->capabilities |= V4L2_IN_CAP_STD; + if (ops->vidioc_s_dv_preset) + p->capabilities |= V4L2_IN_CAP_PRESETS; + if (ops->vidioc_s_dv_timings) + p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS; + if (!ops->vidioc_enum_input) break; @@ -1179,6 +1198,19 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_enum_output) break; + /* + * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS & + * CAP_STD here based on ioctl handler provided by the + * driver. If the driver doesn't support these + * for a specific output, it must override these flags. + */ + if (ops->vidioc_s_std) + p->capabilities |= V4L2_OUT_CAP_STD; + if (ops->vidioc_s_dv_preset) + p->capabilities |= V4L2_OUT_CAP_PRESETS; + if (ops->vidioc_s_dv_timings) + p->capabilities |= V4L2_OUT_CAP_CUSTOM_TIMINGS; + ret = ops->vidioc_enum_output(file, fh, p); if (!ret) dbgarg(cmd, "index=%d, name=%s, type=%d, " @@ -1794,6 +1826,121 @@ static long __video_do_ioctl(struct file *file, } break; } + case VIDIOC_ENUM_DV_PRESETS: + { + struct v4l2_dv_enum_preset *p = arg; + + if (!ops->vidioc_enum_dv_presets) + break; + + ret = ops->vidioc_enum_dv_presets(file, fh, p); + if (!ret) + dbgarg(cmd, + "index=%d, preset=%d, name=%s, width=%d," + " height=%d ", + p->index, p->preset, p->name, p->width, + p->height); + break; + } + case VIDIOC_S_DV_PRESET: + { + struct v4l2_dv_preset *p = arg; + + if (!ops->vidioc_s_dv_preset) + break; + + dbgarg(cmd, "preset=%d\n", p->preset); + ret = ops->vidioc_s_dv_preset(file, fh, p); + break; + } + case VIDIOC_G_DV_PRESET: + { + struct v4l2_dv_preset *p = arg; + + if (!ops->vidioc_g_dv_preset) + break; + + ret = ops->vidioc_g_dv_preset(file, fh, p); + if (!ret) + dbgarg(cmd, "preset=%d\n", p->preset); + break; + } + case VIDIOC_QUERY_DV_PRESET: + { + struct v4l2_dv_preset *p = arg; + + if (!ops->vidioc_query_dv_preset) + break; + + ret = ops->vidioc_query_dv_preset(file, fh, p); + if (!ret) + dbgarg(cmd, "preset=%d\n", p->preset); + break; + } + case VIDIOC_S_DV_TIMINGS: + { + struct v4l2_dv_timings *p = arg; + + if (!ops->vidioc_s_dv_timings) + break; + + switch (p->type) { + case V4L2_DV_BT_656_1120: + dbgarg2("bt-656/1120:interlaced=%d, pixelclock=%lld," + " width=%d, height=%d, polarities=%x," + " hfrontporch=%d, hsync=%d, hbackporch=%d," + " vfrontporch=%d, vsync=%d, vbackporch=%d," + " il_vfrontporch=%d, il_vsync=%d," + " il_vbackporch=%d\n", + p->bt.interlaced, p->bt.pixelclock, + p->bt.width, p->bt.height, p->bt.polarities, + p->bt.hfrontporch, p->bt.hsync, + p->bt.hbackporch, p->bt.vfrontporch, + p->bt.vsync, p->bt.vbackporch, + p->bt.il_vfrontporch, p->bt.il_vsync, + p->bt.il_vbackporch); + ret = ops->vidioc_s_dv_timings(file, fh, p); + break; + default: + dbgarg2("Unknown type %d!\n", p->type); + break; + } + break; + } + case VIDIOC_G_DV_TIMINGS: + { + struct v4l2_dv_timings *p = arg; + + if (!ops->vidioc_g_dv_timings) + break; + + ret = ops->vidioc_g_dv_timings(file, fh, p); + if (!ret) { + switch (p->type) { + case V4L2_DV_BT_656_1120: + dbgarg2("bt-656/1120:interlaced=%d," + " pixelclock=%lld," + " width=%d, height=%d, polarities=%x," + " hfrontporch=%d, hsync=%d," + " hbackporch=%d, vfrontporch=%d," + " vsync=%d, vbackporch=%d," + " il_vfrontporch=%d, il_vsync=%d," + " il_vbackporch=%d\n", + p->bt.interlaced, p->bt.pixelclock, + p->bt.width, p->bt.height, + p->bt.polarities, p->bt.hfrontporch, + p->bt.hsync, p->bt.hbackporch, + p->bt.vfrontporch, p->bt.vsync, + p->bt.vbackporch, p->bt.il_vfrontporch, + p->bt.il_vsync, p->bt.il_vbackporch); + break; + default: + dbgarg2("Unknown type %d!\n", p->type); + break; + } + } + break; + } default: { diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 32b9229..59047eb 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -732,6 +732,99 @@ struct v4l2_standard { }; /* + * V I D E O T I M I N G S D V P R E S E T + */ +struct v4l2_dv_preset { + __u32 preset; + __u32 reserved[4]; +}; + +/* + * D V P R E S E T S E N U M E R A T I O N + */ +struct v4l2_dv_enum_preset { + __u32 index; + __u32 preset; + __u8 name[32]; /* Name of the preset timing */ + __u32 width; + __u32 height; + __u32 reserved[4]; +}; + +/* + * D V P R E S E T V A L U E S + */ +#define V4L2_DV_INVALID 0 +#define V4L2_DV_480P59_94 1 /* BT.1362 */ +#define V4L2_DV_576P50 2 /* BT.1362 */ +#define V4L2_DV_720P24 3 /* SMPTE 296M */ +#define V4L2_DV_720P25 4 /* SMPTE 296M */ +#define V4L2_DV_720P30 5 /* SMPTE 296M */ +#define V4L2_DV_720P50 6 /* SMPTE 296M */ +#define V4L2_DV_720P59_94 7 /* SMPTE 274M */ +#define V4L2_DV_720P60 8 /* SMPTE 274M/296M */ +#define V4L2_DV_1080I29_97 9 /* BT.1120/ SMPTE 274M */ +#define V4L2_DV_1080I30 10 /* BT.1120/ SMPTE 274M */ +#define V4L2_DV_1080I25 11 /* BT.1120 */ +#define V4L2_DV_1080I50 12 /* SMPTE 296M */ +#define V4L2_DV_1080I60 13 /* SMPTE 296M */ +#define V4L2_DV_1080P24 14 /* SMPTE 296M */ +#define V4L2_DV_1080P25 15 /* SMPTE 296M */ +#define V4L2_DV_1080P30 16 /* SMPTE 296M */ +#define V4L2_DV_1080P50 17 /* BT.1120 */ +#define V4L2_DV_1080P60 18 /* BT.1120 */ + +/* + * D V B T T I M I N G S + */ + +/* BT.656/BT.1120 timing data */ +struct v4l2_bt_timings { + __u32 width; /* width in pixels */ + __u32 height; /* height in lines */ + __u32 interlaced; /* Interlaced or progressive */ + __u32 polarities; /* Positive or negative polarity */ + __u64 pixelclock; /* Pixel clock in HZ. Ex. 74.25MHz->74250000 */ + __u32 hfrontporch; /* Horizpontal front porch in pixels */ + __u32 hsync; /* Horizontal Sync length in pixels */ + __u32 hbackporch; /* Horizontal back porch in pixels */ + __u32 vfrontporch; /* Vertical front porch in pixels */ + __u32 vsync; /* Vertical Sync length in lines */ + __u32 vbackporch; /* Vertical back porch in lines */ + __u32 il_vfrontporch; /* Vertical front porch for bottom field of + * interlaced field formats + */ + __u32 il_vsync; /* Vertical sync length for bottom field of + * interlaced field formats + */ + __u32 il_vbackporch; /* Vertical back porch for bottom field of + * interlaced field formats + */ + __u32 reserved[16]; +} __attribute__ ((packed)); + +/* Interlaced or progressive format */ +#define V4L2_DV_PROGRESSIVE 0 +#define V4L2_DV_INTERLACED 1 + +/* Polarities. If bit is not set, it is assumed to be negative polarity */ +#define V4L2_DV_VSYNC_POS_POL 0x00000001 +#define V4L2_DV_HSYNC_POS_POL 0x00000002 + + +/* DV timings */ +struct v4l2_dv_timings { + __u32 type; + union { + struct v4l2_bt_timings bt; + __u32 reserved[32]; + }; +} __attribute__ ((packed)); + +/* Values for the type field */ +#define V4L2_DV_BT_656_1120 0 /* BT.656/1120 timing type */ + +/* * V I D E O I N P U T S */ struct v4l2_input { @@ -742,7 +835,8 @@ struct v4l2_input { __u32 tuner; /* Associated tuner */ v4l2_std_id std; __u32 status; - __u32 reserved[4]; + __u32 capabilities; + __u32 reserved[3]; }; /* Values for the 'type' field */ @@ -773,6 +867,11 @@ struct v4l2_input { #define V4L2_IN_ST_NO_ACCESS 0x02000000 /* Conditional access denied */ #define V4L2_IN_ST_VTR 0x04000000 /* VTR time constant */ +/* capabilities flags */ +#define V4L2_IN_CAP_PRESETS 0x00000001 /* Supports S_DV_PRESET */ +#define V4L2_IN_CAP_CUSTOM_TIMINGS 0x00000002 /* Supports S_DV_TIMINGS */ +#define V4L2_IN_CAP_STD 0x00000004 /* Supports S_STD */ + /* * V I D E O O U T P U T S */ @@ -783,13 +882,19 @@ struct v4l2_output { __u32 audioset; /* Associated audios (bitfield) */ __u32 modulator; /* Associated modulator */ v4l2_std_id std; - __u32 reserved[4]; + __u32 capabilities; + __u32 reserved[3]; }; /* Values for the 'type' field */ #define V4L2_OUTPUT_TYPE_MODULATOR 1 #define V4L2_OUTPUT_TYPE_ANALOG 2 #define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY 3 +/* capabilities flags */ +#define V4L2_OUT_CAP_PRESETS 0x00000001 /* Supports S_DV_PRESET */ +#define V4L2_OUT_CAP_CUSTOM_TIMINGS 0x00000002 /* Supports S_DV_TIMINGS */ +#define V4L2_OUT_CAP_STD 0x00000004 /* Supports S_STD */ + /* * C O N T R O L S */ @@ -1624,6 +1729,13 @@ struct v4l2_dbg_chip_ident { #endif #define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek) +#define VIDIOC_ENUM_DV_PRESETS _IOWR('V', 83, struct v4l2_dv_enum_preset) +#define VIDIOC_S_DV_PRESET _IOWR('V', 84, struct v4l2_dv_preset) +#define VIDIOC_G_DV_PRESET _IOWR('V', 85, struct v4l2_dv_preset) +#define VIDIOC_QUERY_DV_PRESET _IOR('V', 86, struct v4l2_dv_preset) +#define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings) +#define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings) + /* Reminder: when adding new ioctls please add support for them to drivers/media/video/v4l2-compat-ioctl32.c as well! */ diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 7a4529d..e8ba0f2 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -239,6 +239,21 @@ struct v4l2_ioctl_ops { int (*vidioc_enum_frameintervals) (struct file *file, void *fh, struct v4l2_frmivalenum *fival); + /* DV Timings IOCTLs */ + int (*vidioc_enum_dv_presets) (struct file *file, void *fh, + struct v4l2_dv_enum_preset *preset); + + int (*vidioc_s_dv_preset) (struct file *file, void *fh, + struct v4l2_dv_preset *preset); + int (*vidioc_g_dv_preset) (struct file *file, void *fh, + struct v4l2_dv_preset *preset); + int (*vidioc_query_dv_preset) (struct file *file, void *fh, + struct v4l2_dv_preset *qpreset); + int (*vidioc_s_dv_timings) (struct file *file, void *fh, + struct v4l2_dv_timings *timings); + int (*vidioc_g_dv_timings) (struct file *file, void *fh, + struct v4l2_dv_timings *timings); + /* For other private ioctls */ long (*vidioc_default) (struct file *file, void *fh, int cmd, void *arg); diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 00bf176..7a3408f 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -217,6 +217,19 @@ struct v4l2_subdev_audio_ops { s_routing: see s_routing in audio_ops, except this version is for video devices. + + s_dv_preset: set dv (Digital Video) preset in the sub device. Similar to + s_std() + + query_dv_preset: query dv preset in the sub device. This is similar to + querystd() + + s_dv_timings(): Set custom dv timings in the sub device. This is used + when sub device is capable of setting detailed timing information + in the hardware to generate/detect the video signal. + + g_dv_timings(): Get custom dv timings in the sub device. + */ struct v4l2_subdev_video_ops { int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config); @@ -240,6 +253,14 @@ struct v4l2_subdev_video_ops { int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param); int (*enum_framesizes)(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize); int (*enum_frameintervals)(struct v4l2_subdev *sd, struct v4l2_frmivalenum *fival); + int (*s_dv_preset)(struct v4l2_subdev *sd, + struct v4l2_dv_preset *preset); + int (*query_dv_preset)(struct v4l2_subdev *sd, + struct v4l2_dv_preset *preset); + int (*s_dv_timings)(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings); + int (*g_dv_timings)(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings); }; /* -- cgit v0.10.2 From 007701e2c4de94109864c8e85e39b6d8fc474170 Mon Sep 17 00:00:00 2001 From: Muralidharan Karicheri Date: Thu, 3 Dec 2009 01:13:17 -0300 Subject: V4L/DVB (13572): v4l2-spec: Digital Video Timings API documentation This patch updates the v4l2-dvb documentation for the new video timings API added. Also updated the document based on comments from Hans Verkuil. Signed-off-by: Muralidharan Karicheri Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl index bb5ab74..c725cb8 100644 --- a/Documentation/DocBook/media-entities.tmpl +++ b/Documentation/DocBook/media-entities.tmpl @@ -23,6 +23,7 @@ VIDIOC_ENUMINPUT"> VIDIOC_ENUMOUTPUT"> VIDIOC_ENUMSTD"> +VIDIOC_ENUM_DV_PRESETS"> VIDIOC_ENUM_FMT"> VIDIOC_ENUM_FRAMEINTERVALS"> VIDIOC_ENUM_FRAMESIZES"> @@ -30,6 +31,8 @@ VIDIOC_G_AUDOUT"> VIDIOC_G_CROP"> VIDIOC_G_CTRL"> +VIDIOC_G_DV_PRESET"> +VIDIOC_G_DV_TIMINGS"> VIDIOC_G_ENC_INDEX"> VIDIOC_G_EXT_CTRLS"> VIDIOC_G_FBUF"> @@ -53,6 +56,7 @@ VIDIOC_QUERYCTRL"> VIDIOC_QUERYMENU"> VIDIOC_QUERYSTD"> +VIDIOC_QUERY_DV_PRESET"> VIDIOC_REQBUFS"> VIDIOC_STREAMOFF"> VIDIOC_STREAMON"> @@ -60,6 +64,8 @@ VIDIOC_S_AUDOUT"> VIDIOC_S_CROP"> VIDIOC_S_CTRL"> +VIDIOC_S_DV_PRESET"> +VIDIOC_S_DV_TIMINGS"> VIDIOC_S_EXT_CTRLS"> VIDIOC_S_FBUF"> VIDIOC_S_FMT"> @@ -118,6 +124,7 @@ v4l2_audio"> v4l2_audioout"> +v4l2_bt_timings"> v4l2_buffer"> v4l2_capability"> v4l2_captureparm"> @@ -128,6 +135,9 @@ v4l2_dbg_chip_ident"> v4l2_dbg_match"> v4l2_dbg_register"> +v4l2_dv_enum_preset"> +v4l2_dv_preset"> +v4l2_dv_timings"> v4l2_enc_idx"> v4l2_enc_idx_entry"> v4l2_encoder_cmd"> @@ -243,6 +253,10 @@ + + + + @@ -333,6 +347,10 @@ + + + + diff --git a/Documentation/DocBook/media-indices.tmpl b/Documentation/DocBook/media-indices.tmpl index 9e30a23..78d6031 100644 --- a/Documentation/DocBook/media-indices.tmpl +++ b/Documentation/DocBook/media-indices.tmpl @@ -36,6 +36,7 @@ enum v4l2_preemphasis struct v4l2_audio struct v4l2_audioout +struct v4l2_bt_timings struct v4l2_buffer struct v4l2_capability struct v4l2_captureparm @@ -46,6 +47,9 @@ struct v4l2_dbg_chip_ident struct v4l2_dbg_match struct v4l2_dbg_register +struct v4l2_dv_enum_preset +struct v4l2_dv_preset +struct v4l2_dv_timings struct v4l2_enc_idx struct v4l2_enc_idx_entry struct v4l2_encoder_cmd diff --git a/Documentation/DocBook/v4l/common.xml b/Documentation/DocBook/v4l/common.xml index b1a81d2..c65f0ac 100644 --- a/Documentation/DocBook/v4l/common.xml +++ b/Documentation/DocBook/v4l/common.xml @@ -716,6 +716,41 @@ if (-1 == ioctl (fd, &VIDIOC-S-STD;, &std_id)) { } +
+ Digital Video (DV) Timings + + The video standards discussed so far has been dealing with Analog TV and the +corresponding video timings. Today there are many more different hardware interfaces +such as High Definition TV interfaces (HDMI), VGA, DVI connectors etc., that carry +video signals and there is a need to extend the API to select the video timings +for these interfaces. Since it is not possible to extend the &v4l2-std-id; due to +the limited bits available, a new set of IOCTLs is added to set/get video timings at +the input and output: + + DV Presets: Digital Video (DV) presets. These are IDs representing a +video timing at the input/output. Presets are pre-defined timings implemented +by the hardware according to video standards. A __u32 data type is used to represent +a preset unlike the bit mask that is used in &v4l2-std-id; allowing future extensions +to support as many different presets as needed. + + + Custom DV Timings: This will allow applications to define more detailed +custom video timings for the interface. This includes parameters such as width, height, +polarities, frontporch, backporch etc. + + + + To enumerate and query the attributes of DV presets supported by a device, +applications use the &VIDIOC-ENUM-DV-PRESETS; ioctl. To get the current DV preset, +applications use the &VIDIOC-G-DV-PRESET; ioctl and to set a preset they use the +&VIDIOC-S-DV-PRESET; ioctl. + To set custom DV timings for the device, applications use the +&VIDIOC-S-DV-TIMINGS; ioctl and to get current custom DV timings they use the +&VIDIOC-G-DV-TIMINGS; ioctl. + Applications can make use of the and + flags to decide what ioctls are available to set the +video timings for the device. +
&sub-controls; diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml index 937b415..77b7dd8 100644 --- a/Documentation/DocBook/v4l/v4l2.xml +++ b/Documentation/DocBook/v4l/v4l2.xml @@ -411,6 +411,7 @@ and discussions on the V4L mailing list. &sub-encoder-cmd; &sub-enumaudio; &sub-enumaudioout; + &sub-enum-dv-presets; &sub-enum-fmt; &sub-enum-framesizes; &sub-enum-frameintervals; @@ -421,6 +422,8 @@ and discussions on the V4L mailing list. &sub-g-audioout; &sub-g-crop; &sub-g-ctrl; + &sub-g-dv-preset; + &sub-g-dv-timings; &sub-g-enc-index; &sub-g-ext-ctrls; &sub-g-fbuf; @@ -441,6 +444,7 @@ and discussions on the V4L mailing list. &sub-querybuf; &sub-querycap; &sub-queryctrl; + &sub-query-dv-preset; &sub-querystd; &sub-reqbufs; &sub-s-hw-freq-seek; diff --git a/Documentation/DocBook/v4l/videodev2.h.xml b/Documentation/DocBook/v4l/videodev2.h.xml index 3e282ed..0683259 100644 --- a/Documentation/DocBook/v4l/videodev2.h.xml +++ b/Documentation/DocBook/v4l/videodev2.h.xml @@ -734,6 +734,99 @@ struct v4l2_standard { }; /* + * V I D E O T I M I N G S D V P R E S E T + */ +struct v4l2_dv_preset { + __u32 preset; + __u32 reserved[4]; +}; + +/* + * D V P R E S E T S E N U M E R A T I O N + */ +struct v4l2_dv_enum_preset { + __u32 index; + __u32 preset; + __u8 name[32]; /* Name of the preset timing */ + __u32 width; + __u32 height; + __u32 reserved[4]; +}; + +/* + * D V P R E S E T V A L U E S + */ +#define V4L2_DV_INVALID 0 +#define V4L2_DV_480P59_94 1 /* BT.1362 */ +#define V4L2_DV_576P50 2 /* BT.1362 */ +#define V4L2_DV_720P24 3 /* SMPTE 296M */ +#define V4L2_DV_720P25 4 /* SMPTE 296M */ +#define V4L2_DV_720P30 5 /* SMPTE 296M */ +#define V4L2_DV_720P50 6 /* SMPTE 296M */ +#define V4L2_DV_720P59_94 7 /* SMPTE 274M */ +#define V4L2_DV_720P60 8 /* SMPTE 274M/296M */ +#define V4L2_DV_1080I29_97 9 /* BT.1120/ SMPTE 274M */ +#define V4L2_DV_1080I30 10 /* BT.1120/ SMPTE 274M */ +#define V4L2_DV_1080I25 11 /* BT.1120 */ +#define V4L2_DV_1080I50 12 /* SMPTE 296M */ +#define V4L2_DV_1080I60 13 /* SMPTE 296M */ +#define V4L2_DV_1080P24 14 /* SMPTE 296M */ +#define V4L2_DV_1080P25 15 /* SMPTE 296M */ +#define V4L2_DV_1080P30 16 /* SMPTE 296M */ +#define V4L2_DV_1080P50 17 /* BT.1120 */ +#define V4L2_DV_1080P60 18 /* BT.1120 */ + +/* + * D V B T T I M I N G S + */ + +/* BT.656/BT.1120 timing data */ +struct v4l2_bt_timings { + __u32 width; /* width in pixels */ + __u32 height; /* height in lines */ + __u32 interlaced; /* Interlaced or progressive */ + __u32 polarities; /* Positive or negative polarity */ + __u64 pixelclock; /* Pixel clock in HZ. Ex. 74.25MHz->74250000 */ + __u32 hfrontporch; /* Horizpontal front porch in pixels */ + __u32 hsync; /* Horizontal Sync length in pixels */ + __u32 hbackporch; /* Horizontal back porch in pixels */ + __u32 vfrontporch; /* Vertical front porch in pixels */ + __u32 vsync; /* Vertical Sync length in lines */ + __u32 vbackporch; /* Vertical back porch in lines */ + __u32 il_vfrontporch; /* Vertical front porch for bottom field of + * interlaced field formats + */ + __u32 il_vsync; /* Vertical sync length for bottom field of + * interlaced field formats + */ + __u32 il_vbackporch; /* Vertical back porch for bottom field of + * interlaced field formats + */ + __u32 reserved[16]; +} __attribute__ ((packed)); + +/* Interlaced or progressive format */ +#define V4L2_DV_PROGRESSIVE 0 +#define V4L2_DV_INTERLACED 1 + +/* Polarities. If bit is not set, it is assumed to be negative polarity */ +#define V4L2_DV_VSYNC_POS_POL 0x00000001 +#define V4L2_DV_HSYNC_POS_POL 0x00000002 + + +/* DV timings */ +struct v4l2_dv_timings { + __u32 type; + union { + struct v4l2_bt_timings bt; + __u32 reserved[32]; + }; +} __attribute__ ((packed)); + +/* Values for the type field */ +#define V4L2_DV_BT_656_1120 0 /* BT.656/1120 timing type */ + +/* * V I D E O I N P U T S */ struct v4l2_input { @@ -744,7 +837,8 @@ struct v4l2_input { __u32 tuner; /* Associated tuner */ v4l2_std_id std; __u32 status; - __u32 reserved[4]; + __u32 capabilities; + __u32 reserved[3]; }; /* Values for the 'type' field */ @@ -775,6 +869,11 @@ struct v4l2_input { #define V4L2_IN_ST_NO_ACCESS 0x02000000 /* Conditional access denied */ #define V4L2_IN_ST_VTR 0x04000000 /* VTR time constant */ +/* capabilities flags */ +#define V4L2_IN_CAP_PRESETS 0x00000001 /* Supports S_DV_PRESET */ +#define V4L2_IN_CAP_CUSTOM_TIMINGS 0x00000002 /* Supports S_DV_TIMINGS */ +#define V4L2_IN_CAP_STD 0x00000004 /* Supports S_STD */ + /* * V I D E O O U T P U T S */ @@ -785,13 +884,19 @@ struct v4l2_output { __u32 audioset; /* Associated audios (bitfield) */ __u32 modulator; /* Associated modulator */ v4l2_std_id std; - __u32 reserved[4]; + __u32 capabilities; + __u32 reserved[3]; }; /* Values for the 'type' field */ #define V4L2_OUTPUT_TYPE_MODULATOR 1 #define V4L2_OUTPUT_TYPE_ANALOG 2 #define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY 3 +/* capabilities flags */ +#define V4L2_OUT_CAP_PRESETS 0x00000001 /* Supports S_DV_PRESET */ +#define V4L2_OUT_CAP_CUSTOM_TIMINGS 0x00000002 /* Supports S_DV_TIMINGS */ +#define V4L2_OUT_CAP_STD 0x00000004 /* Supports S_STD */ + /* * C O N T R O L S */ @@ -1626,6 +1731,13 @@ struct v4l2_dbg_chip_ident { #endif #define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek) +#define VIDIOC_ENUM_DV_PRESETS _IOWR('V', 83, struct v4l2_dv_enum_preset) +#define VIDIOC_S_DV_PRESET _IOWR('V', 84, struct v4l2_dv_preset) +#define VIDIOC_G_DV_PRESET _IOWR('V', 85, struct v4l2_dv_preset) +#define VIDIOC_QUERY_DV_PRESET _IOR('V', 86, struct v4l2_dv_preset) +#define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings) +#define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings) + /* Reminder: when adding new ioctls please add support for them to drivers/media/video/v4l2-compat-ioctl32.c as well! */ diff --git a/Documentation/DocBook/v4l/vidioc-enum-dv-presets.xml b/Documentation/DocBook/v4l/vidioc-enum-dv-presets.xml new file mode 100644 index 0000000..1d31427 --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-enum-dv-presets.xml @@ -0,0 +1,238 @@ + + + ioctl VIDIOC_ENUM_DV_PRESETS + &manvol; + + + + VIDIOC_ENUM_DV_PRESETS + Enumerate supported Digital Video presets + + + + + + int ioctl + int fd + int request + struct v4l2_dv_enum_preset *argp + + + + + + Arguments + + + + fd + + &fd; + + + + request + + VIDIOC_ENUM_DV_PRESETS + + + + argp + + + + + + + + + Description + + To query the attributes of a DV preset, applications initialize the +index field and zero the reserved array of &v4l2-dv-enum-preset; +and call the VIDIOC_ENUM_DV_PRESETS ioctl with a pointer to this +structure. Drivers fill the rest of the structure or return an +&EINVAL; when the index is out of bounds. To enumerate all DV Presets supported, +applications shall begin at index zero, incrementing by one until the +driver returns EINVAL. Drivers may enumerate a +different set of DV presets after switching the video input or +output. + + + struct <structname>v4l2_dv_enum_presets</structname> + + &cs-str; + + + __u32 + index + Number of the DV preset, set by the +application. + + + __u32 + preset + This field identifies one of the DV preset values listed in . + + + __u8 + name[24] + Name of the preset, a NUL-terminated ASCII string, for example: "720P-60", "1080I-60". This information is +intended for the user. + + + __u32 + width + Width of the active video in pixels for the DV preset. + + + __u32 + height + Height of the active video in lines for the DV preset. + + + __u32 + reserved[4] + Reserved for future extensions. Drivers must set the array to zero. + + + +
+ + + struct <structname>DV Presets</structname> + + &cs-str; + + + Preset + Preset value + Description + + + + + + + + V4L2_DV_INVALID + 0 + Invalid preset value. + + + V4L2_DV_480P59_94 + 1 + 720x480 progressive video at 59.94 fps as per BT.1362. + + + V4L2_DV_576P50 + 2 + 720x576 progressive video at 50 fps as per BT.1362. + + + V4L2_DV_720P24 + 3 + 1280x720 progressive video at 24 fps as per SMPTE 296M. + + + V4L2_DV_720P25 + 4 + 1280x720 progressive video at 25 fps as per SMPTE 296M. + + + V4L2_DV_720P30 + 5 + 1280x720 progressive video at 30 fps as per SMPTE 296M. + + + V4L2_DV_720P50 + 6 + 1280x720 progressive video at 50 fps as per SMPTE 296M. + + + V4L2_DV_720P59_94 + 7 + 1280x720 progressive video at 59.94 fps as per SMPTE 274M. + + + V4L2_DV_720P60 + 8 + 1280x720 progressive video at 60 fps as per SMPTE 274M/296M. + + + V4L2_DV_1080I29_97 + 9 + 1920x1080 interlaced video at 29.97 fps as per BT.1120/SMPTE 274M. + + + V4L2_DV_1080I30 + 10 + 1920x1080 interlaced video at 30 fps as per BT.1120/SMPTE 274M. + + + V4L2_DV_1080I25 + 11 + 1920x1080 interlaced video at 25 fps as per BT.1120. + + + V4L2_DV_1080I50 + 12 + 1920x1080 interlaced video at 50 fps as per SMPTE 296M. + + + V4L2_DV_1080I60 + 13 + 1920x1080 interlaced video at 60 fps as per SMPTE 296M. + + + V4L2_DV_1080P24 + 14 + 1920x1080 progressive video at 24 fps as per SMPTE 296M. + + + V4L2_DV_1080P25 + 15 + 1920x1080 progressive video at 25 fps as per SMPTE 296M. + + + V4L2_DV_1080P30 + 16 + 1920x1080 progressive video at 30 fps as per SMPTE 296M. + + + V4L2_DV_1080P50 + 17 + 1920x1080 progressive video at 50 fps as per BT.1120. + + + V4L2_DV_1080P60 + 18 + 1920x1080 progressive video at 60 fps as per BT.1120. + + + +
+
+ + + &return-value; + + + + EINVAL + + The &v4l2-dv-enum-preset; index +is out of bounds. + + + + +
+ + diff --git a/Documentation/DocBook/v4l/vidioc-enuminput.xml b/Documentation/DocBook/v4l/vidioc-enuminput.xml index 414856b..71b868e 100644 --- a/Documentation/DocBook/v4l/vidioc-enuminput.xml +++ b/Documentation/DocBook/v4l/vidioc-enuminput.xml @@ -124,7 +124,13 @@ current input. __u32 - reserved[4] + capabilities + This field provides capabilities for the +input. See for flags. + + + __u32 + reserved[3] Reserved for future extensions. Drivers must set the array to zero. @@ -261,6 +267,34 @@ flag is set Macrovision has been detected. + + + + Input capabilities + + &cs-def; + + + V4L2_IN_CAP_PRESETS + 0x00000001 + This input supports setting DV presets by using VIDIOC_S_DV_PRESET. + + + V4L2_OUT_CAP_CUSTOM_TIMINGS + 0x00000002 + This input supports setting custom video timings by using VIDIOC_S_DV_TIMINGS. + + + V4L2_IN_CAP_STD + 0x00000004 + This input supports setting the TV standard by using VIDIOC_S_STD. + + + +
diff --git a/Documentation/DocBook/v4l/vidioc-enumoutput.xml b/Documentation/DocBook/v4l/vidioc-enumoutput.xml index e8d16dc..a281d26 100644 --- a/Documentation/DocBook/v4l/vidioc-enumoutput.xml +++ b/Documentation/DocBook/v4l/vidioc-enumoutput.xml @@ -114,7 +114,13 @@ details on video standards and how to switch see __u32 - reserved[4] + capabilities + This field provides capabilities for the +output. See for flags. + + + __u32 + reserved[3] Reserved for future extensions. Drivers must set the array to zero. @@ -147,6 +153,34 @@ CVBS, S-Video, RGB. + + + Output capabilities + + &cs-def; + + + V4L2_OUT_CAP_PRESETS + 0x00000001 + This output supports setting DV presets by using VIDIOC_S_DV_PRESET. + + + V4L2_OUT_CAP_CUSTOM_TIMINGS + 0x00000002 + This output supports setting custom video timings by using VIDIOC_S_DV_TIMINGS. + + + V4L2_OUT_CAP_STD + 0x00000004 + This output supports setting the TV standard by using VIDIOC_S_STD. + + + +
+
&return-value; diff --git a/Documentation/DocBook/v4l/vidioc-g-dv-preset.xml b/Documentation/DocBook/v4l/vidioc-g-dv-preset.xml new file mode 100644 index 0000000..3c6784e --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-g-dv-preset.xml @@ -0,0 +1,111 @@ + + + ioctl VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET + &manvol; + + + + VIDIOC_G_DV_PRESET + VIDIOC_S_DV_PRESET + Query or select the DV preset of the current input or output + + + + + + int ioctl + int fd + int request + &v4l2-dv-preset; +*argp + + + + + + Arguments + + + + fd + + &fd; + + + + request + + VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET + + + + argp + + + + + + + + + Description + To query and select the current DV preset, applications +use the VIDIOC_G_DV_PRESET and VIDIOC_S_DV_PRESET +ioctls which take a pointer to a &v4l2-dv-preset; type as argument. +Applications must zero the reserved array in &v4l2-dv-preset;. +VIDIOC_G_DV_PRESET returns a dv preset in the field +preset of &v4l2-dv-preset;. + + VIDIOC_S_DV_PRESET accepts a pointer to a &v4l2-dv-preset; +that has the preset value to be set. Applications must zero the reserved array in &v4l2-dv-preset;. +If the preset is not supported, it returns an &EINVAL; + + + + &return-value; + + + + EINVAL + + This ioctl is not supported, or the +VIDIOC_S_DV_PRESET,VIDIOC_S_DV_PRESET parameter was unsuitable. + + + + EBUSY + + The device is busy and therefore can not change the preset. + + + + + + struct <structname>v4l2_dv_preset</structname> + + &cs-str; + + + __u32 + preset + Preset value to represent the digital video timings + + + __u32 + reserved[4] + Reserved fields for future use + + + +
+ +
+
+ + diff --git a/Documentation/DocBook/v4l/vidioc-g-dv-timings.xml b/Documentation/DocBook/v4l/vidioc-g-dv-timings.xml new file mode 100644 index 0000000..ecc1957 --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-g-dv-timings.xml @@ -0,0 +1,224 @@ + + + ioctl VIDIOC_G_DV_TIMINGS, VIDIOC_S_DV_TIMINGS + &manvol; + + + + VIDIOC_G_DV_TIMINGS + VIDIOC_S_DV_TIMINGS + Get or set custom DV timings for input or output + + + + + + int ioctl + int fd + int request + &v4l2-dv-timings; +*argp + + + + + + Arguments + + + + fd + + &fd; + + + + request + + VIDIOC_G_DV_TIMINGS, VIDIOC_S_DV_TIMINGS + + + + argp + + + + + + + + + Description + To set custom DV timings for the input or output, applications use the +VIDIOC_S_DV_TIMINGS ioctl and to get the current custom timings, +applications use the VIDIOC_G_DV_TIMINGS ioctl. The detailed timing +information is filled in using the structure &v4l2-dv-timings;. These ioctls take +a pointer to the &v4l2-dv-timings; structure as argument. If the ioctl is not supported +or the timing values are not correct, the driver returns &EINVAL;. + + + + &return-value; + + + + EINVAL + + This ioctl is not supported, or the +VIDIOC_S_DV_TIMINGS parameter was unsuitable. + + + + EBUSY + + The device is busy and therefore can not change the timings. + + + + + + struct <structname>v4l2_bt_timings</structname> + + &cs-str; + + + __u32 + width + Width of the active video in pixels + + + __u32 + height + Height of the active video in lines + + + __u32 + interlaced + Progressive (0) or interlaced (1) + + + __u32 + polarities + This is a bit mask that defines polarities of sync signals. +bit 0 (V4L2_DV_VSYNC_POS_POL) is for vertical sync polarity and bit 1 (V4L2_DV_HSYNC_POS_POL) is for horizontal sync polarity. If the bit is set +(1) it is positive polarity and if is cleared (0), it is negative polarity. + + + __u64 + pixelclock + Pixel clock in Hz. Ex. 74.25MHz->74250000 + + + __u32 + hfrontporch + Horizontal front porch in pixels + + + __u32 + hsync + Horizontal sync length in pixels + + + __u32 + hbackporch + Horizontal back porch in pixels + + + __u32 + vfrontporch + Vertical front porch in lines + + + __u32 + vsync + Vertical sync length in lines + + + __u32 + vbackporch + Vertical back porch in lines + + + __u32 + il_vfrontporch + Vertical front porch in lines for bottom field of interlaced field formats + + + __u32 + il_vsync + Vertical sync length in lines for bottom field of interlaced field formats + + + __u32 + il_vbackporch + Vertical back porch in lines for bottom field of interlaced field formats + + + +
+ + + struct <structname>v4l2_dv_timings</structname> + + &cs-str; + + + __u32 + type + + Type of DV timings as listed in . + + + union + + + + + + &v4l2-bt-timings; + bt + Timings defined by BT.656/1120 specifications + + + + __u32 + reserved[32] + + + + +
+ + + DV Timing types + + &cs-str; + + + Timing type + value + Description + + + + + + + + V4L2_DV_BT_656_1120 + 0 + BT.656/1120 timings + + + +
+
+
+ + diff --git a/Documentation/DocBook/v4l/vidioc-query-dv-preset.xml b/Documentation/DocBook/v4l/vidioc-query-dv-preset.xml new file mode 100644 index 0000000..87e4f0f --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-query-dv-preset.xml @@ -0,0 +1,85 @@ + + + ioctl VIDIOC_QUERY_DV_PRESET + &manvol; + + + + VIDIOC_QUERY_DV_PRESET + Sense the DV preset received by the current +input + + + + + + int ioctl + int fd + int request + &v4l2-dv-preset; *argp + + + + + + Arguments + + + + fd + + &fd; + + + + request + + VIDIOC_QUERY_DV_PRESET + + + + argp + + + + + + + + + Description + + The hardware may be able to detect the current DV preset +automatically, similar to sensing the video standard. To do so, applications +call VIDIOC_QUERY_DV_PRESET with a pointer to a +&v4l2-dv-preset; type. Once the hardware detects a preset, that preset is +returned in the preset field of &v4l2-dv-preset;. When detection is not +possible or fails, the value V4L2_DV_INVALID is returned. + + + + &return-value; + + + EINVAL + + This ioctl is not supported. + + + + EBUSY + + The device is busy and therefore can not sense the preset + + + + + + + -- cgit v0.10.2 From b33f5f8af3fabe6a080c9d06f8f3184a4de3f3c2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 3 Dec 2009 01:32:12 -0300 Subject: V4L/DVB (13573): v4l2-spec: updated revision history, updated version to 2.6.33. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/DocBook/v4l/compat.xml b/Documentation/DocBook/v4l/compat.xml index 4d1902a..b9dbdf9 100644 --- a/Documentation/DocBook/v4l/compat.xml +++ b/Documentation/DocBook/v4l/compat.xml @@ -2291,8 +2291,8 @@ was renamed to v4l2_chip_ident_old New control V4L2_CID_COLORFX was added. - - + +
V4L2 in Linux 2.6.32 @@ -2322,8 +2322,16 @@ more information. Added Remote Controller chapter, describing the default Remote Controller mapping for media devices. - -
+ + +
+ V4L2 in Linux 2.6.33 + + + Added support for Digital Video timings in order to support HDTV receivers and transmitters. + + +
diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml index 77b7dd8..060105a 100644 --- a/Documentation/DocBook/v4l/v4l2.xml +++ b/Documentation/DocBook/v4l/v4l2.xml @@ -74,6 +74,17 @@ Remote Controller chapter. + + + Muralidharan + Karicheri + Documented the Digital Video timings API. + +
+ m-karicheri2@ti.com +
+
+
@@ -89,7 +100,7 @@ Remote Controller chapter. 2008 2009 Bill Dirks, Michael H. Schimek, Hans Verkuil, Martin -Rubli, Andy Walls, Mauro Carvalho Chehab +Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab Except when explicitly stated as GPL, programming examples within @@ -103,6 +114,13 @@ structs, ioctls) must be noted in more detail in the history chapter applications. --> + 2.6.33 + 2009-12-03 + mk + Added documentation for the Digital Video timings API. + + + 2.6.32 2009-08-31 mcc @@ -355,7 +373,7 @@ and discussions on the V4L mailing list. Video for Linux Two API Specification - Revision 2.6.32 + Revision 2.6.33 &sub-common; -- cgit v0.10.2 From b779974bdfcaec2a0eb13e44405baca07e0e92a3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 5 Dec 2009 23:24:50 -0300 Subject: V4L/DVB (13575): em28xx: Use the complete address/command RC5 code for WinTV USB2 This device uses an i2c chip to retrieve the keycode from a RC5 remote. Instead of just getting 6 bits, improve the routine to get 11 bits. This means that the complete RC5 table for Hauppauge Grey IR can be used with this device. Unfortunately, it seems that this IR receiver is not capable of getting the full 14 (or 13 bits) from the RC5 protocol. At lest now, with the new code, it is possible to replace this IR table by another RC5 table. 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 e7a68e2..2510000 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -2285,7 +2285,7 @@ void em28xx_register_i2c_ir(struct em28xx *dev) dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; break; case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: - dev->init_data.ir_codes = &ir_codes_hauppauge_new_table; + dev->init_data.ir_codes = &ir_codes_rc5_hauppauge_new_table; dev->init_data.get_key = em28xx_get_key_em_haup; dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; break; diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 3f5cf02..5ddeb42 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -112,10 +112,13 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char buf[2]; - unsigned char code; + u16 code; + int size; /* poll IR chip */ - if (2 != i2c_master_recv(ir->c, buf, 2)) + size = i2c_master_recv(ir->c, buf, sizeof(buf)); + + if (size != 2) return -EIO; /* Does eliminate repeated parity code */ @@ -124,16 +127,30 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) ir->old = buf[1]; - /* Rearranges bits to the right order */ - code = ((buf[0]&0x01)<<5) | /* 0010 0000 */ - ((buf[0]&0x02)<<3) | /* 0001 0000 */ - ((buf[0]&0x04)<<1) | /* 0000 1000 */ - ((buf[0]&0x08)>>1) | /* 0000 0100 */ - ((buf[0]&0x10)>>3) | /* 0000 0010 */ - ((buf[0]&0x20)>>5); /* 0000 0001 */ - - i2cdprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n", - code, buf[0]); + /* + * Rearranges bits to the right order. + * The bit order were determined experimentally by using + * The original Hauppauge Grey IR and another RC5 that uses addr=0x08 + * The RC5 code has 14 bits, but we've experimentally determined + * the meaning for only 11 bits. + * So, the code translation is not complete. Yet, it is enough to + * work with the provided RC5 IR. + */ + code = + ((buf[0] & 0x01) ? 0x0020 : 0) | /* 0010 0000 */ + ((buf[0] & 0x02) ? 0x0010 : 0) | /* 0001 0000 */ + ((buf[0] & 0x04) ? 0x0008 : 0) | /* 0000 1000 */ + ((buf[0] & 0x08) ? 0x0004 : 0) | /* 0000 0100 */ + ((buf[0] & 0x10) ? 0x0002 : 0) | /* 0000 0010 */ + ((buf[0] & 0x20) ? 0x0001 : 0) | /* 0000 0001 */ + ((buf[1] & 0x08) ? 0x1000 : 0) | /* 0001 0000 */ + ((buf[1] & 0x10) ? 0x0800 : 0) | /* 0000 1000 */ + ((buf[1] & 0x20) ? 0x0400 : 0) | /* 0000 0100 */ + ((buf[1] & 0x40) ? 0x0200 : 0) | /* 0000 0010 */ + ((buf[1] & 0x80) ? 0x0100 : 0); /* 0000 0001 */ + + i2cdprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x%02x)\n", + code, buf[1], buf[0]); /* return key */ *ir_key = code; -- cgit v0.10.2 From 05395a3d86a928d374c970a0b35a6a711072f86c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 6 Dec 2009 08:32:49 -0300 Subject: V4L/DVB (13576): ir-common: fix an oops caused by the usage of an initialized drvdata As reported by Sander Eikelenboom : > Tried to update my v4l-dvb modules today, but got a bug with my pinnacle > card, seems to be related to the recent changes in the ir code. > > Dec 5 23:30:25 security kernel: [ 5.735698] BUG: unable to handle kernel NULL pointer dereference at 0000000000000000 > Dec 5 23:30:25 security kernel: [ 5.735716] IP: [] :ir_common:ir_input_free+0x26/0x3e Thanks-to: Sander Eikelenboom for reporting and testing the fix. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/ir-keytable.c b/drivers/media/common/ir-keytable.c index 26ce5bc..ceef0e8 100644 --- a/drivers/media/common/ir-keytable.c +++ b/drivers/media/common/ir-keytable.c @@ -419,6 +419,9 @@ void ir_input_free(struct input_dev *dev) { struct ir_scancode_table *rc_tab = input_get_drvdata(dev); + if (!rc_tab) + return; + IR_dprintk(1, "Freed keycode table\n"); rc_tab->size = 0; -- cgit v0.10.2 From 0e2f0d348a65b48a8af52d7fd64d77b5759413fa Mon Sep 17 00:00:00 2001 From: Akihiro Tsukada Date: Thu, 19 Nov 2009 12:19:50 -0300 Subject: V4L/DVB (13577): [PATCH] dvb-usb-friio: accept center-shifted frequency This patch adds a fix to accept frequency with its center shifted. The driver used to accept center frequencies of the normal UHF band channels, but in ISDB-T, center frequency is shifted with 1/7MHz. It was shifted internally in the driver, but this patch enables to accept both types of frequency. Signed-off-by: Akihiro Tsukada Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/friio-fe.c b/drivers/media/dvb/dvb-usb/friio-fe.c index 9cbbe42..ebb7b9f 100644 --- a/drivers/media/dvb/dvb-usb/friio-fe.c +++ b/drivers/media/dvb/dvb-usb/friio-fe.c @@ -134,11 +134,13 @@ static int jdvbt90502_pll_set_freq(struct jdvbt90502_state *state, u32 freq) deb_fe("%s: freq=%d, step=%d\n", __func__, freq, state->frontend.ops.info.frequency_stepsize); /* freq -> oscilator frequency conversion. */ - /* freq: 473,000,000 + n*6,000,000 (no 1/7MHz shift to center freq) */ - /* add 400[1/7 MHZ] = 57.142857MHz. 57MHz for the IF, */ - /* 1/7MHz for center freq shift */ + /* freq: 473,000,000 + n*6,000,000 [+ 142857 (center freq. shift)] */ f = freq / state->frontend.ops.info.frequency_stepsize; - f += 400; + /* add 399[1/7 MHZ] = 57MHz for the IF */ + f += 399; + /* add center frequency shift if necessary */ + if (f % 7 == 0) + f++; pll_freq_cmd[DEMOD_REDIRECT_REG] = JDVBT90502_2ND_I2C_REG; /* 0xFE */ pll_freq_cmd[ADDRESS_BYTE] = state->config.pll_address << 1; pll_freq_cmd[DIVIDER_BYTE1] = (f >> 8) & 0x7F; -- cgit v0.10.2 From 81afda5182667dcc89374cb5bb94fd6db01c9263 Mon Sep 17 00:00:00 2001 From: Derek Date: Thu, 19 Nov 2009 13:07:12 -0300 Subject: V4L/DVB (13578): [PATCH] fix genpix driver (no 8psk lock). Genpix is demodulating DVB-S-like signal with 8PSK modulation used) - this non-standard behaviour was broken by rejecting 8PSK in a standard DVB-S tune request. This problem is fixed by simply reverting back to the drivers original behavior with this patch. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c index 20eadf9..7a7f1b2 100644 --- a/drivers/media/dvb/dvb-usb/gp8psk-fe.c +++ b/drivers/media/dvb/dvb-usb/gp8psk-fe.c @@ -146,8 +146,8 @@ static int gp8psk_fe_set_frontend(struct dvb_frontend* fe, switch (c->delivery_system) { case SYS_DVBS: - /* Only QPSK is supported for DVB-S */ - if (c->modulation != QPSK) { + /* Allow QPSK and 8PSK (even for DVB-S) */ + if (c->modulation != QPSK && c->modulation != PSK_8) { deb_fe("%s: unsupported modulation selected (%d)\n", __func__, c->modulation); return -EOPNOTSUPP; -- cgit v0.10.2 From 4bf2c5c30eb50e4d9d9afb4565829ed0e0582d91 Mon Sep 17 00:00:00 2001 From: Pedro Andres Aranda Gutierrez Date: Thu, 19 Nov 2009 13:15:37 -0300 Subject: V4L/DVB (13579): PATCH: better support for INTUIX DVB stick boot The device is bootingcorrectly, but no frontend is attached. This patch corrects this behaviour. Signed-off-by: Pedro Andres Aranda Gutierrez Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c index da34979..b395e85 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/drivers/media/dvb/dvb-usb/dibusb-common.c @@ -243,6 +243,12 @@ static struct dib3000mc_config mod3000p_dib3000p_config = { int dibusb_dib3000mc_frontend_attach(struct dvb_usb_adapter *adap) { + if (adap->dev->udev->descriptor.idVendor == USB_VID_LITEON && + adap->dev->udev->descriptor.idProduct == + USB_PID_LITEON_DVB_T_WARM) { + msleep(1000); + } + if ((adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000P_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL || (adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000MC_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL) { if (adap->priv != NULL) { -- cgit v0.10.2 From e414753c8ce5fb0bd81155406efaefe57f374571 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Mon, 30 Nov 2009 13:52:57 -0300 Subject: V4L/DVB (13580): Add support for PCTV 74e (Pinnacle) + fix USB vendor IDs This patch adds support for PCTV 74e (Pinnacle) and it fixes the USB vendor IDs for PCTV (f.k.a Pinnacle). For convenience all new PCTV USB product IDs are also existing with Pinnacle's USB vendor ID. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 684146f..ad80b93 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1929,14 +1929,18 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D) }, /* 55 */{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D_2) }, { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73A) }, - { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) }, - { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) }, + { USB_DEVICE(USB_VID_PCTV, USB_PID_PINNACLE_PCTV73ESE) }, + { USB_DEVICE(USB_VID_PCTV, USB_PID_PINNACLE_PCTV282E) }, { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7770P) }, /* 60 */{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS_2) }, { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XPVR) }, { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XP) }, { USB_DEVICE(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD) }, { USB_DEVICE(USB_VID_EVOLUTEPC, USB_PID_TVWAY_PLUS) }, +/* 65 */{ USB_DEVICE(USB_VID_PCTV, USB_PID_PINNACLE_PCTV74E) }, + { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) }, + { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) }, + { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV74E) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -2231,18 +2235,22 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 3, + .num_device_descs = 4, .devices = { { "Pinnacle PCTV 73A", { &dib0700_usb_id_table[56], NULL }, { NULL }, }, { "Pinnacle PCTV 73e SE", - { &dib0700_usb_id_table[57], NULL }, + { &dib0700_usb_id_table[57], &dib0700_usb_id_table[66], NULL }, { NULL }, }, { "Pinnacle PCTV 282e", - { &dib0700_usb_id_table[58], NULL }, + { &dib0700_usb_id_table[58], &dib0700_usb_id_table[67], NULL }, + { NULL }, + }, + { "Pinnacle PCTV 74e", + { &dib0700_usb_id_table[65], &dib0700_usb_id_table[68], 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 f1602d4..cf7f2b4 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -47,6 +47,7 @@ #define USB_VID_MSI_2 0x1462 #define USB_VID_OPERA1 0x695c #define USB_VID_PINNACLE 0x2304 +#define USB_VID_PCTV 0x2013 #define USB_VID_PIXELVIEW 0x1554 #define USB_VID_TECHNOTREND 0x0b48 #define USB_VID_TERRATEC 0x0ccd @@ -211,6 +212,7 @@ #define USB_PID_PINNACLE_PCTV801E_SE 0x023b #define USB_PID_PINNACLE_PCTV73A 0x0243 #define USB_PID_PINNACLE_PCTV73ESE 0x0245 +#define USB_PID_PINNACLE_PCTV74E 0x0246 #define USB_PID_PINNACLE_PCTV282E 0x0248 #define USB_PID_PIXELVIEW_SBTVD 0x5010 #define USB_PID_PCTV_200E 0x020e -- cgit v0.10.2 From 20232c4791507189d4e9499f81632a1ce434f2a4 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Tue, 1 Dec 2009 12:08:56 -0300 Subject: V4L/DVB (13582): DiB0700: remove USB IDs of PCTV 74e from the driver The PCTV 74e is not a design based on the dib0700-USB-device controller thus we should not have its USB IDs inside. This reverts partly: Add support for PCTV 74e (Pinnacle) + fix USB vendor IDs Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index ad80b93..923fa15 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1937,10 +1937,8 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XP) }, { USB_DEVICE(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD) }, { USB_DEVICE(USB_VID_EVOLUTEPC, USB_PID_TVWAY_PLUS) }, -/* 65 */{ USB_DEVICE(USB_VID_PCTV, USB_PID_PINNACLE_PCTV74E) }, - { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) }, +/* 65 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) }, { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) }, - { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV74E) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -2235,22 +2233,18 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 4, + .num_device_descs = 3, .devices = { { "Pinnacle PCTV 73A", { &dib0700_usb_id_table[56], NULL }, { NULL }, }, { "Pinnacle PCTV 73e SE", - { &dib0700_usb_id_table[57], &dib0700_usb_id_table[66], NULL }, + { &dib0700_usb_id_table[57], &dib0700_usb_id_table[65], NULL }, { NULL }, }, { "Pinnacle PCTV 282e", - { &dib0700_usb_id_table[58], &dib0700_usb_id_table[67], NULL }, - { NULL }, - }, - { "Pinnacle PCTV 74e", - { &dib0700_usb_id_table[65], &dib0700_usb_id_table[68], NULL }, + { &dib0700_usb_id_table[58], &dib0700_usb_id_table[66], NULL }, { NULL }, }, }, -- cgit v0.10.2 From 03245a5ee69a5faa99b020fe1aca9bafe10c46a9 Mon Sep 17 00:00:00 2001 From: Olivier Grenie Date: Fri, 4 Dec 2009 13:27:57 -0300 Subject: V4L/DVB (13583): DiB8090: Add the DiB0090 tuner driver and STK8096GP-board This patchs adds support for the DiBcom DiB0090 RF tuner and for DiBcom's reference design STK8096GP. Small extracts of the DiB0070 and the DiB8000-driver into a common codebase. Signed-off-by: Patrick Boettcher Signed-off-by: Olivier Grenie Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 923fa15..80a1263 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -18,6 +18,7 @@ #include "xc5000.h" #include "s5h1411.h" #include "dib0070.h" +#include "dib0090.h" #include "lgdt3305.h" #include "mxl5007t.h" @@ -605,17 +606,17 @@ static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event, } break; default: - if (actlen != sizeof(buf)) { - /* We didn't get back the 6 byte message we expected */ - err("Unexpected RC response size [%d]", actlen); - return -1; - } + if (actlen != sizeof(buf)) { + /* We didn't get back the 6 byte message we expected */ + err("Unexpected RC response size [%d]", actlen); + return -1; + } - poll_reply.report_id = buf[0]; - poll_reply.data_state = buf[1]; + poll_reply.report_id = buf[0]; + poll_reply.data_state = buf[1]; poll_reply.system = (buf[2] << 8) | buf[3]; - poll_reply.data = buf[4]; - poll_reply.not_data = buf[5]; + poll_reply.data = buf[4]; + poll_reply.not_data = buf[5]; break; } @@ -632,7 +633,7 @@ static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event, /* Find the key in the map */ for (i = 0; i < d->props.rc_key_map_size; i++) { if (rc5_custom(&keymap[i]) == (poll_reply.system & 0xff) && - rc5_data(&keymap[i]) == poll_reply.data) { + rc5_data(&keymap[i]) == poll_reply.data) { *event = keymap[i].event; found = 1; break; @@ -641,8 +642,8 @@ static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event, if (found == 0) { err("Unknown remote controller key: %04x %02x %02x", - poll_reply.system, - poll_reply.data, poll_reply.not_data); + poll_reply.system, + poll_reply.data, poll_reply.not_data); d->last_event = 0; return 0; } @@ -1476,12 +1477,12 @@ static struct dib8000_config dib807x_dib8000_config[2] = { } }; -static int dib807x_tuner_reset(struct dvb_frontend *fe, int onoff) +static int dib80xx_tuner_reset(struct dvb_frontend *fe, int onoff) { return dib8000_set_gpio(fe, 5, 0, !onoff); } -static int dib807x_tuner_sleep(struct dvb_frontend *fe, int onoff) +static int dib80xx_tuner_sleep(struct dvb_frontend *fe, int onoff) { return dib8000_set_gpio(fe, 0, 0, onoff); } @@ -1494,8 +1495,8 @@ static const struct dib0070_wbd_gain_cfg dib8070_wbd_gain_cfg[] = { static struct dib0070_config dib807x_dib0070_config[2] = { { .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, - .reset = dib807x_tuner_reset, - .sleep = dib807x_tuner_sleep, + .reset = dib80xx_tuner_reset, + .sleep = dib80xx_tuner_sleep, .clock_khz = 12000, .clock_pad_drive = 4, .vga_filter = 1, @@ -1508,8 +1509,8 @@ static struct dib0070_config dib807x_dib0070_config[2] = { .freq_offset_khz_vhf = -100, }, { .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, - .reset = dib807x_tuner_reset, - .sleep = dib807x_tuner_sleep, + .reset = dib80xx_tuner_reset, + .sleep = dib80xx_tuner_sleep, .clock_khz = 12000, .clock_pad_drive = 2, .vga_filter = 1, @@ -1566,12 +1567,12 @@ static int dib807x_tuner_attach(struct dvb_usb_adapter *adap) return 0; } -static int stk807x_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff) +static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff) { return dib8000_pid_filter(adapter->fe, index, pid, onoff); } -static int stk807x_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff) +static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff) { return dib8000_pid_filter_ctrl(adapter->fe, onoff); } @@ -1643,6 +1644,246 @@ static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap) return adap->fe == NULL ? -ENODEV : 0; } +/* STK8096GP */ +struct dibx000_agc_config dib8090_agc_config[2] = { + { + BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND, + /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, + * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ + (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup + + 787,// inv_gain = 1/ 90.4dB // no boost, lower gain due to ramp quantification + 10, // time_stabiliz + + 0, // alpha_level + 118, // thlock + + 0, // wbd_inv + 3530, // wbd_ref + 1, // wbd_sel + 5, // wbd_alpha + + 65535, // agc1_max + 0, // agc1_min + + 65535, // agc2_max + 0, // agc2_min + + 0, // agc1_pt1 + 32, // agc1_pt2 + 114, // agc1_pt3 // 40.4dB + 143, // agc1_slope1 + 144, // agc1_slope2 + 114, // agc2_pt1 + 227, // agc2_pt2 + 116, // agc2_slope1 + 117, // agc2_slope2 + + 28, // alpha_mant // 5Hz with 90.2dB + 26, // alpha_exp + 31, // beta_mant + 51, // beta_exp + + 0, // perform_agc_softsplit + }, + { + BAND_CBAND, + /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, + * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ + (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup + + 787,// inv_gain = 1/ 90.4dB // no boost, lower gain due to ramp quantification + 10, // time_stabiliz + + 0, // alpha_level + 118, // thlock + + 0, // wbd_inv + 3530, // wbd_ref + 1, // wbd_sel + 5, // wbd_alpha + + 0, // agc1_max + 0, // agc1_min + + 65535, // agc2_max + 0, // agc2_min + + 0, // agc1_pt1 + 32, // agc1_pt2 + 114, // agc1_pt3 // 40.4dB + 143, // agc1_slope1 + 144, // agc1_slope2 + 114, // agc2_pt1 + 227, // agc2_pt2 + 116, // agc2_slope1 + 117, // agc2_slope2 + + 28, // alpha_mant // 5Hz with 90.2dB + 26, // alpha_exp + 31, // beta_mant + 51, // beta_exp + + 0, // perform_agc_softsplit + } +}; + +static struct dibx000_bandwidth_config dib8090_pll_config_12mhz = { + 54000, 13500, // internal, sampling + 1, 18, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass + 0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo + (3 << 14) | (1 << 12) | (599 << 0), // sad_cfg: refsel, sel, freq_15k + (0 << 25) | 0, // ifreq = 0 MHz + 20199727, // timf + 12000000, // xtal_hz +}; + +static int dib8090_get_adc_power(struct dvb_frontend *fe) +{ + return dib8000_get_adc_power(fe, 1); +} + +static struct dib8000_config dib809x_dib8000_config = { + .output_mpeg2_in_188_bytes = 1, + + .agc_config_count = 2, + .agc = dib8090_agc_config, + .agc_control = dib0090_dcc_freq, + .pll = &dib8090_pll_config_12mhz, + .tuner_is_baseband = 1, + + .gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS, + .gpio_val = DIB8000_GPIO_DEFAULT_VALUES, + .gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS, + + .hostbus_diversity = 1, + .div_cfg = 0x31, + .output_mode = OUTMODE_MPEG2_FIFO, + .drives = 0x2d98, + .diversity_delay = 144, + .refclksel = 3, +}; + +static struct dib0090_config dib809x_dib0090_config = { + .io.pll_bypass = 1, + .io.pll_range = 1, + .io.pll_prediv = 1, + .io.pll_loopdiv = 20, + .io.adc_clock_ratio = 8, + .io.pll_int_loop_filt = 0, + .io.clock_khz = 12000, + .reset = dib80xx_tuner_reset, + .sleep = dib80xx_tuner_sleep, + .clkouttobamse = 1, + .analog_output = 1, + .i2c_address = DEFAULT_DIB0090_I2C_ADDRESS, + .wbd_vhf_offset = 100, + .wbd_cband_offset = 450, + .use_pwm_agc = 1, + .clkoutdrive = 1, + .get_adc_power = dib8090_get_adc_power, + .freq_offset_khz_uhf = 0, + .freq_offset_khz_vhf = -143, +}; + +static int dib8096_set_param_override(struct dvb_frontend *fe, + struct dvb_frontend_parameters *fep) +{ + struct dvb_usb_adapter *adap = fe->dvb->priv; + struct dib0700_adapter_state *state = adap->priv; + u8 band = BAND_OF_FREQUENCY(fep->frequency/1000); + u16 offset; + int ret = 0; + enum frontend_tune_state tune_state = CT_SHUTDOWN; + u16 ltgain, rf_gain_limit; + + ret = state->set_param_save(fe, fep); + if (ret < 0) + return ret; + + switch (band) { + case BAND_VHF: + offset = 100; + break; + case BAND_UHF: + offset = 550; + break; + default: + offset = 0; + break; + } + offset += (dib0090_get_wbd_offset(fe) * 8 * 18 / 33 + 1) / 2; + dib8000_set_wbd_ref(fe, offset); + + + if (band == BAND_CBAND) + { + deb_info("tuning in CBAND - soft-AGC startup\n"); + /* TODO specific wbd target for dib0090 - needed for startup ? */ + dib0090_set_tune_state(fe, CT_AGC_START); + do + { + ret = dib0090_gain_control(fe); + msleep(ret); + tune_state = dib0090_get_tune_state(fe); + if (tune_state == CT_AGC_STEP_0) + dib8000_set_gpio(fe, 6, 0, 1); + else if (tune_state == CT_AGC_STEP_1) + { + dib0090_get_current_gain(fe, NULL, NULL, &rf_gain_limit, <gain); + if (rf_gain_limit == 0) + dib8000_set_gpio(fe, 6, 0, 0); + } + } + while(tune_statepriv; + struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); + + if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &dib809x_dib0090_config) == NULL) + return -ENODEV; + + st->set_param_save = adap->fe->ops.tuner_ops.set_params; + adap->fe->ops.tuner_ops.set_params = dib8096_set_param_override; + return 0; +} + +static int stk809x_frontend_attach(struct dvb_usb_adapter *adap) +{ + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); + msleep(10); + dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); + + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); + + dib0700_ctrl_clock(adap->dev, 72, 1); + + msleep(10); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); + msleep(10); + dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); + + dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80); + + adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config); + + return adap->fe == NULL ? -ENODEV : 0; +} /* STK7070PD */ static struct dib7000p_config stk7070pd_dib7000p_config[2] = { @@ -1939,6 +2180,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_EVOLUTEPC, USB_PID_TVWAY_PLUS) }, /* 65 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) }, { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) }, + { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK8096GP) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -2473,8 +2715,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 32, - .pid_filter = stk807x_pid_filter, - .pid_filter_ctrl = stk807x_pid_filter_ctrl, + .pid_filter = stk80xx_pid_filter, + .pid_filter_ctrl = stk80xx_pid_filter_ctrl, .frontend_attach = stk807x_frontend_attach, .tuner_attach = dib807x_tuner_attach, @@ -2512,8 +2754,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 32, - .pid_filter = stk807x_pid_filter, - .pid_filter_ctrl = stk807x_pid_filter_ctrl, + .pid_filter = stk80xx_pid_filter, + .pid_filter_ctrl = stk80xx_pid_filter_ctrl, .frontend_attach = stk807xpvr_frontend_attach0, .tuner_attach = dib807x_tuner_attach, @@ -2525,8 +2767,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 32, - .pid_filter = stk807x_pid_filter, - .pid_filter_ctrl = stk807x_pid_filter_ctrl, + .pid_filter = stk80xx_pid_filter, + .pid_filter_ctrl = stk80xx_pid_filter_ctrl, .frontend_attach = stk807xpvr_frontend_attach1, .tuner_attach = dib807x_tuner_attach, @@ -2549,6 +2791,37 @@ struct dvb_usb_device_properties dib0700_devices[] = { .rc_key_map = dib0700_rc_keys, .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), .rc_query = dib0700_rc_query + }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, + .num_adapters = 1, + .adapter = { + { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk80xx_pid_filter, + .pid_filter_ctrl = stk80xx_pid_filter_ctrl, + .frontend_attach = stk809x_frontend_attach, + .tuner_attach = dib809x_tuner_attach, + + DIB0700_DEFAULT_STREAMING_CONFIG(0x02), + + .size_of_priv = + sizeof(struct dib0700_adapter_state), + }, + }, + + .num_device_descs = 1, + .devices = { + { "DiBcom STK8096GP reference design", + { &dib0700_usb_id_table[67], NULL }, + { NULL }, + }, + }, + + .rc_interval = DEFAULT_RC_INTERVAL, + .rc_key_map = dib0700_rc_keys, + .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), + .rc_query = dib0700_rc_query }, }; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index cf7f2b4..bc3581d 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -102,6 +102,7 @@ #define USB_PID_DIBCOM_STK7070PD 0x1ebe #define USB_PID_DIBCOM_STK807XP 0x1f90 #define USB_PID_DIBCOM_STK807XPVR 0x1f98 +#define USB_PID_DIBCOM_STK8096GP 0x1fa0 #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 #define USB_PID_DIBCOM_STK7770P 0x1e80 #define USB_PID_DPOSH_M9206_COLD 0x9206 diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 58aac01..a3b8b697 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -526,6 +526,15 @@ config DVB_TUNER_DIB0070 This device is only used inside a SiP called together with a demodulator for now. +config DVB_TUNER_DIB0090 + tristate "DiBcom DiB0090 silicon base-band tuner" + depends on I2C + default m if DVB_FE_CUSTOMISE + help + A driver for the silicon baseband tuner DiB0090 from DiBcom. + This device is only used inside a SiP called together with a + demodulator for now. + comment "SEC control devices for DVB-S" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 8234825..47575cc 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_DVB_TDA10086) += tda10086.o obj-$(CONFIG_DVB_TDA826X) += tda826x.o obj-$(CONFIG_DVB_TDA8261) += tda8261.o obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o +obj-$(CONFIG_DVB_TUNER_DIB0090) += dib0090.o obj-$(CONFIG_DVB_TUA6100) += tua6100.o obj-$(CONFIG_DVB_S5H1409) += s5h1409.o obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c index 2be17b9..81860b2 100644 --- a/drivers/media/dvb/frontends/dib0070.c +++ b/drivers/media/dvb/frontends/dib0070.c @@ -49,21 +49,6 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); #define DIB0070_P1G 0x03 #define DIB0070S_P1A 0x02 -enum frontend_tune_state { - CT_TUNER_START = 10, - CT_TUNER_STEP_0, - CT_TUNER_STEP_1, - CT_TUNER_STEP_2, - CT_TUNER_STEP_3, - CT_TUNER_STEP_4, - CT_TUNER_STEP_5, - CT_TUNER_STEP_6, - CT_TUNER_STEP_7, - CT_TUNER_STOP, -}; - -#define FE_CALLBACK_TIME_NEVER 0xffffffff - struct dib0070_state { struct i2c_adapter *i2c; struct dvb_frontend *fe; @@ -71,10 +56,10 @@ struct dib0070_state { u16 wbd_ff_offset; u8 revision; - enum frontend_tune_state tune_state; - u32 current_rf; + enum frontend_tune_state tune_state; + u32 current_rf; - /* for the captrim binary search */ + /* for the captrim binary search */ s8 step; u16 adc_diff; @@ -85,7 +70,7 @@ struct dib0070_state { const struct dib0070_tuning *current_tune_table_index; const struct dib0070_lna_match *lna_match; - u8 wbd_gain_current; + u8 wbd_gain_current; u16 wbd_offset_3_3[2]; }; @@ -93,8 +78,8 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) { u8 b[2]; struct i2c_msg msg[2] = { - {.addr = state->cfg->i2c_address,.flags = 0,.buf = ®,.len = 1}, - {.addr = state->cfg->i2c_address,.flags = I2C_M_RD,.buf = b,.len = 2}, + { .addr = state->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 }, + { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 }, }; if (i2c_transfer(state->i2c, msg, 2) != 2) { printk(KERN_WARNING "DiB0070 I2C read failed\n"); @@ -106,7 +91,7 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) { u8 b[3] = { reg, val >> 8, val & 0xff }; - struct i2c_msg msg = {.addr = state->cfg->i2c_address,.flags = 0,.buf = b,.len = 3 }; + struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 }; if (i2c_transfer(state->i2c, &msg, 1) != 1) { printk(KERN_WARNING "DiB0070 I2C write failed\n"); return -EREMOTEIO; @@ -124,30 +109,30 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) { - struct dib0070_state *state = fe->tuner_priv; - u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff; - - if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 7000) - tmp |= (0 << 14); - else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 6000) - tmp |= (1 << 14); - else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 5000) - tmp |= (2 << 14); - else - tmp |= (3 << 14); - - dib0070_write_reg(state, 0x02, tmp); - - /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */ - if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) { - u16 value = dib0070_read_reg(state, 0x17); - - dib0070_write_reg(state, 0x17, value & 0xfffc); - tmp = dib0070_read_reg(state, 0x01) & 0x01ff; - dib0070_write_reg(state, 0x01, tmp | (60 << 9)); - - dib0070_write_reg(state, 0x17, value); - } + struct dib0070_state *state = fe->tuner_priv; + u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff; + + if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000) + tmp |= (0 << 14); + else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000) + tmp |= (1 << 14); + else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000) + tmp |= (2 << 14); + else + tmp |= (3 << 14); + + dib0070_write_reg(state, 0x02, tmp); + + /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */ + if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) { + u16 value = dib0070_read_reg(state, 0x17); + + dib0070_write_reg(state, 0x17, value & 0xfffc); + tmp = dib0070_read_reg(state, 0x01) & 0x01ff; + dib0070_write_reg(state, 0x01, tmp | (60 << 9)); + + dib0070_write_reg(state, 0x17, value); + } return 0; } @@ -160,14 +145,14 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state if (*tune_state == CT_TUNER_STEP_0) { dib0070_write_reg(state, 0x0f, 0xed10); - dib0070_write_reg(state, 0x17, 0x0034); + dib0070_write_reg(state, 0x17, 0x0034); dib0070_write_reg(state, 0x18, 0x0032); state->step = state->captrim = state->fcaptrim = 64; state->adc_diff = 3000; ret = 20; - *tune_state = CT_TUNER_STEP_1; + *tune_state = CT_TUNER_STEP_1; } else if (*tune_state == CT_TUNER_STEP_1) { state->step /= 2; dib0070_write_reg(state, 0x14, state->lo4 | state->captrim); @@ -178,7 +163,7 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state adc = dib0070_read_reg(state, 0x19); - dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc * (u32) 1800 / (u32) 1024); + dprintk( "CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024); if (adc >= 400) { adc -= 400; @@ -189,10 +174,12 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state } if (adc < state->adc_diff) { - dprintk("CAPTRIM=%hd is closer to target (%hd/%hd)", state->captrim, adc, state->adc_diff); + dprintk( "CAPTRIM=%hd is closer to target (%hd/%hd)", state->captrim, adc, state->adc_diff); state->adc_diff = adc; state->fcaptrim = state->captrim; + + } state->captrim += (step_sign * state->step); @@ -213,8 +200,8 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt) { struct dib0070_state *state = fe->tuner_priv; - u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0); - dprintk("CTRL_LO5: 0x%x", lo5); + u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0); + dprintk( "CTRL_LO5: 0x%x", lo5); return dib0070_write_reg(state, 0x15, lo5); } @@ -227,171 +214,175 @@ void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open) dib0070_write_reg(state, 0x1a, 0x0000); } else { dib0070_write_reg(state, 0x1b, 0x4112); - if (state->cfg->vga_filter != 0) { - dib0070_write_reg(state, 0x1a, state->cfg->vga_filter); - dprintk("vga filter register is set to %x", state->cfg->vga_filter); - } else - dib0070_write_reg(state, 0x1a, 0x0009); + if (state->cfg->vga_filter != 0) { + dib0070_write_reg(state, 0x1a, state->cfg->vga_filter); + dprintk( "vga filter register is set to %x", state->cfg->vga_filter); + } else + dib0070_write_reg(state, 0x1a, 0x0009); } } EXPORT_SYMBOL(dib0070_ctrl_agc_filter); struct dib0070_tuning { - u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ - u8 switch_trim; - u8 vco_band; - u8 hfdiv; - u8 vco_multi; - u8 presc; - u8 wbdmux; - u16 tuner_enable; + u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ + u8 switch_trim; + u8 vco_band; + u8 hfdiv; + u8 vco_multi; + u8 presc; + u8 wbdmux; + u16 tuner_enable; }; struct dib0070_lna_match { - u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ - u8 lna_band; + u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ + u8 lna_band; }; static const struct dib0070_tuning dib0070s_tuning_table[] = { - {570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800}, /* UHF */ - {700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800}, - {863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800}, - {1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, /* LBAND */ - {1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, - {2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, - {0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000}, /* SBAND */ + { 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */ + { 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 }, + { 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 }, + { 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */ + { 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, + { 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, + { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */ }; static const struct dib0070_tuning dib0070_tuning_table[] = { - {115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000}, /* FM below 92MHz cannot be tuned */ - {179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000}, /* VHF */ - {189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000}, - {250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000}, - {569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800}, /* UHF */ - {699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800}, - {863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800}, - {0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400}, /* LBAND or everything higher than UHF */ + { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */ + { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */ + { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 }, + { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 }, + { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */ + { 699999, 2, 0 ,1, 4, 2, 2, 0x4000 | 0x0800 }, + { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 }, + { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */ }; static const struct dib0070_lna_match dib0070_lna_flip_chip[] = { - {180000, 0}, /* VHF */ - {188000, 1}, - {196400, 2}, - {250000, 3}, - {550000, 0}, /* UHF */ - {590000, 1}, - {666000, 3}, - {864000, 5}, - {1500000, 0}, /* LBAND or everything higher than UHF */ - {1600000, 1}, - {2000000, 3}, - {0xffffffff, 7}, + { 180000, 0 }, /* VHF */ + { 188000, 1 }, + { 196400, 2 }, + { 250000, 3 }, + { 550000, 0 }, /* UHF */ + { 590000, 1 }, + { 666000, 3 }, + { 864000, 5 }, + { 1500000, 0 }, /* LBAND or everything higher than UHF */ + { 1600000, 1 }, + { 2000000, 3 }, + { 0xffffffff, 7 }, }; static const struct dib0070_lna_match dib0070_lna[] = { - {180000, 0}, /* VHF */ - {188000, 1}, - {196400, 2}, - {250000, 3}, - {550000, 2}, /* UHF */ - {650000, 3}, - {750000, 5}, - {850000, 6}, - {864000, 7}, - {1500000, 0}, /* LBAND or everything higher than UHF */ - {1600000, 1}, - {2000000, 3}, - {0xffffffff, 7}, + { 180000, 0 }, /* VHF */ + { 188000, 1 }, + { 196400, 2 }, + { 250000, 3 }, + { 550000, 2 }, /* UHF */ + { 650000, 3 }, + { 750000, 5 }, + { 850000, 6 }, + { 864000, 7 }, + { 1500000, 0 }, /* LBAND or everything higher than UHF */ + { 1600000, 1 }, + { 2000000, 3 }, + { 0xffffffff, 7 }, }; -#define LPF 100 // define for the loop filter 100kHz by default 16-07-06 +#define LPF 100 // define for the loop filter 100kHz by default 16-07-06 static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) { - struct dib0070_state *state = fe->tuner_priv; + struct dib0070_state *state = fe->tuner_priv; - const struct dib0070_tuning *tune; - const struct dib0070_lna_match *lna_match; + const struct dib0070_tuning *tune; + const struct dib0070_lna_match *lna_match; - enum frontend_tune_state *tune_state = &state->tune_state; - int ret = 10; /* 1ms is the default delay most of the time */ + enum frontend_tune_state *tune_state = &state->tune_state; + int ret = 10; /* 1ms is the default delay most of the time */ - u8 band = (u8) BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000); - u32 freq = fe->dtv_property_cache.frequency / 1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf); + u8 band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000); + u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf); #ifdef CONFIG_SYS_ISDBT - if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1) + if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1) if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))) || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2))) || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))) - freq += 850; + freq += 850; #endif + if (state->current_rf != freq) { + + switch (state->revision) { + case DIB0070S_P1A: + tune = dib0070s_tuning_table; + lna_match = dib0070_lna; + break; + default: + tune = dib0070_tuning_table; + if (state->cfg->flip_chip) + lna_match = dib0070_lna_flip_chip; + else + lna_match = dib0070_lna; + break; + } + while (freq > tune->max_freq) /* find the right one */ + tune++; + while (freq > lna_match->max_freq) /* find the right one */ + lna_match++; + + state->current_tune_table_index = tune; + state->lna_match = lna_match; + } + + if (*tune_state == CT_TUNER_START) { + dprintk( "Tuning for Band: %hd (%d kHz)", band, freq); if (state->current_rf != freq) { + u8 REFDIV; + u32 FBDiv, Rest, FREF, VCOF_kHz; + u8 Den; - switch (state->revision) { - case DIB0070S_P1A: - tune = dib0070s_tuning_table; - lna_match = dib0070_lna; - break; - default: - tune = dib0070_tuning_table; - if (state->cfg->flip_chip) - lna_match = dib0070_lna_flip_chip; - else - lna_match = dib0070_lna; - break; - } - while (freq > tune->max_freq) /* find the right one */ - tune++; - while (freq > lna_match->max_freq) /* find the right one */ - lna_match++; + state->current_rf = freq; + state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7); - state->current_tune_table_index = tune; - state->lna_match = lna_match; - } - if (*tune_state == CT_TUNER_START) { - dprintk("Tuning for Band: %hd (%d kHz)", band, freq); - if (state->current_rf != freq) { - u8 REFDIV; - u32 FBDiv, Rest, FREF, VCOF_kHz; - u8 Den; - - state->current_rf = freq; - state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7); - - dib0070_write_reg(state, 0x17, 0x30); - - VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2; - - switch (band) { - case BAND_VHF: - REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000); - break; - case BAND_FM: - REFDIV = (u8) ((state->cfg->clock_khz) / 1000); - break; - default: - REFDIV = (u8) (state->cfg->clock_khz / 10000); - break; - } - FREF = state->cfg->clock_khz / REFDIV; - - switch (state->revision) { - case DIB0070S_P1A: - FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF); - Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF; - break; - - case DIB0070_P1G: - case DIB0070_P1F: - default: - FBDiv = (freq / (FREF / 2)); - Rest = 2 * freq - FBDiv * FREF; - break; - } + dib0070_write_reg(state, 0x17, 0x30); + + + VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2; + + switch (band) { + case BAND_VHF: + REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000); + break; + case BAND_FM: + REFDIV = (u8) ((state->cfg->clock_khz) / 1000); + break; + default: + REFDIV = (u8) ( state->cfg->clock_khz / 10000); + break; + } + FREF = state->cfg->clock_khz / REFDIV; + + + + switch (state->revision) { + case DIB0070S_P1A: + FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF); + Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF; + break; + + case DIB0070_P1G: + case DIB0070_P1F: + default: + FBDiv = (freq / (FREF / 2)); + Rest = 2 * freq - FBDiv * FREF; + break; + } if (Rest < LPF) Rest = 0; @@ -402,98 +393,102 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par FBDiv += 1; } else if (Rest > (FREF - 2 * LPF)) Rest = FREF - 2 * LPF; - Rest = (Rest * 6528) / (FREF / 10); + Rest = (Rest * 6528) / (FREF / 10); - Den = 1; - if (Rest > 0) { - state->lo4 |= (1 << 14) | (1 << 12); - Den = 255; - } + Den = 1; + if (Rest > 0) { + state->lo4 |= (1 << 14) | (1 << 12); + Den = 255; + } - dib0070_write_reg(state, 0x11, (u16) FBDiv); - dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV); - dib0070_write_reg(state, 0x13, (u16) Rest); - if (state->revision == DIB0070S_P1A) { + dib0070_write_reg(state, 0x11, (u16)FBDiv); + dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV); + dib0070_write_reg(state, 0x13, (u16) Rest); - if (band == BAND_SBAND) { - dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); - dib0070_write_reg(state, 0x1d, 0xFFFF); - } else - dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1); - } + if (state->revision == DIB0070S_P1A) { + + if (band == BAND_SBAND) { + dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); + dib0070_write_reg(state, 0x1d,0xFFFF); + } else + dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1); + } dib0070_write_reg(state, 0x20, 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable); - dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF); - dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest); - dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1); - dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv); - dprintk("VCO = %hd", state->current_tune_table_index->vco_band); - dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq); - - *tune_state = CT_TUNER_STEP_0; - } else { /* we are already tuned to this frequency - the configuration is correct */ - ret = 50; /* wakeup time */ - *tune_state = CT_TUNER_STEP_5; - } - } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) { + dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF); + dprintk( "FBDIV: %d, Rest: %d", FBDiv, Rest); + dprintk( "Num: %hd, Den: %hd, SD: %hd",(u16) Rest, Den, (state->lo4 >> 12) & 0x1); + dprintk( "HFDIV code: %hd", state->current_tune_table_index->hfdiv); + dprintk( "VCO = %hd", state->current_tune_table_index->vco_band); + dprintk( "VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq); + + *tune_state = CT_TUNER_STEP_0; + } else { /* we are already tuned to this frequency - the configuration is correct */ + ret = 50; /* wakeup time */ + *tune_state = CT_TUNER_STEP_5; + } + } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) { - ret = dib0070_captrim(state, tune_state); + ret = dib0070_captrim(state, tune_state); - } else if (*tune_state == CT_TUNER_STEP_4) { - const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; - if (tmp != NULL) { - while (freq / 1000 > tmp->freq) /* find the right one */ - tmp++; + } else if (*tune_state == CT_TUNER_STEP_4) { + const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; + if (tmp != NULL) { + while (freq/1000 > tmp->freq) /* find the right one */ + tmp++; dib0070_write_reg(state, 0x0f, (0 << 15) | (1 << 14) | (3 << 12) | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7) | (state-> current_tune_table_index-> wbdmux << 0)); - state->wbd_gain_current = tmp->wbd_gain_val; - } else { + state->wbd_gain_current = tmp->wbd_gain_val; + } else { dib0070_write_reg(state, 0x0f, (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index-> wbdmux << 0)); - state->wbd_gain_current = 6; - } + state->wbd_gain_current = 6; + } - dib0070_write_reg(state, 0x06, 0x3fff); + dib0070_write_reg(state, 0x06, 0x3fff); dib0070_write_reg(state, 0x07, (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0)); - dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127)); - dib0070_write_reg(state, 0x0d, 0x0d80); + dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127)); + dib0070_write_reg(state, 0x0d, 0x0d80); - dib0070_write_reg(state, 0x18, 0x07ff); - dib0070_write_reg(state, 0x17, 0x0033); - *tune_state = CT_TUNER_STEP_5; - } else if (*tune_state == CT_TUNER_STEP_5) { - dib0070_set_bandwidth(fe, ch); - *tune_state = CT_TUNER_STOP; - } else { - ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */ - } - return ret; + dib0070_write_reg(state, 0x18, 0x07ff); + dib0070_write_reg(state, 0x17, 0x0033); + + + *tune_state = CT_TUNER_STEP_5; + } else if (*tune_state == CT_TUNER_STEP_5) { + dib0070_set_bandwidth(fe, ch); + *tune_state = CT_TUNER_STOP; + } else { + ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */ + } + return ret; } + static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) { - struct dib0070_state *state = fe->tuner_priv; - uint32_t ret; + struct dib0070_state *state = fe->tuner_priv; + uint32_t ret; - state->tune_state = CT_TUNER_START; + state->tune_state = CT_TUNER_START; - do { - ret = dib0070_tune_digital(fe, p); - if (ret != FE_CALLBACK_TIME_NEVER) - msleep(ret / 10); - else - break; - } while (state->tune_state != CT_TUNER_STOP); + do { + ret = dib0070_tune_digital(fe, p); + if (ret != FE_CALLBACK_TIME_NEVER) + msleep(ret/10); + else + break; + } while (state->tune_state != CT_TUNER_STOP); - return 0; + return 0; } static int dib0070_wakeup(struct dvb_frontend *fe) @@ -512,92 +507,111 @@ static int dib0070_sleep(struct dvb_frontend *fe) return 0; } -static const u16 dib0070_p1f_defaults[] = { +u8 dib0070_get_rf_output(struct dvb_frontend *fe) +{ + struct dib0070_state *state = fe->tuner_priv; + return (dib0070_read_reg(state, 0x07) >> 11) & 0x3; +} + +EXPORT_SYMBOL(dib0070_get_rf_output); +int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no) +{ + struct dib0070_state *state = fe->tuner_priv; + u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff; + if (no > 3) no = 3; + if (no < 1) no = 1; + return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11)); +} + +EXPORT_SYMBOL(dib0070_set_rf_output); +static const u16 dib0070_p1f_defaults[] = + +{ 7, 0x02, - 0x0008, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - 0x0002, - 0x0100, + 0x0008, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0002, + 0x0100, 3, 0x0d, - 0x0d80, - 0x0001, - 0x0000, + 0x0d80, + 0x0001, + 0x0000, 4, 0x11, - 0x0000, - 0x0103, - 0x0000, - 0x0000, + 0x0000, + 0x0103, + 0x0000, + 0x0000, 3, 0x16, - 0x0004 | 0x0040, - 0x0030, - 0x07ff, + 0x0004 | 0x0040, + 0x0030, + 0x07ff, 6, 0x1b, - 0x4112, - 0xff00, - 0xc07f, - 0x0000, - 0x0180, - 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001, + 0x4112, + 0xff00, + 0xc07f, + 0x0000, + 0x0180, + 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001, 0, }; static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain) { - u16 tuner_en = dib0070_read_reg(state, 0x20); - u16 offset; - - dib0070_write_reg(state, 0x18, 0x07ff); - dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001); - dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0)); - msleep(9); - offset = dib0070_read_reg(state, 0x19); - dib0070_write_reg(state, 0x20, tuner_en); - return offset; + u16 tuner_en = dib0070_read_reg(state, 0x20); + u16 offset; + + dib0070_write_reg(state, 0x18, 0x07ff); + dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001); + dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0)); + msleep(9); + offset = dib0070_read_reg(state, 0x19); + dib0070_write_reg(state, 0x20, tuner_en); + return offset; } static void dib0070_wbd_offset_calibration(struct dib0070_state *state) { - u8 gain; - for (gain = 6; gain < 8; gain++) { - state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2); - dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain - 6]); - } + u8 gain; + for (gain = 6; gain < 8; gain++) { + state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2); + dprintk( "Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]); + } } u16 dib0070_wbd_offset(struct dvb_frontend *fe) { - struct dib0070_state *state = fe->tuner_priv; - const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; - u32 freq = fe->dtv_property_cache.frequency / 1000; - - if (tmp != NULL) { - while (freq / 1000 > tmp->freq) /* find the right one */ - tmp++; - state->wbd_gain_current = tmp->wbd_gain_val; + struct dib0070_state *state = fe->tuner_priv; + const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; + u32 freq = fe->dtv_property_cache.frequency/1000; + + if (tmp != NULL) { + while (freq/1000 > tmp->freq) /* find the right one */ + tmp++; + state->wbd_gain_current = tmp->wbd_gain_val; } else - state->wbd_gain_current = 6; + state->wbd_gain_current = 6; - return state->wbd_offset_3_3[state->wbd_gain_current - 6]; + return state->wbd_offset_3_3[state->wbd_gain_current - 6]; } - EXPORT_SYMBOL(dib0070_wbd_offset); #define pgm_read_word(w) (*w) static int dib0070_reset(struct dvb_frontend *fe) { - struct dib0070_state *state = fe->tuner_priv; + struct dib0070_state *state = fe->tuner_priv; u16 l, r, *n; HARD_RESET(state); + #ifndef FORCE_SBAND_TUNER if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1) state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff; @@ -605,13 +619,13 @@ static int dib0070_reset(struct dvb_frontend *fe) #else #warning forcing SBAND #endif - state->revision = DIB0070S_P1A; + state->revision = DIB0070S_P1A; /* P1F or not */ - dprintk("Revision: %x", state->revision); + dprintk( "Revision: %x", state->revision); if (state->revision == DIB0070_P1D) { - dprintk("Error: this driver is not to be used meant for P1D or earlier"); + dprintk( "Error: this driver is not to be used meant for P1D or earlier"); return -EINVAL; } @@ -620,7 +634,7 @@ static int dib0070_reset(struct dvb_frontend *fe) while (l) { r = pgm_read_word(n++); do { - dib0070_write_reg(state, (u8) r, pgm_read_word(n++)); + dib0070_write_reg(state, (u8)r, pgm_read_word(n++)); r++; } while (--l); l = pgm_read_word(n++); @@ -633,6 +647,7 @@ static int dib0070_reset(struct dvb_frontend *fe) else r = 2; + r |= state->cfg->osc_buffer_state << 3; dib0070_write_reg(state, 0x10, r); @@ -643,16 +658,24 @@ static int dib0070_reset(struct dvb_frontend *fe) dib0070_write_reg(state, 0x02, r | (1 << 5)); } - if (state->revision == DIB0070S_P1A) - dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); - else + if (state->revision == DIB0070S_P1A) + dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); + else dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter); dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8); - dib0070_wbd_offset_calibration(state); + dib0070_wbd_offset_calibration(state); - return 0; + return 0; +} + +static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct dib0070_state *state = fe->tuner_priv; + + *frequency = 1000 * state->current_rf; + return 0; } static int dib0070_release(struct dvb_frontend *fe) @@ -664,22 +687,22 @@ static int dib0070_release(struct dvb_frontend *fe) static const struct dvb_tuner_ops dib0070_ops = { .info = { - .name = "DiBcom DiB0070", - .frequency_min = 45000000, - .frequency_max = 860000000, - .frequency_step = 1000, - }, - .release = dib0070_release, - - .init = dib0070_wakeup, - .sleep = dib0070_sleep, - .set_params = dib0070_tune, - -// .get_frequency = dib0070_get_frequency, + .name = "DiBcom DiB0070", + .frequency_min = 45000000, + .frequency_max = 860000000, + .frequency_step = 1000, + }, + .release = dib0070_release, + + .init = dib0070_wakeup, + .sleep = dib0070_sleep, + .set_params = dib0070_tune, + + .get_frequency = dib0070_get_frequency, // .get_bandwidth = dib0070_get_bandwidth }; -struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) +struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) { struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL); if (state == NULL) @@ -687,7 +710,7 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter state->cfg = cfg; state->i2c = i2c; - state->fe = fe; + state->fe = fe; fe->tuner_priv = state; if (dib0070_reset(fe) != 0) @@ -699,12 +722,11 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter fe->tuner_priv = state; return fe; - free_mem: +free_mem: kfree(state); fe->tuner_priv = NULL; return NULL; } - EXPORT_SYMBOL(dib0070_attach); MODULE_AUTHOR("Patrick Boettcher "); diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h index eec9e52..45c31fa 100644 --- a/drivers/media/dvb/frontends/dib0070.h +++ b/drivers/media/dvb/frontends/dib0070.h @@ -52,6 +52,8 @@ struct dib0070_config { extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg); extern u16 dib0070_wbd_offset(struct dvb_frontend *); extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, u8 open); +extern u8 dib0070_get_rf_output(struct dvb_frontend *fe); +extern int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no); #else static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) { @@ -62,7 +64,7 @@ static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struc static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); - return -ENODEV; + return 0; } static inline void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open) diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c new file mode 100644 index 0000000..e37d32d --- /dev/null +++ b/drivers/media/dvb/frontends/dib0090.c @@ -0,0 +1,1525 @@ +/* + * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner. + * + * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/) + * + * This program is free software; 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 code is more or less generated from another driver, please + * excuse some codingstyle oddities. + * + */ + +#include +#include + +#include "dvb_frontend.h" + +#include "dib0090.h" +#include "dibx000_common.h" + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); + +#define dprintk(args...) do { \ + if (debug) { \ + printk(KERN_DEBUG "DiB0090: "); \ + printk(args); \ + printk("\n"); \ + } \ +} while (0) + +#define CONFIG_SYS_ISDBT +#define CONFIG_BAND_CBAND +#define CONFIG_BAND_VHF +#define CONFIG_BAND_UHF +#define CONFIG_DIB0090_USE_PWM_AGC + +#define EN_LNA0 0x8000 +#define EN_LNA1 0x4000 +#define EN_LNA2 0x2000 +#define EN_LNA3 0x1000 +#define EN_MIX0 0x0800 +#define EN_MIX1 0x0400 +#define EN_MIX2 0x0200 +#define EN_MIX3 0x0100 +#define EN_IQADC 0x0040 +#define EN_PLL 0x0020 +#define EN_TX 0x0010 +#define EN_BB 0x0008 +#define EN_LO 0x0004 +#define EN_BIAS 0x0001 + +#define EN_IQANA 0x0002 +#define EN_DIGCLK 0x0080 /* not in the 0x24 reg, only in 0x1b */ +#define EN_CRYSTAL 0x0002 + +#define EN_UHF 0x22E9 +#define EN_VHF 0x44E9 +#define EN_LBD 0x11E9 +#define EN_SBD 0x44E9 +#define EN_CAB 0x88E9 + +#define pgm_read_word(w) (*w) + +struct dc_calibration; + +struct dib0090_tuning { + u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ + u8 switch_trim; + u8 lna_tune; + u8 lna_bias; + u16 v2i; + u16 mix; + u16 load; + u16 tuner_enable; +}; + +struct dib0090_pll { + u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ + u8 vco_band; + u8 hfdiv_code; + u8 hfdiv; + u8 topresc; +}; + +struct dib0090_state { + struct i2c_adapter *i2c; + struct dvb_frontend *fe; + const struct dib0090_config *config; + + u8 current_band; + u16 revision; + enum frontend_tune_state tune_state; + u32 current_rf; + + u16 wbd_offset; + s16 wbd_target; /* in dB */ + + s16 rf_gain_limit; /* take-over-point: where to split between bb and rf gain */ + s16 current_gain; /* keeps the currently programmed gain */ + u8 agc_step; /* new binary search */ + + u16 gain[2]; /* for channel monitoring */ + + const u16 *rf_ramp; + const u16 *bb_ramp; + + /* for the software AGC ramps */ + u16 bb_1_def; + u16 rf_lt_def; + u16 gain_reg[4]; + + /* for the captrim/dc-offset search */ + s8 step; + s16 adc_diff; + s16 min_adc_diff; + + s8 captrim; + s8 fcaptrim; + + const struct dc_calibration *dc; + u16 bb6, bb7; + + const struct dib0090_tuning *current_tune_table_index; + const struct dib0090_pll *current_pll_table_index; + + u8 tuner_is_tuned; + u8 agc_freeze; + + u8 reset; +}; + +static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) +{ + u8 b[2]; + struct i2c_msg msg[2] = { + {.addr = state->config->i2c_address,.flags = 0,.buf = ®,.len = 1}, + {.addr = state->config->i2c_address,.flags = I2C_M_RD,.buf = b,.len = 2}, + }; + if (i2c_transfer(state->i2c, msg, 2) != 2) { + printk(KERN_WARNING "DiB0090 I2C read failed\n"); + return 0; + } + return (b[0] << 8) | b[1]; +} + +static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) +{ + u8 b[3] = { reg & 0xff, val >> 8, val & 0xff }; + struct i2c_msg msg = {.addr = state->config->i2c_address,.flags = 0,.buf = b,.len = 3 }; + if (i2c_transfer(state->i2c, &msg, 1) != 1) { + printk(KERN_WARNING "DiB0090 I2C write failed\n"); + return -EREMOTEIO; + } + return 0; +} + +#define HARD_RESET(state) do { if (cfg->reset) { if (cfg->sleep) cfg->sleep(fe, 0); msleep(10); cfg->reset(fe, 1); msleep(10); cfg->reset(fe, 0); msleep(10); } } while (0) +#define ADC_TARGET -220 +#define GAIN_ALPHA 5 +#define WBD_ALPHA 6 +#define LPF 100 +static void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c) +{ + do { + dib0090_write_reg(state, r++, *b++); + } while (--c); +} + +static u16 dib0090_identify(struct dvb_frontend *fe) +{ + struct dib0090_state *state = fe->tuner_priv; + u16 v; + + v = dib0090_read_reg(state, 0x1a); + +#ifdef FIRMWARE_FIREFLY + /* pll is not locked locked */ + if (!(v & 0x800)) + dprintk("FE%d : Identification : pll is not yet locked", fe->id); +#endif + + /* without PLL lock info */ + v &= 0x3ff; + dprintk("P/V: %04x:", v); + + if ((v >> 8) & 0xf) + dprintk("FE%d : Product ID = 0x%x : KROSUS", fe->id, (v >> 8) & 0xf); + else + return 0xff; + + v &= 0xff; + if (((v >> 5) & 0x7) == 0x1) + dprintk("FE%d : MP001 : 9090/8096", fe->id); + else if (((v >> 5) & 0x7) == 0x4) + dprintk("FE%d : MP005 : Single Sband", fe->id); + else if (((v >> 5) & 0x7) == 0x6) + dprintk("FE%d : MP008 : diversity VHF-UHF-LBAND", fe->id); + else if (((v >> 5) & 0x7) == 0x7) + dprintk("FE%d : MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND", fe->id); + else + return 0xff; + + /* revision only */ + if ((v & 0x1f) == 0x3) + dprintk("FE%d : P1-D/E/F detected", fe->id); + else if ((v & 0x1f) == 0x1) + dprintk("FE%d : P1C detected", fe->id); + else if ((v & 0x1f) == 0x0) { +#ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT + dprintk("FE%d : P1-A/B detected: using previous driver - support will be removed soon", fe->id); + dib0090_p1b_register(fe); +#else + dprintk("FE%d : P1-A/B detected: driver is deactivated - not available", fe->id); + return 0xff; +#endif + } + + return v; +} + +static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg) +{ + struct dib0090_state *state = fe->tuner_priv; + + HARD_RESET(state); + + dib0090_write_reg(state, 0x24, EN_PLL); + dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */ + + /* adcClkOutRatio=8->7, release reset */ + dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0); + if (cfg->clkoutdrive != 0) + dib0090_write_reg(state, 0x23, + (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 10) | (1 << 9) | (0 << 8) | (cfg->clkoutdrive << 5) | (cfg-> + clkouttobamse + << 4) | (0 + << + 2) + | (0)); + else + dib0090_write_reg(state, 0x23, + (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 10) | (1 << 9) | (0 << 8) | (7 << 5) | (cfg-> + clkouttobamse << 4) | (0 + << + 2) + | (0)); + + /* enable pll, de-activate reset, ratio: 2/1 = 60MHz */ + dib0090_write_reg(state, 0x21, + (cfg->io.pll_bypass << 15) | (1 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)); + +} + +static int dib0090_wakeup(struct dvb_frontend *fe) +{ + struct dib0090_state *state = fe->tuner_priv; + if (state->config->sleep) + state->config->sleep(fe, 0); + return 0; +} + +static int dib0090_sleep(struct dvb_frontend *fe) +{ + struct dib0090_state *state = fe->tuner_priv; + if (state->config->sleep) + state->config->sleep(fe, 1); + return 0; +} + +extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast) +{ + struct dib0090_state *state = fe->tuner_priv; + if (fast) + dib0090_write_reg(state, 0x04, 0); //1kHz + else + dib0090_write_reg(state, 0x04, 1); //almost frozen +} + +EXPORT_SYMBOL(dib0090_dcc_freq); +static const u16 rf_ramp_pwm_cband[] = { + 0, /* max RF gain in 10th of dB */ + 0, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */ + 0, /* ramp_max = maximum X used on the ramp */ + (0 << 10) | 0, /* 0x2c, LNA 1 = 0dB */ + (0 << 10) | 0, /* 0x2d, LNA 1 */ + (0 << 10) | 0, /* 0x2e, LNA 2 = 0dB */ + (0 << 10) | 0, /* 0x2f, LNA 2 */ + (0 << 10) | 0, /* 0x30, LNA 3 = 0dB */ + (0 << 10) | 0, /* 0x31, LNA 3 */ + (0 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */ + (0 << 10) | 0, /* GAIN_4_2, LNA 4 */ +}; + +static const u16 rf_ramp_vhf[] = { + 412, /* max RF gain in 10th of dB */ + 132, 307, 127, /* LNA1, 13.2dB */ + 105, 412, 255, /* LNA2, 10.5dB */ + 50, 50, 127, /* LNA3, 5dB */ + 125, 175, 127, /* LNA4, 12.5dB */ + 0, 0, 127, /* CBAND, 0dB */ +}; + +static const u16 rf_ramp_uhf[] = { + 412, /* max RF gain in 10th of dB */ + 132, 307, 127, /* LNA1 : total gain = 13.2dB, point on the ramp where this amp is full gain, value to write to get full gain */ + 105, 412, 255, /* LNA2 : 10.5 dB */ + 50, 50, 127, /* LNA3 : 5.0 dB */ + 125, 175, 127, /* LNA4 : 12.5 dB */ + 0, 0, 127, /* CBAND : 0.0 dB */ +}; + +static const u16 rf_ramp_cband[] = { + 332, /* max RF gain in 10th of dB */ + 132, 252, 127, /* LNA1, dB */ + 80, 332, 255, /* LNA2, dB */ + 0, 0, 127, /* LNA3, dB */ + 0, 0, 127, /* LNA4, dB */ + 120, 120, 127, /* LT1 CBAND */ +}; + +static const u16 rf_ramp_pwm_vhf[] = { + 404, /* max RF gain in 10th of dB */ + 25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */ + 1011, /* ramp_max = maximum X used on the ramp */ + (6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */ + (0 << 10) | 756, /* 0x2d, LNA 1 */ + (16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */ + (0 << 10) | 1011, /* 0x2f, LNA 2 */ + (16 << 10) | 290, /* 0x30, LNA 3 = 5dB */ + (0 << 10) | 417, /* 0x31, LNA 3 */ + (7 << 10) | 0, /* GAIN_4_1, LNA 4 = 12.5dB */ + (0 << 10) | 290, /* GAIN_4_2, LNA 4 */ +}; + +static const u16 rf_ramp_pwm_uhf[] = { + 404, /* max RF gain in 10th of dB */ + 25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */ + 1011, /* ramp_max = maximum X used on the ramp */ + (6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */ + (0 << 10) | 756, /* 0x2d, LNA 1 */ + (16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */ + (0 << 10) | 1011, /* 0x2f, LNA 2 */ + (16 << 10) | 0, /* 0x30, LNA 3 = 5dB */ + (0 << 10) | 127, /* 0x31, LNA 3 */ + (7 << 10) | 127, /* GAIN_4_1, LNA 4 = 12.5dB */ + (0 << 10) | 417, /* GAIN_4_2, LNA 4 */ +}; + +static const u16 bb_ramp_boost[] = { + 550, /* max BB gain in 10th of dB */ + 260, 260, 26, /* BB1, 26dB */ + 290, 550, 29, /* BB2, 29dB */ +}; + +static const u16 bb_ramp_pwm_normal[] = { + 500, /* max RF gain in 10th of dB */ + 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x34 */ + 400, + (2 << 9) | 0, /* 0x35 = 21dB */ + (0 << 9) | 168, /* 0x36 */ + (2 << 9) | 168, /* 0x37 = 29dB */ + (0 << 9) | 400, /* 0x38 */ +}; + +struct slope { + int16_t range; + int16_t slope; +}; +static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val) +{ + u8 i; + u16 rest; + u16 ret = 0; + for (i = 0; i < num; i++) { + if (val > slopes[i].range) + rest = slopes[i].range; + else + rest = val; + ret += (rest * slopes[i].slope) / slopes[i].range; + val -= rest; + } + return ret; +} + +static const struct slope dib0090_wbd_slopes[3] = { + {66, 120}, /* -64,-52: offset - 65 */ + {600, 170}, /* -52,-35: 65 - 665 */ + {170, 250}, /* -45,-10: 665 - 835 */ +}; + +static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd) +{ + wbd &= 0x3ff; + if (wbd < state->wbd_offset) + wbd = 0; + else + wbd -= state->wbd_offset; + /* -64dB is the floor */ + return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd); +} + +static void dib0090_wbd_target(struct dib0090_state *state, u32 rf) +{ + u16 offset = 250; + + /* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */ + + if (state->current_band == BAND_VHF) + offset = 650; +#ifndef FIRMWARE_FIREFLY + if (state->current_band == BAND_VHF) + offset = state->config->wbd_vhf_offset; + if (state->current_band == BAND_CBAND) + offset = state->config->wbd_cband_offset; +#endif + + state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset); + dprintk("wbd-target: %d dB", (u32) state->wbd_target); +} + +static const int gain_reg_addr[4] = { + 0x08, 0x0a, 0x0f, 0x01 +}; + +static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force) +{ + u16 rf, bb, ref; + u16 i, v, gain_reg[4] = { 0 }, gain; + const u16 *g; + + if (top_delta < -511) + top_delta = -511; + if (top_delta > 511) + top_delta = 511; + + if (force) { + top_delta *= (1 << WBD_ALPHA); + gain_delta *= (1 << GAIN_ALPHA); + } + + if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit)) /* overflow */ + state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA; + else + state->rf_gain_limit += top_delta; + + if (state->rf_gain_limit < 0) /*underflow */ + state->rf_gain_limit = 0; + + /* use gain as a temporary variable and correct current_gain */ + gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA; + if (gain_delta >= ((s16) gain - state->current_gain)) /* overflow */ + state->current_gain = gain; + else + state->current_gain += gain_delta; + /* cannot be less than 0 (only if gain_delta is less than 0 we can have current_gain < 0) */ + if (state->current_gain < 0) + state->current_gain = 0; + + /* now split total gain to rf and bb gain */ + gain = state->current_gain >> GAIN_ALPHA; + + /* requested gain is bigger than rf gain limit - ACI/WBD adjustment */ + if (gain > (state->rf_gain_limit >> WBD_ALPHA)) { + rf = state->rf_gain_limit >> WBD_ALPHA; + bb = gain - rf; + if (bb > state->bb_ramp[0]) + bb = state->bb_ramp[0]; + } else { /* high signal level -> all gains put on RF */ + rf = gain; + bb = 0; + } + + state->gain[0] = rf; + state->gain[1] = bb; + + /* software ramp */ + /* Start with RF gains */ + g = state->rf_ramp + 1; /* point on RF LNA1 max gain */ + ref = rf; + for (i = 0; i < 7; i++) { /* Go over all amplifiers => 5RF amps + 2 BB amps = 7 amps */ + if (g[0] == 0 || ref < (g[1] - g[0])) /* if total gain of the current amp is null or this amp is not concerned because it starts to work from an higher gain value */ + v = 0; /* force the gain to write for the current amp to be null */ + else if (ref >= g[1]) /* Gain to set is higher than the high working point of this amp */ + v = g[2]; /* force this amp to be full gain */ + else /* compute the value to set to this amp because we are somewhere in his range */ + v = ((ref - (g[1] - g[0])) * g[2]) / g[0]; + + if (i == 0) /* LNA 1 reg mapping */ + gain_reg[0] = v; + else if (i == 1) /* LNA 2 reg mapping */ + gain_reg[0] |= v << 7; + else if (i == 2) /* LNA 3 reg mapping */ + gain_reg[1] = v; + else if (i == 3) /* LNA 4 reg mapping */ + gain_reg[1] |= v << 7; + else if (i == 4) /* CBAND LNA reg mapping */ + gain_reg[2] = v | state->rf_lt_def; + else if (i == 5) /* BB gain 1 reg mapping */ + gain_reg[3] = v << 3; + else if (i == 6) /* BB gain 2 reg mapping */ + gain_reg[3] |= v << 8; + + g += 3; /* go to next gain bloc */ + + /* When RF is finished, start with BB */ + if (i == 4) { + g = state->bb_ramp + 1; /* point on BB gain 1 max gain */ + ref = bb; + } + } + gain_reg[3] |= state->bb_1_def; + gain_reg[3] |= ((bb % 10) * 100) / 125; + +#ifdef DEBUG_AGC + dprintk("GA CALC: DB: %3d(rf) + %3d(bb) = %3d gain_reg[0]=%04x gain_reg[1]=%04x gain_reg[2]=%04x gain_reg[0]=%04x", rf, bb, rf + bb, + gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]); +#endif + + /* Write the amplifier regs */ + for (i = 0; i < 4; i++) { + v = gain_reg[i]; + if (force || state->gain_reg[i] != v) { + state->gain_reg[i] = v; + dib0090_write_reg(state, gain_reg_addr[i], v); + } + } +} + +static void dib0090_set_boost(struct dib0090_state *state, int onoff) +{ + state->bb_1_def &= 0xdfff; + state->bb_1_def |= onoff << 13; +} + +static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg) +{ + state->rf_ramp = cfg; +} + +static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg) +{ + state->rf_ramp = cfg; + + dib0090_write_reg(state, 0x2a, 0xffff); + + dprintk("total RF gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x2a)); + + dib0090_write_regs(state, 0x2c, cfg + 3, 6); + dib0090_write_regs(state, 0x3e, cfg + 9, 2); +} + +static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg) +{ + state->bb_ramp = cfg; + dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */ +} + +static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg) +{ + state->bb_ramp = cfg; + + dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */ + + dib0090_write_reg(state, 0x33, 0xffff); + dprintk("total BB gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x33)); + dib0090_write_regs(state, 0x35, cfg + 3, 4); +} + +void dib0090_pwm_gain_reset(struct dvb_frontend *fe) +{ + struct dib0090_state *state = fe->tuner_priv; + /* reset the AGC */ + + if (state->config->use_pwm_agc) { +#ifdef CONFIG_BAND_SBAND + if (state->current_band == BAND_SBAND) { + dib0090_set_rframp_pwm(state, rf_ramp_pwm_sband); + dib0090_set_bbramp_pwm(state, bb_ramp_pwm_boost); + } else +#endif +#ifdef CONFIG_BAND_CBAND + if (state->current_band == BAND_CBAND) { + dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband); + dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal); + } else +#endif +#ifdef CONFIG_BAND_VHF + if (state->current_band == BAND_VHF) { + dib0090_set_rframp_pwm(state, rf_ramp_pwm_vhf); + dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal); + } else +#endif + { + dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf); + dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal); + } + + if (state->rf_ramp[0] != 0) + dib0090_write_reg(state, 0x32, (3 << 11)); + else + dib0090_write_reg(state, 0x32, (0 << 11)); + + dib0090_write_reg(state, 0x39, (1 << 10)); // 0 gain by default + } +} + +EXPORT_SYMBOL(dib0090_pwm_gain_reset); +int dib0090_gain_control(struct dvb_frontend *fe) +{ + struct dib0090_state *state = fe->tuner_priv; + enum frontend_tune_state *tune_state = &state->tune_state; + int ret = 10; + + u16 wbd_val = 0; + u8 apply_gain_immediatly = 1; + s16 wbd_error = 0, adc_error = 0; + + if (*tune_state == CT_AGC_START) { + state->agc_freeze = 0; + dib0090_write_reg(state, 0x04, 0x0); + +#ifdef CONFIG_BAND_SBAND + if (state->current_band == BAND_SBAND) { + dib0090_set_rframp(state, rf_ramp_sband); + dib0090_set_bbramp(state, bb_ramp_boost); + } else +#endif +#ifdef CONFIG_BAND_VHF + if (state->current_band == BAND_VHF) { + dib0090_set_rframp(state, rf_ramp_vhf); + dib0090_set_bbramp(state, bb_ramp_boost); + } else +#endif +#ifdef CONFIG_BAND_CBAND + if (state->current_band == BAND_CBAND) { + dib0090_set_rframp(state, rf_ramp_cband); + dib0090_set_bbramp(state, bb_ramp_boost); + } else +#endif + { + dib0090_set_rframp(state, rf_ramp_uhf); + dib0090_set_bbramp(state, bb_ramp_boost); + } + + dib0090_write_reg(state, 0x32, 0); + dib0090_write_reg(state, 0x39, 0); + + dib0090_wbd_target(state, state->current_rf); + + state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA; + state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA; + + *tune_state = CT_AGC_STEP_0; + } else if (!state->agc_freeze) { + s16 wbd; + + int adc; + wbd_val = dib0090_read_reg(state, 0x1d); + + /* read and calc the wbd power */ + wbd = dib0090_wbd_to_db(state, wbd_val); + wbd_error = state->wbd_target - wbd; + + if (*tune_state == CT_AGC_STEP_0) { + if (wbd_error < 0 && state->rf_gain_limit > 0) { +#ifdef CONFIG_BAND_CBAND + /* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */ + u8 ltg2 = (state->rf_lt_def >> 10) & 0x7; + if (state->current_band == BAND_CBAND && ltg2) { + ltg2 >>= 1; + state->rf_lt_def &= ltg2 << 10; /* reduce in 3 steps from 7 to 0 */ + } +#endif + } else { + state->agc_step = 0; + *tune_state = CT_AGC_STEP_1; + } + } else { + /* calc the adc power */ + adc = state->config->get_adc_power(fe); + adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21; /* included in [0:-700] */ + + adc_error = (s16) (((s32) ADC_TARGET) - adc); +#ifdef CONFIG_STANDARD_DAB + if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) + adc_error += 130; +#endif +#ifdef CONFIG_STANDARD_DVBT + if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT && + (state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16)) + adc_error += 60; +#endif +#ifdef CONFIG_SYS_ISDBT + if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count > + 0) + && + ((state->fe->dtv_property_cache.layer[0].modulation == + QAM_64) + || (state->fe->dtv_property_cache.layer[0]. + modulation == QAM_16))) + || + ((state->fe->dtv_property_cache.layer[1].segment_count > + 0) + && + ((state->fe->dtv_property_cache.layer[1].modulation == + QAM_64) + || (state->fe->dtv_property_cache.layer[1]. + modulation == QAM_16))) + || + ((state->fe->dtv_property_cache.layer[2].segment_count > + 0) + && + ((state->fe->dtv_property_cache.layer[2].modulation == + QAM_64) + || (state->fe->dtv_property_cache.layer[2]. + modulation == QAM_16))) + ) + ) + adc_error += 60; +#endif + + if (*tune_state == CT_AGC_STEP_1) { /* quickly go to the correct range of the ADC power */ + if (ABS(adc_error) < 50 || state->agc_step++ > 5) { + +#ifdef CONFIG_STANDARD_DAB + if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) { + dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63)); /* cap value = 63 : narrow BB filter : Fc = 1.8MHz */ + dib0090_write_reg(state, 0x04, 0x0); + } else +#endif + { + dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32)); + dib0090_write_reg(state, 0x04, 0x01); /*0 = 1KHz ; 1 = 150Hz ; 2 = 50Hz ; 3 = 50KHz ; 4 = servo fast */ + } + + *tune_state = CT_AGC_STOP; + } + } else { + /* everything higher than or equal to CT_AGC_STOP means tracking */ + ret = 100; /* 10ms interval */ + apply_gain_immediatly = 0; + } + } +#ifdef DEBUG_AGC + dprintk + ("FE: %d, tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm", + (u32) fe->id, (u32) * tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val, + (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA)); +#endif + } + + /* apply gain */ + if (!state->agc_freeze) + dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly); + return ret; +} + +EXPORT_SYMBOL(dib0090_gain_control); +void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt) +{ + struct dib0090_state *state = fe->tuner_priv; + if (rf) + *rf = state->gain[0]; + if (bb) + *bb = state->gain[1]; + if (rf_gain_limit) + *rf_gain_limit = state->rf_gain_limit; + if (rflt) + *rflt = (state->rf_lt_def >> 10) & 0x7; +} + +EXPORT_SYMBOL(dib0090_get_current_gain); +u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner) +{ + struct dib0090_state *st = tuner->tuner_priv; + return st->wbd_offset; +} + +EXPORT_SYMBOL(dib0090_get_wbd_offset); +static const u16 dib0090_defaults[] = { + + 25, 0x01, + 0x0000, + 0x99a0, + 0x6008, + 0x0000, + 0x8acb, + 0x0000, + 0x0405, + 0x0000, + 0x0000, + 0x0000, + 0xb802, + 0x0300, + 0x2d12, + 0xbac0, + 0x7c00, + 0xdbb9, + 0x0954, + 0x0743, + 0x8000, + 0x0001, + 0x0040, + 0x0100, + 0x0000, + 0xe910, + 0x149e, + + 1, 0x1c, + 0xff2d, + + 1, 0x39, + 0x0000, + + 1, 0x1b, + EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL, + 2, 0x1e, + 0x07FF, + 0x0007, + + 1, 0x24, + EN_UHF | EN_CRYSTAL, + + 2, 0x3c, + 0x3ff, + 0x111, + 0 +}; + +static int dib0090_reset(struct dvb_frontend *fe) +{ + struct dib0090_state *state = fe->tuner_priv; + u16 l, r, *n; + + dib0090_reset_digital(fe, state->config); + state->revision = dib0090_identify(fe); + + /* Revision definition */ + if (state->revision == 0xff) + return -EINVAL; +#ifdef EFUSE + else if ((state->revision & 0x1f) >= 3) /* Update the efuse : Only available for KROSUS > P1C */ + dib0090_set_EFUSE(state); +#endif + +#ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT + if (!(state->revision & 0x1)) /* it is P1B - reset is already done */ + return 0; +#endif + + /* Upload the default values */ + n = (u16 *) dib0090_defaults; + l = pgm_read_word(n++); + while (l) { + r = pgm_read_word(n++); + do { + /* DEBUG_TUNER */ + /* dprintk("%d, %d, %d", l, r, pgm_read_word(n)); */ + dib0090_write_reg(state, r, pgm_read_word(n++)); + r++; + } while (--l); + l = pgm_read_word(n++); + } + + /* Congigure in function of the crystal */ + if (state->config->io.clock_khz >= 24000) + l = 1; + else + l = 2; + dib0090_write_reg(state, 0x14, l); + dprintk("Pll lock : %d", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1); + + state->reset = 3; /* enable iq-offset-calibration and wbd-calibration when tuning next time */ + + return 0; +} + +#define steps(u) (((u)>15)?((u)-16):(u)) +#define INTERN_WAIT 10 +static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state) +{ + int ret = INTERN_WAIT * 10; + + switch (*tune_state) { + case CT_TUNER_STEP_2: + /* Turns to positive */ + dib0090_write_reg(state, 0x1f, 0x7); + *tune_state = CT_TUNER_STEP_3; + break; + + case CT_TUNER_STEP_3: + state->adc_diff = dib0090_read_reg(state, 0x1d); + + /* Turns to negative */ + dib0090_write_reg(state, 0x1f, 0x4); + *tune_state = CT_TUNER_STEP_4; + break; + + case CT_TUNER_STEP_4: + state->adc_diff -= dib0090_read_reg(state, 0x1d); + *tune_state = CT_TUNER_STEP_5; + ret = 0; + break; + + default: + break; + } + + return ret; +} + +struct dc_calibration { + uint8_t addr; + uint8_t offset; + uint8_t pga:1; + uint16_t bb1; + uint8_t i:1; +}; + +static const struct dc_calibration dc_table[] = { + /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */ + {0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1}, + {0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0}, + /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */ + {0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1}, + {0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0}, + {0}, +}; + +static void dib0090_set_trim(struct dib0090_state *state) +{ + u16 *val; + + if (state->dc->addr == 0x07) + val = &state->bb7; + else + val = &state->bb6; + + *val &= ~(0x1f << state->dc->offset); + *val |= state->step << state->dc->offset; + + dib0090_write_reg(state, state->dc->addr, *val); +} + +static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state) +{ + int ret = 0; + + switch (*tune_state) { + + case CT_TUNER_START: + /* init */ + dprintk("Internal DC calibration"); + + /* the LNA is off */ + dib0090_write_reg(state, 0x24, 0x02ed); + + /* force vcm2 = 0.8V */ + state->bb6 = 0; + state->bb7 = 0x040d; + + state->dc = dc_table; + + *tune_state = CT_TUNER_STEP_0; + + /* fall through */ + + case CT_TUNER_STEP_0: + dib0090_write_reg(state, 0x01, state->dc->bb1); + dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7)); + + state->step = 0; + + state->min_adc_diff = 1023; + + *tune_state = CT_TUNER_STEP_1; + ret = 50; + break; + + case CT_TUNER_STEP_1: + dib0090_set_trim(state); + + *tune_state = CT_TUNER_STEP_2; + break; + + case CT_TUNER_STEP_2: + case CT_TUNER_STEP_3: + case CT_TUNER_STEP_4: + ret = dib0090_get_offset(state, tune_state); + break; + + case CT_TUNER_STEP_5: /* found an offset */ + dprintk("FE%d: IQC read=%d, current=%x", state->fe->id, (u32) state->adc_diff, state->step); + + /* first turn for this frequency */ + if (state->step == 0) { + if (state->dc->pga && state->adc_diff < 0) + state->step = 0x10; + if (state->dc->pga == 0 && state->adc_diff > 0) + state->step = 0x10; + } + + state->adc_diff = ABS(state->adc_diff); + + if (state->adc_diff < state->min_adc_diff && steps(state->step) < 15) { /* stop search when the delta to 0 is increasing */ + state->step++; + state->min_adc_diff = state->adc_diff; + *tune_state = CT_TUNER_STEP_1; + } else { + + /* the minimum was what we have seen in the step before */ + state->step--; + dib0090_set_trim(state); + + dprintk("FE%d: BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd", state->fe->id, state->dc->addr, state->adc_diff, + state->step); + + state->dc++; + if (state->dc->addr == 0) /* done */ + *tune_state = CT_TUNER_STEP_6; + else + *tune_state = CT_TUNER_STEP_0; + + } + break; + + case CT_TUNER_STEP_6: + dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008); + dib0090_write_reg(state, 0x1f, 0x7); + *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */ + state->reset &= ~0x1; + default: + break; + } + return ret; +} + +static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state) +{ + switch (*tune_state) { + case CT_TUNER_START: + /* WBD-mode=log, Bias=2, Gain=6, Testmode=1, en=1, WBDMUX=1 */ + dib0090_write_reg(state, 0x10, 0xdb09 | (1 << 10)); + dib0090_write_reg(state, 0x24, EN_UHF & 0x0fff); + + *tune_state = CT_TUNER_STEP_0; + return 90; /* wait for the WBDMUX to switch and for the ADC to sample */ + case CT_TUNER_STEP_0: + state->wbd_offset = dib0090_read_reg(state, 0x1d); + dprintk("WBD calibration offset = %d", state->wbd_offset); + + *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */ + state->reset &= ~0x2; + break; + default: + break; + } + return 0; +} + +static void dib0090_set_bandwidth(struct dib0090_state *state) +{ + u16 tmp; + + if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000) + tmp = (3 << 14); + else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000) + tmp = (2 << 14); + else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000) + tmp = (1 << 14); + else + tmp = (0 << 14); + + state->bb_1_def &= 0x3fff; + state->bb_1_def |= tmp; + + dib0090_write_reg(state, 0x01, state->bb_1_def); /* be sure that we have the right bb-filter */ +} + +static const struct dib0090_pll dib0090_pll_table[] = { +#ifdef CONFIG_BAND_CBAND + {56000, 0, 9, 48, 6}, + {70000, 1, 9, 48, 6}, + {87000, 0, 8, 32, 4}, + {105000, 1, 8, 32, 4}, + {115000, 0, 7, 24, 6}, + {140000, 1, 7, 24, 6}, + {170000, 0, 6, 16, 4}, +#endif +#ifdef CONFIG_BAND_VHF + {200000, 1, 6, 16, 4}, + {230000, 0, 5, 12, 6}, + {280000, 1, 5, 12, 6}, + {340000, 0, 4, 8, 4}, + {380000, 1, 4, 8, 4}, + {450000, 0, 3, 6, 6}, +#endif +#ifdef CONFIG_BAND_UHF + {580000, 1, 3, 6, 6}, + {700000, 0, 2, 4, 4}, + {860000, 1, 2, 4, 4}, +#endif +#ifdef CONFIG_BAND_LBAND + {1800000, 1, 0, 2, 4}, +#endif +#ifdef CONFIG_BAND_SBAND + {2900000, 0, 14, 1, 4}, +#endif +}; + +static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = { + +#ifdef CONFIG_BAND_CBAND + {184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB}, + {227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB}, + {380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB}, +#endif +#ifdef CONFIG_BAND_UHF + {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, + {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, + {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, + {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, + {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, + {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, +#endif +#ifdef CONFIG_BAND_LBAND + {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, + {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, + {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, +#endif +#ifdef CONFIG_BAND_SBAND + {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD}, + {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD}, +#endif +}; + +static const struct dib0090_tuning dib0090_tuning_table[] = { + +#ifdef CONFIG_BAND_CBAND + {170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB}, +#endif +#ifdef CONFIG_BAND_VHF + {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF}, + {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF}, + {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF}, +#endif +#ifdef CONFIG_BAND_UHF + {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, + {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, + {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, + {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, + {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, + {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, +#endif +#ifdef CONFIG_BAND_LBAND + {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, + {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, + {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, +#endif +#ifdef CONFIG_BAND_SBAND + {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD}, + {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD}, +#endif +}; + +#define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */ +static int dib0090_tune(struct dvb_frontend *fe) +{ + struct dib0090_state *state = fe->tuner_priv; + const struct dib0090_tuning *tune = state->current_tune_table_index; + const struct dib0090_pll *pll = state->current_pll_table_index; + enum frontend_tune_state *tune_state = &state->tune_state; + + u32 rf; + u16 lo4 = 0xe900, lo5, lo6, Den; + u32 FBDiv, Rest, FREF, VCOF_kHz = 0; + u16 tmp, adc; + int8_t step_sign; + int ret = 10; /* 1ms is the default delay most of the time */ + u8 c, i; + + state->current_band = (u8) BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000); + rf = fe->dtv_property_cache.frequency / 1000 + (state->current_band == + BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->freq_offset_khz_vhf); + /* in any case we first need to do a reset if needed */ + if (state->reset & 0x1) + return dib0090_dc_offset_calibration(state, tune_state); + else if (state->reset & 0x2) + return dib0090_wbd_calibration(state, tune_state); + + /************************* VCO ***************************/ + /* Default values for FG */ + /* from these are needed : */ + /* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv */ + +#ifdef CONFIG_SYS_ISDBT + if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1) + rf += 850; +#endif + + if (state->current_rf != rf) { + state->tuner_is_tuned = 0; + + tune = dib0090_tuning_table; + + tmp = (state->revision >> 5) & 0x7; + if (tmp == 0x4 || tmp == 0x7) { + /* CBAND tuner version for VHF */ + if (state->current_band == BAND_FM || state->current_band == BAND_VHF) { + /* Force CBAND */ + state->current_band = BAND_CBAND; + tune = dib0090_tuning_table_fm_vhf_on_cband; + } + } + + pll = dib0090_pll_table; + /* Look for the interval */ + while (rf > tune->max_freq) + tune++; + while (rf > pll->max_freq) + pll++; + state->current_tune_table_index = tune; + state->current_pll_table_index = pll; + } + + if (*tune_state == CT_TUNER_START) { + + if (state->tuner_is_tuned == 0) + state->current_rf = 0; + + if (state->current_rf != rf) { + + dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim)); + + /* external loop filter, otherwise: + * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4; + * lo6 = 0x0e34 */ + if (pll->vco_band) + lo5 = 0x049e; + else if (state->config->analog_output) + lo5 = 0x041d; + else + lo5 = 0x041c; + + lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7); /* bit 15 is the split to the slave, we do not do it here */ + + if (!state->config->io.pll_int_loop_filt) + lo6 = 0xff28; + else + lo6 = (state->config->io.pll_int_loop_filt << 3); + + VCOF_kHz = (pll->hfdiv * rf) * 2; + + FREF = state->config->io.clock_khz; + + FBDiv = (VCOF_kHz / pll->topresc / FREF); + Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF; + + if (Rest < LPF) + Rest = 0; + else if (Rest < 2 * LPF) + Rest = 2 * LPF; + else if (Rest > (FREF - LPF)) { + Rest = 0; + FBDiv += 1; + } else if (Rest > (FREF - 2 * LPF)) + Rest = FREF - 2 * LPF; + Rest = (Rest * 6528) / (FREF / 10); + + Den = 1; + + dprintk(" ***** ******* Rest value = %d", Rest); + + if (Rest > 0) { + if (state->config->analog_output) + lo6 |= (1 << 2) | 2; + else + lo6 |= (1 << 2) | 1; + Den = 255; + } +#ifdef CONFIG_BAND_SBAND + if (state->current_band == BAND_SBAND) + lo6 &= 0xfffb; +#endif + + dib0090_write_reg(state, 0x15, (u16) FBDiv); + + dib0090_write_reg(state, 0x16, (Den << 8) | 1); + + dib0090_write_reg(state, 0x17, (u16) Rest); + + dib0090_write_reg(state, 0x19, lo5); + + dib0090_write_reg(state, 0x1c, lo6); + + lo6 = tune->tuner_enable; + if (state->config->analog_output) + lo6 = (lo6 & 0xff9f) | 0x2; + + dib0090_write_reg(state, 0x24, lo6 | EN_LO +#ifdef CONFIG_DIB0090_USE_PWM_AGC + | state->config->use_pwm_agc * EN_CRYSTAL +#endif + ); + + state->current_rf = rf; + + /* prepare a complete captrim */ + state->step = state->captrim = state->fcaptrim = 64; + + } else { /* we are already tuned to this frequency - the configuration is correct */ + + /* do a minimal captrim even if the frequency has not changed */ + state->step = 4; + state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f; + } + state->adc_diff = 3000; + + dib0090_write_reg(state, 0x10, 0x2B1); + + dib0090_write_reg(state, 0x1e, 0x0032); + + ret = 20; + *tune_state = CT_TUNER_STEP_1; + } else if (*tune_state == CT_TUNER_STEP_0) { + /* nothing */ + } else if (*tune_state == CT_TUNER_STEP_1) { + state->step /= 2; + dib0090_write_reg(state, 0x18, lo4 | state->captrim); + *tune_state = CT_TUNER_STEP_2; + } else if (*tune_state == CT_TUNER_STEP_2) { + + adc = dib0090_read_reg(state, 0x1d); + dprintk("FE %d CAPTRIM=%d; ADC = %d (ADC) & %dmV", (u32) fe->id, (u32) state->captrim, (u32) adc, + (u32) (adc) * (u32) 1800 / (u32) 1024); + + if (adc >= 400) { + adc -= 400; + step_sign = -1; + } else { + adc = 400 - adc; + step_sign = 1; + } + + if (adc < state->adc_diff) { + dprintk("FE %d CAPTRIM=%d is closer to target (%d/%d)", (u32) fe->id, (u32) state->captrim, (u32) adc, (u32) state->adc_diff); + state->adc_diff = adc; + state->fcaptrim = state->captrim; + + } + + state->captrim += step_sign * state->step; + if (state->step >= 1) + *tune_state = CT_TUNER_STEP_1; + else + *tune_state = CT_TUNER_STEP_3; + + ret = 15; + } else if (*tune_state == CT_TUNER_STEP_3) { + /*write the final cptrim config */ + dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim); + +#ifdef CONFIG_TUNER_DIB0090_CAPTRIM_MEMORY + state->memory[state->memory_index].cap = state->fcaptrim; +#endif + + *tune_state = CT_TUNER_STEP_4; + } else if (*tune_state == CT_TUNER_STEP_4) { + dib0090_write_reg(state, 0x1e, 0x07ff); + + dprintk("FE %d Final Captrim: %d", (u32) fe->id, (u32) state->fcaptrim); + dprintk("FE %d HFDIV code: %d", (u32) fe->id, (u32) pll->hfdiv_code); + dprintk("FE %d VCO = %d", (u32) fe->id, (u32) pll->vco_band); + dprintk("FE %d VCOF in kHz: %d ((%d*%d) << 1))", (u32) fe->id, (u32) ((pll->hfdiv * rf) * 2), (u32) pll->hfdiv, (u32) rf); + dprintk("FE %d REFDIV: %d, FREF: %d", (u32) fe->id, (u32) 1, (u32) state->config->io.clock_khz); + dprintk("FE %d FBDIV: %d, Rest: %d", (u32) fe->id, (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17)); + dprintk("FE %d Num: %d, Den: %d, SD: %d", (u32) fe->id, (u32) dib0090_read_reg(state, 0x17), + (u32) (dib0090_read_reg(state, 0x16) >> 8), (u32) dib0090_read_reg(state, 0x1c) & 0x3); + + c = 4; + i = 3; +#if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND) + if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND)) { + c = 2; + i = 2; + } +#endif + dib0090_write_reg(state, 0x10, (c << 13) | (i << 11) | (WBD +#ifdef CONFIG_DIB0090_USE_PWM_AGC + | (state->config->use_pwm_agc << 1) +#endif + )); + dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | (tune->lna_bias << 0)); + dib0090_write_reg(state, 0x0c, tune->v2i); + dib0090_write_reg(state, 0x0d, tune->mix); + dib0090_write_reg(state, 0x0e, tune->load); + + *tune_state = CT_TUNER_STEP_5; + } else if (*tune_state == CT_TUNER_STEP_5) { + + /* initialize the lt gain register */ + state->rf_lt_def = 0x7c00; + dib0090_write_reg(state, 0x0f, state->rf_lt_def); + + dib0090_set_bandwidth(state); + state->tuner_is_tuned = 1; + *tune_state = CT_TUNER_STOP; + } else + ret = FE_CALLBACK_TIME_NEVER; + return ret; +} + +static int dib0090_release(struct dvb_frontend *fe) +{ + kfree(fe->tuner_priv); + fe->tuner_priv = NULL; + return 0; +} + +enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe) +{ + struct dib0090_state *state = fe->tuner_priv; + + return state->tune_state; +} + +EXPORT_SYMBOL(dib0090_get_tune_state); + +int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) +{ + struct dib0090_state *state = fe->tuner_priv; + + state->tune_state = tune_state; + return 0; +} + +EXPORT_SYMBOL(dib0090_set_tune_state); + +static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency) +{ + struct dib0090_state *state = fe->tuner_priv; + + *frequency = 1000 * state->current_rf; + return 0; +} + +static int dib0090_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) +{ + struct dib0090_state *state = fe->tuner_priv; + uint32_t ret; + + state->tune_state = CT_TUNER_START; + + do { + ret = dib0090_tune(fe); + if (ret != FE_CALLBACK_TIME_NEVER) + msleep(ret / 10); + else + break; + } while (state->tune_state != CT_TUNER_STOP); + + return 0; +} + +static const struct dvb_tuner_ops dib0090_ops = { + .info = { + .name = "DiBcom DiB0090", + .frequency_min = 45000000, + .frequency_max = 860000000, + .frequency_step = 1000, + }, + .release = dib0090_release, + + .init = dib0090_wakeup, + .sleep = dib0090_sleep, + .set_params = dib0090_set_params, + .get_frequency = dib0090_get_frequency, +}; + +struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config) +{ + struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL); + if (st == NULL) + return NULL; + + st->config = config; + st->i2c = i2c; + st->fe = fe; + fe->tuner_priv = st; + + if (dib0090_reset(fe) != 0) + goto free_mem; + + printk(KERN_INFO "DiB0090: successfully identified\n"); + memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops)); + + return fe; + free_mem: + kfree(st); + fe->tuner_priv = NULL; + return NULL; +} + +EXPORT_SYMBOL(dib0090_register); + +MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Olivier Grenie "); +MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/dib0090.h b/drivers/media/dvb/frontends/dib0090.h new file mode 100644 index 0000000..d72b7d7 --- /dev/null +++ b/drivers/media/dvb/frontends/dib0090.h @@ -0,0 +1,114 @@ +/* + * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner. + * + * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/) + * + * This program is free software; 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. + */ +#ifndef DIB0090_H +#define DIB0090_H + +struct dvb_frontend; +struct i2c_adapter; + +#define DEFAULT_DIB0090_I2C_ADDRESS 0x60 + +struct dib0090_io_config { + u32 clock_khz; + + u8 pll_bypass:1; + u8 pll_range:1; + u8 pll_prediv:6; + u8 pll_loopdiv:6; + + u8 adc_clock_ratio; /* valid is 8, 7 ,6 */ + u16 pll_int_loop_filt; // internal loop filt value. If not fill in , default is 8165 +}; + +struct dib0090_config { + struct dib0090_io_config io; + int (*reset) (struct dvb_frontend *, int); + int (*sleep) (struct dvb_frontend *, int); + + /* offset in kHz */ + int freq_offset_khz_uhf; + int freq_offset_khz_vhf; + + int (*get_adc_power) (struct dvb_frontend *); + + u8 clkouttobamse:1; /* activate or deactivate clock output */ + u8 analog_output; + + u8 i2c_address; + /* add drives and other things if necessary */ + u16 wbd_vhf_offset; + u16 wbd_cband_offset; + u8 use_pwm_agc; + u8 clkoutdrive; +}; + +#if defined(CONFIG_DVB_TUNER_DIB0090) || (defined(CONFIG_DVB_TUNER_DIB0090_MODULE) && defined(MODULE)) +extern struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config); +extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast); +extern void dib0090_pwm_gain_reset(struct dvb_frontend *fe); +extern u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner); +extern int dib0090_gain_control(struct dvb_frontend *fe); +extern enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe); +extern int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state); +extern enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe); +extern void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt); +#else +static inline struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0090_config *config) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} + +static inline void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); +} + +static inline void dib0090_pwm_gain_reset(struct dvb_frontend *fe) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); +} + +static inline u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return 0; +} + +static inline int dib0090_gain_control(struct dvb_frontend *fe) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} + +static inline enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return CT_DONE; +} + +static inline int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} + +static inline num frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); +return CT_SHUTDOWN,} + +static inline void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); +} +#endif + +#endif diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c index 898400d..b924e7e 100644 --- a/drivers/media/dvb/frontends/dib8000.c +++ b/drivers/media/dvb/frontends/dib8000.c @@ -28,18 +28,6 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0) -enum frontend_tune_state { - CT_AGC_START = 20, - CT_AGC_STEP_0, - CT_AGC_STEP_1, - CT_AGC_STEP_2, - CT_AGC_STEP_3, - CT_AGC_STEP_4, - CT_AGC_STOP, - - CT_DEMOD_START = 30, -}; - #define FE_STATUS_TUNE_FAILED 0 struct i2c_device { @@ -852,6 +840,14 @@ static int dib8000_set_agc_config(struct dib8000_state *state, u8 band) return 0; } +void dib8000_pwm_agc_reset(struct dvb_frontend *fe) +{ + struct dib8000_state *state = fe->demodulator_priv; + dib8000_set_adc_state(state, DIBX000_ADC_ON); + dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000))); +} +EXPORT_SYMBOL(dib8000_pwm_agc_reset); + static int dib8000_agc_soft_split(struct dib8000_state *state) { u16 agc, split_offset; @@ -939,6 +935,32 @@ static int dib8000_agc_startup(struct dvb_frontend *fe) } +static const int32_t lut_1000ln_mant[] = +{ + 908,7003,7090,7170,7244,7313,7377,7438,7495,7549,7600 +}; + +int32_t dib8000_get_adc_power(struct dvb_frontend *fe, uint8_t mode) +{ + struct dib8000_state *state = fe->demodulator_priv; + uint32_t ix =0, tmp_val =0, exp = 0, mant = 0; + int32_t val; + + val = dib8000_read32(state, 384); + /* mode = 1 : ln_agcpower calc using mant-exp conversion and mantis look up table */ + if(mode) { + tmp_val = val; + while(tmp_val>>=1) + exp++; + mant = (val * 1000 / (1<timf = dib8000_read32(state, 435); @@ -1854,6 +1876,24 @@ static int dib8000_sleep(struct dvb_frontend *fe) } } +enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend* fe) +{ + struct dib8000_state *state = fe->demodulator_priv; + return state->tune_state; +} +EXPORT_SYMBOL(dib8000_get_tune_state); + +int dib8000_set_tune_state(struct dvb_frontend* fe, enum frontend_tune_state tune_state) +{ + struct dib8000_state *state = fe->demodulator_priv; + state->tune_state = tune_state; + return 0; +} +EXPORT_SYMBOL(dib8000_set_tune_state); + + + + static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) { struct dib8000_state *state = fe->demodulator_priv; diff --git a/drivers/media/dvb/frontends/dib8000.h b/drivers/media/dvb/frontends/dib8000.h index 8c89482..de05a0a 100644 --- a/drivers/media/dvb/frontends/dib8000.h +++ b/drivers/media/dvb/frontends/dib8000.h @@ -46,6 +46,10 @@ extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val); extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value); extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff); extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff); +extern int dib8000_set_tune_state(struct dvb_frontend* fe, enum frontend_tune_state tune_state); +extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend* fe); +extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe); +extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode); #else static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg) { @@ -59,35 +63,53 @@ static inline struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe return NULL; } -int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr) +static inline int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; } -int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) +static inline int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; } -int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value) +static inline int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; } -int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) +static inline int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; } -int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) +static inline int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; } +static inline int dib8000_set_tune_state(struct dvb_frontend* fe, enum frontend_tune_state tune_state) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return -ENODEV; +} +static inline enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend* fe) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return CT_SHUTDOWN, +} +static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); +} +static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); +} #endif #endif diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c index 4efca30..e6f3d73 100644 --- a/drivers/media/dvb/frontends/dibx000_common.c +++ b/drivers/media/dvb/frontends/dibx000_common.c @@ -6,7 +6,7 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); -#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); } } while (0) +#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); printk("\n"); } } while (0) static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) { @@ -25,7 +25,7 @@ static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf) { if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) { - dprintk("selecting interface: %d\n", intf); + dprintk("selecting interface: %d", intf); mst->selected_interface = intf; return dibx000_write_word(mst, mst->base_reg + 4, intf); } @@ -171,9 +171,18 @@ void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst) { i2c_del_adapter(&mst->gated_tuner_i2c_adap); } - EXPORT_SYMBOL(dibx000_exit_i2c_master); + +u32 systime() +{ + struct timespec t; + + t = current_kernel_time(); + return (t.tv_sec * 10000) + (t.tv_nsec / 100000); +} +EXPORT_SYMBOL(systime); + MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Common function the DiBcom demodulator family"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h index 5be10ec..06328d8 100644 --- a/drivers/media/dvb/frontends/dibx000_common.h +++ b/drivers/media/dvb/frontends/dibx000_common.h @@ -36,13 +36,17 @@ extern struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst); extern void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst); +extern u32 systime(void); + #define BAND_LBAND 0x01 #define BAND_UHF 0x02 #define BAND_VHF 0x04 #define BAND_SBAND 0x08 -#define BAND_FM 0x10 +#define BAND_FM 0x10 +#define BAND_CBAND 0x20 -#define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 115000 ? BAND_FM : \ +#define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 170000 ? BAND_CBAND : \ + (freq_kHz) <= 115000 ? BAND_FM : \ (freq_kHz) <= 250000 ? BAND_VHF : \ (freq_kHz) <= 863000 ? BAND_UHF : \ (freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND ) @@ -149,4 +153,67 @@ enum dibx000_adc_states { #define OUTMODE_MPEG2_FIFO 5 #define OUTMODE_ANALOG_ADC 6 +enum frontend_tune_state { + CT_TUNER_START = 10, + CT_TUNER_STEP_0, + CT_TUNER_STEP_1, + CT_TUNER_STEP_2, + CT_TUNER_STEP_3, + CT_TUNER_STEP_4, + CT_TUNER_STEP_5, + CT_TUNER_STEP_6, + CT_TUNER_STEP_7, + CT_TUNER_STOP, + + CT_AGC_START = 20, + CT_AGC_STEP_0, + CT_AGC_STEP_1, + CT_AGC_STEP_2, + CT_AGC_STEP_3, + CT_AGC_STEP_4, + CT_AGC_STOP, + + CT_DEMOD_START = 30, + CT_DEMOD_STEP_1, + CT_DEMOD_STEP_2, + CT_DEMOD_STEP_3, + CT_DEMOD_STEP_4, + CT_DEMOD_STEP_5, + CT_DEMOD_STEP_6, + CT_DEMOD_STEP_7, + CT_DEMOD_STEP_8, + CT_DEMOD_STEP_9, + CT_DEMOD_STEP_10, + CT_DEMOD_SEARCH_NEXT = 41, + CT_DEMOD_STEP_LOCKED, + CT_DEMOD_STOP, + + CT_DONE = 100, + CT_SHUTDOWN, + +}; + +struct dvb_frontend_parametersContext { +#define CHANNEL_STATUS_PARAMETERS_UNKNOWN 0x01 +#define CHANNEL_STATUS_PARAMETERS_SET 0x02 + u8 status; + u32 tune_time_estimation[2]; + s32 tps_available; + u16 tps[9]; +}; + +#define FE_STATUS_TUNE_FAILED 0 +#define FE_STATUS_TUNE_TIMED_OUT -1 +#define FE_STATUS_TUNE_TIME_TOO_SHORT -2 +#define FE_STATUS_TUNE_PENDING -3 +#define FE_STATUS_STD_SUCCESS -4 +#define FE_STATUS_FFT_SUCCESS -5 +#define FE_STATUS_DEMOD_SUCCESS -6 +#define FE_STATUS_LOCKED -7 +#define FE_STATUS_DATA_LOCKED -8 + +#define FE_CALLBACK_TIME_NEVER 0xffffffff + +#define ABS(x) ((x<0)?(-x):(x)) + #endif -- cgit v0.10.2 From 9c78303681278b983fac3c6c3c0aa3f93cf2ffa8 Mon Sep 17 00:00:00 2001 From: Olivier Grenie Date: Mon, 7 Dec 2009 07:49:40 -0300 Subject: V4L/DVB (13584): DiBXXX0: fix most of the Codingstyle violations from the previous patch This patch changes most of the Codingstyle violations which were introduced by the previous patch. Line length less that 80 chars are not corrected. Signed-off-by: Olivier Grenie Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 80a1263..d4673c7 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -131,93 +131,95 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap) /* MT226x */ static struct dibx000_agc_config stk7700d_7000p_mt2266_agc_config[2] = { { - BAND_UHF, // band_caps + BAND_UHF, /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1, * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ - (0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup - - 1130, // inv_gain - 21, // time_stabiliz - - 0, // alpha_level - 118, // thlock - - 0, // wbd_inv - 3530, // wbd_ref - 1, // wbd_sel - 0, // wbd_alpha - - 65535, // agc1_max - 33770, // agc1_min - 65535, // agc2_max - 23592, // agc2_min - - 0, // agc1_pt1 - 62, // agc1_pt2 - 255, // agc1_pt3 - 64, // agc1_slope1 - 64, // agc1_slope2 - 132, // agc2_pt1 - 192, // agc2_pt2 - 80, // agc2_slope1 - 80, // agc2_slope2 - - 17, // alpha_mant - 27, // alpha_exp - 23, // beta_mant - 51, // beta_exp - - 1, // perform_agc_softsplit + (0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) + | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), + + 1130, + 21, + + 0, + 118, + + 0, + 3530, + 1, + 0, + + 65535, + 33770, + 65535, + 23592, + + 0, + 62, + 255, + 64, + 64, + 132, + 192, + 80, + 80, + + 17, + 27, + 23, + 51, + + 1, }, { - BAND_VHF | BAND_LBAND, // band_caps + BAND_VHF | BAND_LBAND, /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1, * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ - (0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup - - 2372, // inv_gain - 21, // time_stabiliz - - 0, // alpha_level - 118, // thlock - - 0, // wbd_inv - 3530, // wbd_ref - 1, // wbd_sel - 0, // wbd_alpha - - 65535, // agc1_max - 0, // agc1_min - 65535, // agc2_max - 23592, // agc2_min - - 0, // agc1_pt1 - 128, // agc1_pt2 - 128, // agc1_pt3 - 128, // agc1_slope1 - 0, // agc1_slope2 - 128, // agc2_pt1 - 253, // agc2_pt2 - 81, // agc2_slope1 - 0, // agc2_slope2 - - 17, // alpha_mant - 27, // alpha_exp - 23, // beta_mant - 51, // beta_exp - - 1, // perform_agc_softsplit + (0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) + | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), + + 2372, + 21, + + 0, + 118, + + 0, + 3530, + 1, + 0, + + 65535, + 0, + 65535, + 23592, + + 0, + 128, + 128, + 128, + 0, + 128, + 253, + 81, + 0, + + 17, + 27, + 23, + 51, + + 1, } }; static struct dibx000_bandwidth_config stk7700d_mt2266_pll_config = { - 60000, 30000, // internal, sampling - 1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass - 0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo - (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k - 0, // ifreq - 20452225, // timf + 60000, 30000, + 1, 8, 3, 1, 0, + 0, 0, 1, 1, 2, + (3 << 14) | (1 << 12) | (524 << 0), + 0, + 20452225, }; static struct dib7000p_config stk7700d_dib7000p_mt2266_config[] = { @@ -934,47 +936,48 @@ static struct dvb_usb_rc_key dib0700_rc_keys[] = { /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = { - BAND_UHF | BAND_VHF, // band_caps + BAND_UHF | BAND_VHF, /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ - (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup - - 712, // inv_gain - 41, // time_stabiliz - - 0, // alpha_level - 118, // thlock - - 0, // wbd_inv - 4095, // wbd_ref - 0, // wbd_sel - 0, // wbd_alpha - - 42598, // agc1_max - 17694, // agc1_min - 45875, // agc2_max - 2621, // agc2_min - 0, // agc1_pt1 - 76, // agc1_pt2 - 139, // agc1_pt3 - 52, // agc1_slope1 - 59, // agc1_slope2 - 107, // agc2_pt1 - 172, // agc2_pt2 - 57, // agc2_slope1 - 70, // agc2_slope2 - - 21, // alpha_mant - 25, // alpha_exp - 28, // beta_mant - 48, // beta_exp - - 1, // perform_agc_softsplit - { 0, // split_min - 107, // split_max - 51800, // global_split_min - 24700 // global_split_max + (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) + | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), + + 712, + 41, + + 0, + 118, + + 0, + 4095, + 0, + 0, + + 42598, + 17694, + 45875, + 2621, + 0, + 76, + 139, + 52, + 59, + 107, + 172, + 57, + 70, + + 21, + 25, + 28, + 48, + + 1, + { 0, + 107, + 51800, + 24700 }, }; @@ -983,54 +986,55 @@ static struct dibx000_agc_config stk7700p_7000p_mt2060_agc_config = { /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ - (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup + (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) + | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), - 712, // inv_gain - 41, // time_stabiliz + 712, + 41, - 0, // alpha_level - 118, // thlock + 0, + 118, - 0, // wbd_inv - 4095, // wbd_ref - 0, // wbd_sel - 0, // wbd_alpha + 0, + 4095, + 0, + 0, - 42598, // agc1_max - 16384, // agc1_min - 42598, // agc2_max - 0, // agc2_min + 42598, + 16384, + 42598, + 0, - 0, // agc1_pt1 - 137, // agc1_pt2 - 255, // agc1_pt3 + 0, + 137, + 255, - 0, // agc1_slope1 - 255, // agc1_slope2 + 0, + 255, - 0, // agc2_pt1 - 0, // agc2_pt2 + 0, + 0, - 0, // agc2_slope1 - 41, // agc2_slope2 + 0, + 41, - 15, // alpha_mant - 25, // alpha_exp + 15, + 25, - 28, // beta_mant - 48, // beta_exp + 28, + 48, - 0, // perform_agc_softsplit + 0, }; static struct dibx000_bandwidth_config stk7700p_pll_config = { - 60000, 30000, // internal, sampling - 1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass - 0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo - (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k - 60258167, // ifreq - 20452225, // timf - 30000000, // xtal + 60000, 30000, + 1, 8, 3, 1, 0, + 0, 0, 1, 1, 0, + (3 << 14) | (1 << 12) | (524 << 0), + 60258167, + 20452225, + 30000000, }; static struct dib7000m_config stk7700p_dib7000m_config = { @@ -1116,41 +1120,42 @@ static struct dibx000_agc_config dib7070_agc_config = { BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND, /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ - (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup - - 600, // inv_gain - 10, // time_stabiliz - - 0, // alpha_level - 118, // thlock - - 0, // wbd_inv - 3530, // wbd_ref - 1, // wbd_sel - 5, // wbd_alpha - - 65535, // agc1_max - 0, // agc1_min - - 65535, // agc2_max - 0, // agc2_min - - 0, // agc1_pt1 - 40, // agc1_pt2 - 183, // agc1_pt3 - 206, // agc1_slope1 - 255, // agc1_slope2 - 72, // agc2_pt1 - 152, // agc2_pt2 - 88, // agc2_slope1 - 90, // agc2_slope2 - - 17, // alpha_mant - 27, // alpha_exp - 23, // beta_mant - 51, // beta_exp - - 0, // perform_agc_softsplit + (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) + | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), + + 600, + 10, + + 0, + 118, + + 0, + 3530, + 1, + 5, + + 65535, + 0, + + 65535, + 0, + + 0, + 40, + 183, + 206, + 255, + 72, + 152, + 88, + 90, + + 17, + 27, + 23, + 51, + + 0, }; static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) @@ -1277,13 +1282,13 @@ static int stk70x0p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff) } static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = { - 60000, 15000, // internal, sampling - 1, 20, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass - 0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo - (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k - (0 << 25) | 0, // ifreq = 0.000000 MHz - 20452225, // timf - 12000000, // xtal_hz + 60000, 15000, + 1, 20, 3, 1, 0, + 0, 0, 1, 1, 2, + (3 << 14) | (1 << 12) | (524 << 0), + (0 << 25) | 0, + 20452225, + 12000000, }; static struct dib7000p_config dib7070p_dib7000p_config = { @@ -1567,12 +1572,14 @@ static int dib807x_tuner_attach(struct dvb_usb_adapter *adap) return 0; } -static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff) +static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index, + u16 pid, int onoff) { return dib8000_pid_filter(adapter->fe, index, pid, onoff); } -static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff) +static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter, + int onoff) { return dib8000_pid_filter_ctrl(adapter->fe, onoff); } @@ -1648,94 +1655,98 @@ static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap) struct dibx000_agc_config dib8090_agc_config[2] = { { BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND, - /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, - * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ - (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup - - 787,// inv_gain = 1/ 90.4dB // no boost, lower gain due to ramp quantification - 10, // time_stabiliz - - 0, // alpha_level - 118, // thlock - - 0, // wbd_inv - 3530, // wbd_ref - 1, // wbd_sel - 5, // wbd_alpha - - 65535, // agc1_max - 0, // agc1_min - - 65535, // agc2_max - 0, // agc2_min - - 0, // agc1_pt1 - 32, // agc1_pt2 - 114, // agc1_pt3 // 40.4dB - 143, // agc1_slope1 - 144, // agc1_slope2 - 114, // agc2_pt1 - 227, // agc2_pt2 - 116, // agc2_slope1 - 117, // agc2_slope2 - - 28, // alpha_mant // 5Hz with 90.2dB - 26, // alpha_exp - 31, // beta_mant - 51, // beta_exp - - 0, // perform_agc_softsplit + /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, + * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, + * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ + (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) + | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), + + 787, + 10, + + 0, + 118, + + 0, + 3530, + 1, + 5, + + 65535, + 0, + + 65535, + 0, + + 0, + 32, + 114, + 143, + 144, + 114, + 227, + 116, + 117, + + 28, + 26, + 31, + 51, + + 0, }, { BAND_CBAND, - /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, - * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ - (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup - - 787,// inv_gain = 1/ 90.4dB // no boost, lower gain due to ramp quantification - 10, // time_stabiliz - - 0, // alpha_level - 118, // thlock - - 0, // wbd_inv - 3530, // wbd_ref - 1, // wbd_sel - 5, // wbd_alpha - - 0, // agc1_max - 0, // agc1_min - - 65535, // agc2_max - 0, // agc2_min - - 0, // agc1_pt1 - 32, // agc1_pt2 - 114, // agc1_pt3 // 40.4dB - 143, // agc1_slope1 - 144, // agc1_slope2 - 114, // agc2_pt1 - 227, // agc2_pt2 - 116, // agc2_slope1 - 117, // agc2_slope2 - - 28, // alpha_mant // 5Hz with 90.2dB - 26, // alpha_exp - 31, // beta_mant - 51, // beta_exp - - 0, // perform_agc_softsplit + /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, + * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, + * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ + (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) + | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), + + 787, + 10, + + 0, + 118, + + 0, + 3530, + 1, + 5, + + 0, + 0, + + 65535, + 0, + + 0, + 32, + 114, + 143, + 144, + 114, + 227, + 116, + 117, + + 28, + 26, + 31, + 51, + + 0, } }; static struct dibx000_bandwidth_config dib8090_pll_config_12mhz = { - 54000, 13500, // internal, sampling - 1, 18, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass - 0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo - (3 << 14) | (1 << 12) | (599 << 0), // sad_cfg: refsel, sel, freq_15k - (0 << 25) | 0, // ifreq = 0 MHz - 20199727, // timf - 12000000, // xtal_hz + 54000, 13500, + 1, 18, 3, 1, 0, + 0, 0, 1, 1, 2, + (3 << 14) | (1 << 12) | (599 << 0), + (0 << 25) | 0, + 20199727, + 12000000, }; static int dib8090_get_adc_power(struct dvb_frontend *fe) @@ -1802,13 +1813,13 @@ static int dib8096_set_param_override(struct dvb_frontend *fe, return ret; switch (band) { - case BAND_VHF: + case BAND_VHF: offset = 100; break; - case BAND_UHF: + case BAND_UHF: offset = 550; break; - default: + default: offset = 0; break; } @@ -1816,31 +1827,26 @@ static int dib8096_set_param_override(struct dvb_frontend *fe, dib8000_set_wbd_ref(fe, offset); - if (band == BAND_CBAND) - { + if (band == BAND_CBAND) { deb_info("tuning in CBAND - soft-AGC startup\n"); /* TODO specific wbd target for dib0090 - needed for startup ? */ dib0090_set_tune_state(fe, CT_AGC_START); - do - { - ret = dib0090_gain_control(fe); - msleep(ret); - tune_state = dib0090_get_tune_state(fe); - if (tune_state == CT_AGC_STEP_0) - dib8000_set_gpio(fe, 6, 0, 1); - else if (tune_state == CT_AGC_STEP_1) - { - dib0090_get_current_gain(fe, NULL, NULL, &rf_gain_limit, <gain); - if (rf_gain_limit == 0) - dib8000_set_gpio(fe, 6, 0, 0); - } - } - while(tune_statecaptrim, adc, (u32) adc*(u32)1800/(u32)1024); + dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024); if (adc >= 400) { adc -= 400; @@ -174,7 +174,7 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state } if (adc < state->adc_diff) { - dprintk( "CAPTRIM=%hd is closer to target (%hd/%hd)", state->captrim, adc, state->adc_diff); + dprintk("CAPTRIM=%hd is closer to target (%hd/%hd)", state->captrim, adc, state->adc_diff); state->adc_diff = adc; state->fcaptrim = state->captrim; @@ -201,7 +201,7 @@ static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf { struct dib0070_state *state = fe->tuner_priv; u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0); - dprintk( "CTRL_LO5: 0x%x", lo5); + dprintk("CTRL_LO5: 0x%x", lo5); return dib0070_write_reg(state, 0x15, lo5); } @@ -215,10 +215,10 @@ void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open) } else { dib0070_write_reg(state, 0x1b, 0x4112); if (state->cfg->vga_filter != 0) { - dib0070_write_reg(state, 0x1a, state->cfg->vga_filter); - dprintk( "vga filter register is set to %x", state->cfg->vga_filter); + dib0070_write_reg(state, 0x1a, state->cfg->vga_filter); + dprintk("vga filter register is set to %x", state->cfg->vga_filter); } else - dib0070_write_reg(state, 0x1a, 0x0009); + dib0070_write_reg(state, 0x1a, 0x0009); } } @@ -255,7 +255,7 @@ static const struct dib0070_tuning dib0070_tuning_table[] = { { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 }, { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 }, { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */ - { 699999, 2, 0 ,1, 4, 2, 2, 0x4000 | 0x0800 }, + { 699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800 }, { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 }, { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */ }; @@ -291,7 +291,7 @@ static const struct dib0070_lna_match dib0070_lna[] = { { 0xffffffff, 7 }, }; -#define LPF 100 // define for the loop filter 100kHz by default 16-07-06 +#define LPF 100 static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) { struct dib0070_state *state = fe->tuner_priv; @@ -313,7 +313,7 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2))) || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))) - freq += 850; + freq += 850; #endif if (state->current_rf != freq) { @@ -340,95 +340,95 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par } if (*tune_state == CT_TUNER_START) { - dprintk( "Tuning for Band: %hd (%d kHz)", band, freq); + dprintk("Tuning for Band: %hd (%d kHz)", band, freq); if (state->current_rf != freq) { - u8 REFDIV; - u32 FBDiv, Rest, FREF, VCOF_kHz; - u8 Den; - - state->current_rf = freq; - state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7); - - - dib0070_write_reg(state, 0x17, 0x30); - - - VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2; - - switch (band) { - case BAND_VHF: - REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000); - break; - case BAND_FM: - REFDIV = (u8) ((state->cfg->clock_khz) / 1000); - break; - default: - REFDIV = (u8) ( state->cfg->clock_khz / 10000); - break; - } - FREF = state->cfg->clock_khz / REFDIV; - - - - switch (state->revision) { - case DIB0070S_P1A: - FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF); - Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF; - break; - - case DIB0070_P1G: - case DIB0070_P1F: - default: - FBDiv = (freq / (FREF / 2)); - Rest = 2 * freq - FBDiv * FREF; - break; - } - - if (Rest < LPF) - Rest = 0; - else if (Rest < 2 * LPF) - Rest = 2 * LPF; - else if (Rest > (FREF - LPF)) { - Rest = 0; - FBDiv += 1; - } else if (Rest > (FREF - 2 * LPF)) - Rest = FREF - 2 * LPF; - Rest = (Rest * 6528) / (FREF / 10); - - Den = 1; - if (Rest > 0) { - state->lo4 |= (1 << 14) | (1 << 12); - Den = 255; - } - - - dib0070_write_reg(state, 0x11, (u16)FBDiv); - dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV); - dib0070_write_reg(state, 0x13, (u16) Rest); - - if (state->revision == DIB0070S_P1A) { - - if (band == BAND_SBAND) { - dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); - dib0070_write_reg(state, 0x1d,0xFFFF); - } else - dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1); - } - - dib0070_write_reg(state, 0x20, - 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable); - - dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF); - dprintk( "FBDIV: %d, Rest: %d", FBDiv, Rest); - dprintk( "Num: %hd, Den: %hd, SD: %hd",(u16) Rest, Den, (state->lo4 >> 12) & 0x1); - dprintk( "HFDIV code: %hd", state->current_tune_table_index->hfdiv); - dprintk( "VCO = %hd", state->current_tune_table_index->vco_band); - dprintk( "VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq); - - *tune_state = CT_TUNER_STEP_0; + u8 REFDIV; + u32 FBDiv, Rest, FREF, VCOF_kHz; + u8 Den; + + state->current_rf = freq; + state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7); + + + dib0070_write_reg(state, 0x17, 0x30); + + + VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2; + + switch (band) { + case BAND_VHF: + REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000); + break; + case BAND_FM: + REFDIV = (u8) ((state->cfg->clock_khz) / 1000); + break; + default: + REFDIV = (u8) (state->cfg->clock_khz / 10000); + break; + } + FREF = state->cfg->clock_khz / REFDIV; + + + + switch (state->revision) { + case DIB0070S_P1A: + FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF); + Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF; + break; + + case DIB0070_P1G: + case DIB0070_P1F: + default: + FBDiv = (freq / (FREF / 2)); + Rest = 2 * freq - FBDiv * FREF; + break; + } + + if (Rest < LPF) + Rest = 0; + else if (Rest < 2 * LPF) + Rest = 2 * LPF; + else if (Rest > (FREF - LPF)) { + Rest = 0; + FBDiv += 1; + } else if (Rest > (FREF - 2 * LPF)) + Rest = FREF - 2 * LPF; + Rest = (Rest * 6528) / (FREF / 10); + + Den = 1; + if (Rest > 0) { + state->lo4 |= (1 << 14) | (1 << 12); + Den = 255; + } + + + dib0070_write_reg(state, 0x11, (u16)FBDiv); + dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV); + dib0070_write_reg(state, 0x13, (u16) Rest); + + if (state->revision == DIB0070S_P1A) { + + if (band == BAND_SBAND) { + dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); + dib0070_write_reg(state, 0x1d, 0xFFFF); + } else + dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1); + } + + dib0070_write_reg(state, 0x20, + 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable); + + dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF); + dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest); + dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1); + dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv); + dprintk("VCO = %hd", state->current_tune_table_index->vco_band); + dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq); + + *tune_state = CT_TUNER_STEP_0; } else { /* we are already tuned to this frequency - the configuration is correct */ - ret = 50; /* wakeup time */ - *tune_state = CT_TUNER_STEP_5; + ret = 50; /* wakeup time */ + *tune_state = CT_TUNER_STEP_5; } } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) { @@ -437,13 +437,13 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par } else if (*tune_state == CT_TUNER_STEP_4) { const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; if (tmp != NULL) { - while (freq/1000 > tmp->freq) /* find the right one */ - tmp++; - dib0070_write_reg(state, 0x0f, - (0 << 15) | (1 << 14) | (3 << 12) | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7) | (state-> - current_tune_table_index-> - wbdmux << 0)); - state->wbd_gain_current = tmp->wbd_gain_val; + while (freq/1000 > tmp->freq) /* find the right one */ + tmp++; + dib0070_write_reg(state, 0x0f, + (0 << 15) | (1 << 14) | (3 << 12) + | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7) + | (state->current_tune_table_index->wbdmux << 0)); + state->wbd_gain_current = tmp->wbd_gain_val; } else { dib0070_write_reg(state, 0x0f, (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index-> @@ -483,7 +483,7 @@ static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters do { ret = dib0070_tune_digital(fe, p); if (ret != FE_CALLBACK_TIME_NEVER) - msleep(ret/10); + msleep(ret/10); else break; } while (state->tune_state != CT_TUNER_STOP); @@ -512,18 +512,20 @@ u8 dib0070_get_rf_output(struct dvb_frontend *fe) struct dib0070_state *state = fe->tuner_priv; return (dib0070_read_reg(state, 0x07) >> 11) & 0x3; } - EXPORT_SYMBOL(dib0070_get_rf_output); + int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no) { struct dib0070_state *state = fe->tuner_priv; u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff; - if (no > 3) no = 3; - if (no < 1) no = 1; + if (no > 3) + no = 3; + if (no < 1) + no = 1; return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11)); } - EXPORT_SYMBOL(dib0070_set_rf_output); + static const u16 dib0070_p1f_defaults[] = { @@ -582,7 +584,7 @@ static void dib0070_wbd_offset_calibration(struct dib0070_state *state) u8 gain; for (gain = 6; gain < 8; gain++) { state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2); - dprintk( "Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]); + dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]); } } @@ -622,10 +624,10 @@ static int dib0070_reset(struct dvb_frontend *fe) state->revision = DIB0070S_P1A; /* P1F or not */ - dprintk( "Revision: %x", state->revision); + dprintk("Revision: %x", state->revision); if (state->revision == DIB0070_P1D) { - dprintk( "Error: this driver is not to be used meant for P1D or earlier"); + dprintk("Error: this driver is not to be used meant for P1D or earlier"); return -EINVAL; } @@ -702,7 +704,7 @@ static const struct dvb_tuner_ops dib0070_ops = { // .get_bandwidth = dib0070_get_bandwidth }; -struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) +struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) { struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL); if (state == NULL) diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c index e37d32d..6145527 100644 --- a/drivers/media/dvb/frontends/dib0090.c +++ b/drivers/media/dvb/frontends/dib0090.c @@ -149,8 +149,8 @@ static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) { u8 b[2]; struct i2c_msg msg[2] = { - {.addr = state->config->i2c_address,.flags = 0,.buf = ®,.len = 1}, - {.addr = state->config->i2c_address,.flags = I2C_M_RD,.buf = b,.len = 2}, + {.addr = state->config->i2c_address, .flags = 0, .buf = ®, .len = 1}, + {.addr = state->config->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2}, }; if (i2c_transfer(state->i2c, msg, 2) != 2) { printk(KERN_WARNING "DiB0090 I2C read failed\n"); @@ -162,7 +162,7 @@ static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) { u8 b[3] = { reg & 0xff, val >> 8, val & 0xff }; - struct i2c_msg msg = {.addr = state->config->i2c_address,.flags = 0,.buf = b,.len = 3 }; + struct i2c_msg msg = {.addr = state->config->i2c_address, .flags = 0, .buf = b, .len = 3 }; if (i2c_transfer(state->i2c, &msg, 1) != 1) { printk(KERN_WARNING "DiB0090 I2C write failed\n"); return -EREMOTEIO; @@ -287,12 +287,12 @@ extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast) { struct dib0090_state *state = fe->tuner_priv; if (fast) - dib0090_write_reg(state, 0x04, 0); //1kHz + dib0090_write_reg(state, 0x04, 0); else - dib0090_write_reg(state, 0x04, 1); //almost frozen + dib0090_write_reg(state, 0x04, 1); } - EXPORT_SYMBOL(dib0090_dcc_freq); + static const u16 rf_ramp_pwm_cband[] = { 0, /* max RF gain in 10th of dB */ 0, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */ @@ -616,11 +616,11 @@ void dib0090_pwm_gain_reset(struct dvb_frontend *fe) else dib0090_write_reg(state, 0x32, (0 << 11)); - dib0090_write_reg(state, 0x39, (1 << 10)); // 0 gain by default + dib0090_write_reg(state, 0x39, (1 << 10)); } } - EXPORT_SYMBOL(dib0090_pwm_gain_reset); + int dib0090_gain_control(struct dvb_frontend *fe) { struct dib0090_state *state = fe->tuner_priv; @@ -760,7 +760,7 @@ int dib0090_gain_control(struct dvb_frontend *fe) #ifdef DEBUG_AGC dprintk ("FE: %d, tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm", - (u32) fe->id, (u32) * tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val, + (u32) fe->id, (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val, (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA)); #endif } @@ -770,8 +770,8 @@ int dib0090_gain_control(struct dvb_frontend *fe) dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly); return ret; } - EXPORT_SYMBOL(dib0090_gain_control); + void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt) { struct dib0090_state *state = fe->tuner_priv; @@ -784,15 +784,15 @@ void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * if (rflt) *rflt = (state->rf_lt_def >> 10) & 0x7; } - EXPORT_SYMBOL(dib0090_get_current_gain); + u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner) { struct dib0090_state *st = tuner->tuner_priv; return st->wbd_offset; } - EXPORT_SYMBOL(dib0090_get_wbd_offset); + static const u16 dib0090_defaults[] = { 25, 0x01, @@ -891,7 +891,7 @@ static int dib0090_reset(struct dvb_frontend *fe) return 0; } -#define steps(u) (((u)>15)?((u)-16):(u)) +#define steps(u) (((u) > 15) ? ((u)-16) : (u)) #define INTERN_WAIT 10 static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state) { @@ -1439,7 +1439,6 @@ enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe) return state->tune_state; } - EXPORT_SYMBOL(dib0090_get_tune_state); int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) @@ -1449,7 +1448,6 @@ int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tun state->tune_state = tune_state; return 0; } - EXPORT_SYMBOL(dib0090_set_tune_state); static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency) @@ -1516,7 +1514,6 @@ struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapte fe->tuner_priv = NULL; return NULL; } - EXPORT_SYMBOL(dib0090_register); MODULE_AUTHOR("Patrick Boettcher "); diff --git a/drivers/media/dvb/frontends/dib0090.h b/drivers/media/dvb/frontends/dib0090.h index d72b7d7..83cc8ae 100644 --- a/drivers/media/dvb/frontends/dib0090.h +++ b/drivers/media/dvb/frontends/dib0090.h @@ -24,7 +24,7 @@ struct dib0090_io_config { u8 pll_loopdiv:6; u8 adc_clock_ratio; /* valid is 8, 7 ,6 */ - u16 pll_int_loop_filt; // internal loop filt value. If not fill in , default is 8165 + u16 pll_int_loop_filt; }; struct dib0090_config { diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c index b924e7e..5218a5c 100644 --- a/drivers/media/dvb/frontends/dib8000.c +++ b/drivers/media/dvb/frontends/dib8000.c @@ -937,21 +937,21 @@ static int dib8000_agc_startup(struct dvb_frontend *fe) static const int32_t lut_1000ln_mant[] = { - 908,7003,7090,7170,7244,7313,7377,7438,7495,7549,7600 + 908, 7003, 7090, 7170, 7244, 7313, 7377, 7438, 7495, 7549, 7600 }; int32_t dib8000_get_adc_power(struct dvb_frontend *fe, uint8_t mode) { struct dib8000_state *state = fe->demodulator_priv; - uint32_t ix =0, tmp_val =0, exp = 0, mant = 0; + uint32_t ix = 0, tmp_val = 0, exp = 0, mant = 0; int32_t val; val = dib8000_read32(state, 384); /* mode = 1 : ln_agcpower calc using mant-exp conversion and mantis look up table */ - if(mode) { + if (mode) { tmp_val = val; - while(tmp_val>>=1) - exp++; + while (tmp_val >>= 1) + exp++; mant = (val * 1000 / (1<demodulator_priv; return state->tune_state; } EXPORT_SYMBOL(dib8000_get_tune_state); -int dib8000_set_tune_state(struct dvb_frontend* fe, enum frontend_tune_state tune_state) +int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) { struct dib8000_state *state = fe->demodulator_priv; state->tune_state = tune_state; diff --git a/drivers/media/dvb/frontends/dib8000.h b/drivers/media/dvb/frontends/dib8000.h index de05a0a..d99619a 100644 --- a/drivers/media/dvb/frontends/dib8000.h +++ b/drivers/media/dvb/frontends/dib8000.h @@ -46,8 +46,8 @@ extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val); extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value); extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff); extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff); -extern int dib8000_set_tune_state(struct dvb_frontend* fe, enum frontend_tune_state tune_state); -extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend* fe); +extern int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state); +extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe); extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe); extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode); #else @@ -92,12 +92,12 @@ static inline int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; } -static inline int dib8000_set_tune_state(struct dvb_frontend* fe, enum frontend_tune_state tune_state) +static inline int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return -ENODEV; } -static inline enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend* fe) +static inline enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return CT_SHUTDOWN, diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h index 06328d8..4f5d141 100644 --- a/drivers/media/dvb/frontends/dibx000_common.h +++ b/drivers/media/dvb/frontends/dibx000_common.h @@ -45,7 +45,7 @@ extern u32 systime(void); #define BAND_FM 0x10 #define BAND_CBAND 0x20 -#define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 170000 ? BAND_CBAND : \ +#define BAND_OF_FREQUENCY(freq_kHz) ((freq_kHz) <= 170000 ? BAND_CBAND : \ (freq_kHz) <= 115000 ? BAND_FM : \ (freq_kHz) <= 250000 ? BAND_VHF : \ (freq_kHz) <= 863000 ? BAND_UHF : \ @@ -214,6 +214,6 @@ struct dvb_frontend_parametersContext { #define FE_CALLBACK_TIME_NEVER 0xffffffff -#define ABS(x) ((x<0)?(-x):(x)) +#define ABS(x) ((x < 0) ? (-x) : (x)) #endif -- cgit v0.10.2 From 9542f502cf5a51b34d1c04c25206a8d69d4b8d0f Mon Sep 17 00:00:00 2001 From: Olivier Grenie Date: Mon, 7 Dec 2009 08:09:04 -0300 Subject: V4L/DVB (13585): STK807xPVR: correct the enumeration STK807xPVR: correct the enumeration Signed-off-by: Olivier Grenie Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index d4673c7..44972d0 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1632,7 +1632,7 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap) dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); /* initialize IC 0 */ - dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x80); + dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80); adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib807x_dib8000_config[0]); @@ -1643,7 +1643,7 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap) static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap) { /* initialize IC 1 */ - dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x82); + dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82); adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82, &dib807x_dib8000_config[1]); -- cgit v0.10.2 From acc5c9ee393952c00eb7fab8bdd529d45226f6ed Mon Sep 17 00:00:00 2001 From: Olivier Grenie Date: Mon, 7 Dec 2009 08:22:53 -0300 Subject: V4L/DVB (13586): DiB0700: Add parameter to change the buffer size Add parameter to change the buffer size. This buffer size is specified in number of Ts packet. This parameter is stored inside the state. For firmware higher than 1.21, the xfer buffer size can be changed inside the dib0700 usb bridge the firware version is stored inside the state Signed-off-by: Patrick Boettcher Signed-off-by: Olivier Grenie Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h index 8b544fe..495a905 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/dvb/dvb-usb/dib0700.h @@ -20,20 +20,22 @@ extern int dvb_usb_dib0700_debug; #define deb_fwdata(args...) dprintk(dvb_usb_dib0700_debug,0x04,args) #define deb_data(args...) dprintk(dvb_usb_dib0700_debug,0x08,args) -#define REQUEST_I2C_READ 0x2 -#define REQUEST_I2C_WRITE 0x3 -#define REQUEST_POLL_RC 0x4 /* deprecated in firmware v1.20 */ -#define REQUEST_JUMPRAM 0x8 -#define REQUEST_SET_CLOCK 0xB -#define REQUEST_SET_GPIO 0xC -#define REQUEST_ENABLE_VIDEO 0xF +#define REQUEST_SET_USB_XFER_LEN 0x0 /* valid only for firmware version */ + /* higher than 1.21 */ +#define REQUEST_I2C_READ 0x2 +#define REQUEST_I2C_WRITE 0x3 +#define REQUEST_POLL_RC 0x4 /* deprecated in firmware v1.20 */ +#define REQUEST_JUMPRAM 0x8 +#define REQUEST_SET_CLOCK 0xB +#define REQUEST_SET_GPIO 0xC +#define REQUEST_ENABLE_VIDEO 0xF // 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog) // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) -#define REQUEST_SET_RC 0x11 -#define REQUEST_NEW_I2C_READ 0x12 -#define REQUEST_NEW_I2C_WRITE 0x13 -#define REQUEST_GET_VERSION 0x15 +#define REQUEST_SET_RC 0x11 +#define REQUEST_NEW_I2C_READ 0x12 +#define REQUEST_NEW_I2C_WRITE 0x13 +#define REQUEST_GET_VERSION 0x15 struct dib0700_state { u8 channel_state; @@ -44,6 +46,8 @@ struct dib0700_state { u8 is_dib7000pc; u8 fw_use_new_i2c_api; u8 disable_streaming_master_mode; + u32 fw_version; + u32 nb_packet_buffer_size; }; extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index db7f7f7..0d3c9a9 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -17,6 +17,14 @@ int dvb_usb_dib0700_ir_proto = 1; module_param(dvb_usb_dib0700_ir_proto, int, 0644); MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (default), 2=RC6)."); +static int nb_packet_buffer_size = 21; +module_param(nb_packet_buffer_size, int, 0644); +MODULE_PARM_DESC(nb_packet_buffer_size, + "Set the dib0700 driver data buffer size. This parameter " + "corresponds to the number of TS packets. The actual size of " + "the data buffer corresponds to this parameter " + "multiplied by 188 (default: 21)"); + DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); @@ -28,10 +36,14 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, sizeof(b), USB_CTRL_GET_TIMEOUT); - *hwversion = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; - *romversion = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | b[7]; - *ramversion = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11]; - *fwtype = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15]; + if (hwversion != NULL) + *hwversion = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; + if (romversion != NULL) + *romversion = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | b[7]; + if (ramversion != NULL) + *ramversion = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11]; + if (fwtype != NULL) + *fwtype = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15]; return ret; } @@ -97,6 +109,27 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_ return dib0700_ctrl_wr(d,buf,3); } +static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) +{ + struct dib0700_state *st = d->priv; + u8 b[3]; + int ret; + + if (st->fw_version >= 0x10201) { + b[0] = REQUEST_SET_USB_XFER_LEN; + b[1] = (nb_ts_packets >> 8)&0xff; + b[2] = nb_ts_packets & 0xff; + + deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets); + + ret = dib0700_ctrl_wr(d, b, 3); + } else { + deb_info("this firmware does not allow to change the USB xfer len\n"); + ret = -EIO; + } + return ret; +} + /* * I2C master xfer function (supported in 1.20 firmware) */ @@ -328,7 +361,9 @@ static int dib0700_jumpram(struct usb_device *udev, u32 address) int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw) { struct hexline hx; - int pos = 0, ret, act_len; + int pos = 0, ret, act_len, i, adap_num; + u8 b[16]; + u32 fw_version; u8 buf[260]; @@ -364,6 +399,34 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw } else ret = -EIO; + /* the number of ts packet has to be at least 1 */ + if (nb_packet_buffer_size < 1) + nb_packet_buffer_size = 1; + + /* get the fimware version */ + usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + REQUEST_GET_VERSION, + USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, + b, sizeof(b), USB_CTRL_GET_TIMEOUT); + fw_version = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11]; + + /* set the buffer size - DVB-USB is allocating URB buffers + * only after the firwmare download was successful */ + for (i = 0; i < dib0700_device_count; i++) { + for (adap_num = 0; adap_num < dib0700_devices[i].num_adapters; + adap_num++) { + if (fw_version >= 0x10201) + dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 188*nb_packet_buffer_size; + else { + /* for fw version older than 1.20.1, + * the buffersize has to be n times 512 */ + dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512; + if (dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize < 512) + dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 512; + } + } + } + return ret; } @@ -371,6 +434,18 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) { struct dib0700_state *st = adap->dev->priv; u8 b[4]; + int ret; + + if ((onoff != 0) && (st->fw_version >= 0x10201)) { + /* for firmware later than 1.20.1, + * the USB xfer length can be set */ + ret = dib0700_set_usb_xfer_len(adap->dev, + st->nb_packet_buffer_size); + if (ret < 0) { + deb_info("can not set the USB xfer len\n"); + return ret; + } + } b[0] = REQUEST_ENABLE_VIDEO; b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */ @@ -415,9 +490,21 @@ static int dib0700_probe(struct usb_interface *intf, for (i = 0; i < dib0700_device_count; i++) if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, - &dev, adapter_nr) == 0) - { + &dev, adapter_nr) == 0) { + struct dib0700_state *st = dev->priv; + u32 hwversion, romversion, fw_version, fwtype; + + dib0700_get_version(dev, &hwversion, &romversion, + &fw_version, &fwtype); + + deb_info("Firmware version: %x, %d, 0x%x, %d\n", + hwversion, romversion, fw_version, fwtype); + + st->fw_version = fw_version; + st->nb_packet_buffer_size = (u32)nb_packet_buffer_size; + dib0700_rc_setup(dev); + return 0; } -- cgit v0.10.2 From 89dfc557d1b85bbaf04ca4c9927c6ea22df72e04 Mon Sep 17 00:00:00 2001 From: Olivier Grenie Date: Mon, 30 Nov 2009 06:38:49 -0300 Subject: V4L/DVB (13587): DiB8000: enhance status lock Enhance status lock behaviour. Signed-off-by: Olivier Grenie Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c index 5218a5c..bb2ec15 100644 --- a/drivers/media/dvb/frontends/dib8000.c +++ b/drivers/media/dvb/frontends/dib8000.c @@ -2083,29 +2083,31 @@ static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat) *stat = 0; - if ((lock >> 14) & 1) // AGC + if ((lock >> 13) & 1) *stat |= FE_HAS_SIGNAL; - if ((lock >> 8) & 1) // Equal + if ((lock >> 8) & 1) /* Equal */ *stat |= FE_HAS_CARRIER; - if ((lock >> 3) & 1) // TMCC_SYNC + if (((lock >> 1) & 0xf) == 0xf) /* TMCC_SYNC */ *stat |= FE_HAS_SYNC; - if ((lock >> 5) & 7) // FEC MPEG + if (((lock >> 12) & 1) && ((lock >> 5) & 7)) /* FEC MPEG */ *stat |= FE_HAS_LOCK; - lock = dib8000_read_word(state, 554); // Viterbi Layer A - if (lock & 0x01) - *stat |= FE_HAS_VITERBI; + if ((lock >> 12) & 1) { + lock = dib8000_read_word(state, 554); /* Viterbi Layer A */ + if (lock & 0x01) + *stat |= FE_HAS_VITERBI; - lock = dib8000_read_word(state, 555); // Viterbi Layer B - if (lock & 0x01) - *stat |= FE_HAS_VITERBI; + lock = dib8000_read_word(state, 555); /* Viterbi Layer B */ + if (lock & 0x01) + *stat |= FE_HAS_VITERBI; - lock = dib8000_read_word(state, 556); // Viterbi Layer C - if (lock & 0x01) - *stat |= FE_HAS_VITERBI; + lock = dib8000_read_word(state, 556); /* Viterbi Layer C */ + if (lock & 0x01) + *stat |= FE_HAS_VITERBI; + } return 0; } -- cgit v0.10.2 From 6e8fdbd023ef6a05da444baacfea75fdf97bdc50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20N=C3=A9meth?= Date: Sun, 22 Nov 2009 18:52:37 -0300 Subject: V4L/DVB (13589): dib8000: merge two conditionals MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge two ifs: the condition is the same. The second if uses the ncoeff which is initialized in the first if. Cc: Patrick Boettcher Signed-off-by: Márton Németh Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c index bb2ec15..335c6c0 100644 --- a/drivers/media/dvb/frontends/dib8000.c +++ b/drivers/media/dvb/frontends/dib8000.c @@ -1423,10 +1423,9 @@ static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosear } break; } - } - if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) for (i = 0; i < 8; i++) dib8000_write_word(state, 343 + i, ncoeff[i]); + } // P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5 dib8000_write_word(state, 351, -- cgit v0.10.2 From 7eca61eb6a57a3aae10e77d9306cda0b8c23cdab Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 22 Nov 2009 23:02:02 -0300 Subject: V4L/DVB (13590): cpia: convert it to use proc_fops X-Patchwork-Id: 62090 Signed-off-by: Alexey Dobriyan Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index d6f2653..551ddf2 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -244,72 +245,67 @@ static void rvfree(void *mem, unsigned long size) #ifdef CONFIG_PROC_FS static struct proc_dir_entry *cpia_proc_root=NULL; -static int cpia_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int cpia_proc_show(struct seq_file *m, void *v) { - char *out = page; - int len, tmp; - struct cam_data *cam = data; + struct cam_data *cam = m->private; + int tmp; char tmpstr[29]; - /* IMPORTANT: This output MUST be kept under PAGE_SIZE - * or we need to get more sophisticated. */ - - out += sprintf(out, "read-only\n-----------------------\n"); - out += sprintf(out, "V4L Driver version: %d.%d.%d\n", + 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); - out += sprintf(out, "CPIA Version: %d.%02d (%d.%d)\n", + 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); - out += sprintf(out, "CPIA PnP-ID: %04x:%04x:%04x\n", + seq_printf(m, "CPIA PnP-ID: %04x:%04x:%04x\n", cam->params.pnpID.vendor, cam->params.pnpID.product, cam->params.pnpID.deviceRevision); - out += sprintf(out, "VP-Version: %d.%d %04x\n", + seq_printf(m, "VP-Version: %d.%d %04x\n", cam->params.vpVersion.vpVersion, cam->params.vpVersion.vpRevision, cam->params.vpVersion.cameraHeadID); - out += sprintf(out, "system_state: %#04x\n", + seq_printf(m, "system_state: %#04x\n", cam->params.status.systemState); - out += sprintf(out, "grab_state: %#04x\n", + seq_printf(m, "grab_state: %#04x\n", cam->params.status.grabState); - out += sprintf(out, "stream_state: %#04x\n", + seq_printf(m, "stream_state: %#04x\n", cam->params.status.streamState); - out += sprintf(out, "fatal_error: %#04x\n", + seq_printf(m, "fatal_error: %#04x\n", cam->params.status.fatalError); - out += sprintf(out, "cmd_error: %#04x\n", + seq_printf(m, "cmd_error: %#04x\n", cam->params.status.cmdError); - out += sprintf(out, "debug_flags: %#04x\n", + seq_printf(m, "debug_flags: %#04x\n", cam->params.status.debugFlags); - out += sprintf(out, "vp_status: %#04x\n", + seq_printf(m, "vp_status: %#04x\n", cam->params.status.vpStatus); - out += sprintf(out, "error_code: %#04x\n", + seq_printf(m, "error_code: %#04x\n", cam->params.status.errorCode); /* QX3 specific entries */ if (cam->params.qx3.qx3_detected) { - out += sprintf(out, "button: %4d\n", + seq_printf(m, "button: %4d\n", cam->params.qx3.button); - out += sprintf(out, "cradled: %4d\n", + seq_printf(m, "cradled: %4d\n", cam->params.qx3.cradled); } - out += sprintf(out, "video_size: %s\n", + seq_printf(m, "video_size: %s\n", cam->params.format.videoSize == VIDEOSIZE_CIF ? "CIF " : "QCIF"); - out += sprintf(out, "roi: (%3d, %3d) to (%3d, %3d)\n", + 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); - out += sprintf(out, "actual_fps: %3d\n", cam->fps); - out += sprintf(out, "transfer_rate: %4dkB/s\n", + seq_printf(m, "actual_fps: %3d\n", cam->fps); + seq_printf(m, "transfer_rate: %4dkB/s\n", cam->transfer_rate); - out += sprintf(out, "\nread-write\n"); - out += sprintf(out, "----------------------- current min" + seq_printf(m, "\nread-write\n"); + seq_printf(m, "----------------------- current min" " max default comment\n"); - out += sprintf(out, "brightness: %8d %8d %8d %8d\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) @@ -318,26 +314,26 @@ static int cpia_read_proc(char *page, char **start, off_t off, else tmp = 96; - out += sprintf(out, "contrast: %8d %8d %8d %8d" + seq_printf(m, "contrast: %8d %8d %8d %8d" " steps of 8\n", cam->params.colourParams.contrast, 0, tmp, 48); - out += sprintf(out, "saturation: %8d %8d %8d %8d\n", + 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); - out += sprintf(out, "sensor_fps: %4d.%03d %8d %8d %8d\n", + seq_printf(m, "sensor_fps: %4d.%03d %8d %8d %8d\n", tmp/1000, tmp%1000, 3, 30, 15); - out += sprintf(out, "stream_start_line: %8d %8d %8d %8d\n", + 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); - out += sprintf(out, "sub_sample: %8s %8s %8s %8s\n", + seq_printf(m, "sub_sample: %8s %8s %8s %8s\n", cam->params.format.subSample == SUBSAMPLE_420 ? "420" : "422", "420", "422", "422"); - out += sprintf(out, "yuv_order: %8s %8s %8s %8s\n", + seq_printf(m, "yuv_order: %8s %8s %8s %8s\n", cam->params.format.yuvOrder == YUVORDER_YUYV ? "YUYV" : "UYVY", "YUYV" , "UYVY", "YUYV"); - out += sprintf(out, "ecp_timing: %8s %8s %8s %8s\n", + seq_printf(m, "ecp_timing: %8s %8s %8s %8s\n", cam->params.ecpTiming ? "slow" : "normal", "slow", "normal", "normal"); @@ -346,13 +342,13 @@ static int cpia_read_proc(char *page, char **start, off_t off, } else { sprintf(tmpstr, "manual"); } - out += sprintf(out, "color_balance_mode: %8s %8s %8s" + seq_printf(m, "color_balance_mode: %8s %8s %8s" " %8s\n", tmpstr, "manual", "auto", "auto"); - out += sprintf(out, "red_gain: %8d %8d %8d %8d\n", + seq_printf(m, "red_gain: %8d %8d %8d %8d\n", cam->params.colourBalance.redGain, 0, 212, 32); - out += sprintf(out, "green_gain: %8d %8d %8d %8d\n", + seq_printf(m, "green_gain: %8d %8d %8d %8d\n", cam->params.colourBalance.greenGain, 0, 212, 6); - out += sprintf(out, "blue_gain: %8d %8d %8d %8d\n", + seq_printf(m, "blue_gain: %8d %8d %8d %8d\n", cam->params.colourBalance.blueGain, 0, 212, 92); if (cam->params.version.firmwareVersion == 1 && @@ -363,10 +359,10 @@ static int cpia_read_proc(char *page, char **start, off_t off, sprintf(tmpstr, "%8d %8d %8d", 1, 8, 2); if (cam->params.exposure.gainMode == 0) - out += sprintf(out, "max_gain: unknown %28s" + seq_printf(m, "max_gain: unknown %28s" " powers of 2\n", tmpstr); else - out += sprintf(out, "max_gain: %8d %28s" + seq_printf(m, "max_gain: %8d %28s" " 1,2,4 or 8 \n", 1<<(cam->params.exposure.gainMode-1), tmpstr); @@ -382,12 +378,12 @@ static int cpia_read_proc(char *page, char **start, off_t off, sprintf(tmpstr, "unknown"); break; } - out += sprintf(out, "exposure_mode: %8s %8s %8s" + seq_printf(m, "exposure_mode: %8s %8s %8s" " %8s\n", tmpstr, "manual", "auto", "auto"); - out += sprintf(out, "centre_weight: %8s %8s %8s %8s\n", + seq_printf(m, "centre_weight: %8s %8s %8s %8s\n", (2-cam->params.exposure.centreWeight) ? "on" : "off", "off", "on", "on"); - out += sprintf(out, "gain: %8d %8d max_gain %8d 1,2,4,8 possible\n", + 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) @@ -396,7 +392,7 @@ static int cpia_read_proc(char *page, char **start, off_t off, else tmp = 510; - out += sprintf(out, "fine_exp: %8d %8d %8d %8d\n", + 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) @@ -405,127 +401,122 @@ static int cpia_read_proc(char *page, char **start, off_t off, else tmp = MAX_EXP; - out += sprintf(out, "coarse_exp: %8d %8d %8d" + seq_printf(m, "coarse_exp: %8d %8d %8d" " %8d\n", cam->params.exposure.coarseExpLo+ 256*cam->params.exposure.coarseExpHi, 0, tmp, 185); - out += sprintf(out, "red_comp: %8d %8d %8d %8d\n", + seq_printf(m, "red_comp: %8d %8d %8d %8d\n", cam->params.exposure.redComp, COMP_RED, 255, COMP_RED); - out += sprintf(out, "green1_comp: %8d %8d %8d %8d\n", + seq_printf(m, "green1_comp: %8d %8d %8d %8d\n", cam->params.exposure.green1Comp, COMP_GREEN1, 255, COMP_GREEN1); - out += sprintf(out, "green2_comp: %8d %8d %8d %8d\n", + seq_printf(m, "green2_comp: %8d %8d %8d %8d\n", cam->params.exposure.green2Comp, COMP_GREEN2, 255, COMP_GREEN2); - out += sprintf(out, "blue_comp: %8d %8d %8d %8d\n", + seq_printf(m, "blue_comp: %8d %8d %8d %8d\n", cam->params.exposure.blueComp, COMP_BLUE, 255, COMP_BLUE); - out += sprintf(out, "apcor_gain1: %#8x %#8x %#8x %#8x\n", + seq_printf(m, "apcor_gain1: %#8x %#8x %#8x %#8x\n", cam->params.apcor.gain1, 0, 0xff, 0x1c); - out += sprintf(out, "apcor_gain2: %#8x %#8x %#8x %#8x\n", + seq_printf(m, "apcor_gain2: %#8x %#8x %#8x %#8x\n", cam->params.apcor.gain2, 0, 0xff, 0x1a); - out += sprintf(out, "apcor_gain4: %#8x %#8x %#8x %#8x\n", + seq_printf(m, "apcor_gain4: %#8x %#8x %#8x %#8x\n", cam->params.apcor.gain4, 0, 0xff, 0x2d); - out += sprintf(out, "apcor_gain8: %#8x %#8x %#8x %#8x\n", + seq_printf(m, "apcor_gain8: %#8x %#8x %#8x %#8x\n", cam->params.apcor.gain8, 0, 0xff, 0x2a); - out += sprintf(out, "vl_offset_gain1: %8d %8d %8d %8d\n", + seq_printf(m, "vl_offset_gain1: %8d %8d %8d %8d\n", cam->params.vlOffset.gain1, 0, 255, 24); - out += sprintf(out, "vl_offset_gain2: %8d %8d %8d %8d\n", + seq_printf(m, "vl_offset_gain2: %8d %8d %8d %8d\n", cam->params.vlOffset.gain2, 0, 255, 28); - out += sprintf(out, "vl_offset_gain4: %8d %8d %8d %8d\n", + seq_printf(m, "vl_offset_gain4: %8d %8d %8d %8d\n", cam->params.vlOffset.gain4, 0, 255, 30); - out += sprintf(out, "vl_offset_gain8: %8d %8d %8d %8d\n", + seq_printf(m, "vl_offset_gain8: %8d %8d %8d %8d\n", cam->params.vlOffset.gain8, 0, 255, 30); - out += sprintf(out, "flicker_control: %8s %8s %8s %8s\n", + seq_printf(m, "flicker_control: %8s %8s %8s %8s\n", cam->params.flickerControl.flickerMode ? "on" : "off", "off", "on", "off"); - out += sprintf(out, "mains_frequency: %8d %8d %8d %8d" + 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) - out += sprintf(out, "allowable_overexposure: %4dauto auto %8d auto\n", + seq_printf(m, "allowable_overexposure: %4dauto auto %8d auto\n", -cam->params.flickerControl.allowableOverExposure, 255); else - out += sprintf(out, "allowable_overexposure: %8d auto %8d auto\n", + seq_printf(m, "allowable_overexposure: %8d auto %8d auto\n", cam->params.flickerControl.allowableOverExposure, 255); - out += sprintf(out, "compression_mode: "); + seq_printf(m, "compression_mode: "); switch(cam->params.compression.mode) { case CPIA_COMPRESSION_NONE: - out += sprintf(out, "%8s", "none"); + seq_printf(m, "%8s", "none"); break; case CPIA_COMPRESSION_AUTO: - out += sprintf(out, "%8s", "auto"); + seq_printf(m, "%8s", "auto"); break; case CPIA_COMPRESSION_MANUAL: - out += sprintf(out, "%8s", "manual"); + seq_printf(m, "%8s", "manual"); break; default: - out += sprintf(out, "%8s", "unknown"); + seq_printf(m, "%8s", "unknown"); break; } - out += sprintf(out, " none,auto,manual auto\n"); - out += sprintf(out, "decimation_enable: %8s %8s %8s %8s\n", + 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"); - out += sprintf(out, "compression_target: %9s %9s %9s %9s\n", + seq_printf(m, "compression_target: %9s %9s %9s %9s\n", cam->params.compressionTarget.frTargeting == CPIA_COMPRESSION_TARGET_FRAMERATE ? "framerate":"quality", "framerate", "quality", "quality"); - out += sprintf(out, "target_framerate: %8d %8d %8d %8d\n", + seq_printf(m, "target_framerate: %8d %8d %8d %8d\n", cam->params.compressionTarget.targetFR, 1, 30, 15); - out += sprintf(out, "target_quality: %8d %8d %8d %8d\n", + seq_printf(m, "target_quality: %8d %8d %8d %8d\n", cam->params.compressionTarget.targetQ, 1, 64, 5); - out += sprintf(out, "y_threshold: %8d %8d %8d %8d\n", + seq_printf(m, "y_threshold: %8d %8d %8d %8d\n", cam->params.yuvThreshold.yThreshold, 0, 31, 6); - out += sprintf(out, "uv_threshold: %8d %8d %8d %8d\n", + seq_printf(m, "uv_threshold: %8d %8d %8d %8d\n", cam->params.yuvThreshold.uvThreshold, 0, 31, 6); - out += sprintf(out, "hysteresis: %8d %8d %8d %8d\n", + seq_printf(m, "hysteresis: %8d %8d %8d %8d\n", cam->params.compressionParams.hysteresis, 0, 255, 3); - out += sprintf(out, "threshold_max: %8d %8d %8d %8d\n", + seq_printf(m, "threshold_max: %8d %8d %8d %8d\n", cam->params.compressionParams.threshMax, 0, 255, 11); - out += sprintf(out, "small_step: %8d %8d %8d %8d\n", + seq_printf(m, "small_step: %8d %8d %8d %8d\n", cam->params.compressionParams.smallStep, 0, 255, 1); - out += sprintf(out, "large_step: %8d %8d %8d %8d\n", + seq_printf(m, "large_step: %8d %8d %8d %8d\n", cam->params.compressionParams.largeStep, 0, 255, 3); - out += sprintf(out, "decimation_hysteresis: %8d %8d %8d %8d\n", + seq_printf(m, "decimation_hysteresis: %8d %8d %8d %8d\n", cam->params.compressionParams.decimationHysteresis, 0, 255, 2); - out += sprintf(out, "fr_diff_step_thresh: %8d %8d %8d %8d\n", + seq_printf(m, "fr_diff_step_thresh: %8d %8d %8d %8d\n", cam->params.compressionParams.frDiffStepThresh, 0, 255, 5); - out += sprintf(out, "q_diff_step_thresh: %8d %8d %8d %8d\n", + seq_printf(m, "q_diff_step_thresh: %8d %8d %8d %8d\n", cam->params.compressionParams.qDiffStepThresh, 0, 255, 3); - out += sprintf(out, "decimation_thresh_mod: %8d %8d %8d %8d\n", + 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) { - out += sprintf(out, "toplight: %8s %8s %8s %8s\n", + seq_printf(m, "toplight: %8s %8s %8s %8s\n", cam->params.qx3.toplight ? "on" : "off", "off", "on", "off"); - out += sprintf(out, "bottomlight: %8s %8s %8s %8s\n", + seq_printf(m, "bottomlight: %8s %8s %8s %8s\n", cam->params.qx3.bottomlight ? "on" : "off", "off", "on", "off"); } - len = out - page; - len -= off; - if (len < count) { - *eof = 1; - if (len <= 0) return 0; - } else - len = count; - - *start = page + off; - return len; + 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, unsigned long *count, +static int match(char *checkstr, char **buffer, size_t *count, int *find_colon, int *err) { int ret, colon_found = 1; @@ -551,7 +542,7 @@ static int match(char *checkstr, char **buffer, unsigned long *count, return ret; } -static unsigned long int value(char **buffer, unsigned long *count, int *err) +static unsigned long int value(char **buffer, size_t *count, int *err) { char *p; unsigned long int ret; @@ -565,10 +556,10 @@ static unsigned long int value(char **buffer, unsigned long *count, int *err) return ret; } -static int cpia_write_proc(struct file *file, const char __user *buf, - unsigned long count, void *data) +static ssize_t cpia_proc_write(struct file *file, const char __user *buf, + size_t count, loff_t *pos) { - struct cam_data *cam = data; + struct cam_data *cam = PDE(file->f_path.dentry->d_inode)->data; struct cam_params new_params; char *page, *buffer; int retval, find_colon; @@ -582,7 +573,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf, * from the comx driver */ if (count > PAGE_SIZE) { - printk(KERN_ERR "count is %lu > %d!!!\n", count, (int)PAGE_SIZE); + printk(KERN_ERR "count is %zu > %d!!!\n", count, (int)PAGE_SIZE); return -ENOSPC; } @@ -1340,6 +1331,15 @@ out: 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; @@ -1347,14 +1347,12 @@ static void create_proc_cpia_cam(struct cam_data *cam) if (!cpia_proc_root || !cam) return; - ent = create_proc_entry(video_device_node_name(&cam->vdev), - S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root); + ent = proc_create_data(video_device_node_name(&cam->vdev), + S_IRUGO|S_IWUSR, cpia_proc_root, + &cpia_proc_fops, cam); if (!ent) return; - ent->data = cam; - ent->read_proc = cpia_read_proc; - ent->write_proc = cpia_write_proc; /* size of the proc entry is 3736 bytes for the standard webcam; the extra features of the QX3 microscope add 189 bytes. -- cgit v0.10.2 From d995a18733a683c1c086a4d48315976f8c25d89b Mon Sep 17 00:00:00 2001 From: Lukas Karas Date: Tue, 24 Nov 2009 12:06:52 -0300 Subject: V4L/DVB (13591): add support for IR on FlyDVB Trio (saa7134) saa7134: Add support for IR reciever on card LifeView FlyDVB Trio -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html [mchehab@redhat.com: CodingStyle fixes and ported upstream] Tested-by: Petr Fiala Signed-off-by: Lukas Karas 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 64360d2..2856e78 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -353,6 +353,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir_type = IR_TYPE_RC5; ir_codes = &ir_codes_fusionhdtv_mce_table; break; + case 0x0b: case 0x47: case 0x71: if (adap->id == I2C_HW_B_CX2388x || @@ -422,7 +423,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) /* Make sure we are all setup before going on */ if (!name || !ir->get_key || !ir_type || !ir_codes) { - dprintk(1, DEVNAME ": Unsupported device at address 0x%02x\n", + dprintk(1, ": Unsupported device at address 0x%02x\n", addr); err = -ENODEV; goto err_out_free; diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 7e40d6d..03f5727 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -7211,9 +7211,31 @@ int saa7134_board_init2(struct saa7134_dev *dev) } case SAA7134_BOARD_FLYDVB_TRIO: { + u8 temp = 0; + int rc; u8 data[] = { 0x3c, 0x33, 0x62}; struct i2c_msg msg = {.addr=0x09, .flags=0, .buf=data, .len = sizeof(data)}; i2c_transfer(&dev->i2c_adap, &msg, 1); + + /* + * send weak up message to pic16C505 chip + * @ LifeView FlyDVB Trio + */ + msg.buf = &temp; + msg.addr = 0x0b; + msg.len = 1; + if (1 != i2c_transfer(&dev->i2c_adap, &msg, 1)) { + printk(KERN_WARNING "%s: send wake up byte to pic16C505" + "(IR chip) failed\n", dev->name); + } else { + msg.flags = I2C_M_RD; + rc = i2c_transfer(&dev->i2c_adap, &msg, 1); + printk(KERN_INFO "%s: probe IR chip @ i2c 0x%02x: %s\n", + dev->name, msg.addr, + (1 == rc) ? "yes" : "no"); + if (rc == 1) + dev->has_remote = SAA7134_REMOTE_I2C; + } break; } case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 744918b..411a841 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -127,6 +127,61 @@ static int build_key(struct saa7134_dev *dev) /* --------------------- Chip specific I2C key builders ----------------- */ +static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +{ + int gpio; + int attempt = 0; + unsigned char b; + + /* We need this to access GPI Used by the saa_readl macro. */ + struct saa7134_dev *dev = ir->c->adapter->algo_data; + + if (dev == NULL) { + dprintk("get_key_flydvb_trio: " + "gir->c->adapter->algo_data is NULL!\n"); + return -EIO; + } + + /* rising SAA7134_GPIGPRESCAN reads the status */ + saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + + gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); + + if (0x40000 & ~gpio) + return 0; /* No button press */ + + /* No button press - only before first key pressed */ + if (b == 0xFF) + return 0; + + /* poll IR chip */ + /* weak up the IR chip */ + b = 0; + + while (1 != i2c_master_send(ir->c, &b, 1)) { + if ((attempt++) < 10) { + /* + * wait a bit for next attempt - + * I don't know how make it better + */ + msleep(10); + continue; + } + i2cdprintk("send wake up byte to pic16C505 (IR chip)" + "failed %dx\n", attempt); + return -EIO; + } + if (1 != i2c_master_recv(ir->c, &b, 1)) { + i2cdprintk("read error\n"); + return -EIO; + } + + *ir_key = b; + *ir_raw = b; + return 1; +} + static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { @@ -622,6 +677,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x020000; polling = 50; /* ms */ break; + break; } if (NULL == ir_codes) { printk("%s: Oops: IR config error [card=%d]\n", @@ -788,6 +844,12 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: info.addr = 0x40; break; + case SAA7134_BOARD_FLYDVB_TRIO: + dev->init_data.name = "FlyDVB Trio"; + dev->init_data.get_key = get_key_flydvb_trio; + dev->init_data.ir_codes = &ir_codes_flydvb_table; + info.addr = 0x0b; + break; default: dprintk("No I2C IR support for board %x\n", dev->board); return; -- cgit v0.10.2 From 38ffcd10d6831efd15ec5a223b1050eac12d4c28 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Mon, 30 Nov 2009 14:14:36 -0300 Subject: V4L/DVB (13581): DiBUSB: fix I2c access when there is a read-access w/o write sequence This patch fixes the behaviour of the dibusb-i2c-access which was previously changed to avoid accidental EEprom writes: Now it allow i2c-reads without prepended i2c-writes, but it is still not doing anything in case the EEprom is addressed. Thanks to Mario Bachmann for testing. Tested-by: Mario Bachmann Cc: Mario Bachmann Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c index b395e85..9143b56 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/drivers/media/dvb/dvb-usb/dibusb-common.c @@ -142,8 +142,13 @@ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num } else if ((msg[i].flags & I2C_M_RD) == 0) { if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0) break; - } else - break; + } else if (msg[i].addr != 0x50) { + /* 0x50 is the address of the eeprom - we need to protect it + * from dibusb's bad i2c implementation: reads without + * writing the offset before are forbidden */ + if (dibusb_i2c_msg(d, msg[i].addr, NULL, 0, msg[i].buf, msg[i].len) < 0) + break; + } } mutex_unlock(&d->i2c_mutex); -- cgit v0.10.2 From 4315c414474cf43994f0c562ce8faea3628f550b Mon Sep 17 00:00:00 2001 From: Andrea Odetti Date: Thu, 10 Dec 2009 16:26:10 -0300 Subject: V4L/DVB (13593): PWC: parameter trace is only available in debug This patch fixes a small issue where modinfo says the parameter "trace" is always available, while it only works if CONFIG_USB_PWC_DEBUG is enabled. Signed-off-by: Andrea Odetti Signed-off-by: Douglas Schilling Landgraf 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 d0e2b57..aea7e22 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -1947,7 +1947,9 @@ MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30"); MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve"); MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers"); +#ifdef CONFIG_USB_PWC_DEBUG MODULE_PARM_DESC(trace, "For debugging purposes"); +#endif MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off"); MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)"); MODULE_PARM_DESC(leds, "LED on,off time in milliseconds"); -- cgit v0.10.2 From cb63c2aad232930da8c8b5c5020dd560cb885cf5 Mon Sep 17 00:00:00 2001 From: Thiago Farina Date: Thu, 10 Dec 2009 16:40:50 -0300 Subject: V4L/DVB (13594): cpia2: use __stringify macro. Replace MAKE_STRING to __stringify macro Signed-off-by: Thiago Farina Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 30d39b1..6f91415 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -38,17 +38,12 @@ #include #include #include +#include #include #include "cpia2.h" #include "cpia2dev.h" - -//#define _CPIA2_DEBUG_ - -#define MAKE_STRING_1(x) #x -#define MAKE_STRING(x) MAKE_STRING_1(x) - static int video_nr = -1; module_param(video_nr, int, 0); MODULE_PARM_DESC(video_nr,"video device to register (0=/dev/video0, etc)"); @@ -60,26 +55,26 @@ MODULE_PARM_DESC(buffer_size, "Size for each frame buffer in bytes (default 68k) static int num_buffers = 3; module_param(num_buffers, int, 0); MODULE_PARM_DESC(num_buffers, "Number of frame buffers (1-" - MAKE_STRING(VIDEO_MAX_FRAME) ", default 3)"); + __stringify(VIDEO_MAX_FRAME) ", default 3)"); static int alternate = DEFAULT_ALT; module_param(alternate, int, 0); -MODULE_PARM_DESC(alternate, "USB Alternate (" MAKE_STRING(USBIF_ISO_1) "-" - MAKE_STRING(USBIF_ISO_6) ", default " - MAKE_STRING(DEFAULT_ALT) ")"); +MODULE_PARM_DESC(alternate, "USB Alternate (" __stringify(USBIF_ISO_1) "-" + __stringify(USBIF_ISO_6) ", default " + __stringify(DEFAULT_ALT) ")"); static int flicker_freq = 60; module_param(flicker_freq, int, 0); -MODULE_PARM_DESC(flicker_freq, "Flicker frequency (" MAKE_STRING(50) "or" - MAKE_STRING(60) ", default " - MAKE_STRING(60) ")"); +MODULE_PARM_DESC(flicker_freq, "Flicker frequency (" __stringify(50) "or" + __stringify(60) ", default " + __stringify(60) ")"); static int flicker_mode = NEVER_FLICKER; module_param(flicker_mode, int, 0); MODULE_PARM_DESC(flicker_mode, - "Flicker supression (" MAKE_STRING(NEVER_FLICKER) "or" - MAKE_STRING(ANTI_FLICKER_ON) ", default " - MAKE_STRING(NEVER_FLICKER) ")"); + "Flicker supression (" __stringify(NEVER_FLICKER) "or" + __stringify(ANTI_FLICKER_ON) ", default " + __stringify(NEVER_FLICKER) ")"); MODULE_AUTHOR("Steve Miller (STMicroelectronics) "); MODULE_DESCRIPTION("V4L-driver for STMicroelectronics CPiA2 based cameras"); -- cgit v0.10.2 From 50e9d31183ed61c787b870cb3ee8f6c3db8c8a1e Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 10 Dec 2009 16:44:51 -0300 Subject: V4L/DVB (13596): ov511.c typo: lock => unlock This was found with a static checker and has not been tested, but it seems pretty clear that the mutex_lock() was supposed to be mutex_unlock() Signed-off-by: Dan Carpenter Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index c71865d..e0bce8d 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -5877,7 +5877,7 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) goto error; } - mutex_lock(&ov->lock); + mutex_unlock(&ov->lock); return 0; -- cgit v0.10.2 From 0d94e29459d372b6c5dda964a8b35a8d40050ca7 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Thu, 10 Dec 2009 16:46:06 -0300 Subject: V4L/DVB (13597): bttv: add i2c addr for old WinTV card to IR probe list There are old bttv-driven Hauppauge WinTV series cards that have their IR part at i2c addr 0x71, which doesn't get considered in the new 2.6.31 i2c code. From a 2.6.29 kernel: lirc_i2c: chip 0x10005 found @ 0x71 (Hauppauge PVR150) Minor cosmetic glitch, the card in question isn't actually a PVR-150, its: 03:06.0 Multimedia video controller: Brooktree Corporation Bt878 Video Capture (rev 11) Subsystem: Hauppauge computer works Inc. WinTV Series Flags: bus master, medium devsel, latency 32, IRQ 19 Memory at f4ffe000 (32-bit, prefetchable) [size=4K] Capabilities: [44] Vital Product Data Capabilities: [4c] Power Management version 2 Kernel driver in use: bttv Kernel modules: bttv Device ID: 0x109e:0x036e, Sub-Device ID: 0x0070:0x13eb This simply adds 0x71 to the list of addresses i2c_new_probed_device should consider, which gets IR working on this card again. Reported-by: Adam Williamson Tested-by: Adam Williamson Signed-off-by: Jarod Wilson Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c index beda363..a9d9ee73 100644 --- a/drivers/media/video/bt8xx/bttv-i2c.c +++ b/drivers/media/video/bt8xx/bttv-i2c.c @@ -400,7 +400,7 @@ int __devinit init_bttv_i2c(struct bttv *btv) That's why we probe 0x1a (~0x34) first. CB */ const unsigned short addr_list[] = { - 0x1a, 0x18, 0x4b, 0x64, 0x30, + 0x1a, 0x18, 0x4b, 0x64, 0x30, 0x71, I2C_CLIENT_END }; -- cgit v0.10.2 From 31bedfa5068936b15a388842be1d03cdd1bdfb07 Mon Sep 17 00:00:00 2001 From: Muralidharan Karicheri Date: Thu, 10 Dec 2009 16:47:48 -0300 Subject: V4L/DVB (13598): videobuf_dma_contig_user_get() for non-aligned offsets If a USERPTR address that is not aligned to page boundary is passed to the videobuf_dma_contig_user_get() function, it saves a page aligned address to the dma_handle. This is not correct. This issue is observed when using USERPTR IO machism for buffer exchange. Updates from last version:- Adding offset for size calculation as per comment from Magnus Damm. This ensures the last page is also included for checking if memory is contiguous. Signed-off-by: Muralidharan Karicheri Acked-by: Magnus Damm Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c index d25f284..22c0109 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/video/videobuf-dma-contig.c @@ -141,9 +141,11 @@ static int videobuf_dma_contig_user_get(struct videobuf_dma_contig_memory *mem, struct vm_area_struct *vma; unsigned long prev_pfn, this_pfn; unsigned long pages_done, user_address; + unsigned int offset; int ret; - mem->size = PAGE_ALIGN(vb->size); + offset = vb->baddr & ~PAGE_MASK; + mem->size = PAGE_ALIGN(vb->size + offset); mem->is_userptr = 0; ret = -EINVAL; @@ -166,7 +168,7 @@ static int videobuf_dma_contig_user_get(struct videobuf_dma_contig_memory *mem, break; if (pages_done == 0) - mem->dma_handle = this_pfn << PAGE_SHIFT; + mem->dma_handle = (this_pfn << PAGE_SHIFT) + offset; else if (this_pfn != (prev_pfn + 1)) ret = -EFAULT; -- cgit v0.10.2 From 1aa925c957d37e077edb1de4553481734b8462cf Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Thu, 10 Dec 2009 16:49:34 -0300 Subject: V4L/DVB (13599): radio-si470x: move some file operations to common file The read and poll file operations of the si470x usb driver can be used also equally on the si470x i2c driver, so they go to the common file. Signed-off-by: Joonyoung Shim Acked-by: Tobias Lorenz Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c index f33315f..4da0f15 100644 --- a/drivers/media/radio/si470x/radio-si470x-common.c +++ b/drivers/media/radio/si470x/radio-si470x-common.c @@ -426,6 +426,104 @@ int si470x_rds_on(struct si470x_device *radio) /************************************************************************** + * File Operations Interface + **************************************************************************/ + +/* + * si470x_fops_read - read RDS data + */ +static ssize_t si470x_fops_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + unsigned int block_count = 0; + + /* switch on rds reception */ + if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) + si470x_rds_on(radio); + + /* block if no new data available */ + while (radio->wr_index == radio->rd_index) { + if (file->f_flags & O_NONBLOCK) { + retval = -EWOULDBLOCK; + goto done; + } + if (wait_event_interruptible(radio->read_queue, + radio->wr_index != radio->rd_index) < 0) { + retval = -EINTR; + goto done; + } + } + + /* calculate block count from byte count */ + count /= 3; + + /* copy RDS block out of internal buffer and to user buffer */ + mutex_lock(&radio->lock); + while (block_count < count) { + if (radio->rd_index == radio->wr_index) + break; + + /* always transfer rds complete blocks */ + if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3)) + /* retval = -EFAULT; */ + break; + + /* increment and wrap read pointer */ + radio->rd_index += 3; + if (radio->rd_index >= radio->buf_size) + radio->rd_index = 0; + + /* increment counters */ + block_count++; + buf += 3; + retval += 3; + } + mutex_unlock(&radio->lock); + +done: + return retval; +} + + +/* + * si470x_fops_poll - poll RDS data + */ +static unsigned int si470x_fops_poll(struct file *file, + struct poll_table_struct *pts) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* switch on rds reception */ + if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) + si470x_rds_on(radio); + + poll_wait(file, &radio->read_queue, pts); + + if (radio->rd_index != radio->wr_index) + retval = POLLIN | POLLRDNORM; + + return retval; +} + + +/* + * si470x_fops - file operations interface + */ +static const struct v4l2_file_operations si470x_fops = { + .owner = THIS_MODULE, + .read = si470x_fops_read, + .poll = si470x_fops_poll, + .ioctl = video_ioctl2, + .open = si470x_fops_open, + .release = si470x_fops_release, +}; + + + +/************************************************************************** * Video4Linux Interface **************************************************************************/ diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index 2d53b6a..4816a6d 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -173,7 +173,7 @@ int si470x_disconnect_check(struct si470x_device *radio) /* * si470x_fops_open - file open */ -static int si470x_fops_open(struct file *file) +int si470x_fops_open(struct file *file) { struct si470x_device *radio = video_drvdata(file); int retval = 0; @@ -194,7 +194,7 @@ static int si470x_fops_open(struct file *file) /* * si470x_fops_release - file release */ -static int si470x_fops_release(struct file *file) +int si470x_fops_release(struct file *file) { struct si470x_device *radio = video_drvdata(file); int retval = 0; @@ -215,17 +215,6 @@ static int si470x_fops_release(struct file *file) } -/* - * si470x_fops - file operations interface - */ -const struct v4l2_file_operations si470x_fops = { - .owner = THIS_MODULE, - .ioctl = video_ioctl2, - .open = si470x_fops_open, - .release = si470x_fops_release, -}; - - /************************************************************************** * Video4Linux Interface diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c index f2d0e1d..a96e1b9 100644 --- a/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/drivers/media/radio/si470x/radio-si470x-usb.c @@ -509,89 +509,9 @@ resubmit: **************************************************************************/ /* - * si470x_fops_read - read RDS data - */ -static ssize_t si470x_fops_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - unsigned int block_count = 0; - - /* switch on rds reception */ - if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) - si470x_rds_on(radio); - - /* block if no new data available */ - while (radio->wr_index == radio->rd_index) { - if (file->f_flags & O_NONBLOCK) { - retval = -EWOULDBLOCK; - goto done; - } - if (wait_event_interruptible(radio->read_queue, - radio->wr_index != radio->rd_index) < 0) { - retval = -EINTR; - goto done; - } - } - - /* calculate block count from byte count */ - count /= 3; - - /* copy RDS block out of internal buffer and to user buffer */ - mutex_lock(&radio->lock); - while (block_count < count) { - if (radio->rd_index == radio->wr_index) - break; - - /* always transfer rds complete blocks */ - if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3)) - /* retval = -EFAULT; */ - break; - - /* increment and wrap read pointer */ - radio->rd_index += 3; - if (radio->rd_index >= radio->buf_size) - radio->rd_index = 0; - - /* increment counters */ - block_count++; - buf += 3; - retval += 3; - } - mutex_unlock(&radio->lock); - -done: - return retval; -} - - -/* - * si470x_fops_poll - poll RDS data - */ -static unsigned int si470x_fops_poll(struct file *file, - struct poll_table_struct *pts) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - - /* switch on rds reception */ - if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) - si470x_rds_on(radio); - - poll_wait(file, &radio->read_queue, pts); - - if (radio->rd_index != radio->wr_index) - retval = POLLIN | POLLRDNORM; - - return retval; -} - - -/* * si470x_fops_open - file open */ -static int si470x_fops_open(struct file *file) +int si470x_fops_open(struct file *file) { struct si470x_device *radio = video_drvdata(file); int retval; @@ -645,7 +565,7 @@ done: /* * si470x_fops_release - file release */ -static int si470x_fops_release(struct file *file) +int si470x_fops_release(struct file *file) { struct si470x_device *radio = video_drvdata(file); int retval = 0; @@ -688,19 +608,6 @@ done: } -/* - * si470x_fops - file operations interface - */ -const struct v4l2_file_operations si470x_fops = { - .owner = THIS_MODULE, - .read = si470x_fops_read, - .poll = si470x_fops_poll, - .ioctl = video_ioctl2, - .open = si470x_fops_open, - .release = si470x_fops_release, -}; - - /************************************************************************** * Video4Linux Interface diff --git a/drivers/media/radio/si470x/radio-si470x.h b/drivers/media/radio/si470x/radio-si470x.h index d0af194..f646f79 100644 --- a/drivers/media/radio/si470x/radio-si470x.h +++ b/drivers/media/radio/si470x/radio-si470x.h @@ -212,7 +212,6 @@ struct si470x_device { /************************************************************************** * Common Functions **************************************************************************/ -extern const struct v4l2_file_operations si470x_fops; extern struct video_device si470x_viddev_template; int si470x_get_register(struct si470x_device *radio, int regnr); int si470x_set_register(struct si470x_device *radio, int regnr); @@ -221,5 +220,7 @@ int si470x_set_freq(struct si470x_device *radio, unsigned int freq); int si470x_start(struct si470x_device *radio); int si470x_stop(struct si470x_device *radio); int si470x_rds_on(struct si470x_device *radio); +int si470x_fops_open(struct file *file); +int si470x_fops_release(struct file *file); int si470x_vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *capability); -- cgit v0.10.2 From fe2137dd4e6e4b2f5e758765d5305e8dbb0d931c Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Thu, 10 Dec 2009 16:50:34 -0300 Subject: V4L/DVB (13600): radio-si470x: support RDS on si470x i2c driver This patch is to support RDS on si470x i2c driver. The routine of RDS operation is almost same with thing of usb driver, but this uses RDS interrupt. Signed-off-by: Joonyoung Shim Acked-by: Tobias Lorenz Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index 4816a6d..b8c0d5c 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -22,22 +22,17 @@ */ -/* - * ToDo: - * - RDS support - */ - - /* driver definitions */ #define DRIVER_AUTHOR "Joonyoung Shim "; -#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 0) +#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 1) #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" #define DRIVER_DESC "I2C radio driver for Si470x FM Radio Receivers" -#define DRIVER_VERSION "1.0.0" +#define DRIVER_VERSION "1.0.1" /* kernel includes */ #include #include +#include #include "radio-si470x.h" @@ -62,6 +57,20 @@ static int radio_nr = -1; module_param(radio_nr, int, 0444); MODULE_PARM_DESC(radio_nr, "Radio Nr"); +/* RDS buffer blocks */ +static unsigned int rds_buf = 100; +module_param(rds_buf, uint, 0444); +MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*"); + +/* RDS maximum block errors */ +static unsigned short max_rds_errors = 1; +/* 0 means 0 errors requiring correction */ +/* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */ +/* 2 means 3-5 errors requiring correction */ +/* 3 means 6+ errors or errors in checkword, correction not possible */ +module_param(max_rds_errors, ushort, 0644); +MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*"); + /************************************************************************** @@ -181,12 +190,21 @@ int si470x_fops_open(struct file *file) mutex_lock(&radio->lock); radio->users++; - if (radio->users == 1) + if (radio->users == 1) { /* start radio */ retval = si470x_start(radio); + if (retval < 0) + goto done; + + /* enable RDS interrupt */ + radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDSIEN; + radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_GPIO2; + radio->registers[SYSCONFIG1] |= 0x1 << 2; + retval = si470x_set_register(radio, SYSCONFIG1); + } +done: mutex_unlock(&radio->lock); - return retval; } @@ -242,6 +260,105 @@ int si470x_vidioc_querycap(struct file *file, void *priv, **************************************************************************/ /* + * si470x_i2c_interrupt_work - rds processing function + */ +static void si470x_i2c_interrupt_work(struct work_struct *work) +{ + struct si470x_device *radio = container_of(work, + struct si470x_device, radio_work); + unsigned char regnr; + unsigned char blocknum; + unsigned short bler; /* rds block errors */ + unsigned short rds; + unsigned char tmpbuf[3]; + int retval = 0; + + /* safety checks */ + if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) + return; + + /* Update RDS registers */ + for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) { + retval = si470x_get_register(radio, STATUSRSSI + regnr); + if (retval < 0) + return; + } + + /* get rds blocks */ + if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) + /* No RDS group ready, better luck next time */ + return; + + for (blocknum = 0; blocknum < 4; blocknum++) { + switch (blocknum) { + default: + bler = (radio->registers[STATUSRSSI] & + STATUSRSSI_BLERA) >> 9; + rds = radio->registers[RDSA]; + break; + case 1: + bler = (radio->registers[READCHAN] & + READCHAN_BLERB) >> 14; + rds = radio->registers[RDSB]; + break; + case 2: + bler = (radio->registers[READCHAN] & + READCHAN_BLERC) >> 12; + rds = radio->registers[RDSC]; + break; + case 3: + bler = (radio->registers[READCHAN] & + READCHAN_BLERD) >> 10; + rds = radio->registers[RDSD]; + break; + }; + + /* Fill the V4L2 RDS buffer */ + put_unaligned_le16(rds, &tmpbuf); + tmpbuf[2] = blocknum; /* offset name */ + tmpbuf[2] |= blocknum << 3; /* received offset */ + if (bler > max_rds_errors) + tmpbuf[2] |= 0x80; /* uncorrectable errors */ + else if (bler > 0) + tmpbuf[2] |= 0x40; /* corrected error(s) */ + + /* copy RDS block to internal buffer */ + memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3); + radio->wr_index += 3; + + /* wrap write pointer */ + if (radio->wr_index >= radio->buf_size) + radio->wr_index = 0; + + /* check for overflow */ + if (radio->wr_index == radio->rd_index) { + /* increment and wrap read pointer */ + radio->rd_index += 3; + if (radio->rd_index >= radio->buf_size) + radio->rd_index = 0; + } + } + + if (radio->wr_index != radio->rd_index) + wake_up_interruptible(&radio->read_queue); +} + + +/* + * si470x_i2c_interrupt - interrupt handler + */ +static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id) +{ + struct si470x_device *radio = dev_id; + + if (!work_pending(&radio->radio_work)) + schedule_work(&radio->radio_work); + + return IRQ_HANDLED; +} + + +/* * si470x_i2c_probe - probe for the device */ static int __devinit si470x_i2c_probe(struct i2c_client *client, @@ -257,6 +374,8 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, retval = -ENOMEM; goto err_initial; } + + INIT_WORK(&radio->radio_work, si470x_i2c_interrupt_work); radio->users = 0; radio->client = client; mutex_init(&radio->lock); @@ -308,6 +427,26 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, /* set initial frequency */ si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ + /* rds buffer allocation */ + radio->buf_size = rds_buf * 3; + radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); + if (!radio->buffer) { + retval = -EIO; + goto err_video; + } + + /* rds buffer configuration */ + radio->wr_index = 0; + radio->rd_index = 0; + init_waitqueue_head(&radio->read_queue); + + retval = request_irq(client->irq, si470x_i2c_interrupt, + IRQF_TRIGGER_FALLING, DRIVER_NAME, radio); + if (retval) { + dev_err(&client->dev, "Failed to register interrupt\n"); + goto err_rds; + } + /* register video device */ retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); @@ -319,6 +458,9 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, return 0; err_all: + free_irq(client->irq, radio); +err_rds: + kfree(radio->buffer); err_video: video_device_release(radio->videodev); err_radio: @@ -335,6 +477,8 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client) { struct si470x_device *radio = i2c_get_clientdata(client); + free_irq(client->irq, radio); + cancel_work_sync(&radio->radio_work); video_unregister_device(radio->videodev); kfree(radio); i2c_set_clientdata(client, NULL); diff --git a/drivers/media/radio/si470x/radio-si470x.h b/drivers/media/radio/si470x/radio-si470x.h index f646f79..29e05cf 100644 --- a/drivers/media/radio/si470x/radio-si470x.h +++ b/drivers/media/radio/si470x/radio-si470x.h @@ -181,6 +181,7 @@ struct si470x_device { #if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE) struct i2c_client *client; + struct work_struct radio_work; #endif }; -- cgit v0.10.2 From d1471f02dfb5b3424ee3afb6459d8cb97730af76 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Thu, 10 Dec 2009 16:52:50 -0300 Subject: V4L/DVB (13601): radio-si470x: support PM functions This patch is to support PM of the si470x i2c driver. Signed-off-by: Joonyoung Shim Acked-by: Tobias Lorenz Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index b8c0d5c..5466015 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -487,6 +487,44 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client) } +#ifdef CONFIG_PM +/* + * si470x_i2c_suspend - suspend the device + */ +static int si470x_i2c_suspend(struct i2c_client *client, pm_message_t mesg) +{ + struct si470x_device *radio = i2c_get_clientdata(client); + + /* power down */ + radio->registers[POWERCFG] |= POWERCFG_DISABLE; + if (si470x_set_register(radio, POWERCFG) < 0) + return -EIO; + + return 0; +} + + +/* + * si470x_i2c_resume - resume the device + */ +static int si470x_i2c_resume(struct i2c_client *client) +{ + struct si470x_device *radio = i2c_get_clientdata(client); + + /* power up : need 110ms */ + radio->registers[POWERCFG] |= POWERCFG_ENABLE; + if (si470x_set_register(radio, POWERCFG) < 0) + return -EIO; + msleep(110); + + return 0; +} +#else +#define si470x_i2c_suspend NULL +#define si470x_i2c_resume NULL +#endif + + /* * si470x_i2c_driver - i2c driver interface */ @@ -497,6 +535,8 @@ static struct i2c_driver si470x_i2c_driver = { }, .probe = si470x_i2c_probe, .remove = __devexit_p(si470x_i2c_remove), + .suspend = si470x_i2c_suspend, + .resume = si470x_i2c_resume, .id_table = si470x_i2c_id, }; -- cgit v0.10.2 From 0a25f3b292c5c70de80d2b1f1cf3f5b9aae91b86 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Thu, 10 Dec 2009 16:54:48 -0300 Subject: V4L/DVB (13602): bttv: fix MODULE_PARM_DESC for i2c_debug and i2c_hw Currently, i2c_debug shows up w/o a desc in modinfo, and i2c_hw shows up with i2c_debug's desc. Fix that. [dougsland@redhat.com: fixed checkpatch.pl warning (space between MODULE_PARM_DESC arguments)] Signed-off-by: Jarod Wilson Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c index a9d9ee73..63aa31a 100644 --- a/drivers/media/video/bt8xx/bttv-i2c.c +++ b/drivers/media/video/bt8xx/bttv-i2c.c @@ -40,7 +40,7 @@ static int i2c_debug; static int i2c_hw; static int i2c_scan; module_param(i2c_debug, int, 0644); -MODULE_PARM_DESC(i2c_hw,"configure i2c debug level"); +MODULE_PARM_DESC(i2c_debug, "configure i2c debug level"); module_param(i2c_hw, int, 0444); MODULE_PARM_DESC(i2c_hw,"force use of hardware i2c support, " "instead of software bitbang"); -- cgit v0.10.2 From f68fdb9a8c3d4bc245752f4d312f7035063ab64e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 10 Dec 2009 16:59:02 -0300 Subject: V4L/DVB (13604): vpss: move vpss_remove to .devexit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function vpss_remove is used only wrapped by __devexit_p so define it using __devexit. Signed-off-by: Uwe Kleine-König Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/davinci/vpss.c b/drivers/media/video/davinci/vpss.c index 453236b..7ee72ec 100644 --- a/drivers/media/video/davinci/vpss.c +++ b/drivers/media/video/davinci/vpss.c @@ -268,7 +268,7 @@ fail1: return status; } -static int vpss_remove(struct platform_device *pdev) +static int __devexit vpss_remove(struct platform_device *pdev) { iounmap(oper_cfg.vpss_bl_regs_base); release_mem_region(oper_cfg.r1->start, oper_cfg.len1); -- cgit v0.10.2 From 50e55fd13fcf2d098e2b969c9d1bc270ae5f8b12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 10 Dec 2009 17:00:13 -0300 Subject: V4L/DVB (13605): sh_mobile_ceu_camera: don't use __exit_p to wrap sh_mobile_ceu_remove MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function sh_mobile_ceu_remove is defined using __devexit, so don't use __exit_p but __devexit_p to wrap it. Signed-off-by: Uwe Kleine-König Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 961e448..7509990 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -1836,7 +1836,7 @@ static struct platform_driver sh_mobile_ceu_driver = { .pm = &sh_mobile_ceu_dev_pm_ops, }, .probe = sh_mobile_ceu_probe, - .remove = __exit_p(sh_mobile_ceu_remove), + .remove = __devexit_p(sh_mobile_ceu_remove), }; static int __init sh_mobile_ceu_init(void) -- cgit v0.10.2 From 9d8938248c3b67904a8108a6fc3dcceb9d7f2aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 10 Dec 2009 17:01:13 -0300 Subject: V4L/DVB (13606): vpfe_capture: move vpfe_remove to .devexit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function vpfe_remove is used only wrapped by __devexit_p so define it using __devexit. Signed-off-by: Uwe Kleine-König Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index f2d3c9b..87e9796 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -2090,7 +2090,7 @@ probe_free_dev_mem: /* * vpfe_remove : It un-register device from V4L2 driver */ -static int vpfe_remove(struct platform_device *pdev) +static int __devexit vpfe_remove(struct platform_device *pdev) { struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev); struct resource *res; -- cgit v0.10.2 From 0b0a860fec1a6d4cdcd0dc5241390d083a82c00d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 10 Dec 2009 17:02:16 -0300 Subject: V4L/DVB (13607): vpif: move vpif_remove to .devexit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function vpif_remove is used only wrapped by __devexit_p so define it using __devexit. Signed-off-by: Uwe Kleine-König Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/davinci/vpif.c b/drivers/media/video/davinci/vpif.c index 3b8eac3..1f532e3 100644 --- a/drivers/media/video/davinci/vpif.c +++ b/drivers/media/video/davinci/vpif.c @@ -266,7 +266,7 @@ fail: return status; } -static int vpif_remove(struct platform_device *pdev) +static int __devexit vpif_remove(struct platform_device *pdev) { iounmap(vpif_base); release_mem_region(res->start, res_len); -- cgit v0.10.2 From 4b8303747474033d6d73828607eafab77c620d96 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Thu, 10 Dec 2009 17:06:44 -0300 Subject: V4L/DVB (13608): radio-sf16fmi: fix mute, add SF16-FMP to texts Fix completely broken mute handling radio-sf16fmi. The sound was muted immediately after tuning in KRadio. Also fix typos and add SF16-FMP to the texts. Signed-off-by: Ondrej Zary Acked-by: Petr Vandrovec Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 4c2b8a2..0fe93f2 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -215,7 +215,7 @@ config RADIO_MIROPCM20 module will be called radio-miropcm20. config RADIO_SF16FMI - tristate "SF16FMI Radio" + tristate "SF16-FMI/SF16-FMP Radio" depends on ISA && VIDEO_V4L2 ---help--- Choose Y here if you have one of these FM radio cards. If you diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 93990b7..e9ecfe1 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -1,4 +1,4 @@ -/* SF16FMI radio driver for Linux radio support +/* SF16-FMI and SF16-FMP radio driver for Linux radio support * heavily based on rtrack driver... * (c) 1997 M. Kirkwood * (c) 1998 Petr Vandrovec, vandrove@vc.cvut.cz @@ -11,7 +11,7 @@ * * Frequency control is done digitally -- ie out(port,encodefreq(95.8)); * No volume control - only mute/unmute - you have to use line volume - * control on SB-part of SF16FMI + * control on SB-part of SF16-FMI/SF16-FMP * * Converted to V4L2 API by Mauro Carvalho Chehab */ @@ -30,14 +30,14 @@ #include MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood"); -MODULE_DESCRIPTION("A driver for the SF16MI radio."); +MODULE_DESCRIPTION("A driver for the SF16-FMI and SF16-FMP radio."); MODULE_LICENSE("GPL"); static int io = -1; static int radio_nr = -1; module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the SF16MI card (0x284 or 0x384)"); +MODULE_PARM_DESC(io, "I/O address of the SF16-FMI or SF16-FMP card (0x284 or 0x384)"); module_param(radio_nr, int, 0); #define RADIO_VERSION KERNEL_VERSION(0, 0, 2) @@ -47,7 +47,7 @@ struct fmi struct v4l2_device v4l2_dev; struct video_device vdev; int io; - int curvol; /* 1 or 0 */ + bool mute; unsigned long curfreq; /* freq in kHz */ struct mutex lock; }; @@ -105,7 +105,7 @@ static inline int fmi_setfreq(struct fmi *fmi, unsigned long freq) outbits(8, 0xC0, fmi->io); msleep(143); /* was schedule_timeout(HZ/7) */ mutex_unlock(&fmi->lock); - if (fmi->curvol) + if (!fmi->mute) fmi_unmute(fmi); return 0; } @@ -116,7 +116,7 @@ static inline int fmi_getsigstr(struct fmi *fmi) int res; mutex_lock(&fmi->lock); - val = fmi->curvol ? 0x08 : 0x00; /* unmute/mute */ + val = fmi->mute ? 0x00 : 0x08; /* mute/unmute */ outb(val, fmi->io); outb(val | 0x10, fmi->io); msleep(143); /* was schedule_timeout(HZ/7) */ @@ -208,7 +208,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - ctrl->value = fmi->curvol; + ctrl->value = fmi->mute; return 0; } return -EINVAL; @@ -225,7 +225,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, fmi_mute(fmi); else fmi_unmute(fmi); - fmi->curvol = ctrl->value; + fmi->mute = ctrl->value; return 0; } return -EINVAL; -- cgit v0.10.2 From 67cabf503cd0ad7473cf1856f9c9bb6320098be6 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Thu, 10 Dec 2009 17:12:32 -0300 Subject: V4L/DVB (13609): radio-sf16fmi: add autoprobing Add automatic probing of ports 0x284 and 0x384 to radio-sf16fmi if no card is found using PnP. Signed-off-by: Ondrej Zary Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 0fe93f2..3f40f37 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -218,10 +218,7 @@ config RADIO_SF16FMI tristate "SF16-FMI/SF16-FMP Radio" depends on ISA && VIDEO_V4L2 ---help--- - Choose Y here if you have one of these FM radio cards. If you - compile the driver into the kernel and your card is not PnP one, you - have to add "sf16fm=" to the kernel command line (I/O address is - 0x284 or 0x384). + Choose Y here if you have one of these FM radio cards. In order to control your radio card, you will need to use programs that are compatible with the Video For Linux API. Information on diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index e9ecfe1..985359d1 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -54,6 +54,7 @@ struct fmi static struct fmi fmi_card; static struct pnp_dev *dev; +bool pnp_attached; /* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */ /* It is only useful to give freq in interval of 800 (=0.05Mhz), @@ -320,26 +321,54 @@ static int __init fmi_init(void) { struct fmi *fmi = &fmi_card; struct v4l2_device *v4l2_dev = &fmi->v4l2_dev; - int res; + int res, i; + int probe_ports[] = { 0, 0x284, 0x384 }; + + if (io < 0) { + for (i = 0; i < ARRAY_SIZE(probe_ports); i++) { + io = probe_ports[i]; + if (io == 0) { + io = isapnp_fmi_probe(); + if (io < 0) + continue; + pnp_attached = 1; + } + if (!request_region(io, 2, "radio-sf16fmi")) { + if (pnp_attached) + pnp_device_detach(dev); + io = -1; + continue; + } + if (pnp_attached || + ((inb(io) & 0xf9) == 0xf9 && (inb(io) & 0x4) == 0)) + break; + release_region(io, 2); + io = -1; + } + } else { + if (!request_region(io, 2, "radio-sf16fmi")) { + printk(KERN_ERR "radio-sf16fmi: port %#x already in use\n", io); + return -EBUSY; + } + if (inb(io) == 0xff) { + printk(KERN_ERR "radio-sf16fmi: card not present at %#x\n", io); + release_region(io, 2); + return -ENODEV; + } + } + if (io < 0) { + printk(KERN_ERR "radio-sf16fmi: no cards found\n"); + return -ENODEV; + } - if (io < 0) - io = isapnp_fmi_probe(); strlcpy(v4l2_dev->name, "sf16fmi", sizeof(v4l2_dev->name)); fmi->io = io; - if (fmi->io < 0) { - v4l2_err(v4l2_dev, "No PnP card found.\n"); - return fmi->io; - } - if (!request_region(io, 2, "radio-sf16fmi")) { - v4l2_err(v4l2_dev, "port 0x%x already in use\n", fmi->io); - pnp_device_detach(dev); - return -EBUSY; - } res = v4l2_device_register(NULL, v4l2_dev); if (res < 0) { release_region(fmi->io, 2); - pnp_device_detach(dev); + if (pnp_attached) + pnp_device_detach(dev); v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); return res; } @@ -356,7 +385,8 @@ static int __init fmi_init(void) if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { v4l2_device_unregister(v4l2_dev); release_region(fmi->io, 2); - pnp_device_detach(dev); + if (pnp_attached) + pnp_device_detach(dev); return -EINVAL; } @@ -373,7 +403,7 @@ static void __exit fmi_exit(void) video_unregister_device(&fmi->vdev); v4l2_device_unregister(&fmi->v4l2_dev); release_region(fmi->io, 2); - if (dev) + if (dev && pnp_attached) pnp_device_detach(dev); } -- cgit v0.10.2 From ddb0b34f1345e1fec60f168bd99c487699f65212 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 10 Dec 2009 17:14:27 -0300 Subject: V4L/DVB (13610): uvc: Correct size given to memset Memset should be given the size of the structure, not the size of the pointer. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ type T; T *x; expression E; @@ memset(x, E, sizeof( + * x)) // Signed-off-by: Julia Lawall Acked-by: Laurent Pinchart Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 05139a4..9a98028 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -145,7 +145,7 @@ static int uvc_get_video_ctrl(struct uvc_streaming *stream, uvc_warn_once(stream->dev, UVC_WARN_MINMAX, "UVC non " "compliance - GET_MIN/MAX(PROBE) incorrectly " "supported. Enabling workaround.\n"); - memset(ctrl, 0, sizeof ctrl); + memset(ctrl, 0, sizeof *ctrl); ctrl->wCompQuality = le16_to_cpup((__le16 *)data); ret = 0; goto out; -- cgit v0.10.2 From 909d15a70d6a269ba599c539c55a574482355ff1 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 10 Dec 2009 17:17:49 -0300 Subject: V4L/DVB (13611): radio-tea5764: Correct size given to memset Memset should be given the size of the structure, not the size of the pointer. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ type T; T *x; expression E; @@ memset(x, E, sizeof( + * x)) // Signed-off-by: Julia Lawall Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 1d357b7..8e718bf 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -314,7 +314,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (v->index > 0) return -EINVAL; - memset(v, 0, sizeof(v)); + memset(v, 0, sizeof(*v)); strcpy(v->name, "FM"); v->type = V4L2_TUNER_RADIO; tea5764_i2c_read(radio); @@ -373,7 +373,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, if (f->tuner != 0) return -EINVAL; tea5764_i2c_read(radio); - memset(f, 0, sizeof(f)); + memset(f, 0, sizeof(*f)); f->type = V4L2_TUNER_RADIO; if (r->tnctrl & TEA5764_TNCTRL_PUPD0) f->frequency = (tea5764_get_freq(radio) * 2) / 125; -- cgit v0.10.2 From e27d38112eb727df189a9ebf560aa104cb102253 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 11 Dec 2009 08:00:00 -0300 Subject: V4L/DVB (13612): IR: Move common IR code to drivers/media/IR This is the first step of creating a common code for IR that can be used by other input devices. For now, keep IR dir at drivers/media, to easy the movement of the IR files, but later patches may move it to drivers/IR or drivers/input/IR. No functional changes is done on this patch. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig new file mode 100644 index 0000000..5b4ac96 --- /dev/null +++ b/drivers/media/IR/Kconfig @@ -0,0 +1,4 @@ +config VIDEO_IR + tristate + depends on INPUT + default INPUT diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile new file mode 100644 index 0000000..2781f43 --- /dev/null +++ b/drivers/media/IR/Makefile @@ -0,0 +1,3 @@ +ir-common-objs := ir-functions.o ir-keymaps.o ir-keytable.o + +obj-$(CONFIG_VIDEO_IR) += ir-common.o diff --git a/drivers/media/IR/ir-functions.c b/drivers/media/IR/ir-functions.c new file mode 100644 index 0000000..e616f62 --- /dev/null +++ b/drivers/media/IR/ir-functions.c @@ -0,0 +1,373 @@ +/* + * + * some common structs and functions to handle infrared remotes via + * input layer ... + * + * (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 + +/* -------------------------------------------------------------------------- */ + +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)"); + +int media_ir_debug; /* media_ir_debug level (0,1,2) */ +module_param_named(debug, media_ir_debug, int, 0644); + +/* -------------------------------------------------------------------------- */ + +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, + int ir_type, struct ir_scancode_table *ir_codes) +{ + ir->ir_type = ir_type; + + ir->keytable.size = ir_roundup_tablesize(ir_codes->size); + ir->keytable.scan = kzalloc(ir->keytable.size * + sizeof(struct ir_scancode), GFP_KERNEL); + if (!ir->keytable.scan) + return -ENOMEM; + + IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n", + ir->keytable.size, + ir->keytable.size * sizeof(ir->keytable.scan)); + + ir_copy_table(&ir->keytable, ir_codes); + ir_set_keycode_table(dev, &ir->keytable); + + clear_bit(0, dev->keybit); + set_bit(EV_KEY, dev->evbit); + 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) +{ + 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); + +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 */ + +/* decode raw bit pattern to RC5 code */ +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; +} +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; + 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, 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; + } + } +} +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-keymaps.c b/drivers/media/IR/ir-keymaps.c new file mode 100644 index 0000000..9bbe6b1 --- /dev/null +++ b/drivers/media/IR/ir-keymaps.c @@ -0,0 +1,3395 @@ +/* + Keytables for supported remote controls, used on drivers/media + 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; 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. +*/ + +/* + * NOTICE FOR DEVELOPERS: + * The IR mappings should be as close as possible to what's + * specified at: + * http://linuxtv.org/wiki/index.php/Remote_Controllers + */ +#include + +#include +#include + +/* empty keytable, can be used as placeholder for not-yet created keytables */ +static struct ir_scancode ir_codes_empty[] = { + { 0x2a, KEY_COFFEE }, +}; + +struct ir_scancode_table ir_codes_empty_table = { + .scan = ir_codes_empty, + .size = ARRAY_SIZE(ir_codes_empty), +}; +EXPORT_SYMBOL_GPL(ir_codes_empty_table); + +/* Michal Majchrowicz */ +static struct ir_scancode ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_proteus_2309_table = { + .scan = ir_codes_proteus_2309, + .size = ARRAY_SIZE(ir_codes_proteus_2309), +}; +EXPORT_SYMBOL_GPL(ir_codes_proteus_2309_table); + +/* 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 +' */ +}; + +struct ir_scancode_table ir_codes_avermedia_dvbt_table = { + .scan = ir_codes_avermedia_dvbt, + .size = ARRAY_SIZE(ir_codes_avermedia_dvbt), +}; +EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt_table); + +/* Mauro Carvalho Chehab */ +static struct ir_scancode ir_codes_avermedia_m135a[] = { + { 0x00, KEY_POWER2 }, + { 0x2e, KEY_DOT }, /* '.' */ + { 0x01, KEY_MODE }, /* TV/FM */ + + { 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 }, + { 0x11, KEY_0 }, + + { 0x13, KEY_RIGHT }, /* -> */ + { 0x12, KEY_LEFT }, /* <- */ + + { 0x17, KEY_SLEEP }, /* Capturar Imagem */ + { 0x10, KEY_SHUFFLE }, /* Amostra */ + + /* FIXME: The keys bellow aren't ok */ + + { 0x43, KEY_CHANNELUP }, + { 0x42, KEY_CHANNELDOWN }, + { 0x1f, KEY_VOLUMEUP }, + { 0x1e, KEY_VOLUMEDOWN }, + { 0x0c, KEY_ENTER }, + + { 0x14, KEY_MUTE }, + { 0x08, KEY_AUDIO }, + + { 0x03, KEY_TEXT }, + { 0x04, KEY_EPG }, + { 0x2b, KEY_TV2 }, /* TV2 */ + + { 0x1d, KEY_RED }, + { 0x1c, KEY_YELLOW }, + { 0x41, KEY_GREEN }, + { 0x40, KEY_BLUE }, + + { 0x1a, KEY_PLAYPAUSE }, + { 0x19, KEY_RECORD }, + { 0x18, KEY_PLAY }, + { 0x1b, KEY_STOP }, +}; + +struct ir_scancode_table ir_codes_avermedia_m135a_table = { + .scan = ir_codes_avermedia_m135a, + .size = ARRAY_SIZE(ir_codes_avermedia_m135a), +}; +EXPORT_SYMBOL_GPL(ir_codes_avermedia_m135a_table); + +/* Oldrich Jedlicka */ +static struct ir_scancode ir_codes_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 */ +}; + +struct ir_scancode_table ir_codes_avermedia_cardbus_table = { + .scan = ir_codes_avermedia_cardbus, + .size = ARRAY_SIZE(ir_codes_avermedia_cardbus), +}; +EXPORT_SYMBOL_GPL(ir_codes_avermedia_cardbus_table); + +/* Attila Kondoros */ +static struct ir_scancode ir_codes_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 <<<< */ +}; + +struct ir_scancode_table ir_codes_apac_viewcomp_table = { + .scan = ir_codes_apac_viewcomp, + .size = ARRAY_SIZE(ir_codes_apac_viewcomp), +}; +EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp_table); + +/* ---------------------------------------------------------------------- */ + +static struct ir_scancode ir_codes_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 */ +}; + +struct ir_scancode_table ir_codes_pixelview_table = { + .scan = ir_codes_pixelview, + .size = ARRAY_SIZE(ir_codes_pixelview), +}; +EXPORT_SYMBOL_GPL(ir_codes_pixelview_table); + +/* + Mauro Carvalho Chehab + present on PV MPEG 8000GT + */ +static struct ir_scancode ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_pixelview_new_table = { + .scan = ir_codes_pixelview_new, + .size = ARRAY_SIZE(ir_codes_pixelview_new), +}; +EXPORT_SYMBOL_GPL(ir_codes_pixelview_new_table); + +static struct ir_scancode ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_nebula_table = { + .scan = ir_codes_nebula, + .size = ARRAY_SIZE(ir_codes_nebula), +}; +EXPORT_SYMBOL_GPL(ir_codes_nebula_table); + +/* DigitalNow DNTV Live DVB-T Remote */ +static struct ir_scancode ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_dntv_live_dvb_t_table = { + .scan = ir_codes_dntv_live_dvb_t, + .size = ARRAY_SIZE(ir_codes_dntv_live_dvb_t), +}; +EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvb_t_table); + +/* ---------------------------------------------------------------------- */ + +/* IO-DATA BCTV7E Remote */ +static struct ir_scancode ir_codes_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 >| */ +}; + +struct ir_scancode_table ir_codes_iodata_bctv7e_table = { + .scan = ir_codes_iodata_bctv7e, + .size = ARRAY_SIZE(ir_codes_iodata_bctv7e), +}; +EXPORT_SYMBOL_GPL(ir_codes_iodata_bctv7e_table); + +/* ---------------------------------------------------------------------- */ + +/* ADS Tech Instant TV DVB-T PCI Remote */ +static struct ir_scancode ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_adstech_dvb_t_pci_table = { + .scan = ir_codes_adstech_dvb_t_pci, + .size = ARRAY_SIZE(ir_codes_adstech_dvb_t_pci), +}; +EXPORT_SYMBOL_GPL(ir_codes_adstech_dvb_t_pci_table); + +/* ---------------------------------------------------------------------- */ + +/* MSI TV@nywhere MASTER remote */ + +static struct ir_scancode ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_msi_tvanywhere_table = { + .scan = ir_codes_msi_tvanywhere, + .size = ARRAY_SIZE(ir_codes_msi_tvanywhere), +}; +EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_table); + +/* ---------------------------------------------------------------------- */ + +/* + 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 ir_codes_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 */ +}; + +struct ir_scancode_table ir_codes_msi_tvanywhere_plus_table = { + .scan = ir_codes_msi_tvanywhere_plus, + .size = ARRAY_SIZE(ir_codes_msi_tvanywhere_plus), +}; +EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_plus_table); + +/* ---------------------------------------------------------------------- */ + +/* Cinergy 1400 DVB-T */ +static struct ir_scancode ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_cinergy_1400_table = { + .scan = ir_codes_cinergy_1400, + .size = ARRAY_SIZE(ir_codes_cinergy_1400), +}; +EXPORT_SYMBOL_GPL(ir_codes_cinergy_1400_table); + +/* ---------------------------------------------------------------------- */ + +/* AVERTV STUDIO 303 Remote */ +static struct ir_scancode ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_avertv_303_table = { + .scan = ir_codes_avertv_303, + .size = ARRAY_SIZE(ir_codes_avertv_303), +}; +EXPORT_SYMBOL_GPL(ir_codes_avertv_303_table); + +/* ---------------------------------------------------------------------- */ + +/* DigitalNow DNTV Live! DVB-T Pro Remote */ +static struct ir_scancode ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_dntv_live_dvbt_pro_table = { + .scan = ir_codes_dntv_live_dvbt_pro, + .size = ARRAY_SIZE(ir_codes_dntv_live_dvbt_pro), +}; +EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvbt_pro_table); + +static struct ir_scancode ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_em_terratec_table = { + .scan = ir_codes_em_terratec, + .size = ARRAY_SIZE(ir_codes_em_terratec), +}; +EXPORT_SYMBOL_GPL(ir_codes_em_terratec_table); + +static struct ir_scancode ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_pinnacle_grey_table = { + .scan = ir_codes_pinnacle_grey, + .size = ARRAY_SIZE(ir_codes_pinnacle_grey), +}; +EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey_table); + +static struct ir_scancode ir_codes_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 */ +}; + +struct ir_scancode_table ir_codes_flyvideo_table = { + .scan = ir_codes_flyvideo, + .size = ARRAY_SIZE(ir_codes_flyvideo), +}; +EXPORT_SYMBOL_GPL(ir_codes_flyvideo_table); + +static struct ir_scancode ir_codes_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 >>| */ +}; + +struct ir_scancode_table ir_codes_flydvb_table = { + .scan = ir_codes_flydvb, + .size = ARRAY_SIZE(ir_codes_flydvb), +}; +EXPORT_SYMBOL_GPL(ir_codes_flydvb_table); + +static struct ir_scancode ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_cinergy_table = { + .scan = ir_codes_cinergy, + .size = ARRAY_SIZE(ir_codes_cinergy), +}; +EXPORT_SYMBOL_GPL(ir_codes_cinergy_table); + +/* Alfons Geser + * updates from Job D. R. Borges */ +static struct ir_scancode ir_codes_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) */ +}; + +struct ir_scancode_table ir_codes_eztv_table = { + .scan = ir_codes_eztv, + .size = ARRAY_SIZE(ir_codes_eztv), +}; +EXPORT_SYMBOL_GPL(ir_codes_eztv_table); + +/* Alex Hermann */ +static struct ir_scancode ir_codes_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+ */ +}; + +struct ir_scancode_table ir_codes_avermedia_table = { + .scan = ir_codes_avermedia, + .size = ARRAY_SIZE(ir_codes_avermedia), +}; +EXPORT_SYMBOL_GPL(ir_codes_avermedia_table); + +static struct ir_scancode ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_videomate_tv_pvr_table = { + .scan = ir_codes_videomate_tv_pvr, + .size = ARRAY_SIZE(ir_codes_videomate_tv_pvr), +}; +EXPORT_SYMBOL_GPL(ir_codes_videomate_tv_pvr_table); + +/* Michael Tokarev + http://www.corpit.ru/mjt/beholdTV/remote_control.jpg + 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 ir_codes_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 ? */ +}; + +struct ir_scancode_table ir_codes_manli_table = { + .scan = ir_codes_manli, + .size = ARRAY_SIZE(ir_codes_manli), +}; +EXPORT_SYMBOL_GPL(ir_codes_manli_table); + +/* Mike Baikov */ +static struct ir_scancode ir_codes_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 */ +}; + +struct ir_scancode_table ir_codes_gotview7135_table = { + .scan = ir_codes_gotview7135, + .size = ARRAY_SIZE(ir_codes_gotview7135), +}; +EXPORT_SYMBOL_GPL(ir_codes_gotview7135_table); + +static struct ir_scancode ir_codes_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 ? */ + +}; + +struct ir_scancode_table ir_codes_purpletv_table = { + .scan = ir_codes_purpletv, + .size = ARRAY_SIZE(ir_codes_purpletv), +}; +EXPORT_SYMBOL_GPL(ir_codes_purpletv_table); + +/* 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 ir_codes_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 */ +}; + +struct ir_scancode_table ir_codes_pctv_sedna_table = { + .scan = ir_codes_pctv_sedna, + .size = ARRAY_SIZE(ir_codes_pctv_sedna), +}; +EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna_table); + +/* Mark Phalan */ +static struct ir_scancode ir_codes_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 */ +}; + +struct ir_scancode_table ir_codes_pv951_table = { + .scan = ir_codes_pv951, + .size = ARRAY_SIZE(ir_codes_pv951), +}; +EXPORT_SYMBOL_GPL(ir_codes_pv951_table); + +/* generic RC5 keytable */ +/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ +/* used by old (black) Hauppauge remotes */ +static struct ir_scancode ir_codes_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 */ + +}; + +struct ir_scancode_table ir_codes_rc5_tv_table = { + .scan = ir_codes_rc5_tv, + .size = ARRAY_SIZE(ir_codes_rc5_tv), +}; +EXPORT_SYMBOL_GPL(ir_codes_rc5_tv_table); + +/* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ +static struct ir_scancode ir_codes_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 */ +}; + +struct ir_scancode_table ir_codes_winfast_table = { + .scan = ir_codes_winfast, + .size = ARRAY_SIZE(ir_codes_winfast), +}; +EXPORT_SYMBOL_GPL(ir_codes_winfast_table); + +static struct ir_scancode ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_pinnacle_color_table = { + .scan = ir_codes_pinnacle_color, + .size = ARRAY_SIZE(ir_codes_pinnacle_color), +}; +EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color_table); + +/* 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 ir_codes_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) */ +}; + +struct ir_scancode_table ir_codes_hauppauge_new_table = { + .scan = ir_codes_hauppauge_new, + .size = ARRAY_SIZE(ir_codes_hauppauge_new), +}; +EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new_table); + +static struct ir_scancode ir_codes_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 }, + +}; + +struct ir_scancode_table ir_codes_npgtech_table = { + .scan = ir_codes_npgtech, + .size = ARRAY_SIZE(ir_codes_npgtech), +}; +EXPORT_SYMBOL_GPL(ir_codes_npgtech_table); + +/* Norwood Micro (non-Pro) TV Tuner + By Peter Naulls + Key comments are the functions given in the manual */ +static struct ir_scancode ir_codes_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 */ +}; + +struct ir_scancode_table ir_codes_norwood_table = { + .scan = ir_codes_norwood, + .size = ARRAY_SIZE(ir_codes_norwood), +}; +EXPORT_SYMBOL_GPL(ir_codes_norwood_table); + +/* 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 ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_budget_ci_old_table = { + .scan = ir_codes_budget_ci_old, + .size = ARRAY_SIZE(ir_codes_budget_ci_old), +}; +EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old_table); + +/* + * 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 ir_codes_asus_pc39[] = { + /* Keys 0 to 9 */ + { 0x15, KEY_0 }, + { 0x29, KEY_1 }, + { 0x2d, KEY_2 }, + { 0x2b, KEY_3 }, + { 0x09, KEY_4 }, + { 0x0d, KEY_5 }, + { 0x0b, KEY_6 }, + { 0x31, KEY_7 }, + { 0x35, KEY_8 }, + { 0x33, KEY_9 }, + + { 0x3e, KEY_RADIO }, /* radio */ + { 0x03, KEY_MENU }, /* dvd/menu */ + { 0x2a, KEY_VOLUMEUP }, + { 0x19, KEY_VOLUMEDOWN }, + { 0x37, KEY_UP }, + { 0x3b, KEY_DOWN }, + { 0x27, KEY_LEFT }, + { 0x2f, KEY_RIGHT }, + { 0x25, KEY_VIDEO }, /* video */ + { 0x39, KEY_AUDIO }, /* music */ + + { 0x21, KEY_TV }, /* tv */ + { 0x1d, KEY_EXIT }, /* back */ + { 0x0a, KEY_CHANNELUP }, /* channel / program + */ + { 0x1b, KEY_CHANNELDOWN }, /* channel / program - */ + { 0x1a, KEY_ENTER }, /* enter */ + + { 0x06, KEY_PAUSE }, /* play/pause */ + { 0x1e, KEY_PREVIOUS }, /* rew */ + { 0x26, KEY_NEXT }, /* forward */ + { 0x0e, KEY_REWIND }, /* backward << */ + { 0x3a, KEY_FASTFORWARD }, /* forward >> */ + { 0x36, KEY_STOP }, + { 0x2e, KEY_RECORD }, /* recording */ + { 0x16, KEY_POWER }, /* the button that reads "close" */ + + { 0x11, KEY_ZOOM }, /* full screen */ + { 0x13, KEY_MACRO }, /* recall */ + { 0x23, KEY_HOME }, /* home */ + { 0x05, KEY_PVR }, /* picture */ + { 0x3d, KEY_MUTE }, /* mute */ + { 0x01, KEY_DVD }, /* dvd */ +}; + +struct ir_scancode_table ir_codes_asus_pc39_table = { + .scan = ir_codes_asus_pc39, + .size = ARRAY_SIZE(ir_codes_asus_pc39), +}; +EXPORT_SYMBOL_GPL(ir_codes_asus_pc39_table); + + +/* Encore ENLTV-FM - black plastic, white front cover with white glowing buttons + Juan Pablo Sormani */ +static struct ir_scancode ir_codes_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 */ +}; + +struct ir_scancode_table ir_codes_encore_enltv_table = { + .scan = ir_codes_encore_enltv, + .size = ARRAY_SIZE(ir_codes_encore_enltv), +}; +EXPORT_SYMBOL_GPL(ir_codes_encore_enltv_table); + +/* Encore ENLTV2-FM - silver plastic - "Wand Media" written at the botton + Mauro Carvalho Chehab */ +static struct ir_scancode ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_encore_enltv2_table = { + .scan = ir_codes_encore_enltv2, + .size = ARRAY_SIZE(ir_codes_encore_enltv2), +}; +EXPORT_SYMBOL_GPL(ir_codes_encore_enltv2_table); + +/* for the Technotrend 1500 bundled remotes (grey and black): */ +static struct ir_scancode ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_tt_1500_table = { + .scan = ir_codes_tt_1500, + .size = ARRAY_SIZE(ir_codes_tt_1500), +}; +EXPORT_SYMBOL_GPL(ir_codes_tt_1500_table); + +/* DViCO FUSION HDTV MCE remote */ +static struct ir_scancode ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_fusionhdtv_mce_table = { + .scan = ir_codes_fusionhdtv_mce, + .size = ARRAY_SIZE(ir_codes_fusionhdtv_mce), +}; +EXPORT_SYMBOL_GPL(ir_codes_fusionhdtv_mce_table); + +/* Pinnacle PCTV HD 800i mini remote */ +static struct ir_scancode ir_codes_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 "?" */ +}; + +struct ir_scancode_table ir_codes_pinnacle_pctv_hd_table = { + .scan = ir_codes_pinnacle_pctv_hd, + .size = ARRAY_SIZE(ir_codes_pinnacle_pctv_hd), +}; +EXPORT_SYMBOL_GPL(ir_codes_pinnacle_pctv_hd_table); + +/* + * 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 ir_codes_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 }, + +}; + +struct ir_scancode_table ir_codes_behold_table = { + .scan = ir_codes_behold, + .size = ARRAY_SIZE(ir_codes_behold), +}; +EXPORT_SYMBOL_GPL(ir_codes_behold_table); + +/* 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 ir_codes_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 }, + +}; + +struct ir_scancode_table ir_codes_behold_columbus_table = { + .scan = ir_codes_behold_columbus, + .size = ARRAY_SIZE(ir_codes_behold_columbus), +}; +EXPORT_SYMBOL_GPL(ir_codes_behold_columbus_table); + +/* + * Remote control for the Genius TVGO A11MCE + * Adrian Pardini + */ +static struct ir_scancode ir_codes_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 }, +}; + +struct ir_scancode_table ir_codes_genius_tvgo_a11mce_table = { + .scan = ir_codes_genius_tvgo_a11mce, + .size = ARRAY_SIZE(ir_codes_genius_tvgo_a11mce), +}; +EXPORT_SYMBOL_GPL(ir_codes_genius_tvgo_a11mce_table); + +/* + * Remote control for Powercolor Real Angel 330 + * Daniel Fraga + */ +static struct ir_scancode ir_codes_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 */ +}; + +struct ir_scancode_table ir_codes_powercolor_real_angel_table = { + .scan = ir_codes_powercolor_real_angel, + .size = ARRAY_SIZE(ir_codes_powercolor_real_angel), +}; +EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel_table); + +/* Kworld Plus TV Analog Lite PCI IR + Mauro Carvalho Chehab + */ +static struct ir_scancode ir_codes_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 */ +}; +struct ir_scancode_table ir_codes_kworld_plus_tv_analog_table = { + .scan = ir_codes_kworld_plus_tv_analog, + .size = ARRAY_SIZE(ir_codes_kworld_plus_tv_analog), +}; +EXPORT_SYMBOL_GPL(ir_codes_kworld_plus_tv_analog_table); + +/* Kaiomy TVnPC U2 + Mauro Carvalho Chehab + */ +static struct ir_scancode ir_codes_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}, +}; +struct ir_scancode_table ir_codes_kaiomy_table = { + .scan = ir_codes_kaiomy, + .size = ARRAY_SIZE(ir_codes_kaiomy), +}; +EXPORT_SYMBOL_GPL(ir_codes_kaiomy_table); + +static struct ir_scancode ir_codes_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}, +}; +struct ir_scancode_table ir_codes_avermedia_a16d_table = { + .scan = ir_codes_avermedia_a16d, + .size = ARRAY_SIZE(ir_codes_avermedia_a16d), +}; +EXPORT_SYMBOL_GPL(ir_codes_avermedia_a16d_table); + +/* Encore ENLTV-FM v5.3 + Mauro Carvalho Chehab + */ +static struct ir_scancode ir_codes_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 */ +}; +struct ir_scancode_table ir_codes_encore_enltv_fm53_table = { + .scan = ir_codes_encore_enltv_fm53, + .size = ARRAY_SIZE(ir_codes_encore_enltv_fm53), +}; +EXPORT_SYMBOL_GPL(ir_codes_encore_enltv_fm53_table); + +/* Zogis Real Audio 220 - 32 keys IR */ +static struct ir_scancode ir_codes_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 */ + +}; +struct ir_scancode_table ir_codes_real_audio_220_32_keys_table = { + .scan = ir_codes_real_audio_220_32_keys, + .size = ARRAY_SIZE(ir_codes_real_audio_220_32_keys), +}; +EXPORT_SYMBOL_GPL(ir_codes_real_audio_220_32_keys_table); + +/* ATI TV Wonder HD 600 USB + Devin Heitmueller + */ +static struct ir_scancode ir_codes_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}, +}; +struct ir_scancode_table ir_codes_ati_tv_wonder_hd_600_table = { + .scan = ir_codes_ati_tv_wonder_hd_600, + .size = ARRAY_SIZE(ir_codes_ati_tv_wonder_hd_600), +}; +EXPORT_SYMBOL_GPL(ir_codes_ati_tv_wonder_hd_600_table); + +/* DVBWorld remotes + Igor M. Liplianin + */ +static struct ir_scancode ir_codes_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 */ +}; +struct ir_scancode_table ir_codes_dm1105_nec_table = { + .scan = ir_codes_dm1105_nec, + .size = ARRAY_SIZE(ir_codes_dm1105_nec), +}; +EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec_table); + +static struct ir_scancode ir_codes_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}, +}; +struct ir_scancode_table ir_codes_tevii_nec_table = { + .scan = ir_codes_tevii_nec, + .size = ARRAY_SIZE(ir_codes_tevii_nec), +}; +EXPORT_SYMBOL_GPL(ir_codes_tevii_nec_table); + +static struct ir_scancode ir_codes_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}, +}; +struct ir_scancode_table ir_codes_tbs_nec_table = { + .scan = ir_codes_tbs_nec, + .size = ARRAY_SIZE(ir_codes_tbs_nec), +}; +EXPORT_SYMBOL_GPL(ir_codes_tbs_nec_table); + +/* Terratec Cinergy Hybrid T USB XS + Devin Heitmueller + */ +static struct ir_scancode ir_codes_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}, +}; +struct ir_scancode_table ir_codes_terratec_cinergy_xs_table = { + .scan = ir_codes_terratec_cinergy_xs, + .size = ARRAY_SIZE(ir_codes_terratec_cinergy_xs), +}; +EXPORT_SYMBOL_GPL(ir_codes_terratec_cinergy_xs_table); + +/* EVGA inDtube + Devin Heitmueller + */ +static struct ir_scancode ir_codes_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}, +}; +struct ir_scancode_table ir_codes_evga_indtube_table = { + .scan = ir_codes_evga_indtube, + .size = ARRAY_SIZE(ir_codes_evga_indtube), +}; +EXPORT_SYMBOL_GPL(ir_codes_evga_indtube_table); + +static struct ir_scancode ir_codes_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}, +}; +struct ir_scancode_table ir_codes_videomate_s350_table = { + .scan = ir_codes_videomate_s350, + .size = ARRAY_SIZE(ir_codes_videomate_s350), +}; +EXPORT_SYMBOL_GPL(ir_codes_videomate_s350_table); + +/* GADMEI UTV330+ RM008Z remote + Shine Liu + */ +static struct ir_scancode ir_codes_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 */ +}; +struct ir_scancode_table ir_codes_gadmei_rm008z_table = { + .scan = ir_codes_gadmei_rm008z, + .size = ARRAY_SIZE(ir_codes_gadmei_rm008z), +}; +EXPORT_SYMBOL_GPL(ir_codes_gadmei_rm008z_table); + +/************************************************************* + * COMPLETE SCANCODE TABLES + * Instead of just a partial scancode, the tables bellow + * contains the complete scancode and the receiver protocol + *************************************************************/ + +/* + * 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 ir_codes_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) */ +}; + +struct ir_scancode_table ir_codes_rc5_hauppauge_new_table = { + .scan = ir_codes_rc5_hauppauge_new, + .size = ARRAY_SIZE(ir_codes_rc5_hauppauge_new), + .ir_type = IR_TYPE_RC5, +}; +EXPORT_SYMBOL_GPL(ir_codes_rc5_hauppauge_new_table); + +/* Terratec Cinergy Hybrid T USB XS FM + Mauro Carvalho Chehab + */ +static struct ir_scancode ir_codes_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}, +}; +struct ir_scancode_table ir_codes_nec_terratec_cinergy_xs_table = { + .scan = ir_codes_nec_terratec_cinergy_xs, + .size = ARRAY_SIZE(ir_codes_nec_terratec_cinergy_xs), + .ir_type = IR_TYPE_NEC, +}; +EXPORT_SYMBOL_GPL(ir_codes_nec_terratec_cinergy_xs_table); + diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c new file mode 100644 index 0000000..99ed2de --- /dev/null +++ b/drivers/media/IR/ir-keytable.c @@ -0,0 +1,433 @@ +/* ir-register.c - handle IR scancode->keycode tables + * + * Copyright (C) 2009 by Mauro Carvalho Chehab + */ + +#include + +#include + +#define IR_TAB_MIN_SIZE 32 +#define IR_TAB_MAX_SIZE 1024 + + +/** + * ir_seek_table() - returns the element order on the table + * @rc_tab: the ir_scancode_table with the keymap to be used + * @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_UNKNOWN. Otherwise, returns the + * corresponding keycode from the table. + */ +static int ir_seek_table(struct ir_scancode_table *rc_tab, u32 scancode) +{ + int rc; + unsigned long flags; + struct ir_scancode *keymap = rc_tab->scan; + + spin_lock_irqsave(&rc_tab->lock, flags); + + /* FIXME: replace it by a binary search */ + + for (rc = 0; rc < rc_tab->size; rc++) + if (keymap[rc].scancode == scancode) + goto exit; + + /* Not found */ + rc = -EINVAL; + +exit: + spin_unlock_irqrestore(&rc_tab->lock, flags); + return rc; +} + +/** + * ir_roundup_tablesize() - gets an optimum value for the table size + * @n_elems: minimum number of entries to store keycodes + * + * This routine is used to choose the keycode table size. + * + * In order to have some empty space for new keycodes, + * and knowing in advance that kmalloc allocates only power of two + * segments, it optimizes the allocated space to have some spare space + * for those new keycodes by using the maximum number of entries that + * will be effectively be allocated by kmalloc. + * In order to reduce the quantity of table resizes, it has a minimum + * table size of IR_TAB_MIN_SIZE. + */ +int ir_roundup_tablesize(int n_elems) +{ + size_t size; + + if (n_elems < IR_TAB_MIN_SIZE) + n_elems = IR_TAB_MIN_SIZE; + + /* + * As kmalloc only allocates sizes of power of two, get as + * much entries as possible for the allocated memory segment + */ + size = roundup_pow_of_two(n_elems * sizeof(struct ir_scancode)); + n_elems = size / sizeof(struct ir_scancode); + + return n_elems; +} + +/** + * ir_copy_table() - copies a keytable, discarding the unused entries + * @destin: destin table + * @origin: origin table + * + * Copies all entries where the keycode is not KEY_UNKNOWN/KEY_RESERVED + */ + +int ir_copy_table(struct ir_scancode_table *destin, + const struct ir_scancode_table *origin) +{ + int i, j = 0; + + for (i = 0; i < origin->size; i++) { + if (origin->scan[i].keycode == KEY_UNKNOWN || + origin->scan[i].keycode == KEY_RESERVED) + continue; + + memcpy(&destin->scan[j], &origin->scan[i], sizeof(struct ir_scancode)); + j++; + } + destin->size = j; + + IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size); + + return 0; +} + +/** + * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table + * @dev: the struct input_dev device descriptor + * @scancode: the desired scancode + * @keycode: the keycode to be retorned. + * + * This routine is used to handle evdev EVIOCGKEY ioctl. + * If the key is not found, returns -EINVAL, otherwise, returns 0. + */ +static int ir_getkeycode(struct input_dev *dev, + int scancode, int *keycode) +{ + int elem; + struct ir_scancode_table *rc_tab = input_get_drvdata(dev); + + elem = ir_seek_table(rc_tab, scancode); + if (elem >= 0) { + *keycode = rc_tab->scan[elem].keycode; + return 0; + } + + /* + * Scancode not found and table can't be expanded + */ + if (elem < 0 && rc_tab->size == IR_TAB_MAX_SIZE) + return -EINVAL; + + /* + * If is there extra space, returns KEY_RESERVED, + * otherwise, input core won't let ir_setkeycode to work + */ + *keycode = KEY_RESERVED; + return 0; +} + + +/** + * ir_is_resize_needed() - Check if the table needs rezise + * @table: keycode table that may need to resize + * @n_elems: minimum number of entries to store keycodes + * + * Considering that kmalloc uses power of two storage areas, this + * routine detects if the real alloced size will change. If not, it + * just returns without doing nothing. Otherwise, it will extend or + * reduce the table size to meet the new needs. + * + * It returns 0 if no resize is needed, 1 otherwise. + */ +static int ir_is_resize_needed(struct ir_scancode_table *table, int n_elems) +{ + int cur_size = ir_roundup_tablesize(table->size); + int new_size = ir_roundup_tablesize(n_elems); + + if (cur_size == new_size) + return 0; + + /* Resize is needed */ + return 1; +} + +/** + * ir_delete_key() - remove a keycode from the table + * @rc_tab: keycode table + * @elem: element to be removed + * + */ +static void ir_delete_key(struct ir_scancode_table *rc_tab, int elem) +{ + unsigned long flags = 0; + int newsize = rc_tab->size - 1; + int resize = ir_is_resize_needed(rc_tab, newsize); + struct ir_scancode *oldkeymap = rc_tab->scan; + struct ir_scancode *newkeymap; + + if (resize) { + newkeymap = kzalloc(ir_roundup_tablesize(newsize) * + sizeof(*newkeymap), GFP_ATOMIC); + + /* There's no memory for resize. Keep the old table */ + if (!newkeymap) + resize = 0; + } + + if (!resize) { + newkeymap = oldkeymap; + + /* We'll modify the live table. Lock it */ + spin_lock_irqsave(&rc_tab->lock, flags); + } + + /* + * Copy the elements before the one that will be deleted + * if (!resize), both oldkeymap and newkeymap points + * to the same place, so, there's no need to copy + */ + if (resize && elem > 0) + memcpy(newkeymap, oldkeymap, + elem * sizeof(*newkeymap)); + + /* + * Copy the other elements overwriting the element to be removed + * This operation applies to both resize and non-resize case + */ + if (elem < newsize) + memcpy(&newkeymap[elem], &oldkeymap[elem + 1], + (newsize - elem) * sizeof(*newkeymap)); + + if (resize) { + /* + * As the copy happened to a temporary table, only here + * it needs to lock while replacing the table pointers + * to use the new table + */ + spin_lock_irqsave(&rc_tab->lock, flags); + rc_tab->size = newsize; + rc_tab->scan = newkeymap; + spin_unlock_irqrestore(&rc_tab->lock, flags); + + /* Frees the old keytable */ + kfree(oldkeymap); + } else { + rc_tab->size = newsize; + spin_unlock_irqrestore(&rc_tab->lock, flags); + } +} + +/** + * ir_insert_key() - insert a keycode at the table + * @rc_tab: keycode table + * @scancode: the desired scancode + * @keycode: the keycode to be retorned. + * + */ +static int ir_insert_key(struct ir_scancode_table *rc_tab, + int scancode, int keycode) +{ + unsigned long flags; + int elem = rc_tab->size; + int newsize = rc_tab->size + 1; + int resize = ir_is_resize_needed(rc_tab, newsize); + struct ir_scancode *oldkeymap = rc_tab->scan; + struct ir_scancode *newkeymap; + + if (resize) { + newkeymap = kzalloc(ir_roundup_tablesize(newsize) * + sizeof(*newkeymap), GFP_ATOMIC); + if (!newkeymap) + return -ENOMEM; + + memcpy(newkeymap, oldkeymap, + rc_tab->size * sizeof(*newkeymap)); + } else + newkeymap = oldkeymap; + + /* Stores the new code at the table */ + IR_dprintk(1, "#%d: New scan 0x%04x with key 0x%04x\n", + rc_tab->size, scancode, keycode); + + spin_lock_irqsave(&rc_tab->lock, flags); + rc_tab->size = newsize; + if (resize) { + rc_tab->scan = newkeymap; + kfree(oldkeymap); + } + newkeymap[elem].scancode = scancode; + newkeymap[elem].keycode = keycode; + spin_unlock_irqrestore(&rc_tab->lock, flags); + + return 0; +} + +/** + * ir_setkeycode() - set a keycode at the evdev scancode ->keycode table + * @dev: the struct input_dev device descriptor + * @scancode: the desired scancode + * @keycode: the keycode to be retorned. + * + * This routine is used to handle evdev EVIOCSKEY ioctl. + * There's one caveat here: how can we increase the size of the table? + * If the key is not found, returns -EINVAL, otherwise, returns 0. + */ +static int ir_setkeycode(struct input_dev *dev, + int scancode, int keycode) +{ + int rc = 0; + struct ir_scancode_table *rc_tab = input_get_drvdata(dev); + struct ir_scancode *keymap = rc_tab->scan; + unsigned long flags; + + /* + * Handle keycode table deletions + * + * If userspace is adding a KEY_UNKNOWN or KEY_RESERVED, + * deal as a trial to remove an existing scancode attribution + * if table become too big, reduce it to save space + */ + if (keycode == KEY_UNKNOWN || keycode == KEY_RESERVED) { + rc = ir_seek_table(rc_tab, scancode); + if (rc < 0) + return 0; + + IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", rc, scancode); + clear_bit(keymap[rc].keycode, dev->keybit); + ir_delete_key(rc_tab, rc); + + return 0; + } + + /* + * Handle keycode replacements + * + * If the scancode exists, just replace by the new value + */ + rc = ir_seek_table(rc_tab, scancode); + if (rc >= 0) { + IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n", + rc, scancode, keycode); + + clear_bit(keymap[rc].keycode, dev->keybit); + + spin_lock_irqsave(&rc_tab->lock, flags); + keymap[rc].keycode = keycode; + spin_unlock_irqrestore(&rc_tab->lock, flags); + + set_bit(keycode, dev->keybit); + + return 0; + } + + /* + * Handle new scancode inserts + * + * reallocate table if needed and insert a new keycode + */ + + /* Avoid growing the table indefinitely */ + if (rc_tab->size + 1 > IR_TAB_MAX_SIZE) + return -EINVAL; + + rc = ir_insert_key(rc_tab, scancode, keycode); + if (rc < 0) + return rc; + set_bit(keycode, dev->keybit); + + return 0; +} + +/** + * 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_UNKNOWN. Otherwise, returns the + * corresponding keycode from the table. + */ +u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) +{ + struct ir_scancode_table *rc_tab = input_get_drvdata(dev); + struct ir_scancode *keymap = rc_tab->scan; + int elem; + + elem = ir_seek_table(rc_tab, scancode); + if (elem >= 0) { + IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", + dev->name, scancode, keymap[elem].keycode); + + return rc_tab->scan[elem].keycode; + } + + printk(KERN_INFO "%s: unknown key for scancode 0x%04x\n", + dev->name, scancode); + + /* Reports userspace that an unknown keycode were got */ + return KEY_RESERVED; +} + +/** + * ir_set_keycode_table() - 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 should be called before registering the IR device. + */ +int ir_set_keycode_table(struct input_dev *input_dev, + struct ir_scancode_table *rc_tab) +{ + struct ir_scancode *keymap = rc_tab->scan; + int i; + + spin_lock_init(&rc_tab->lock); + + if (rc_tab->scan == NULL || !rc_tab->size) + return -EINVAL; + + /* set the bits for the keys */ + IR_dprintk(1, "key map size: %d\n", rc_tab->size); + for (i = 0; i < rc_tab->size; i++) { + IR_dprintk(1, "#%d: setting bit for keycode 0x%04x\n", + i, keymap[i].keycode); + set_bit(keymap[i].keycode, input_dev->keybit); + } + + input_dev->getkeycode = ir_getkeycode; + input_dev->setkeycode = ir_setkeycode; + input_set_drvdata(input_dev, rc_tab); + + return 0; +} + +void ir_input_free(struct input_dev *dev) +{ + struct ir_scancode_table *rc_tab = input_get_drvdata(dev); + + if (!rc_tab) + return; + + IR_dprintk(1, "Freed keycode table\n"); + + rc_tab->size = 0; + kfree(rc_tab->scan); + rc_tab->scan = NULL; +} +EXPORT_SYMBOL_GPL(ir_input_free); + diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index ba69bee..a28541b 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -99,6 +99,7 @@ config VIDEO_MEDIA comment "Multimedia drivers" source "drivers/media/common/Kconfig" +source "drivers/media/IR/Kconfig" # # Tuner drivers for DVB and V4L diff --git a/drivers/media/Makefile b/drivers/media/Makefile index 09a829d..499b081 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile @@ -2,7 +2,7 @@ # Makefile for the kernel multimedia device drivers. # -obj-y += common/ video/ +obj-y += common/ IR/ video/ obj-$(CONFIG_VIDEO_DEV) += radio/ obj-$(CONFIG_DVB_CORE) += dvb/ diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile index 169b337..e3ec963 100644 --- a/drivers/media/common/Makefile +++ b/drivers/media/common/Makefile @@ -1,8 +1,6 @@ saa7146-objs := saa7146_i2c.o saa7146_core.o saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o -ir-common-objs := ir-functions.o ir-keymaps.o ir-keytable.o obj-y += tuners/ obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o -obj-$(CONFIG_VIDEO_IR) += ir-common.o diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c deleted file mode 100644 index e616f62..0000000 --- a/drivers/media/common/ir-functions.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - * - * some common structs and functions to handle infrared remotes via - * input layer ... - * - * (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 - -/* -------------------------------------------------------------------------- */ - -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)"); - -int media_ir_debug; /* media_ir_debug level (0,1,2) */ -module_param_named(debug, media_ir_debug, int, 0644); - -/* -------------------------------------------------------------------------- */ - -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, - int ir_type, struct ir_scancode_table *ir_codes) -{ - ir->ir_type = ir_type; - - ir->keytable.size = ir_roundup_tablesize(ir_codes->size); - ir->keytable.scan = kzalloc(ir->keytable.size * - sizeof(struct ir_scancode), GFP_KERNEL); - if (!ir->keytable.scan) - return -ENOMEM; - - IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n", - ir->keytable.size, - ir->keytable.size * sizeof(ir->keytable.scan)); - - ir_copy_table(&ir->keytable, ir_codes); - ir_set_keycode_table(dev, &ir->keytable); - - clear_bit(0, dev->keybit); - set_bit(EV_KEY, dev->evbit); - 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) -{ - 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); - -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 */ - -/* decode raw bit pattern to RC5 code */ -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; -} -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; - 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, 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; - } - } -} -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/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c deleted file mode 100644 index 9bbe6b1..0000000 --- a/drivers/media/common/ir-keymaps.c +++ /dev/null @@ -1,3395 +0,0 @@ -/* - Keytables for supported remote controls, used on drivers/media - 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; 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. -*/ - -/* - * NOTICE FOR DEVELOPERS: - * The IR mappings should be as close as possible to what's - * specified at: - * http://linuxtv.org/wiki/index.php/Remote_Controllers - */ -#include - -#include -#include - -/* empty keytable, can be used as placeholder for not-yet created keytables */ -static struct ir_scancode ir_codes_empty[] = { - { 0x2a, KEY_COFFEE }, -}; - -struct ir_scancode_table ir_codes_empty_table = { - .scan = ir_codes_empty, - .size = ARRAY_SIZE(ir_codes_empty), -}; -EXPORT_SYMBOL_GPL(ir_codes_empty_table); - -/* Michal Majchrowicz */ -static struct ir_scancode ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_proteus_2309_table = { - .scan = ir_codes_proteus_2309, - .size = ARRAY_SIZE(ir_codes_proteus_2309), -}; -EXPORT_SYMBOL_GPL(ir_codes_proteus_2309_table); - -/* 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 +' */ -}; - -struct ir_scancode_table ir_codes_avermedia_dvbt_table = { - .scan = ir_codes_avermedia_dvbt, - .size = ARRAY_SIZE(ir_codes_avermedia_dvbt), -}; -EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt_table); - -/* Mauro Carvalho Chehab */ -static struct ir_scancode ir_codes_avermedia_m135a[] = { - { 0x00, KEY_POWER2 }, - { 0x2e, KEY_DOT }, /* '.' */ - { 0x01, KEY_MODE }, /* TV/FM */ - - { 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 }, - { 0x11, KEY_0 }, - - { 0x13, KEY_RIGHT }, /* -> */ - { 0x12, KEY_LEFT }, /* <- */ - - { 0x17, KEY_SLEEP }, /* Capturar Imagem */ - { 0x10, KEY_SHUFFLE }, /* Amostra */ - - /* FIXME: The keys bellow aren't ok */ - - { 0x43, KEY_CHANNELUP }, - { 0x42, KEY_CHANNELDOWN }, - { 0x1f, KEY_VOLUMEUP }, - { 0x1e, KEY_VOLUMEDOWN }, - { 0x0c, KEY_ENTER }, - - { 0x14, KEY_MUTE }, - { 0x08, KEY_AUDIO }, - - { 0x03, KEY_TEXT }, - { 0x04, KEY_EPG }, - { 0x2b, KEY_TV2 }, /* TV2 */ - - { 0x1d, KEY_RED }, - { 0x1c, KEY_YELLOW }, - { 0x41, KEY_GREEN }, - { 0x40, KEY_BLUE }, - - { 0x1a, KEY_PLAYPAUSE }, - { 0x19, KEY_RECORD }, - { 0x18, KEY_PLAY }, - { 0x1b, KEY_STOP }, -}; - -struct ir_scancode_table ir_codes_avermedia_m135a_table = { - .scan = ir_codes_avermedia_m135a, - .size = ARRAY_SIZE(ir_codes_avermedia_m135a), -}; -EXPORT_SYMBOL_GPL(ir_codes_avermedia_m135a_table); - -/* Oldrich Jedlicka */ -static struct ir_scancode ir_codes_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 */ -}; - -struct ir_scancode_table ir_codes_avermedia_cardbus_table = { - .scan = ir_codes_avermedia_cardbus, - .size = ARRAY_SIZE(ir_codes_avermedia_cardbus), -}; -EXPORT_SYMBOL_GPL(ir_codes_avermedia_cardbus_table); - -/* Attila Kondoros */ -static struct ir_scancode ir_codes_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 <<<< */ -}; - -struct ir_scancode_table ir_codes_apac_viewcomp_table = { - .scan = ir_codes_apac_viewcomp, - .size = ARRAY_SIZE(ir_codes_apac_viewcomp), -}; -EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp_table); - -/* ---------------------------------------------------------------------- */ - -static struct ir_scancode ir_codes_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 */ -}; - -struct ir_scancode_table ir_codes_pixelview_table = { - .scan = ir_codes_pixelview, - .size = ARRAY_SIZE(ir_codes_pixelview), -}; -EXPORT_SYMBOL_GPL(ir_codes_pixelview_table); - -/* - Mauro Carvalho Chehab - present on PV MPEG 8000GT - */ -static struct ir_scancode ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_pixelview_new_table = { - .scan = ir_codes_pixelview_new, - .size = ARRAY_SIZE(ir_codes_pixelview_new), -}; -EXPORT_SYMBOL_GPL(ir_codes_pixelview_new_table); - -static struct ir_scancode ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_nebula_table = { - .scan = ir_codes_nebula, - .size = ARRAY_SIZE(ir_codes_nebula), -}; -EXPORT_SYMBOL_GPL(ir_codes_nebula_table); - -/* DigitalNow DNTV Live DVB-T Remote */ -static struct ir_scancode ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_dntv_live_dvb_t_table = { - .scan = ir_codes_dntv_live_dvb_t, - .size = ARRAY_SIZE(ir_codes_dntv_live_dvb_t), -}; -EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvb_t_table); - -/* ---------------------------------------------------------------------- */ - -/* IO-DATA BCTV7E Remote */ -static struct ir_scancode ir_codes_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 >| */ -}; - -struct ir_scancode_table ir_codes_iodata_bctv7e_table = { - .scan = ir_codes_iodata_bctv7e, - .size = ARRAY_SIZE(ir_codes_iodata_bctv7e), -}; -EXPORT_SYMBOL_GPL(ir_codes_iodata_bctv7e_table); - -/* ---------------------------------------------------------------------- */ - -/* ADS Tech Instant TV DVB-T PCI Remote */ -static struct ir_scancode ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_adstech_dvb_t_pci_table = { - .scan = ir_codes_adstech_dvb_t_pci, - .size = ARRAY_SIZE(ir_codes_adstech_dvb_t_pci), -}; -EXPORT_SYMBOL_GPL(ir_codes_adstech_dvb_t_pci_table); - -/* ---------------------------------------------------------------------- */ - -/* MSI TV@nywhere MASTER remote */ - -static struct ir_scancode ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_msi_tvanywhere_table = { - .scan = ir_codes_msi_tvanywhere, - .size = ARRAY_SIZE(ir_codes_msi_tvanywhere), -}; -EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_table); - -/* ---------------------------------------------------------------------- */ - -/* - 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 ir_codes_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 */ -}; - -struct ir_scancode_table ir_codes_msi_tvanywhere_plus_table = { - .scan = ir_codes_msi_tvanywhere_plus, - .size = ARRAY_SIZE(ir_codes_msi_tvanywhere_plus), -}; -EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_plus_table); - -/* ---------------------------------------------------------------------- */ - -/* Cinergy 1400 DVB-T */ -static struct ir_scancode ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_cinergy_1400_table = { - .scan = ir_codes_cinergy_1400, - .size = ARRAY_SIZE(ir_codes_cinergy_1400), -}; -EXPORT_SYMBOL_GPL(ir_codes_cinergy_1400_table); - -/* ---------------------------------------------------------------------- */ - -/* AVERTV STUDIO 303 Remote */ -static struct ir_scancode ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_avertv_303_table = { - .scan = ir_codes_avertv_303, - .size = ARRAY_SIZE(ir_codes_avertv_303), -}; -EXPORT_SYMBOL_GPL(ir_codes_avertv_303_table); - -/* ---------------------------------------------------------------------- */ - -/* DigitalNow DNTV Live! DVB-T Pro Remote */ -static struct ir_scancode ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_dntv_live_dvbt_pro_table = { - .scan = ir_codes_dntv_live_dvbt_pro, - .size = ARRAY_SIZE(ir_codes_dntv_live_dvbt_pro), -}; -EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvbt_pro_table); - -static struct ir_scancode ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_em_terratec_table = { - .scan = ir_codes_em_terratec, - .size = ARRAY_SIZE(ir_codes_em_terratec), -}; -EXPORT_SYMBOL_GPL(ir_codes_em_terratec_table); - -static struct ir_scancode ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_pinnacle_grey_table = { - .scan = ir_codes_pinnacle_grey, - .size = ARRAY_SIZE(ir_codes_pinnacle_grey), -}; -EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey_table); - -static struct ir_scancode ir_codes_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 */ -}; - -struct ir_scancode_table ir_codes_flyvideo_table = { - .scan = ir_codes_flyvideo, - .size = ARRAY_SIZE(ir_codes_flyvideo), -}; -EXPORT_SYMBOL_GPL(ir_codes_flyvideo_table); - -static struct ir_scancode ir_codes_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 >>| */ -}; - -struct ir_scancode_table ir_codes_flydvb_table = { - .scan = ir_codes_flydvb, - .size = ARRAY_SIZE(ir_codes_flydvb), -}; -EXPORT_SYMBOL_GPL(ir_codes_flydvb_table); - -static struct ir_scancode ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_cinergy_table = { - .scan = ir_codes_cinergy, - .size = ARRAY_SIZE(ir_codes_cinergy), -}; -EXPORT_SYMBOL_GPL(ir_codes_cinergy_table); - -/* Alfons Geser - * updates from Job D. R. Borges */ -static struct ir_scancode ir_codes_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) */ -}; - -struct ir_scancode_table ir_codes_eztv_table = { - .scan = ir_codes_eztv, - .size = ARRAY_SIZE(ir_codes_eztv), -}; -EXPORT_SYMBOL_GPL(ir_codes_eztv_table); - -/* Alex Hermann */ -static struct ir_scancode ir_codes_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+ */ -}; - -struct ir_scancode_table ir_codes_avermedia_table = { - .scan = ir_codes_avermedia, - .size = ARRAY_SIZE(ir_codes_avermedia), -}; -EXPORT_SYMBOL_GPL(ir_codes_avermedia_table); - -static struct ir_scancode ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_videomate_tv_pvr_table = { - .scan = ir_codes_videomate_tv_pvr, - .size = ARRAY_SIZE(ir_codes_videomate_tv_pvr), -}; -EXPORT_SYMBOL_GPL(ir_codes_videomate_tv_pvr_table); - -/* Michael Tokarev - http://www.corpit.ru/mjt/beholdTV/remote_control.jpg - 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 ir_codes_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 ? */ -}; - -struct ir_scancode_table ir_codes_manli_table = { - .scan = ir_codes_manli, - .size = ARRAY_SIZE(ir_codes_manli), -}; -EXPORT_SYMBOL_GPL(ir_codes_manli_table); - -/* Mike Baikov */ -static struct ir_scancode ir_codes_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 */ -}; - -struct ir_scancode_table ir_codes_gotview7135_table = { - .scan = ir_codes_gotview7135, - .size = ARRAY_SIZE(ir_codes_gotview7135), -}; -EXPORT_SYMBOL_GPL(ir_codes_gotview7135_table); - -static struct ir_scancode ir_codes_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 ? */ - -}; - -struct ir_scancode_table ir_codes_purpletv_table = { - .scan = ir_codes_purpletv, - .size = ARRAY_SIZE(ir_codes_purpletv), -}; -EXPORT_SYMBOL_GPL(ir_codes_purpletv_table); - -/* 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 ir_codes_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 */ -}; - -struct ir_scancode_table ir_codes_pctv_sedna_table = { - .scan = ir_codes_pctv_sedna, - .size = ARRAY_SIZE(ir_codes_pctv_sedna), -}; -EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna_table); - -/* Mark Phalan */ -static struct ir_scancode ir_codes_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 */ -}; - -struct ir_scancode_table ir_codes_pv951_table = { - .scan = ir_codes_pv951, - .size = ARRAY_SIZE(ir_codes_pv951), -}; -EXPORT_SYMBOL_GPL(ir_codes_pv951_table); - -/* generic RC5 keytable */ -/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ -/* used by old (black) Hauppauge remotes */ -static struct ir_scancode ir_codes_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 */ - -}; - -struct ir_scancode_table ir_codes_rc5_tv_table = { - .scan = ir_codes_rc5_tv, - .size = ARRAY_SIZE(ir_codes_rc5_tv), -}; -EXPORT_SYMBOL_GPL(ir_codes_rc5_tv_table); - -/* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ -static struct ir_scancode ir_codes_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 */ -}; - -struct ir_scancode_table ir_codes_winfast_table = { - .scan = ir_codes_winfast, - .size = ARRAY_SIZE(ir_codes_winfast), -}; -EXPORT_SYMBOL_GPL(ir_codes_winfast_table); - -static struct ir_scancode ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_pinnacle_color_table = { - .scan = ir_codes_pinnacle_color, - .size = ARRAY_SIZE(ir_codes_pinnacle_color), -}; -EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color_table); - -/* 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 ir_codes_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) */ -}; - -struct ir_scancode_table ir_codes_hauppauge_new_table = { - .scan = ir_codes_hauppauge_new, - .size = ARRAY_SIZE(ir_codes_hauppauge_new), -}; -EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new_table); - -static struct ir_scancode ir_codes_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 }, - -}; - -struct ir_scancode_table ir_codes_npgtech_table = { - .scan = ir_codes_npgtech, - .size = ARRAY_SIZE(ir_codes_npgtech), -}; -EXPORT_SYMBOL_GPL(ir_codes_npgtech_table); - -/* Norwood Micro (non-Pro) TV Tuner - By Peter Naulls - Key comments are the functions given in the manual */ -static struct ir_scancode ir_codes_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 */ -}; - -struct ir_scancode_table ir_codes_norwood_table = { - .scan = ir_codes_norwood, - .size = ARRAY_SIZE(ir_codes_norwood), -}; -EXPORT_SYMBOL_GPL(ir_codes_norwood_table); - -/* 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 ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_budget_ci_old_table = { - .scan = ir_codes_budget_ci_old, - .size = ARRAY_SIZE(ir_codes_budget_ci_old), -}; -EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old_table); - -/* - * 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 ir_codes_asus_pc39[] = { - /* Keys 0 to 9 */ - { 0x15, KEY_0 }, - { 0x29, KEY_1 }, - { 0x2d, KEY_2 }, - { 0x2b, KEY_3 }, - { 0x09, KEY_4 }, - { 0x0d, KEY_5 }, - { 0x0b, KEY_6 }, - { 0x31, KEY_7 }, - { 0x35, KEY_8 }, - { 0x33, KEY_9 }, - - { 0x3e, KEY_RADIO }, /* radio */ - { 0x03, KEY_MENU }, /* dvd/menu */ - { 0x2a, KEY_VOLUMEUP }, - { 0x19, KEY_VOLUMEDOWN }, - { 0x37, KEY_UP }, - { 0x3b, KEY_DOWN }, - { 0x27, KEY_LEFT }, - { 0x2f, KEY_RIGHT }, - { 0x25, KEY_VIDEO }, /* video */ - { 0x39, KEY_AUDIO }, /* music */ - - { 0x21, KEY_TV }, /* tv */ - { 0x1d, KEY_EXIT }, /* back */ - { 0x0a, KEY_CHANNELUP }, /* channel / program + */ - { 0x1b, KEY_CHANNELDOWN }, /* channel / program - */ - { 0x1a, KEY_ENTER }, /* enter */ - - { 0x06, KEY_PAUSE }, /* play/pause */ - { 0x1e, KEY_PREVIOUS }, /* rew */ - { 0x26, KEY_NEXT }, /* forward */ - { 0x0e, KEY_REWIND }, /* backward << */ - { 0x3a, KEY_FASTFORWARD }, /* forward >> */ - { 0x36, KEY_STOP }, - { 0x2e, KEY_RECORD }, /* recording */ - { 0x16, KEY_POWER }, /* the button that reads "close" */ - - { 0x11, KEY_ZOOM }, /* full screen */ - { 0x13, KEY_MACRO }, /* recall */ - { 0x23, KEY_HOME }, /* home */ - { 0x05, KEY_PVR }, /* picture */ - { 0x3d, KEY_MUTE }, /* mute */ - { 0x01, KEY_DVD }, /* dvd */ -}; - -struct ir_scancode_table ir_codes_asus_pc39_table = { - .scan = ir_codes_asus_pc39, - .size = ARRAY_SIZE(ir_codes_asus_pc39), -}; -EXPORT_SYMBOL_GPL(ir_codes_asus_pc39_table); - - -/* Encore ENLTV-FM - black plastic, white front cover with white glowing buttons - Juan Pablo Sormani */ -static struct ir_scancode ir_codes_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 */ -}; - -struct ir_scancode_table ir_codes_encore_enltv_table = { - .scan = ir_codes_encore_enltv, - .size = ARRAY_SIZE(ir_codes_encore_enltv), -}; -EXPORT_SYMBOL_GPL(ir_codes_encore_enltv_table); - -/* Encore ENLTV2-FM - silver plastic - "Wand Media" written at the botton - Mauro Carvalho Chehab */ -static struct ir_scancode ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_encore_enltv2_table = { - .scan = ir_codes_encore_enltv2, - .size = ARRAY_SIZE(ir_codes_encore_enltv2), -}; -EXPORT_SYMBOL_GPL(ir_codes_encore_enltv2_table); - -/* for the Technotrend 1500 bundled remotes (grey and black): */ -static struct ir_scancode ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_tt_1500_table = { - .scan = ir_codes_tt_1500, - .size = ARRAY_SIZE(ir_codes_tt_1500), -}; -EXPORT_SYMBOL_GPL(ir_codes_tt_1500_table); - -/* DViCO FUSION HDTV MCE remote */ -static struct ir_scancode ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_fusionhdtv_mce_table = { - .scan = ir_codes_fusionhdtv_mce, - .size = ARRAY_SIZE(ir_codes_fusionhdtv_mce), -}; -EXPORT_SYMBOL_GPL(ir_codes_fusionhdtv_mce_table); - -/* Pinnacle PCTV HD 800i mini remote */ -static struct ir_scancode ir_codes_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 "?" */ -}; - -struct ir_scancode_table ir_codes_pinnacle_pctv_hd_table = { - .scan = ir_codes_pinnacle_pctv_hd, - .size = ARRAY_SIZE(ir_codes_pinnacle_pctv_hd), -}; -EXPORT_SYMBOL_GPL(ir_codes_pinnacle_pctv_hd_table); - -/* - * 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 ir_codes_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 }, - -}; - -struct ir_scancode_table ir_codes_behold_table = { - .scan = ir_codes_behold, - .size = ARRAY_SIZE(ir_codes_behold), -}; -EXPORT_SYMBOL_GPL(ir_codes_behold_table); - -/* 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 ir_codes_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 }, - -}; - -struct ir_scancode_table ir_codes_behold_columbus_table = { - .scan = ir_codes_behold_columbus, - .size = ARRAY_SIZE(ir_codes_behold_columbus), -}; -EXPORT_SYMBOL_GPL(ir_codes_behold_columbus_table); - -/* - * Remote control for the Genius TVGO A11MCE - * Adrian Pardini - */ -static struct ir_scancode ir_codes_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 }, -}; - -struct ir_scancode_table ir_codes_genius_tvgo_a11mce_table = { - .scan = ir_codes_genius_tvgo_a11mce, - .size = ARRAY_SIZE(ir_codes_genius_tvgo_a11mce), -}; -EXPORT_SYMBOL_GPL(ir_codes_genius_tvgo_a11mce_table); - -/* - * Remote control for Powercolor Real Angel 330 - * Daniel Fraga - */ -static struct ir_scancode ir_codes_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 */ -}; - -struct ir_scancode_table ir_codes_powercolor_real_angel_table = { - .scan = ir_codes_powercolor_real_angel, - .size = ARRAY_SIZE(ir_codes_powercolor_real_angel), -}; -EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel_table); - -/* Kworld Plus TV Analog Lite PCI IR - Mauro Carvalho Chehab - */ -static struct ir_scancode ir_codes_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 */ -}; -struct ir_scancode_table ir_codes_kworld_plus_tv_analog_table = { - .scan = ir_codes_kworld_plus_tv_analog, - .size = ARRAY_SIZE(ir_codes_kworld_plus_tv_analog), -}; -EXPORT_SYMBOL_GPL(ir_codes_kworld_plus_tv_analog_table); - -/* Kaiomy TVnPC U2 - Mauro Carvalho Chehab - */ -static struct ir_scancode ir_codes_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}, -}; -struct ir_scancode_table ir_codes_kaiomy_table = { - .scan = ir_codes_kaiomy, - .size = ARRAY_SIZE(ir_codes_kaiomy), -}; -EXPORT_SYMBOL_GPL(ir_codes_kaiomy_table); - -static struct ir_scancode ir_codes_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}, -}; -struct ir_scancode_table ir_codes_avermedia_a16d_table = { - .scan = ir_codes_avermedia_a16d, - .size = ARRAY_SIZE(ir_codes_avermedia_a16d), -}; -EXPORT_SYMBOL_GPL(ir_codes_avermedia_a16d_table); - -/* Encore ENLTV-FM v5.3 - Mauro Carvalho Chehab - */ -static struct ir_scancode ir_codes_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 */ -}; -struct ir_scancode_table ir_codes_encore_enltv_fm53_table = { - .scan = ir_codes_encore_enltv_fm53, - .size = ARRAY_SIZE(ir_codes_encore_enltv_fm53), -}; -EXPORT_SYMBOL_GPL(ir_codes_encore_enltv_fm53_table); - -/* Zogis Real Audio 220 - 32 keys IR */ -static struct ir_scancode ir_codes_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 */ - -}; -struct ir_scancode_table ir_codes_real_audio_220_32_keys_table = { - .scan = ir_codes_real_audio_220_32_keys, - .size = ARRAY_SIZE(ir_codes_real_audio_220_32_keys), -}; -EXPORT_SYMBOL_GPL(ir_codes_real_audio_220_32_keys_table); - -/* ATI TV Wonder HD 600 USB - Devin Heitmueller - */ -static struct ir_scancode ir_codes_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}, -}; -struct ir_scancode_table ir_codes_ati_tv_wonder_hd_600_table = { - .scan = ir_codes_ati_tv_wonder_hd_600, - .size = ARRAY_SIZE(ir_codes_ati_tv_wonder_hd_600), -}; -EXPORT_SYMBOL_GPL(ir_codes_ati_tv_wonder_hd_600_table); - -/* DVBWorld remotes - Igor M. Liplianin - */ -static struct ir_scancode ir_codes_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 */ -}; -struct ir_scancode_table ir_codes_dm1105_nec_table = { - .scan = ir_codes_dm1105_nec, - .size = ARRAY_SIZE(ir_codes_dm1105_nec), -}; -EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec_table); - -static struct ir_scancode ir_codes_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}, -}; -struct ir_scancode_table ir_codes_tevii_nec_table = { - .scan = ir_codes_tevii_nec, - .size = ARRAY_SIZE(ir_codes_tevii_nec), -}; -EXPORT_SYMBOL_GPL(ir_codes_tevii_nec_table); - -static struct ir_scancode ir_codes_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}, -}; -struct ir_scancode_table ir_codes_tbs_nec_table = { - .scan = ir_codes_tbs_nec, - .size = ARRAY_SIZE(ir_codes_tbs_nec), -}; -EXPORT_SYMBOL_GPL(ir_codes_tbs_nec_table); - -/* Terratec Cinergy Hybrid T USB XS - Devin Heitmueller - */ -static struct ir_scancode ir_codes_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}, -}; -struct ir_scancode_table ir_codes_terratec_cinergy_xs_table = { - .scan = ir_codes_terratec_cinergy_xs, - .size = ARRAY_SIZE(ir_codes_terratec_cinergy_xs), -}; -EXPORT_SYMBOL_GPL(ir_codes_terratec_cinergy_xs_table); - -/* EVGA inDtube - Devin Heitmueller - */ -static struct ir_scancode ir_codes_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}, -}; -struct ir_scancode_table ir_codes_evga_indtube_table = { - .scan = ir_codes_evga_indtube, - .size = ARRAY_SIZE(ir_codes_evga_indtube), -}; -EXPORT_SYMBOL_GPL(ir_codes_evga_indtube_table); - -static struct ir_scancode ir_codes_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}, -}; -struct ir_scancode_table ir_codes_videomate_s350_table = { - .scan = ir_codes_videomate_s350, - .size = ARRAY_SIZE(ir_codes_videomate_s350), -}; -EXPORT_SYMBOL_GPL(ir_codes_videomate_s350_table); - -/* GADMEI UTV330+ RM008Z remote - Shine Liu - */ -static struct ir_scancode ir_codes_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 */ -}; -struct ir_scancode_table ir_codes_gadmei_rm008z_table = { - .scan = ir_codes_gadmei_rm008z, - .size = ARRAY_SIZE(ir_codes_gadmei_rm008z), -}; -EXPORT_SYMBOL_GPL(ir_codes_gadmei_rm008z_table); - -/************************************************************* - * COMPLETE SCANCODE TABLES - * Instead of just a partial scancode, the tables bellow - * contains the complete scancode and the receiver protocol - *************************************************************/ - -/* - * 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 ir_codes_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) */ -}; - -struct ir_scancode_table ir_codes_rc5_hauppauge_new_table = { - .scan = ir_codes_rc5_hauppauge_new, - .size = ARRAY_SIZE(ir_codes_rc5_hauppauge_new), - .ir_type = IR_TYPE_RC5, -}; -EXPORT_SYMBOL_GPL(ir_codes_rc5_hauppauge_new_table); - -/* Terratec Cinergy Hybrid T USB XS FM - Mauro Carvalho Chehab - */ -static struct ir_scancode ir_codes_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}, -}; -struct ir_scancode_table ir_codes_nec_terratec_cinergy_xs_table = { - .scan = ir_codes_nec_terratec_cinergy_xs, - .size = ARRAY_SIZE(ir_codes_nec_terratec_cinergy_xs), - .ir_type = IR_TYPE_NEC, -}; -EXPORT_SYMBOL_GPL(ir_codes_nec_terratec_cinergy_xs_table); - diff --git a/drivers/media/common/ir-keytable.c b/drivers/media/common/ir-keytable.c deleted file mode 100644 index ceef0e8..0000000 --- a/drivers/media/common/ir-keytable.c +++ /dev/null @@ -1,432 +0,0 @@ -/* ir-register.c - handle IR scancode->keycode tables - * - * Copyright (C) 2009 by Mauro Carvalho Chehab - */ - -#include - -#include - -#define IR_TAB_MIN_SIZE 32 -#define IR_TAB_MAX_SIZE 1024 - -/** - * ir_seek_table() - returns the element order on the table - * @rc_tab: the ir_scancode_table with the keymap to be used - * @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_UNKNOWN. Otherwise, returns the - * corresponding keycode from the table. - */ -static int ir_seek_table(struct ir_scancode_table *rc_tab, u32 scancode) -{ - int rc; - unsigned long flags; - struct ir_scancode *keymap = rc_tab->scan; - - spin_lock_irqsave(&rc_tab->lock, flags); - - /* FIXME: replace it by a binary search */ - - for (rc = 0; rc < rc_tab->size; rc++) - if (keymap[rc].scancode == scancode) - goto exit; - - /* Not found */ - rc = -EINVAL; - -exit: - spin_unlock_irqrestore(&rc_tab->lock, flags); - return rc; -} - -/** - * ir_roundup_tablesize() - gets an optimum value for the table size - * @n_elems: minimum number of entries to store keycodes - * - * This routine is used to choose the keycode table size. - * - * In order to have some empty space for new keycodes, - * and knowing in advance that kmalloc allocates only power of two - * segments, it optimizes the allocated space to have some spare space - * for those new keycodes by using the maximum number of entries that - * will be effectively be allocated by kmalloc. - * In order to reduce the quantity of table resizes, it has a minimum - * table size of IR_TAB_MIN_SIZE. - */ -int ir_roundup_tablesize(int n_elems) -{ - size_t size; - - if (n_elems < IR_TAB_MIN_SIZE) - n_elems = IR_TAB_MIN_SIZE; - - /* - * As kmalloc only allocates sizes of power of two, get as - * much entries as possible for the allocated memory segment - */ - size = roundup_pow_of_two(n_elems * sizeof(struct ir_scancode)); - n_elems = size / sizeof(struct ir_scancode); - - return n_elems; -} - -/** - * ir_copy_table() - copies a keytable, discarding the unused entries - * @destin: destin table - * @origin: origin table - * - * Copies all entries where the keycode is not KEY_UNKNOWN/KEY_RESERVED - */ - -int ir_copy_table(struct ir_scancode_table *destin, - const struct ir_scancode_table *origin) -{ - int i, j = 0; - - for (i = 0; i < origin->size; i++) { - if (origin->scan[i].keycode == KEY_UNKNOWN || - origin->scan[i].keycode == KEY_RESERVED) - continue; - - memcpy(&destin->scan[j], &origin->scan[i], sizeof(struct ir_scancode)); - j++; - } - destin->size = j; - - IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size); - - return 0; -} - -/** - * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table - * @dev: the struct input_dev device descriptor - * @scancode: the desired scancode - * @keycode: the keycode to be retorned. - * - * This routine is used to handle evdev EVIOCGKEY ioctl. - * If the key is not found, returns -EINVAL, otherwise, returns 0. - */ -static int ir_getkeycode(struct input_dev *dev, - int scancode, int *keycode) -{ - int elem; - struct ir_scancode_table *rc_tab = input_get_drvdata(dev); - - elem = ir_seek_table(rc_tab, scancode); - if (elem >= 0) { - *keycode = rc_tab->scan[elem].keycode; - return 0; - } - - /* - * Scancode not found and table can't be expanded - */ - if (elem < 0 && rc_tab->size == IR_TAB_MAX_SIZE) - return -EINVAL; - - /* - * If is there extra space, returns KEY_RESERVED, - * otherwise, input core won't let ir_setkeycode to work - */ - *keycode = KEY_RESERVED; - return 0; -} - - -/** - * ir_is_resize_needed() - Check if the table needs rezise - * @table: keycode table that may need to resize - * @n_elems: minimum number of entries to store keycodes - * - * Considering that kmalloc uses power of two storage areas, this - * routine detects if the real alloced size will change. If not, it - * just returns without doing nothing. Otherwise, it will extend or - * reduce the table size to meet the new needs. - * - * It returns 0 if no resize is needed, 1 otherwise. - */ -static int ir_is_resize_needed(struct ir_scancode_table *table, int n_elems) -{ - int cur_size = ir_roundup_tablesize(table->size); - int new_size = ir_roundup_tablesize(n_elems); - - if (cur_size == new_size) - return 0; - - /* Resize is needed */ - return 1; -} - -/** - * ir_delete_key() - remove a keycode from the table - * @rc_tab: keycode table - * @elem: element to be removed - * - */ -static void ir_delete_key(struct ir_scancode_table *rc_tab, int elem) -{ - unsigned long flags = 0; - int newsize = rc_tab->size - 1; - int resize = ir_is_resize_needed(rc_tab, newsize); - struct ir_scancode *oldkeymap = rc_tab->scan; - struct ir_scancode *newkeymap; - - if (resize) { - newkeymap = kzalloc(ir_roundup_tablesize(newsize) * - sizeof(*newkeymap), GFP_ATOMIC); - - /* There's no memory for resize. Keep the old table */ - if (!newkeymap) - resize = 0; - } - - if (!resize) { - newkeymap = oldkeymap; - - /* We'll modify the live table. Lock it */ - spin_lock_irqsave(&rc_tab->lock, flags); - } - - /* - * Copy the elements before the one that will be deleted - * if (!resize), both oldkeymap and newkeymap points - * to the same place, so, there's no need to copy - */ - if (resize && elem > 0) - memcpy(newkeymap, oldkeymap, - elem * sizeof(*newkeymap)); - - /* - * Copy the other elements overwriting the element to be removed - * This operation applies to both resize and non-resize case - */ - if (elem < newsize) - memcpy(&newkeymap[elem], &oldkeymap[elem + 1], - (newsize - elem) * sizeof(*newkeymap)); - - if (resize) { - /* - * As the copy happened to a temporary table, only here - * it needs to lock while replacing the table pointers - * to use the new table - */ - spin_lock_irqsave(&rc_tab->lock, flags); - rc_tab->size = newsize; - rc_tab->scan = newkeymap; - spin_unlock_irqrestore(&rc_tab->lock, flags); - - /* Frees the old keytable */ - kfree(oldkeymap); - } else { - rc_tab->size = newsize; - spin_unlock_irqrestore(&rc_tab->lock, flags); - } -} - -/** - * ir_insert_key() - insert a keycode at the table - * @rc_tab: keycode table - * @scancode: the desired scancode - * @keycode: the keycode to be retorned. - * - */ -static int ir_insert_key(struct ir_scancode_table *rc_tab, - int scancode, int keycode) -{ - unsigned long flags; - int elem = rc_tab->size; - int newsize = rc_tab->size + 1; - int resize = ir_is_resize_needed(rc_tab, newsize); - struct ir_scancode *oldkeymap = rc_tab->scan; - struct ir_scancode *newkeymap; - - if (resize) { - newkeymap = kzalloc(ir_roundup_tablesize(newsize) * - sizeof(*newkeymap), GFP_ATOMIC); - if (!newkeymap) - return -ENOMEM; - - memcpy(newkeymap, oldkeymap, - rc_tab->size * sizeof(*newkeymap)); - } else - newkeymap = oldkeymap; - - /* Stores the new code at the table */ - IR_dprintk(1, "#%d: New scan 0x%04x with key 0x%04x\n", - rc_tab->size, scancode, keycode); - - spin_lock_irqsave(&rc_tab->lock, flags); - rc_tab->size = newsize; - if (resize) { - rc_tab->scan = newkeymap; - kfree(oldkeymap); - } - newkeymap[elem].scancode = scancode; - newkeymap[elem].keycode = keycode; - spin_unlock_irqrestore(&rc_tab->lock, flags); - - return 0; -} - -/** - * ir_setkeycode() - set a keycode at the evdev scancode ->keycode table - * @dev: the struct input_dev device descriptor - * @scancode: the desired scancode - * @keycode: the keycode to be retorned. - * - * This routine is used to handle evdev EVIOCSKEY ioctl. - * There's one caveat here: how can we increase the size of the table? - * If the key is not found, returns -EINVAL, otherwise, returns 0. - */ -static int ir_setkeycode(struct input_dev *dev, - int scancode, int keycode) -{ - int rc = 0; - struct ir_scancode_table *rc_tab = input_get_drvdata(dev); - struct ir_scancode *keymap = rc_tab->scan; - unsigned long flags; - - /* - * Handle keycode table deletions - * - * If userspace is adding a KEY_UNKNOWN or KEY_RESERVED, - * deal as a trial to remove an existing scancode attribution - * if table become too big, reduce it to save space - */ - if (keycode == KEY_UNKNOWN || keycode == KEY_RESERVED) { - rc = ir_seek_table(rc_tab, scancode); - if (rc < 0) - return 0; - - IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", rc, scancode); - clear_bit(keymap[rc].keycode, dev->keybit); - ir_delete_key(rc_tab, rc); - - return 0; - } - - /* - * Handle keycode replacements - * - * If the scancode exists, just replace by the new value - */ - rc = ir_seek_table(rc_tab, scancode); - if (rc >= 0) { - IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n", - rc, scancode, keycode); - - clear_bit(keymap[rc].keycode, dev->keybit); - - spin_lock_irqsave(&rc_tab->lock, flags); - keymap[rc].keycode = keycode; - spin_unlock_irqrestore(&rc_tab->lock, flags); - - set_bit(keycode, dev->keybit); - - return 0; - } - - /* - * Handle new scancode inserts - * - * reallocate table if needed and insert a new keycode - */ - - /* Avoid growing the table indefinitely */ - if (rc_tab->size + 1 > IR_TAB_MAX_SIZE) - return -EINVAL; - - rc = ir_insert_key(rc_tab, scancode, keycode); - if (rc < 0) - return rc; - set_bit(keycode, dev->keybit); - - return 0; -} - -/** - * 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_UNKNOWN. Otherwise, returns the - * corresponding keycode from the table. - */ -u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) -{ - struct ir_scancode_table *rc_tab = input_get_drvdata(dev); - struct ir_scancode *keymap = rc_tab->scan; - int elem; - - elem = ir_seek_table(rc_tab, scancode); - if (elem >= 0) { - IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", - dev->name, scancode, keymap[elem].keycode); - - return rc_tab->scan[elem].keycode; - } - - printk(KERN_INFO "%s: unknown key for scancode 0x%04x\n", - dev->name, scancode); - - /* Reports userspace that an unknown keycode were got */ - return KEY_RESERVED; -} - -/** - * ir_set_keycode_table() - 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 should be called before registering the IR device. - */ -int ir_set_keycode_table(struct input_dev *input_dev, - struct ir_scancode_table *rc_tab) -{ - struct ir_scancode *keymap = rc_tab->scan; - int i; - - spin_lock_init(&rc_tab->lock); - - if (rc_tab->scan == NULL || !rc_tab->size) - return -EINVAL; - - /* set the bits for the keys */ - IR_dprintk(1, "key map size: %d\n", rc_tab->size); - for (i = 0; i < rc_tab->size; i++) { - IR_dprintk(1, "#%d: setting bit for keycode 0x%04x\n", - i, keymap[i].keycode); - set_bit(keymap[i].keycode, input_dev->keybit); - } - - input_dev->getkeycode = ir_getkeycode; - input_dev->setkeycode = ir_setkeycode; - input_set_drvdata(input_dev, rc_tab); - - return 0; -} - -void ir_input_free(struct input_dev *dev) -{ - struct ir_scancode_table *rc_tab = input_get_drvdata(dev); - - if (!rc_tab) - return; - - IR_dprintk(1, "Freed keycode table\n"); - - rc_tab->size = 0; - kfree(rc_tab->scan); - rc_tab->scan = NULL; -} -EXPORT_SYMBOL_GPL(ir_input_free); - diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 9dc74c9..f63909d 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -37,10 +37,6 @@ config VIDEO_BTCX depends on PCI tristate -config VIDEO_IR - tristate - depends on INPUT - config VIDEO_TVEEPROM tristate depends on I2C -- cgit v0.10.2 From 446e4a64d2f6efddc63a47169ba3c8037b620307 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 11 Dec 2009 08:34:07 -0300 Subject: V4L/DVB (13613): IR: create ir-core module Split the ir-common into two separate modules: - ir-core: it is the IR-independent functions; - ir-common: has the common part used by V4L drivers. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig index 5b4ac96..4dde7d1 100644 --- a/drivers/media/IR/Kconfig +++ b/drivers/media/IR/Kconfig @@ -1,4 +1,9 @@ -config VIDEO_IR +config IR_CORE tristate depends on INPUT default INPUT + +config VIDEO_IR + tristate + depends on IR_CORE + default IR_CORE diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index 2781f43..df5ddb4 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile @@ -1,3 +1,5 @@ -ir-common-objs := ir-functions.o ir-keymaps.o ir-keytable.o +ir-common-objs := ir-functions.o ir-keymaps.o +ir-core-objs := ir-keytable.o +obj-$(CONFIG_IR_CORE) += ir-core.o obj-$(CONFIG_VIDEO_IR) += ir-common.o diff --git a/drivers/media/IR/ir-functions.c b/drivers/media/IR/ir-functions.c index e616f62..2db2294 100644 --- a/drivers/media/IR/ir-functions.c +++ b/drivers/media/IR/ir-functions.c @@ -34,9 +34,6 @@ static int repeat = 1; module_param(repeat, int, 0444); MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)"); -int media_ir_debug; /* media_ir_debug level (0,1,2) */ -module_param_named(debug, media_ir_debug, int, 0644); - /* -------------------------------------------------------------------------- */ static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 99ed2de..20d642d 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -1,6 +1,15 @@ /* ir-register.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 @@ -10,7 +19,6 @@ #define IR_TAB_MIN_SIZE 32 #define IR_TAB_MAX_SIZE 1024 - /** * ir_seek_table() - returns the element order on the table * @rc_tab: the ir_scancode_table with the keymap to be used @@ -73,6 +81,7 @@ int ir_roundup_tablesize(int n_elems) return n_elems; } +EXPORT_SYMBOL_GPL(ir_roundup_tablesize); /** * ir_copy_table() - copies a keytable, discarding the unused entries @@ -101,6 +110,7 @@ int ir_copy_table(struct ir_scancode_table *destin, return 0; } +EXPORT_SYMBOL_GPL(ir_copy_table); /** * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table @@ -137,7 +147,6 @@ static int ir_getkeycode(struct input_dev *dev, return 0; } - /** * ir_is_resize_needed() - Check if the table needs rezise * @table: keycode table that may need to resize @@ -379,6 +388,7 @@ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) /* Reports userspace that an unknown keycode were got */ return KEY_RESERVED; } +EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); /** * ir_set_keycode_table() - sets the IR keycode table and add the handlers @@ -415,6 +425,7 @@ int ir_set_keycode_table(struct input_dev *input_dev, return 0; } +EXPORT_SYMBOL_GPL(ir_set_keycode_table); void ir_input_free(struct input_dev *dev) { @@ -431,3 +442,9 @@ void ir_input_free(struct input_dev *dev) } EXPORT_SYMBOL_GPL(ir_input_free); +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/include/media/ir-common.h b/include/media/ir-common.h index 45bf5cf..18d3004 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -26,31 +26,7 @@ #include #include #include -#include - -extern int media_ir_debug; /* media_ir_debug level (0,1,2) */ -#define IR_dprintk(level, fmt, arg...) if (media_ir_debug >= level) \ - printk(KERN_DEBUG "%s: " fmt , __func__, ## arg) - -enum ir_type { - IR_TYPE_UNKNOWN = 0, - IR_TYPE_RC5 = 1, - IR_TYPE_PD = 2, /* Pulse distance encoded IR */ - IR_TYPE_NEC = 3, - IR_TYPE_OTHER = 99, -}; - -struct ir_scancode { - u16 scancode; - u32 keycode; -}; - -struct ir_scancode_table { - struct ir_scancode *scan; - int size; - enum ir_type ir_type; - spinlock_t lock; -}; +#include #define RC5_START(x) (((x)>>12)&3) #define RC5_TOGGLE(x) (((x)>>11)&1) @@ -123,19 +99,6 @@ u32 ir_rc5_decode(unsigned int code); void ir_rc5_timer_end(unsigned long data); void ir_rc5_timer_keyup(unsigned long data); -/* Routines from ir-keytable.c */ - -u32 ir_g_keycode_from_table(struct input_dev *input_dev, - u32 scancode); - -int ir_set_keycode_table(struct input_dev *input_dev, - struct ir_scancode_table *rc_tab); - -int ir_roundup_tablesize(int n_elems); -int ir_copy_table(struct ir_scancode_table *destin, - const struct ir_scancode_table *origin); -void ir_input_free(struct input_dev *input_dev); - /* scancode->keycode map tables from ir-keymaps.c */ extern struct ir_scancode_table ir_codes_empty_table; diff --git a/include/media/ir-core.h b/include/media/ir-core.h new file mode 100644 index 0000000..825d04a --- /dev/null +++ b/include/media/ir-core.h @@ -0,0 +1,57 @@ +/* + * Remote Controller core header + * + * This program is free software; 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 + +extern int ir_core_debug; +#define IR_dprintk(level, fmt, arg...) if (ir_core_debug >= level) \ + printk(KERN_DEBUG "%s: " fmt , __func__, ## arg) + +enum ir_type { + IR_TYPE_UNKNOWN = 0, + IR_TYPE_RC5 = 1, + IR_TYPE_PD = 2, /* Pulse distance encoded IR */ + IR_TYPE_NEC = 3, + IR_TYPE_OTHER = 99, +}; + +struct ir_scancode { + u16 scancode; + u32 keycode; +}; + +struct ir_scancode_table { + struct ir_scancode *scan; + int size; + enum ir_type ir_type; + spinlock_t lock; +}; + +/* Routines from ir-keytable.c */ + +u32 ir_g_keycode_from_table(struct input_dev *input_dev, + u32 scancode); + +int ir_set_keycode_table(struct input_dev *input_dev, + struct ir_scancode_table *rc_tab); + +int ir_roundup_tablesize(int n_elems); +int ir_copy_table(struct ir_scancode_table *destin, + const struct ir_scancode_table *origin); +void ir_input_free(struct input_dev *input_dev); + +#endif -- cgit v0.10.2 From 865fbf20bed00d456556ecd4b4c9dadc45cba759 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 11 Dec 2009 09:29:57 -0300 Subject: V4L/DVB (13614): dib0090: Fix compilation when module is not selected Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/dib0090.h b/drivers/media/dvb/frontends/dib0090.h index 83cc8ae..24ab5bf 100644 --- a/drivers/media/dvb/frontends/dib0090.h +++ b/drivers/media/dvb/frontends/dib0090.h @@ -100,11 +100,6 @@ static inline int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_ return -ENODEV; } -static inline num frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe) -{ - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -return CT_SHUTDOWN,} - static inline void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -- cgit v0.10.2 From 75543cce0c1f46be495b981d8d3eda0882721d07 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 11 Dec 2009 09:44:23 -0300 Subject: V4L/DVB (13615): ir-core: create ir_input_register Move non-V4L specific stuff from ir-functions ir_input_init() into a new function to register ir devices: ir_input_register(). Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/IR/ir-functions.c b/drivers/media/IR/ir-functions.c index 2db2294..7401a79 100644 --- a/drivers/media/IR/ir-functions.c +++ b/drivers/media/IR/ir-functions.c @@ -56,24 +56,11 @@ int ir_input_init(struct input_dev *dev, struct ir_input_state *ir, { ir->ir_type = ir_type; - ir->keytable.size = ir_roundup_tablesize(ir_codes->size); - ir->keytable.scan = kzalloc(ir->keytable.size * - sizeof(struct ir_scancode), GFP_KERNEL); - if (!ir->keytable.scan) - return -ENOMEM; - - IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n", - ir->keytable.size, - ir->keytable.size * sizeof(ir->keytable.scan)); - - ir_copy_table(&ir->keytable, ir_codes); - ir_set_keycode_table(dev, &ir->keytable); - - clear_bit(0, dev->keybit); - set_bit(EV_KEY, dev->evbit); if (repeat) set_bit(EV_REP, dev->evbit); + ir_input_register(dev, ir_codes); + return 0; } EXPORT_SYMBOL_GPL(ir_input_init); diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 20d642d..ddb8a0f 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -125,7 +125,8 @@ static int ir_getkeycode(struct input_dev *dev, int scancode, int *keycode) { int elem; - struct ir_scancode_table *rc_tab = input_get_drvdata(dev); + struct ir_input_dev *ir_dev = input_get_drvdata(dev); + struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; elem = ir_seek_table(rc_tab, scancode); if (elem >= 0) { @@ -296,7 +297,8 @@ static int ir_setkeycode(struct input_dev *dev, int scancode, int keycode) { int rc = 0; - struct ir_scancode_table *rc_tab = input_get_drvdata(dev); + struct ir_input_dev *ir_dev = input_get_drvdata(dev); + struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; struct ir_scancode *keymap = rc_tab->scan; unsigned long flags; @@ -370,7 +372,8 @@ static int ir_setkeycode(struct input_dev *dev, */ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) { - struct ir_scancode_table *rc_tab = input_get_drvdata(dev); + struct ir_input_dev *ir_dev = input_get_drvdata(dev); + struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; struct ir_scancode *keymap = rc_tab->scan; int elem; @@ -391,7 +394,7 @@ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); /** - * ir_set_keycode_table() - sets the IR keycode table and add the handlers + * 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 @@ -400,17 +403,34 @@ EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); * an IR. * It should be called before registering the IR device. */ -int ir_set_keycode_table(struct input_dev *input_dev, - struct ir_scancode_table *rc_tab) +int ir_input_register(struct input_dev *input_dev, + struct ir_scancode_table *rc_tab) { - struct ir_scancode *keymap = rc_tab->scan; + struct ir_input_dev *ir_dev; + struct ir_scancode *keymap = rc_tab->scan; int i; - spin_lock_init(&rc_tab->lock); - if (rc_tab->scan == NULL || !rc_tab->size) return -EINVAL; + ir_dev = kzalloc(sizeof(*ir_dev), GFP_KERNEL); + if (!ir_dev) + return -ENOMEM; + + spin_lock_init(&rc_tab->lock); + + ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size); + ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size * + sizeof(struct ir_scancode), GFP_KERNEL); + if (!ir_dev->rc_tab.scan) + return -ENOMEM; + + IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n", + ir_dev->rc_tab.size, + ir_dev->rc_tab.size * sizeof(ir_dev->rc_tab.scan)); + + ir_copy_table(&ir_dev->rc_tab, rc_tab); + /* set the bits for the keys */ IR_dprintk(1, "key map size: %d\n", rc_tab->size); for (i = 0; i < rc_tab->size; i++) { @@ -418,18 +438,22 @@ int ir_set_keycode_table(struct input_dev *input_dev, i, keymap[i].keycode); set_bit(keymap[i].keycode, input_dev->keybit); } + clear_bit(0, input_dev->keybit); + + set_bit(EV_KEY, input_dev->evbit); input_dev->getkeycode = ir_getkeycode; input_dev->setkeycode = ir_setkeycode; - input_set_drvdata(input_dev, rc_tab); + input_set_drvdata(input_dev, ir_dev); return 0; } -EXPORT_SYMBOL_GPL(ir_set_keycode_table); +EXPORT_SYMBOL_GPL(ir_input_register); void ir_input_free(struct input_dev *dev) { - struct ir_scancode_table *rc_tab = input_get_drvdata(dev); + struct ir_input_dev *ir_dev = input_get_drvdata(dev); + struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; if (!rc_tab) return; @@ -439,6 +463,9 @@ void ir_input_free(struct input_dev *dev) rc_tab->size = 0; kfree(rc_tab->scan); rc_tab->scan = NULL; + + kfree(ir_dev); + input_set_drvdata(dev, NULL); } EXPORT_SYMBOL_GPL(ir_input_free); diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 18d3004..ac8ced6 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -37,8 +37,6 @@ struct ir_input_state { /* configuration */ int ir_type; - struct ir_scancode_table keytable; - /* key info */ u32 ir_key; /* ir scancode */ u32 keycode; /* linux key code */ diff --git a/include/media/ir-core.h b/include/media/ir-core.h index 825d04a..ea76c19 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h @@ -41,6 +41,11 @@ struct ir_scancode_table { spinlock_t lock; }; +struct ir_input_dev { + struct input_dev *dev; + struct ir_scancode_table rc_tab; +}; + /* Routines from ir-keytable.c */ u32 ir_g_keycode_from_table(struct input_dev *input_dev, @@ -50,8 +55,8 @@ int ir_set_keycode_table(struct input_dev *input_dev, struct ir_scancode_table *rc_tab); int ir_roundup_tablesize(int n_elems); -int ir_copy_table(struct ir_scancode_table *destin, - const struct ir_scancode_table *origin); +int ir_input_register(struct input_dev *dev, + struct ir_scancode_table *ir_codes); void ir_input_free(struct input_dev *input_dev); #endif -- cgit v0.10.2 From 38ef6aa884e3fd389f7d444b8dd36c16832e36b4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 11 Dec 2009 09:47:42 -0300 Subject: V4L/DVB (13616): IR: rename ir_input_free as ir_input_unregister Now, ir_input_free does more than just freeing the keytab. Better to rename it as ir_input_unregister. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index ddb8a0f..e9c9bd3 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -450,7 +450,7 @@ int ir_input_register(struct input_dev *input_dev, } EXPORT_SYMBOL_GPL(ir_input_register); -void ir_input_free(struct input_dev *dev) +void ir_input_unregister(struct input_dev *dev) { struct ir_input_dev *ir_dev = input_get_drvdata(dev); struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; @@ -467,7 +467,7 @@ void ir_input_free(struct input_dev *dev) kfree(ir_dev); input_set_drvdata(dev, NULL); } -EXPORT_SYMBOL_GPL(ir_input_free); +EXPORT_SYMBOL_GPL(ir_input_unregister); int ir_core_debug; /* ir_debug level (0,1,2) */ EXPORT_SYMBOL_GPL(ir_core_debug); diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index 53e3f2a..34e4e56 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -613,7 +613,7 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) err = input_register_device(input_dev); if (err) { - ir_input_free(input_dev); + ir_input_unregister(input_dev); input_free_device(input_dev); return err; } @@ -623,7 +623,7 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105) { - ir_input_free(dm1105->ir.input_dev); + ir_input_unregister(dm1105->ir.input_dev); input_unregister_device(dm1105->ir.input_dev); } diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 7d193eb..9c9070a 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -286,7 +286,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) return 0; out2: - ir_input_free(input_dev); + ir_input_unregister(input_dev); input_free_device(input_dev); out1: return error; @@ -304,7 +304,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci) del_timer_sync(&dev->timer); ir_input_nokey(dev, &budget_ci->ir.state); - ir_input_free(dev); + ir_input_unregister(dev); input_unregister_device(dev); } diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 84a957e..0e1a7aa 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -403,7 +403,7 @@ int bttv_input_init(struct bttv *btv) bttv_ir_stop(btv); btv->remote = NULL; err_out_free: - ir_input_free(input_dev); + ir_input_unregister(input_dev); input_free_device(input_dev); kfree(ir); return err; @@ -415,7 +415,7 @@ void bttv_input_fini(struct bttv *btv) return; bttv_ir_stop(btv); - ir_input_free(btv->remote->dev); + ir_input_unregister(btv->remote->dev); input_unregister_device(btv->remote->dev); kfree(btv->remote); btv->remote = NULL; diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c index cd135f0..5eba1ec 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/video/cx231xx/cx231xx-input.c @@ -226,7 +226,7 @@ err_out_stop: cx231xx_ir_stop(ir); dev->ir = NULL; err_out_free: - ir_input_free(input_dev); + ir_input_unregister(input_dev); input_free_device(input_dev); kfree(ir); return err; @@ -241,7 +241,7 @@ int cx231xx_ir_fini(struct cx231xx *dev) return 0; cx231xx_ir_stop(ir); - ir_input_free(ir->input); + ir_input_unregister(ir->input); input_unregister_device(ir->input); kfree(ir); diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index 469e083..2a5e4d9 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c @@ -407,7 +407,7 @@ err_out_stop: cx23885_input_ir_stop(dev); dev->ir_input = NULL; err_out_free: - ir_input_free(input_dev); + ir_input_unregister(input_dev); input_free_device(input_dev); kfree(ir); return ret; @@ -420,7 +420,7 @@ void cx23885_input_fini(struct cx23885_dev *dev) if (dev->ir_input == NULL) return; - ir_input_free(dev->ir_input->dev); + ir_input_unregister(dev->ir_input->dev); input_unregister_device(dev->ir_input->dev); kfree(dev->ir_input); dev->ir_input = NULL; diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 92b8cdf..d4dc2c2 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -393,7 +393,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) cx88_ir_stop(core, ir); core->ir = NULL; err_out_free: - ir_input_free(input_dev); + ir_input_unregister(input_dev); input_free_device(input_dev); kfree(ir); return err; @@ -408,7 +408,7 @@ int cx88_ir_fini(struct cx88_core *core) return 0; cx88_ir_stop(core, ir); - ir_input_free(ir->input); + ir_input_unregister(ir->input); input_unregister_device(ir->input); kfree(ir); diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 5ddeb42..9dc4e14 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -422,7 +422,7 @@ int em28xx_ir_init(struct em28xx *dev) em28xx_ir_stop(ir); dev->ir = NULL; err_out_free: - ir_input_free(input_dev); + ir_input_unregister(input_dev); input_free_device(input_dev); kfree(ir); return err; @@ -437,7 +437,7 @@ int em28xx_ir_fini(struct em28xx *dev) return 0; em28xx_ir_stop(ir); - ir_input_free(ir->input); + ir_input_unregister(ir->input); input_unregister_device(ir->input); kfree(ir); diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 2856e78..9d8e78d 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -460,7 +460,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) return 0; err_out_free: - ir_input_free(input_dev); + ir_input_unregister(input_dev); input_free_device(input_dev); kfree(ir); return err; @@ -474,7 +474,7 @@ static int ir_remove(struct i2c_client *client) cancel_delayed_work_sync(&ir->work); /* unregister device */ - ir_input_free(ir->input); + ir_input_unregister(ir->input); input_unregister_device(ir->input); /* free memory */ diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 411a841..5093e7a 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -742,7 +742,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa7134_ir_stop(dev); dev->remote = NULL; err_out_free: - ir_input_free(input_dev); + ir_input_unregister(input_dev); input_free_device(input_dev); kfree(ir); return err; @@ -754,7 +754,7 @@ void saa7134_input_fini(struct saa7134_dev *dev) return; saa7134_ir_stop(dev); - ir_input_free(dev->remote->dev); + ir_input_unregister(dev->remote->dev); input_unregister_device(dev->remote->dev); kfree(dev->remote); dev->remote = NULL; diff --git a/include/media/ir-core.h b/include/media/ir-core.h index ea76c19..299d201 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h @@ -57,6 +57,6 @@ int ir_set_keycode_table(struct input_dev *input_dev, int ir_roundup_tablesize(int n_elems); int ir_input_register(struct input_dev *dev, struct ir_scancode_table *ir_codes); -void ir_input_free(struct input_dev *input_dev); +void ir_input_unregister(struct input_dev *input_dev); #endif -- cgit v0.10.2 From 579e7d60ba0035228aadad69eb2ffeb138c51311 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 11 Dec 2009 11:20:59 -0300 Subject: V4L/DVB (13617): ir: move input_register_device() to happen inside ir_input_register() We'll need to register a sysfs class for the IR devices. As such, the better is to have the input_register_device()/input_unregister_device() inside the ir register/unregister functions. Also, solves a naming problem with V4L ir_input_init() function, that were, in fact, registering a device. While here, do a few cleanups at budget-ci IR logic. Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/IR/ir-functions.c b/drivers/media/IR/ir-functions.c index 7401a79..776a136 100644 --- a/drivers/media/IR/ir-functions.c +++ b/drivers/media/IR/ir-functions.c @@ -52,15 +52,13 @@ static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) /* -------------------------------------------------------------------------- */ int ir_input_init(struct input_dev *dev, struct ir_input_state *ir, - int ir_type, struct ir_scancode_table *ir_codes) + int ir_type) { ir->ir_type = ir_type; if (repeat) set_bit(EV_REP, dev->evbit); - ir_input_register(dev, ir_codes); - return 0; } EXPORT_SYMBOL_GPL(ir_input_init); diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index e9c9bd3..bff7a53 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -12,8 +12,8 @@ * GNU General Public License for more details. */ -#include +#include #include #define IR_TAB_MIN_SIZE 32 @@ -408,7 +408,7 @@ int ir_input_register(struct input_dev *input_dev, { struct ir_input_dev *ir_dev; struct ir_scancode *keymap = rc_tab->scan; - int i; + int i, rc; if (rc_tab->scan == NULL || !rc_tab->size) return -EINVAL; @@ -446,26 +446,34 @@ int ir_input_register(struct input_dev *input_dev, input_dev->setkeycode = ir_setkeycode; input_set_drvdata(input_dev, ir_dev); - return 0; + rc = input_register_device(input_dev); + if (rc < 0) { + kfree(rc_tab->scan); + kfree(ir_dev); + input_set_drvdata(input_dev, NULL); + } + + return rc; } EXPORT_SYMBOL_GPL(ir_input_register); void ir_input_unregister(struct input_dev *dev) { 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; - if (!rc_tab) + if (!ir_dev) return; IR_dprintk(1, "Freed keycode table\n"); + rc_tab = &ir_dev->rc_tab; rc_tab->size = 0; kfree(rc_tab->scan); rc_tab->scan = NULL; kfree(ir_dev); - input_set_drvdata(dev, NULL); + input_unregister_device(dev); } EXPORT_SYMBOL_GPL(ir_input_unregister); diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index 34e4e56..f0f483a 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -589,7 +589,7 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys), "pci-%s/ir0", pci_name(dm1105->pdev)); - err = ir_input_init(input_dev, &dm1105->ir.ir, ir_type, ir_codes); + err = ir_input_init(input_dev, &dm1105->ir.ir, ir_type); if (err < 0) { input_free_device(input_dev); return err; @@ -611,20 +611,14 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) INIT_WORK(&dm1105->ir.work, dm1105_emit_key); - err = input_register_device(input_dev); - if (err) { - ir_input_unregister(input_dev); - input_free_device(input_dev); - return err; - } + err = ir_input_register(input_dev, ir_codes); - return 0; + return err; } void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105) { ir_input_unregister(dm1105->ir.input_dev); - input_unregister_device(dm1105->ir.input_dev); } static int __devinit dm1105dvb_hw_init(struct dm1105dvb *dm1105dvb) diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 9c9070a..9782e05 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -190,12 +190,13 @@ 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; int error; + struct ir_scancode_table *ir_codes; + budget_ci->ir.dev = input_dev = input_allocate_device(); if (!input_dev) { printk(KERN_ERR "budget_ci: IR interface initialisation failed\n"); - error = -ENOMEM; - goto out1; + return -ENOMEM; } snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name), @@ -217,6 +218,11 @@ static int msp430_ir_init(struct budget_ci *budget_ci) } input_dev->dev.parent = &saa->pci->dev; + if (rc5_device < 0) + budget_ci->ir.rc5_device = IR_DEVICE_ANY; + else + budget_ci->ir.rc5_device = rc5_device; + /* Select keymap and address */ switch (budget_ci->budget.dev->pci->subsystem_device) { case 0x100c: @@ -224,53 +230,34 @@ static int msp430_ir_init(struct budget_ci *budget_ci) case 0x1011: case 0x1012: /* The hauppauge keymap is a superset of these remotes */ - error = ir_input_init(input_dev, &budget_ci->ir.state, - IR_TYPE_RC5, &ir_codes_hauppauge_new_table); - if (error < 0) - goto out2; + ir_codes = &ir_codes_hauppauge_new_table; if (rc5_device < 0) budget_ci->ir.rc5_device = 0x1f; - else - budget_ci->ir.rc5_device = rc5_device; break; case 0x1010: case 0x1017: case 0x101a: /* for the Technotrend 1500 bundled remote */ - error = ir_input_init(input_dev, &budget_ci->ir.state, - IR_TYPE_RC5, &ir_codes_tt_1500_table); - if (error < 0) - goto out2; - - if (rc5_device < 0) - budget_ci->ir.rc5_device = IR_DEVICE_ANY; - else - budget_ci->ir.rc5_device = rc5_device; + ir_codes = &ir_codes_tt_1500_table; break; default: /* unknown remote */ - error = ir_input_init(input_dev, &budget_ci->ir.state, - IR_TYPE_RC5, &ir_codes_budget_ci_old_table); - if (error < 0) - goto out2; - - if (rc5_device < 0) - budget_ci->ir.rc5_device = IR_DEVICE_ANY; - else - budget_ci->ir.rc5_device = rc5_device; + ir_codes = &ir_codes_budget_ci_old_table; break; } + ir_input_init(input_dev, &budget_ci->ir.state, IR_TYPE_RC5); + /* initialise the key-up timeout handler */ init_timer(&budget_ci->ir.timer_keyup); budget_ci->ir.timer_keyup.function = msp430_ir_keyup; budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir; budget_ci->ir.last_raw = 0xffff; /* An impossible value */ - error = input_register_device(input_dev); + error = ir_input_register(input_dev, ir_codes); if (error) { printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error); - goto out2; + return error; } /* note: these must be after input_register_device */ @@ -284,12 +271,6 @@ static int msp430_ir_init(struct budget_ci *budget_ci) saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); return 0; - -out2: - ir_input_unregister(input_dev); - input_free_device(input_dev); -out1: - return error; } static void msp430_ir_deinit(struct budget_ci *budget_ci) @@ -305,7 +286,6 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci) ir_input_nokey(dev, &budget_ci->ir.state); ir_input_unregister(dev); - input_unregister_device(dev); } static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 0e1a7aa..277a092 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -368,7 +368,7 @@ 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, ir_codes); + err = ir_input_init(input_dev, &ir->ir, ir_type); if (err < 0) goto err_out_free; @@ -389,7 +389,7 @@ int bttv_input_init(struct bttv *btv) bttv_ir_start(btv, ir); /* all done */ - err = input_register_device(btv->remote->dev); + err = ir_input_register(btv->remote->dev, ir_codes); if (err) goto err_out_stop; @@ -403,8 +403,6 @@ int bttv_input_init(struct bttv *btv) bttv_ir_stop(btv); btv->remote = NULL; err_out_free: - ir_input_unregister(input_dev); - input_free_device(input_dev); kfree(ir); return err; } @@ -416,7 +414,6 @@ void bttv_input_fini(struct bttv *btv) bttv_ir_stop(btv); ir_input_unregister(btv->remote->dev); - input_unregister_device(btv->remote->dev); kfree(btv->remote); btv->remote = NULL; } diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c index 5eba1ec..15826f9 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/video/cx231xx/cx231xx-input.c @@ -197,8 +197,7 @@ int cx231xx_ir_init(struct cx231xx *dev) usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); strlcat(ir->phys, "/input0", sizeof(ir->phys)); - err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER, - dev->board.ir_codes); + err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER); if (err < 0) goto err_out_free; @@ -217,7 +216,7 @@ int cx231xx_ir_init(struct cx231xx *dev) cx231xx_ir_start(ir); /* all done */ - err = input_register_device(ir->input); + err = ir_input_register(ir->input, dev->board.ir_codes); if (err) goto err_out_stop; @@ -226,8 +225,6 @@ err_out_stop: cx231xx_ir_stop(ir); dev->ir = NULL; err_out_free: - ir_input_unregister(input_dev); - input_free_device(input_dev); kfree(ir); return err; } @@ -242,7 +239,6 @@ int cx231xx_ir_fini(struct cx231xx *dev) cx231xx_ir_stop(ir); ir_input_unregister(ir->input); - input_unregister_device(ir->input); kfree(ir); /* done */ diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index 2a5e4d9..768eec9 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c @@ -377,7 +377,7 @@ int cx23885_input_init(struct cx23885_dev *dev) cx23885_boards[dev->board].name); snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci)); - ret = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); + ret = ir_input_init(input_dev, &ir->ir, ir_type); if (ret < 0) goto err_out_free; @@ -397,7 +397,7 @@ int cx23885_input_init(struct cx23885_dev *dev) dev->ir_input = ir; cx23885_input_ir_start(dev); - ret = input_register_device(ir->dev); + ret = ir_input_register(ir->dev, ir_codes); if (ret) goto err_out_stop; @@ -407,8 +407,6 @@ err_out_stop: cx23885_input_ir_stop(dev); dev->ir_input = NULL; err_out_free: - ir_input_unregister(input_dev); - input_free_device(input_dev); kfree(ir); return ret; } @@ -421,7 +419,6 @@ void cx23885_input_fini(struct cx23885_dev *dev) if (dev->ir_input == NULL) return; ir_input_unregister(dev->ir_input->dev); - input_unregister_device(dev->ir_input->dev); kfree(dev->ir_input); dev->ir_input = NULL; } diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index d4dc2c2..f9fda18 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -360,7 +360,7 @@ 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)); - err = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); + err = ir_input_init(input_dev, &ir->ir, ir_type); if (err < 0) goto err_out_free; @@ -383,7 +383,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) cx88_ir_start(core, ir); /* all done */ - err = input_register_device(ir->input); + err = ir_input_register(ir->input, ir_codes); if (err) goto err_out_stop; @@ -393,8 +393,6 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) cx88_ir_stop(core, ir); core->ir = NULL; err_out_free: - ir_input_unregister(input_dev); - input_free_device(input_dev); kfree(ir); return err; } @@ -409,7 +407,6 @@ int cx88_ir_fini(struct cx88_core *core) cx88_ir_stop(core, ir); ir_input_unregister(ir->input); - input_unregister_device(ir->input); kfree(ir); /* done */ diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 9dc4e14..af0d935 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -393,8 +393,7 @@ int em28xx_ir_init(struct em28xx *dev) usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); strlcat(ir->phys, "/input0", sizeof(ir->phys)); - err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER, - dev->board.ir_codes); + err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER); if (err < 0) goto err_out_free; @@ -413,7 +412,7 @@ int em28xx_ir_init(struct em28xx *dev) em28xx_ir_start(ir); /* all done */ - err = input_register_device(ir->input); + err = ir_input_register(ir->input, dev->board.ir_codes); if (err) goto err_out_stop; @@ -422,8 +421,6 @@ int em28xx_ir_init(struct em28xx *dev) em28xx_ir_stop(ir); dev->ir = NULL; err_out_free: - ir_input_unregister(input_dev); - input_free_device(input_dev); kfree(ir); return err; } @@ -438,7 +435,6 @@ int em28xx_ir_fini(struct em28xx *dev) em28xx_ir_stop(ir); ir_input_unregister(ir->input); - input_unregister_device(ir->input); kfree(ir); /* done */ diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 9d8e78d..b86e353 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -438,7 +438,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) dev_name(&client->dev)); /* init + register input device */ - err = ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes); + err = ir_input_init(input_dev, &ir->ir, ir_type); if (err < 0) goto err_out_free; @@ -446,7 +446,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) input_dev->name = ir->name; input_dev->phys = ir->phys; - err = input_register_device(ir->input); + err = ir_input_register(ir->input, ir->ir_codes); if (err) goto err_out_free; @@ -460,8 +460,6 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) return 0; err_out_free: - ir_input_unregister(input_dev); - input_free_device(input_dev); kfree(ir); return err; } @@ -475,7 +473,6 @@ static int ir_remove(struct i2c_client *client) /* unregister device */ ir_input_unregister(ir->input); - input_unregister_device(ir->input); /* free memory */ kfree(ir); diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 5093e7a..f8e9859 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -708,7 +708,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci)); - err = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); + err = ir_input_init(input_dev, &ir->ir, ir_type); if (err < 0) goto err_out_free; @@ -728,7 +728,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) dev->remote = ir; saa7134_ir_start(dev, ir); - err = input_register_device(ir->dev); + err = ir_input_register(ir->dev, ir_codes); if (err) goto err_out_stop; @@ -742,8 +742,6 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa7134_ir_stop(dev); dev->remote = NULL; err_out_free: - ir_input_unregister(input_dev); - input_free_device(input_dev); kfree(ir); return err; } @@ -755,7 +753,6 @@ void saa7134_input_fini(struct saa7134_dev *dev) saa7134_ir_stop(dev); ir_input_unregister(dev->remote->dev); - input_unregister_device(dev->remote->dev); kfree(dev->remote); dev->remote = NULL; } diff --git a/include/media/ir-common.h b/include/media/ir-common.h index ac8ced6..2c6af24 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -84,7 +84,7 @@ struct card_ir { /* Routines from ir-functions.c */ int ir_input_init(struct input_dev *dev, struct ir_input_state *ir, - int ir_type, struct ir_scancode_table *ir_codes); + int 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); -- cgit v0.10.2 From 2e535ed5a16b8cc23301f3d26cfd49f3091aadcc Mon Sep 17 00:00:00 2001 From: Muralidharan Karicheri Date: Thu, 10 Dec 2009 04:39:47 -0300 Subject: V4L/DVB (13618): v4l2: Adding helper function to get dv preset description This patch adds a helper function to get description of a digital video preset added by the video timing API. This will be useful for drivers implementing the above API. Signed-off-by: Muralidharan Karicheri Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index e8e5aff..36b5cb8 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -1024,3 +1024,50 @@ void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax, } } EXPORT_SYMBOL_GPL(v4l_bound_align_image); + +/** + * v4l_fill_dv_preset_info - fill description of a digital video preset + * @preset - preset value + * @info - pointer to struct v4l2_dv_enum_preset + * + * drivers can use this helper function to fill description of dv preset + * in info. + */ +int v4l_fill_dv_preset_info(u32 preset, struct v4l2_dv_enum_preset *info) +{ + static const struct v4l2_dv_preset_info { + u16 width; + u16 height; + const char *name; + } dv_presets[] = { + { 0, 0, "Invalid" }, /* V4L2_DV_INVALID */ + { 720, 480, "480p@59.94" }, /* V4L2_DV_480P59_94 */ + { 720, 576, "576p@50" }, /* V4L2_DV_576P50 */ + { 1280, 720, "720p@24" }, /* V4L2_DV_720P24 */ + { 1280, 720, "720p@25" }, /* V4L2_DV_720P25 */ + { 1280, 720, "720p@30" }, /* V4L2_DV_720P30 */ + { 1280, 720, "720p@50" }, /* V4L2_DV_720P50 */ + { 1280, 720, "720p@59.94" }, /* V4L2_DV_720P59_94 */ + { 1280, 720, "720p@60" }, /* V4L2_DV_720P60 */ + { 1920, 1080, "1080i@29.97" }, /* V4L2_DV_1080I29_97 */ + { 1920, 1080, "1080i@30" }, /* V4L2_DV_1080I30 */ + { 1920, 1080, "1080i@25" }, /* V4L2_DV_1080I25 */ + { 1920, 1080, "1080i@50" }, /* V4L2_DV_1080I50 */ + { 1920, 1080, "1080i@60" }, /* V4L2_DV_1080I60 */ + { 1920, 1080, "1080p@24" }, /* V4L2_DV_1080P24 */ + { 1920, 1080, "1080p@25" }, /* V4L2_DV_1080P25 */ + { 1920, 1080, "1080p@30" }, /* V4L2_DV_1080P30 */ + { 1920, 1080, "1080p@50" }, /* V4L2_DV_1080P50 */ + { 1920, 1080, "1080p@60" }, /* V4L2_DV_1080P60 */ + }; + + if (info == NULL || preset >= ARRAY_SIZE(dv_presets)) + return -EINVAL; + + info->preset = preset; + info->width = dv_presets[preset].width; + info->height = dv_presets[preset].height; + strlcpy(info->name, dv_presets[preset].name, sizeof(info->name)); + return 0; +} +EXPORT_SYMBOL_GPL(v4l_fill_dv_preset_info); diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 1c25b10..1c7b259 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -212,5 +212,5 @@ void v4l_bound_align_image(unsigned int *w, unsigned int wmin, unsigned int *h, unsigned int hmin, unsigned int hmax, unsigned int halign, unsigned int salign); - +int v4l_fill_dv_preset_info(u32 preset, struct v4l2_dv_enum_preset *info); #endif /* V4L2_COMMON_H_ */ -- cgit v0.10.2 From 422eaac5d5367bab71fa2cc33393b2ea894498fe Mon Sep 17 00:00:00 2001 From: Muralidharan Karicheri Date: Thu, 10 Dec 2009 10:31:44 -0300 Subject: V4L/DVB (13619): v4l2-spec: Adds EBUSY error code for S_STD and QUERYSTD ioctls During review of Video Timing API documentation, Hans Verkuil had a comment on adding EBUSY error code for VIDIOC_S_STD and VIDIOC_QUERYSTD ioctls. This patch updates the document for this. Signed-off-by: Muralidharan Karicheri Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/DocBook/v4l/vidioc-g-std.xml b/Documentation/DocBook/v4l/vidioc-g-std.xml index b6f5d26..912f851 100644 --- a/Documentation/DocBook/v4l/vidioc-g-std.xml +++ b/Documentation/DocBook/v4l/vidioc-g-std.xml @@ -86,6 +86,12 @@ standards. VIDIOC_S_STD parameter was unsuitable. + + EBUSY + + The device is busy and therefore can not change the standard + + diff --git a/Documentation/DocBook/v4l/vidioc-querystd.xml b/Documentation/DocBook/v4l/vidioc-querystd.xml index b5a7ff9..1a9e603 100644 --- a/Documentation/DocBook/v4l/vidioc-querystd.xml +++ b/Documentation/DocBook/v4l/vidioc-querystd.xml @@ -70,6 +70,12 @@ current video input or output. This ioctl is not supported. + + EBUSY + + The device is busy and therefore can not detect the standard + + -- cgit v0.10.2 From 37b372e5ebe187037e01885151a0afb546a38520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=83=C2=A1rton=20N=C3=83=C2=A9meth?= Date: Thu, 10 Dec 2009 11:31:09 -0300 Subject: V4L/DVB (13621): gspca - some subdrivers: Make device_table[]s constant. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Márton Németh Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index 2f0b8d6..c98b5d6 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c @@ -1046,14 +1046,14 @@ static struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] __devinitconst = { {USB_DEVICE(0x0572, 0x0041)}, {} }; MODULE_DEVICE_TABLE(usb, device_table); /* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, +static int __devinit sd_probe(struct usb_interface *intf, const struct usb_device_id *id) { return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index 9de8641..fdf4c0ec 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c @@ -864,7 +864,7 @@ static struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] __devinitconst = { {USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106}, #if !defined CONFIG_USB_ET61X251 && !defined CONFIG_USB_ET61X251_MODULE {USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX}, @@ -875,7 +875,7 @@ static __devinitdata struct usb_device_id device_table[] = { MODULE_DEVICE_TABLE(usb, device_table); /* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, +static int __devinit sd_probe(struct usb_interface *intf, const struct usb_device_id *id) { return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index e128514..de0b66c 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -1229,7 +1229,7 @@ static struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] __devinitconst = { {USB_DEVICE(0x06f8, 0x3009)}, {USB_DEVICE(0x093a, 0x2620)}, {USB_DEVICE(0x093a, 0x2621)}, @@ -1245,7 +1245,7 @@ static __devinitdata struct usb_device_id device_table[] = { MODULE_DEVICE_TABLE(usb, device_table); /* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, +static int __devinit sd_probe(struct usb_interface *intf, const struct usb_device_id *id) { return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index e5697a6..42cfcdf 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -863,7 +863,7 @@ static struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] __devinitconst = { {USB_DEVICE(0x093a, 0x2600)}, {USB_DEVICE(0x093a, 0x2601)}, {USB_DEVICE(0x093a, 0x2603)}, @@ -875,7 +875,7 @@ static __devinitdata struct usb_device_id device_table[] = { MODULE_DEVICE_TABLE(usb, device_table); /* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, +static int __devinit sd_probe(struct usb_interface *intf, const struct usb_device_id *id) { return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 5be95bc..ddff2b5 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -1226,7 +1226,7 @@ static const struct sd_desc sd_desc = { .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge -static __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] __devinitconst = { {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)}, /* TAS5110C1B */ {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)}, /* TAS5110C1B */ #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE @@ -1257,7 +1257,7 @@ static __devinitdata struct usb_device_id device_table[] = { MODULE_DEVICE_TABLE(usb, device_table); /* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, +static int __devinit sd_probe(struct usb_interface *intf, const struct usb_device_id *id) { return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index ab28cc2..39257e4 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c @@ -685,7 +685,7 @@ static struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] __devinitconst = { {USB_DEVICE(0x06e1, 0xa190)}, /*fixme: may be IntelPCCameraPro BRIDGE_SPCA505 {USB_DEVICE(0x0733, 0x0430)}, */ @@ -696,7 +696,7 @@ static __devinitdata struct usb_device_id device_table[] = { MODULE_DEVICE_TABLE(usb, device_table); /* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, +static int __devinit sd_probe(struct usb_interface *intf, const struct usb_device_id *id) { return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), -- cgit v0.10.2 From 83955556669f69fccfd332b52e9b1796d60c77bd Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 12 Dec 2009 06:58:01 -0300 Subject: V4L/DVB (13626): gspca - many subdrivers: Fix some warnings. - gl860.c:332:15: warning: cast to restricted __le16 - gl860.c:333:15: warning: cast to restricted __le16 - gl860-mi1320.c:348:5: warning: symbol 'mi1320_camera_settings' was not declared. Should it be static? - gl860-mi2020.c:772:5: warning: symbol 'mi2020_camera_settings' was not declared. Should it be static? - m5602_ov9650.c:444:7: warning: symbol 'data' shadows an earlier one - m5602_core.c:84:5: warning: symbol 'm5602_wait_for_i2c' was not declared. Should it be static? - m5602_core.c:391:6: warning: symbol 'm5602_disconnect' was not declared. Should it be static? - m5602_s5k4aa.c:530:23: warning: dubious: x | !y - m5602_s5k4aa.c:575:23: warning: dubious: x | !y - gspca.c:1196:13: warning: potentially expensive pointer subtraction - mr97310a.c:70:5: warning: symbol 'force_sensor_type' was not declared. Should it be static? - ov519.c:2025:4: warning: do-while statement is not a compound statement - ov519.c:2063:4: warning: do-while statement is not a compound statement - ov519.c:2089:4: warning: do-while statement is not a compound statement - ov519.c:1985:34: warning: incorrect type in assignment (different base types) - sn9c20x.c:1164:5: warning: symbol 'i2c_r1' was not declared. Should it be static? - sn9c20x.c:1189:5: warning: symbol 'i2c_r2' was not declared. Should it be static? - sn9c20x.c:2237:27: warning: right shift by bigger than source value - sn9c20x.c:2237:27: warning: right shift by bigger than source value Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gl860/gl860-mi1320.c b/drivers/media/video/gspca/gl860/gl860-mi1320.c index 1355e52..c276a7d 100644 --- a/drivers/media/video/gspca/gl860/gl860-mi1320.c +++ b/drivers/media/video/gspca/gl860/gl860-mi1320.c @@ -345,7 +345,7 @@ static int mi1320_configure_alt(struct gspca_dev *gspca_dev) return 0; } -int mi1320_camera_settings(struct gspca_dev *gspca_dev) +static int mi1320_camera_settings(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; diff --git a/drivers/media/video/gspca/gl860/gl860-mi2020.c b/drivers/media/video/gspca/gl860/gl860-mi2020.c index 80cb3f1..7c31b4f 100644 --- a/drivers/media/video/gspca/gl860/gl860-mi2020.c +++ b/drivers/media/video/gspca/gl860/gl860-mi2020.c @@ -769,7 +769,7 @@ static int mi2020_configure_alt(struct gspca_dev *gspca_dev) return 0; } -int mi2020_camera_settings(struct gspca_dev *gspca_dev) +static int mi2020_camera_settings(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c index bd3c21a..4878c8f 100644 --- a/drivers/media/video/gspca/gl860/gl860.c +++ b/drivers/media/video/gspca/gl860/gl860.c @@ -40,7 +40,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, static void sd_callback(struct gspca_dev *gspca_dev); static int gl860_guess_sensor(struct gspca_dev *gspca_dev, - s32 vendor_id, s32 product_id); + u16 vendor_id, u16 product_id); /*============================ driver options ==============================*/ @@ -326,11 +326,11 @@ static int sd_config(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; - s32 vendor_id, product_id; + u16 vendor_id, product_id; /* Get USB VendorID and ProductID */ - vendor_id = le16_to_cpu(id->idVendor); - product_id = le16_to_cpu(id->idProduct); + vendor_id = id->idVendor; + product_id = id->idProduct; sd->nbRightUp = 1; sd->nbIm = -1; @@ -673,7 +673,7 @@ void fetch_idxdata(struct gspca_dev *gspca_dev, struct idxdata *tbl, int len) } static int gl860_guess_sensor(struct gspca_dev *gspca_dev, - s32 vendor_id, s32 product_id) + u16 vendor_id, u16 product_id) { struct sd *sd = (struct sd *) gspca_dev; u8 probe, nb26, nb96, nOV, ntry; diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 95a8b84..e930a67 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -1175,12 +1175,14 @@ static int vidioc_queryctrl(struct file *file, void *priv, continue; ctrls = &gspca_dev->sd_desc->ctrls[i]; } + if (ctrls == NULL) + return -EINVAL; } else { ctrls = get_ctrl(gspca_dev, id); + if (ctrls == NULL) + return -EINVAL; i = ctrls - gspca_dev->sd_desc->ctrls; } - if (ctrls == NULL) - return -EINVAL; memcpy(q_ctrl, ctrls, sizeof *q_ctrl); if (gspca_dev->ctrl_inac & (1 << i)) q_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c index 844fc1d..4294c75 100644 --- a/drivers/media/video/gspca/m5602/m5602_core.c +++ b/drivers/media/video/gspca/m5602/m5602_core.c @@ -81,7 +81,7 @@ int m5602_write_bridge(struct sd *sd, const u8 address, const u8 i2c_data) return (err < 0) ? err : 0; } -int m5602_wait_for_i2c(struct sd *sd) +static int m5602_wait_for_i2c(struct sd *sd) { int err; u8 data; @@ -388,7 +388,7 @@ static int m5602_probe(struct usb_interface *intf, THIS_MODULE); } -void m5602_disconnect(struct usb_interface *intf) +static void m5602_disconnect(struct usb_interface *intf) { struct gspca_dev *gspca_dev = usb_get_intfdata(intf); struct sd *sd = (struct sd *) gspca_dev; diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c index c2739d6..923cdd5 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -439,7 +439,7 @@ int ov9650_start(struct sd *sd) err = m5602_write_bridge(sd, res_init_ov9650[i][1], res_init_ov9650[i][2]); else if (res_init_ov9650[i][0] == SENSOR) { - u8 data = res_init_ov9650[i][2]; + data = res_init_ov9650[i][2]; err = m5602_write_sensor(sd, res_init_ov9650[i][1], &data, 1); } diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index a27afeb..aa2f3c7e 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -525,7 +525,10 @@ static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); if (err < 0) return err; - data = (data & 0xfe) | !val; + if (val) + data &= 0xfe; + else + data |= 0x01; err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); return err; } @@ -570,7 +573,10 @@ static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); if (err < 0) return err; - data = (data & 0xfe) | !val; + if (val) + data &= 0xfe; + else + data |= 0x01; err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); return err; } diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index 126d968..9154870 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c @@ -67,7 +67,7 @@ MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver"); MODULE_LICENSE("GPL"); /* global parameters */ -int force_sensor_type = -1; +static int force_sensor_type = -1; module_param(force_sensor_type, int, 0644); MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)"); diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index ad9ec33..b4f9657 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -1982,7 +1982,7 @@ static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n) { int ret; - *((u32 *)sd->gspca_dev.usb_buf) = __cpu_to_le32(value); + *((__le32 *) sd->gspca_dev.usb_buf) = __cpu_to_le32(value); ret = usb_control_msg(sd->gspca_dev.dev, usb_sndctrlpipe(sd->gspca_dev.dev, 0), @@ -2021,9 +2021,9 @@ static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value) if (rc < 0) return rc; - do + do { rc = reg_r(sd, R511_I2C_CTL); - while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ + } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ if (rc < 0) return rc; @@ -2055,9 +2055,9 @@ static int ov511_i2c_r(struct sd *sd, __u8 reg) if (rc < 0) return rc; - do + do { rc = reg_r(sd, R511_I2C_CTL); - while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ + } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ if (rc < 0) return rc; @@ -2081,9 +2081,9 @@ static int ov511_i2c_r(struct sd *sd, __u8 reg) if (rc < 0) return rc; - do + do { rc = reg_r(sd, R511_I2C_CTL); - while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ + } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ if (rc < 0) return rc; diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index a3d8f46..4cff803 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -1158,7 +1158,7 @@ static int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val) return i2c_w(gspca_dev, row); } -int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) +static int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) { struct sd *sd = (struct sd *) gspca_dev; u8 row[8]; @@ -1183,7 +1183,7 @@ int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) return 0; } -int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) +static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) { struct sd *sd = (struct sd *) gspca_dev; u8 row[8]; @@ -2175,8 +2175,7 @@ static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode) } #define HW_WIN(mode, hstart, vstart) \ -((const u8 []){hstart & 0xff, hstart >> 8, \ -vstart & 0xff, vstart >> 8, \ +((const u8 []){hstart, 0, vstart, 0, \ (mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \ (mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)}) -- cgit v0.10.2 From 174c44e4a7d2418e8990c075dd7f5de51699781e Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 12 Dec 2009 13:20:49 -0300 Subject: V4L/DVB (13627): gspca - zc3xx: Set the quality for sensor tas5130c. - setting the quality gives a better brightness Reported-by: Benoit GIRARD Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 1d525c4..1a800fc 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -6919,7 +6919,6 @@ static int sd_start(struct gspca_dev *gspca_dev) switch (sd->sensor) { case SENSOR_OV7620: case SENSOR_PAS202B: - case SENSOR_TAS5130CXX: reg_r(gspca_dev, 0x0180); /* from win */ reg_w(dev, 0x00, 0x0180); break; -- cgit v0.10.2 From 247cb142a924fad215337170a5201a5cf9d960e1 Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Sat, 12 Dec 2009 13:37:44 -0300 Subject: V4L/DVB (13630): Print bitrate measured by stv0900 demod in stv0900_read_status Signed-off-by: Abylay Ospan Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c index df49ea0..8762c86 100644 --- a/drivers/media/dvb/frontends/stv0900_core.c +++ b/drivers/media/dvb/frontends/stv0900_core.c @@ -1451,6 +1451,8 @@ static int stv0900_status(struct stv0900_internal *intp, { enum fe_stv0900_search_state demod_state; int locked = FALSE; + u8 tsbitrate0_val, tsbitrate1_val; + s32 bitrate; demod_state = stv0900_get_bits(intp, HEADER_MODE); switch (demod_state) { @@ -1473,6 +1475,17 @@ static int stv0900_status(struct stv0900_internal *intp, dprintk("%s: locked = %d\n", __func__, locked); + if (stvdebug) { + /* Print TS bitrate */ + tsbitrate0_val = stv0900_read_reg(intp, TSBITRATE0); + tsbitrate1_val = stv0900_read_reg(intp, TSBITRATE1); + /* Formula Bit rate = Mclk * px_tsfifo_bitrate / 16384 */ + bitrate = (stv0900_get_mclk_freq(intp, intp->quartz)/1000000) + * (tsbitrate1_val << 8 | tsbitrate0_val); + bitrate /= 16384; + dprintk("TS bitrate = %d Mbit/sec \n", bitrate); + }; + return locked; } -- cgit v0.10.2 From 4a4bc5e4f976bf00ae3c96b57a5bcead72ade5ea Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 11 Dec 2009 11:06:00 -0300 Subject: V4L/DVB (13642): tw9910: The driver can also handle revision 1 of the chip Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 269ab04..7bf90a2 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c @@ -883,11 +883,12 @@ static int tw9910_video_probe(struct soc_camera_device *icd, /* * check and show Product ID + * So far only revisions 0 and 1 have been seen */ val = i2c_smbus_read_byte_data(client, ID); if (0x0B != GET_ID(val) || - 0x00 != GET_ReV(val)) { + 0x01 < GET_ReV(val)) { dev_err(&client->dev, "Product ID error %x:%x\n", GET_ID(val), GET_ReV(val)); return -ENODEV; -- cgit v0.10.2 From 11e3d1adbe0246fc8d6c06f7e42aff5bead25670 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 11 Dec 2009 11:06:00 -0300 Subject: V4L/DVB (13643): soc-camera: remove no longer needed struct members Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 3d74e60..c5afc8c 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -24,8 +24,6 @@ struct soc_camera_device { struct device *pdev; /* Platform device */ s32 user_width; s32 user_height; - unsigned short width_min; - unsigned short height_min; unsigned short y_skip_top; /* Lines to skip at the top */ unsigned char iface; /* Host number */ unsigned char devnum; /* Device number per host */ -- cgit v0.10.2 From 325361088b73269f4cc96256276a142addbf3454 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 11 Dec 2009 11:14:46 -0300 Subject: V4L/DVB (13644): v4l: add new v4l2-subdev sensor operations, use g_skip_top_lines in soc-camera Introduce new v4l2-subdev sensor operations, move .enum_framesizes() and .enum_frameintervals() methods to it, add a new .g_skip_top_lines() method and switch soc-camera to use it instead of .y_skip_top soc_camera_device member, which can now be removed. Signed-off-by: Guennadi Liakhovetski Reviewed-by: Hans Verkuil Reviewed-by: Sergio Aguirre Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 45388d2..17be2d4 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -82,6 +82,7 @@ struct mt9m001 { int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ unsigned int gain; unsigned int exposure; + unsigned short y_skip_top; /* Lines to skip at the top */ unsigned char autoexposure; }; @@ -222,7 +223,7 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) soc_camera_limit_side(&rect.top, &rect.height, MT9M001_ROW_SKIP, MT9M001_MIN_HEIGHT, MT9M001_MAX_HEIGHT); - total_h = rect.height + icd->y_skip_top + vblank; + total_h = rect.height + mt9m001->y_skip_top + vblank; /* Blanking and start values - default... */ ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank); @@ -239,7 +240,7 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) ret = reg_write(client, MT9M001_WINDOW_WIDTH, rect.width - 1); if (!ret) ret = reg_write(client, MT9M001_WINDOW_HEIGHT, - rect.height + icd->y_skip_top - 1); + rect.height + mt9m001->y_skip_top - 1); if (!ret && mt9m001->autoexposure) { ret = reg_write(client, MT9M001_SHUTTER_WIDTH, total_h); if (!ret) { @@ -327,13 +328,13 @@ static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct i2c_client *client = sd->priv; - struct soc_camera_device *icd = client->dev.platform_data; + struct mt9m001 *mt9m001 = to_mt9m001(client); struct v4l2_pix_format *pix = &f->fmt.pix; v4l_bound_align_image(&pix->width, MT9M001_MIN_WIDTH, MT9M001_MAX_WIDTH, 1, - &pix->height, MT9M001_MIN_HEIGHT + icd->y_skip_top, - MT9M001_MAX_HEIGHT + icd->y_skip_top, 0, 0); + &pix->height, MT9M001_MIN_HEIGHT + mt9m001->y_skip_top, + MT9M001_MAX_HEIGHT + mt9m001->y_skip_top, 0, 0); if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8 || pix->pixelformat == V4L2_PIX_FMT_SBGGR16) @@ -552,7 +553,7 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (ctrl->value) { const u16 vblank = 25; unsigned int total_h = mt9m001->rect.height + - icd->y_skip_top + vblank; + mt9m001->y_skip_top + vblank; if (reg_write(client, MT9M001_SHUTTER_WIDTH, total_h) < 0) return -EIO; @@ -655,6 +656,16 @@ static void mt9m001_video_remove(struct soc_camera_device *icd) icl->free_bus(icl); } +static int mt9m001_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines) +{ + struct i2c_client *client = sd->priv; + struct mt9m001 *mt9m001 = to_mt9m001(client); + + *lines = mt9m001->y_skip_top; + + return 0; +} + static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = { .g_ctrl = mt9m001_g_ctrl, .s_ctrl = mt9m001_s_ctrl, @@ -675,9 +686,14 @@ static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { .cropcap = mt9m001_cropcap, }; +static struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = { + .g_skip_top_lines = mt9m001_g_skip_top_lines, +}; + static struct v4l2_subdev_ops mt9m001_subdev_ops = { .core = &mt9m001_subdev_core_ops, .video = &mt9m001_subdev_video_ops, + .sensor = &mt9m001_subdev_sensor_ops, }; static int mt9m001_probe(struct i2c_client *client, @@ -714,8 +730,8 @@ static int mt9m001_probe(struct i2c_client *client, /* Second stage probe - when a capture adapter is there */ icd->ops = &mt9m001_ops; - icd->y_skip_top = 0; + mt9m001->y_skip_top = 0; mt9m001->rect.left = MT9M001_COLUMN_SKIP; mt9m001->rect.top = MT9M001_ROW_SKIP; mt9m001->rect.width = MT9M001_MAX_WIDTH; diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index 90da699..30db625 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c @@ -1019,7 +1019,6 @@ static int mt9m111_probe(struct i2c_client *client, /* Second stage probe - when a capture adapter is there */ icd->ops = &mt9m111_ops; - icd->y_skip_top = 0; mt9m111->rect.left = MT9M111_MIN_DARK_COLS; mt9m111->rect.top = MT9M111_MIN_DARK_ROWS; diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index 6966f64..1adbb7b 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c @@ -74,6 +74,7 @@ struct mt9t031 { u16 xskip; u16 yskip; unsigned int gain; + unsigned short y_skip_top; /* Lines to skip at the top */ unsigned int exposure; unsigned char autoexposure; }; @@ -301,9 +302,9 @@ static int mt9t031_set_params(struct soc_camera_device *icd, ret = reg_write(client, MT9T031_WINDOW_WIDTH, rect->width - 1); if (ret >= 0) ret = reg_write(client, MT9T031_WINDOW_HEIGHT, - rect->height + icd->y_skip_top - 1); + rect->height + mt9t031->y_skip_top - 1); if (ret >= 0 && mt9t031->autoexposure) { - unsigned int total_h = rect->height + icd->y_skip_top + vblank; + unsigned int total_h = rect->height + mt9t031->y_skip_top + vblank; ret = set_shutter(client, total_h); if (ret >= 0) { const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; @@ -657,7 +658,7 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) const u16 vblank = MT9T031_VERTICAL_BLANK; const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; unsigned int total_h = mt9t031->rect.height + - icd->y_skip_top + vblank; + mt9t031->y_skip_top + vblank; if (set_shutter(client, total_h) < 0) return -EIO; @@ -714,6 +715,16 @@ static int mt9t031_video_probe(struct i2c_client *client) return ret; } +static int mt9t031_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines) +{ + struct i2c_client *client = sd->priv; + struct mt9t031 *mt9t031 = to_mt9t031(client); + + *lines = mt9t031->y_skip_top; + + return 0; +} + static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { .g_ctrl = mt9t031_g_ctrl, .s_ctrl = mt9t031_s_ctrl, @@ -734,9 +745,14 @@ static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { .cropcap = mt9t031_cropcap, }; +static struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = { + .g_skip_top_lines = mt9t031_g_skip_top_lines, +}; + static struct v4l2_subdev_ops mt9t031_subdev_ops = { .core = &mt9t031_subdev_core_ops, .video = &mt9t031_subdev_video_ops, + .sensor = &mt9t031_subdev_sensor_ops, }; static int mt9t031_probe(struct i2c_client *client, @@ -773,8 +789,8 @@ static int mt9t031_probe(struct i2c_client *client, /* Second stage probe - when a capture adapter is there */ icd->ops = &mt9t031_ops; - icd->y_skip_top = 0; + mt9t031->y_skip_top = 0; mt9t031->rect.left = MT9T031_COLUMN_SKIP; mt9t031->rect.top = MT9T031_ROW_SKIP; mt9t031->rect.width = MT9T031_MAX_WIDTH; diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 995607f..b71898f 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -97,6 +97,7 @@ struct mt9v022 { __u32 fourcc; int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ u16 chip_control; + unsigned short y_skip_top; /* Lines to skip at the top */ }; static struct mt9v022 *to_mt9v022(const struct i2c_client *client) @@ -265,7 +266,6 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) struct i2c_client *client = sd->priv; struct mt9v022 *mt9v022 = to_mt9v022(client); struct v4l2_rect rect = a->c; - struct soc_camera_device *icd = client->dev.platform_data; int ret; /* Bayer format - even size lengths */ @@ -287,10 +287,10 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) if (ret >= 0) { if (ret & 1) /* Autoexposure */ ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, - rect.height + icd->y_skip_top + 43); + rect.height + mt9v022->y_skip_top + 43); else ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, - rect.height + icd->y_skip_top + 43); + rect.height + mt9v022->y_skip_top + 43); } /* Setup frame format: defaults apart from width and height */ if (!ret) @@ -309,7 +309,7 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect.width); if (!ret) ret = reg_write(client, MT9V022_WINDOW_HEIGHT, - rect.height + icd->y_skip_top); + rect.height + mt9v022->y_skip_top); if (ret < 0) return ret; @@ -410,15 +410,15 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) static int mt9v022_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct i2c_client *client = sd->priv; - struct soc_camera_device *icd = client->dev.platform_data; + struct mt9v022 *mt9v022 = to_mt9v022(client); struct v4l2_pix_format *pix = &f->fmt.pix; int align = pix->pixelformat == V4L2_PIX_FMT_SBGGR8 || pix->pixelformat == V4L2_PIX_FMT_SBGGR16; v4l_bound_align_image(&pix->width, MT9V022_MIN_WIDTH, MT9V022_MAX_WIDTH, align, - &pix->height, MT9V022_MIN_HEIGHT + icd->y_skip_top, - MT9V022_MAX_HEIGHT + icd->y_skip_top, align, 0); + &pix->height, MT9V022_MIN_HEIGHT + mt9v022->y_skip_top, + MT9V022_MAX_HEIGHT + mt9v022->y_skip_top, align, 0); return 0; } @@ -787,6 +787,16 @@ static void mt9v022_video_remove(struct soc_camera_device *icd) icl->free_bus(icl); } +static int mt9v022_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines) +{ + struct i2c_client *client = sd->priv; + struct mt9v022 *mt9v022 = to_mt9v022(client); + + *lines = mt9v022->y_skip_top; + + return 0; +} + static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = { .g_ctrl = mt9v022_g_ctrl, .s_ctrl = mt9v022_s_ctrl, @@ -807,9 +817,14 @@ static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = { .cropcap = mt9v022_cropcap, }; +static struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = { + .g_skip_top_lines = mt9v022_g_skip_top_lines, +}; + static struct v4l2_subdev_ops mt9v022_subdev_ops = { .core = &mt9v022_subdev_core_ops, .video = &mt9v022_subdev_video_ops, + .sensor = &mt9v022_subdev_sensor_ops, }; static int mt9v022_probe(struct i2c_client *client, @@ -851,8 +866,7 @@ static int mt9v022_probe(struct i2c_client *client, * MT9V022 _really_ corrupts the first read out line. * TODO: verify on i.MX31 */ - icd->y_skip_top = 1; - + mt9v022->y_skip_top = 1; mt9v022->rect.left = MT9V022_COLUMN_SKIP; mt9v022->rect.top = MT9V022_ROW_SKIP; mt9v022->rect.width = MT9V022_MAX_WIDTH; diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 51b683c..4df09a6 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -1051,8 +1051,13 @@ static void pxa_camera_setup_cicr(struct soc_camera_device *icd, { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); unsigned long dw, bpp; - u32 cicr0, cicr1, cicr2, cicr3, cicr4 = 0; + u32 cicr0, cicr1, cicr2, cicr3, cicr4 = 0, y_skip_top; + int ret = v4l2_subdev_call(sd, sensor, g_skip_top_lines, &y_skip_top); + + if (ret < 0) + y_skip_top = 0; /* Datawidth is now guaranteed to be equal to one of the three values. * We fix bit-per-pixel equal to data-width... */ @@ -1118,7 +1123,7 @@ static void pxa_camera_setup_cicr(struct soc_camera_device *icd, cicr2 = 0; cicr3 = CICR3_LPF_VAL(icd->user_height - 1) | - CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); + CICR3_BFW_VAL(min((u32)255, y_skip_top)); cicr4 |= pcdev->mclk_divisor; __raw_writel(cicr1, pcdev->base + CICR1); diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c index b6a575c..c7c9151 100644 --- a/drivers/media/video/soc_camera_platform.c +++ b/drivers/media/video/soc_camera_platform.c @@ -128,7 +128,6 @@ static int soc_camera_platform_probe(struct platform_device *pdev) /* Set the control device reference */ dev_set_drvdata(&icd->dev, &pdev->dev); - icd->y_skip_top = 0; icd->ops = &soc_camera_platform_ops; ici = to_soc_camera_host(icd->dev.parent); diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index c5afc8c..218639f 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -24,7 +24,6 @@ struct soc_camera_device { struct device *pdev; /* Platform device */ s32 user_width; s32 user_height; - unsigned short y_skip_top; /* Lines to skip at the top */ unsigned char iface; /* Host number */ unsigned char devnum; /* Device number per host */ unsigned char buswidth; /* See comment in .c */ diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 7a3408f..a128458 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -263,6 +263,17 @@ struct v4l2_subdev_video_ops { struct v4l2_dv_timings *timings); }; +/** + * struct v4l2_subdev_sensor_ops - v4l2-subdev sensor operations + * @g_skip_top_lines: number of lines at the top of the image to be skipped. + * This is needed for some sensors, which always corrupt + * several top lines of the output image, or which send their + * metadata in them. + */ +struct v4l2_subdev_sensor_ops { + int (*g_skip_top_lines)(struct v4l2_subdev *sd, u32 *lines); +}; + /* interrupt_service_routine: Called by the bridge chip's interrupt service handler, when an IR interrupt status has be raised due to this subdev, @@ -347,11 +358,12 @@ struct v4l2_subdev_ir_ops { }; struct v4l2_subdev_ops { - const struct v4l2_subdev_core_ops *core; - const struct v4l2_subdev_tuner_ops *tuner; - const struct v4l2_subdev_audio_ops *audio; - const struct v4l2_subdev_video_ops *video; - const struct v4l2_subdev_ir_ops *ir; + const struct v4l2_subdev_core_ops *core; + const struct v4l2_subdev_tuner_ops *tuner; + const struct v4l2_subdev_audio_ops *audio; + const struct v4l2_subdev_video_ops *video; + const struct v4l2_subdev_ir_ops *ir; + const struct v4l2_subdev_sensor_ops *sensor; }; #define V4L2_SUBDEV_NAME_SIZE 32 -- cgit v0.10.2 From 5d28d525452f170e30bc038955439731462a5228 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 11 Dec 2009 11:15:05 -0300 Subject: V4L/DVB (13645): soc-camera: fix multi-line comment coding style Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 17be2d4..cc90660 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -17,9 +17,11 @@ #include #include -/* mt9m001 i2c address 0x5d +/* + * mt9m001 i2c address 0x5d * The platform has to define ctruct i2c_board_info objects and link to them - * from struct soc_camera_link */ + * from struct soc_camera_link + */ /* mt9m001 selected register addresses */ #define MT9M001_CHIP_VERSION 0x00 @@ -47,8 +49,10 @@ #define MT9M001_ROW_SKIP 12 static const struct soc_camera_data_format mt9m001_colour_formats[] = { - /* Order important: first natively supported, - * second supported with a GPIO extender */ + /* + * Order important: first natively supported, + * second supported with a GPIO extender + */ { .name = "Bayer (sRGB) 10 bit", .depth = 10, @@ -230,8 +234,10 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) if (!ret) ret = reg_write(client, MT9M001_VERTICAL_BLANKING, vblank); - /* The caller provides a supported format, as verified per - * call to icd->try_fmt() */ + /* + * The caller provides a supported format, as verified per + * call to icd->try_fmt() + */ if (!ret) ret = reg_write(client, MT9M001_COLUMN_START, rect.left); if (!ret) @@ -569,8 +575,10 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return 0; } -/* Interface active, can use i2c. If it fails, it can indeed mean, that - * this wasn't our capture interface, so, we wait for the right one */ +/* + * Interface active, can use i2c. If it fails, it can indeed mean, that + * this wasn't our capture interface, so, we wait for the right one + */ static int mt9m001_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { @@ -580,8 +588,10 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, unsigned long flags; int ret; - /* We must have a parent by now. And it cannot be a wrong one. - * So this entire test is completely redundant. */ + /* + * 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) return -ENODEV; @@ -737,8 +747,10 @@ static int mt9m001_probe(struct i2c_client *client, mt9m001->rect.width = MT9M001_MAX_WIDTH; mt9m001->rect.height = MT9M001_MAX_HEIGHT; - /* Simulated autoexposure. If enabled, we calculate shutter width - * ourselves in the driver based on vertical blanking and frame width */ + /* + * Simulated autoexposure. If enabled, we calculate shutter width + * ourselves in the driver based on vertical blanking and frame width + */ mt9m001->autoexposure = 1; ret = mt9m001_video_probe(icd, client); diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index 1adbb7b..e3f664f 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c @@ -17,9 +17,11 @@ #include #include -/* mt9t031 i2c address 0x5d +/* + * mt9t031 i2c address 0x5d * The platform has to define i2c_board_info and link to it from - * struct soc_camera_link */ + * struct soc_camera_link + */ /* mt9t031 selected register addresses */ #define MT9T031_CHIP_VERSION 0x00 @@ -292,8 +294,10 @@ static int mt9t031_set_params(struct soc_camera_device *icd, dev_dbg(&client->dev, "new physical left %u, top %u\n", rect->left, rect->top); - /* The caller provides a supported format, as guaranteed by - * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */ + /* + * The caller provides a supported format, as guaranteed by + * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() + */ if (ret >= 0) ret = reg_write(client, MT9T031_COLUMN_START, rect->left); if (ret >= 0) @@ -674,8 +678,10 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return 0; } -/* Interface active, can use i2c. If it fails, it can indeed mean, that - * this wasn't our capture interface, so, we wait for the right one */ +/* + * Interface active, can use i2c. If it fails, it can indeed mean, that + * this wasn't our capture interface, so, we wait for the right one + */ static int mt9t031_video_probe(struct i2c_client *client) { struct soc_camera_device *icd = client->dev.platform_data; @@ -796,8 +802,10 @@ static int mt9t031_probe(struct i2c_client *client, mt9t031->rect.width = MT9T031_MAX_WIDTH; mt9t031->rect.height = MT9T031_MAX_HEIGHT; - /* Simulated autoexposure. If enabled, we calculate shutter width - * ourselves in the driver based on vertical blanking and frame width */ + /* + * Simulated autoexposure. If enabled, we calculate shutter width + * ourselves in the driver based on vertical blanking and frame width + */ mt9t031->autoexposure = 1; mt9t031->xskip = 1; diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index b71898f..f60a9a1 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -18,9 +18,11 @@ #include #include -/* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c +/* + * mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c * The platform has to define ctruct i2c_board_info objects and link to them - * from struct soc_camera_link */ + * from struct soc_camera_link + */ static char *sensor_type; module_param(sensor_type, charp, S_IRUGO); @@ -63,8 +65,10 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\""); #define MT9V022_ROW_SKIP 4 static const struct soc_camera_data_format mt9v022_colour_formats[] = { - /* Order important: first natively supported, - * second supported with a GPIO extender */ + /* + * Order important: first natively supported, + * second supported with a GPIO extender + */ { .name = "Bayer (sRGB) 10 bit", .depth = 10, @@ -144,9 +148,11 @@ static int mt9v022_init(struct i2c_client *client) struct mt9v022 *mt9v022 = to_mt9v022(client); int ret; - /* Almost the default mode: master, parallel, simultaneous, and an + /* + * Almost the default mode: master, parallel, simultaneous, and an * undocumented bit 0x200, which is present in table 7, but not in 8, - * plus snapshot mode to disable scan for now */ + * plus snapshot mode to disable scan for now + */ mt9v022->chip_control |= 0x10; ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control); if (!ret) @@ -298,8 +304,10 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) if (!ret) ret = reg_write(client, MT9V022_ROW_START, rect.top); if (!ret) - /* Default 94, Phytec driver says: - * "width + horizontal blank >= 660" */ + /* + * Default 94, Phytec driver says: + * "width + horizontal blank >= 660" + */ ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING, rect.width > 660 - 43 ? 43 : 660 - rect.width); @@ -376,8 +384,10 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) }; int ret; - /* The caller provides a supported format, as verified per call to - * icd->try_fmt(), datawidth is from our supported format list */ + /* + * The caller provides a supported format, as verified per call to + * icd->try_fmt(), datawidth is from our supported format list + */ switch (pix->pixelformat) { case V4L2_PIX_FMT_GREY: case V4L2_PIX_FMT_Y16: @@ -635,8 +645,10 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 48 + range / 2) / range + 16; if (gain >= 32) gain &= ~1; - /* The user wants to set gain manually, hope, she - * knows, what she's doing... Switch AGC off. */ + /* + * The user wants to set gain manually, hope, she + * knows, what she's doing... Switch AGC off. + */ if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0) return -EIO; @@ -655,8 +667,10 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) unsigned long range = qctrl->maximum - qctrl->minimum; unsigned long shutter = ((ctrl->value - qctrl->minimum) * 479 + range / 2) / range + 1; - /* The user wants to set shutter width manually, hope, - * she knows, what she's doing... Switch AEC off. */ + /* + * The user wants to set shutter width manually, hope, + * she knows, what she's doing... Switch AEC off. + */ if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1) < 0) return -EIO; @@ -689,8 +703,10 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return 0; } -/* Interface active, can use i2c. If it fails, it can indeed mean, that - * this wasn't our capture interface, so, we wait for the right one */ +/* + * Interface active, can use i2c. If it fails, it can indeed mean, that + * this wasn't our capture interface, so, we wait for the right one + */ static int mt9v022_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c index 7280229..4c1a439 100644 --- a/drivers/media/video/mx1_camera.c +++ b/drivers/media/video/mx1_camera.c @@ -99,9 +99,11 @@ struct mx1_buffer { int inwork; }; -/* i.MX1/i.MXL is only supposed to handle one camera on its Camera Sensor +/* + * i.MX1/i.MXL is only supposed to handle one camera on its Camera Sensor * Interface. If anyone ever builds hardware to enable more than - * one camera, they will have to modify this driver too */ + * one camera, they will have to modify this driver too + */ struct mx1_camera_dev { struct soc_camera_host soc_host; struct soc_camera_device *icd; @@ -151,8 +153,10 @@ static void free_buffer(struct videobuf_queue *vq, struct mx1_buffer *buf) dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); - /* This waits until this buffer is out of danger, i.e., until it is no - * longer in STATE_QUEUED or STATE_ACTIVE */ + /* + * This waits until this buffer is out of danger, i.e., until it is no + * longer in STATE_QUEUED or STATE_ACTIVE + */ videobuf_waiton(vb, 0, 0); videobuf_dma_contig_free(vq, vb); @@ -174,8 +178,10 @@ static int mx1_videobuf_prepare(struct videobuf_queue *vq, BUG_ON(NULL == icd->current_fmt); - /* I think, in buf_prepare you only have to protect global data, - * the actual buffer is yours */ + /* + * I think, in buf_prepare you only have to protect global data, + * the actual buffer is yours + */ buf->inwork = 1; if (buf->fmt != icd->current_fmt || @@ -381,8 +387,10 @@ static int mclk_get_divisor(struct mx1_camera_dev *pcdev) lcdclk = clk_get_rate(pcdev->clk); - /* We verify platform_mclk_10khz != 0, so if anyone breaks it, here - * they get a nice Oops */ + /* + * We verify platform_mclk_10khz != 0, so if anyone breaks it, here + * they get a nice Oops + */ div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1; dev_dbg(pcdev->icd->dev.parent, @@ -420,8 +428,10 @@ static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev) clk_disable(pcdev->clk); } -/* The following two functions absolutely depend on the fact, that - * there can be only one camera on i.MX1/i.MXL camera sensor interface */ +/* + * The following two functions absolutely depend on the fact, that + * there can be only one camera on i.MX1/i.MXL camera sensor interface + */ static int mx1_camera_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); @@ -578,10 +588,12 @@ static int mx1_camera_reqbufs(struct soc_camera_file *icf, { int i; - /* This is for locking debugging only. I removed spinlocks and now I + /* + * This is for locking debugging only. I removed spinlocks and now I * check whether .prepare is ever called on a linked buffer, or whether * a dma IRQ can occur for an in-work or unlinked buffer. Until now - * it hadn't triggered */ + * it hadn't triggered + */ for (i = 0; i < p->count; i++) { struct mx1_buffer *buf = container_of(icf->vb_vidq.bufs[i], struct mx1_buffer, vb); diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index 7db82bd..ae7d483 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c @@ -564,8 +564,10 @@ static int test_platform_param(struct mx3_camera_dev *mx3_cam, SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_LOW; - /* If requested data width is supported by the platform, use it or any - * possible lower value - i.MX31 is smart enough to schift bits */ + /* + * If requested data width is supported by the platform, use it or any + * possible lower value - i.MX31 is smart enough to schift bits + */ switch (buswidth) { case 15: if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15)) @@ -1027,8 +1029,10 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; } - /* Make the camera work in widest common mode, we'll take care of - * the rest */ + /* + * Make the camera work in widest common mode, we'll take care of + * the rest + */ if (common_flags & SOCAM_DATAWIDTH_15) common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) | SOCAM_DATAWIDTH_15; @@ -1152,8 +1156,10 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev) if (!(mx3_cam->platform_flags & (MX3_CAMERA_DATAWIDTH_4 | MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10 | MX3_CAMERA_DATAWIDTH_15))) { - /* Platform hasn't set available data widths. This is bad. - * Warn and use a default. */ + /* + * Platform hasn't set available data widths. This is bad. + * Warn and use a default. + */ dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " "data widths, using default 8 bit\n"); mx3_cam->platform_flags |= MX3_CAMERA_DATAWIDTH_8; diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 4df09a6..f063f59 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -197,9 +197,11 @@ struct pxa_buffer { struct pxa_camera_dev { struct soc_camera_host soc_host; - /* PXA27x is only supposed to handle one camera on its Quick Capture + /* + * PXA27x is only supposed to handle one camera on its Quick Capture * interface. If anyone ever builds hardware to enable more than - * one camera, they will have to modify this driver too */ + * one camera, they will have to modify this driver too + */ struct soc_camera_device *icd; struct clk *clk; @@ -267,8 +269,10 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, &buf->vb, buf->vb.baddr, buf->vb.bsize); - /* This waits until this buffer is out of danger, i.e., until it is no - * longer in STATE_QUEUED or STATE_ACTIVE */ + /* + * This waits until this buffer is out of danger, i.e., until it is no + * longer in STATE_QUEUED or STATE_ACTIVE + */ videobuf_waiton(&buf->vb, 0, 0); videobuf_dma_unmap(vq, dma); videobuf_dma_free(dma); @@ -437,15 +441,19 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, WARN_ON(!list_empty(&vb->queue)); #ifdef DEBUG - /* This can be useful if you want to see if we actually fill - * the buffer with something */ + /* + * This can be useful if you want to see if we actually fill + * the buffer with something + */ memset((void *)vb->baddr, 0xaa, vb->bsize); #endif BUG_ON(NULL == icd->current_fmt); - /* I think, in buf_prepare you only have to protect global data, - * the actual buffer is yours */ + /* + * I think, in buf_prepare you only have to protect global data, + * the actual buffer is yours + */ buf->inwork = 1; if (buf->fmt != icd->current_fmt || @@ -834,8 +842,10 @@ static void pxa_camera_init_videobuf(struct videobuf_queue *q, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; - /* We must pass NULL as dev pointer, then all pci_* dma operations - * transform to normal dma_* ones. */ + /* + * We must pass NULL as dev pointer, then all pci_* dma operations + * transform to normal dma_* ones. + */ videobuf_queue_sg_init(q, &pxa_videobuf_ops, NULL, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, sizeof(struct pxa_buffer), icd); @@ -1059,8 +1069,10 @@ static void pxa_camera_setup_cicr(struct soc_camera_device *icd, if (ret < 0) y_skip_top = 0; - /* Datawidth is now guaranteed to be equal to one of the three values. - * We fix bit-per-pixel equal to data-width... */ + /* + * Datawidth is now guaranteed to be equal to one of the three values. + * We fix bit-per-pixel equal to data-width... + */ switch (flags & SOCAM_DATAWIDTH_MASK) { case SOCAM_DATAWIDTH_10: dw = 4; @@ -1071,8 +1083,10 @@ static void pxa_camera_setup_cicr(struct soc_camera_device *icd, bpp = 0x20; break; default: - /* Actually it can only be 8 now, - * default is just to silence compiler warnings */ + /* + * Actually it can only be 8 now, + * default is just to silence compiler warnings + */ case SOCAM_DATAWIDTH_8: dw = 2; bpp = 0; @@ -1524,10 +1538,12 @@ static int pxa_camera_reqbufs(struct soc_camera_file *icf, { int i; - /* This is for locking debugging only. I removed spinlocks and now I + /* + * This is for locking debugging only. I removed spinlocks and now I * check whether .prepare is ever called on a linked buffer, or whether * a dma IRQ can occur for an in-work or unlinked buffer. Until now - * it hadn't triggered */ + * it hadn't triggered + */ for (i = 0; i < p->count; i++) { struct pxa_buffer *buf = container_of(icf->vb_vidq.bufs[i], struct pxa_buffer, vb); @@ -1662,8 +1678,10 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev) pcdev->platform_flags = pcdev->pdata->flags; if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 | PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) { - /* Platform hasn't set available data widths. This is bad. - * Warn and use a default. */ + /* + * Platform hasn't set available data widths. This is bad. + * Warn and use a default. + */ dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " "data widths, using default 10 bit\n"); pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10; diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 7509990..3271944 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -252,7 +252,8 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) u32 status; int ret = 0; - /* The hardware is _very_ picky about this sequence. Especially + /* + * The hardware is _very_ picky about this sequence. Especially * the CEU_CETCR_MAGIC value. It seems like we need to acknowledge * several not-so-well documented interrupt sources in CETCR. */ @@ -321,8 +322,10 @@ static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq, WARN_ON(!list_empty(&vb->queue)); #ifdef DEBUG - /* This can be useful if you want to see if we actually fill - * the buffer with something */ + /* + * This can be useful if you want to see if we actually fill + * the buffer with something + */ memset((void *)vb->baddr, 0xaa, vb->bsize); #endif @@ -709,7 +712,8 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CFLCR, pcdev->cflcr); - /* A few words about byte order (observed in Big Endian mode) + /* + * A few words about byte order (observed in Big Endian mode) * * In data fetch mode bytes are received in chunks of 8 bytes. * D0, D1, D2, D3, D4, D5, D6, D7 (D0 received first) @@ -1573,10 +1577,12 @@ static int sh_mobile_ceu_reqbufs(struct soc_camera_file *icf, { int i; - /* This is for locking debugging only. I removed spinlocks and now I + /* + * This is for locking debugging only. I removed spinlocks and now I * check whether .prepare is ever called on a linked buffer, or whether * a dma IRQ can occur for an in-work or unlinked buffer. Until now - * it hadn't triggered */ + * it hadn't triggered + */ for (i = 0; i < p->count; i++) { struct sh_mobile_ceu_buffer *buf; diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 804c675..5fdedc7 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -621,8 +621,10 @@ static int soc_camera_streamoff(struct file *file, void *priv, 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 */ + /* + * This calls buf_release from host driver's videobuf_queue_ops for all + * remaining buffers. When the last buffer is freed, stop capture + */ videobuf_streamoff(&icf->vb_vidq); v4l2_subdev_call(sd, video, s_stream, 0); @@ -1004,8 +1006,10 @@ epower: return ret; } -/* This is called on device_unregister, which only means we have to disconnect - * from the host, but not remove ourselves from the device list */ +/* + * This is called on device_unregister, which only means we have to disconnect + * from the host, but not remove ourselves from the device list + */ static int soc_camera_remove(struct device *dev) { struct soc_camera_device *icd = to_soc_camera_dev(dev); @@ -1205,8 +1209,10 @@ static int soc_camera_device_register(struct soc_camera_device *icd) } if (num < 0) - /* ok, we have 256 cameras on this host... - * man, stay reasonable... */ + /* + * ok, we have 256 cameras on this host... + * man, stay reasonable... + */ return -ENOMEM; icd->devnum = num; @@ -1333,9 +1339,11 @@ escdevreg: return ret; } -/* Only called on rmmod for each platform device, since they are not +/* + * Only called on rmmod for each platform device, since they are not * hot-pluggable. Now we know, that all our users - hosts and devices have - * been unloaded already */ + * been unloaded already + */ static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) { struct soc_camera_device *icd = platform_get_drvdata(pdev); diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 7bf90a2..3cb9ba6 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c @@ -180,9 +180,8 @@ */ /* VBICNTL */ -/* RTSEL : control the real time signal -* output from the MPOUT pin -*/ + +/* RTSEL : control the real time signal output from the MPOUT pin */ #define RTSEL_MASK 0x07 #define RTSEL_VLOSS 0x00 /* 0000 = Video loss */ #define RTSEL_HLOCK 0x01 /* 0001 = H-lock */ @@ -596,7 +595,8 @@ static int tw9910_g_register(struct v4l2_subdev *sd, if (ret < 0) return ret; - /* ret = int + /* + * ret = int * reg->val = __u64 */ reg->val = (__u64)ret; diff --git a/include/media/ov772x.h b/include/media/ov772x.h index 30d9629..37bcd09 100644 --- a/include/media/ov772x.h +++ b/include/media/ov772x.h @@ -1,4 +1,5 @@ -/* ov772x Camera +/* + * ov772x Camera * * Copyright (C) 2008 Renesas Solutions Corp. * Kuninori Morimoto -- cgit v0.10.2 From 6ed7c03884ee7c05ff880cafb46ae20915e22e3c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 11 Dec 2009 11:15:06 -0300 Subject: V4L/DVB (13646): sh_mobile_ceu_camera: do not mark host occupied, when adding a client fails Currently, if resetting the host interface, when adding a new client, fails, a negative error code is returned, but the host is still marked as occupied. Fix this bug. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 3271944..2a38e1d 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -459,6 +459,7 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; + int ret; if (pcdev->icd) return -EBUSY; @@ -469,9 +470,11 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) pm_runtime_get_sync(ici->v4l2_dev.dev); - pcdev->icd = icd; + ret = sh_mobile_ceu_soft_reset(pcdev); + if (!ret) + pcdev->icd = icd; - return sh_mobile_ceu_soft_reset(pcdev); + return ret; } /* Called with .video_lock held */ -- cgit v0.10.2 From ee81152ff007a94f90327809566a4b7ff771ffd3 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 11 Dec 2009 11:15:06 -0300 Subject: V4L/DVB (13647): v4l: Add a 10-bit monochrome and missing 8- and 10-bit Bayer fourcc codes The 16-bit monochrome fourcc code has been previously abused for a 10-bit format, add a new 10-bit code instead. Also add missing 8- and 10-bit Bayer fourcc codes for completeness. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 59047eb..d4962a7 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -294,6 +294,7 @@ struct v4l2_pix_format { /* Grey formats */ #define V4L2_PIX_FMT_GREY v4l2_fourcc('G', 'R', 'E', 'Y') /* 8 Greyscale */ +#define V4L2_PIX_FMT_Y10 v4l2_fourcc('Y', '1', '0', ' ') /* 10 Greyscale */ #define V4L2_PIX_FMT_Y16 v4l2_fourcc('Y', '1', '6', ' ') /* 16 Greyscale */ /* Palette formats */ @@ -329,7 +330,11 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B', 'A', '8', '1') /* 8 BGBG.. GRGR.. */ #define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */ #define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G') /* 8 GRGR.. BGBG.. */ -#define V4L2_PIX_FMT_SGRBG10 v4l2_fourcc('B', 'A', '1', '0') /* 10bit raw bayer */ +#define V4L2_PIX_FMT_SRGGB8 v4l2_fourcc('R', 'G', 'G', 'B') /* 8 RGRG.. GBGB.. */ +#define V4L2_PIX_FMT_SBGGR10 v4l2_fourcc('B', 'G', '1', '0') /* 10 BGBG.. GRGR.. */ +#define V4L2_PIX_FMT_SGBRG10 v4l2_fourcc('G', 'B', '1', '0') /* 10 GBGB.. RGRG.. */ +#define V4L2_PIX_FMT_SGRBG10 v4l2_fourcc('B', 'A', '1', '0') /* 10 GRGR.. BGBG.. */ +#define V4L2_PIX_FMT_SRGGB10 v4l2_fourcc('R', 'G', '1', '0') /* 10 RGRG.. GBGB.. */ /* 10bit raw bayer DPCM compressed to 8 bits */ #define V4L2_PIX_FMT_SGRBG10DPCM8 v4l2_fourcc('B', 'D', '1', '0') /* -- cgit v0.10.2 From 3fd7ceffddd52c2f8c004a7999ccb705d592cbfd Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 11 Dec 2009 11:15:06 -0300 Subject: V4L/DVB (13648): soc-camera: add a private field to struct soc_camera_link Up to now, if a client driver needed platform data apart from those contained in struct soc_camera_link, it had to embed the struct into its own object. This makes the use of such a driver in configurations other than soc-camera Signed-off-by: Mauro Carvalho Chehab diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 218639f..831efff 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -104,6 +104,8 @@ struct soc_camera_link { int i2c_adapter_id; struct i2c_board_info *board_info; const char *module_name; + void *priv; + /* * 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 0f4482940a75b52db931e1fff181c9d267e462d2 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 11 Dec 2009 11:31:35 -0300 Subject: V4L/DVB (13650): soc-camera: switch drivers and platforms to use .priv in struct soc_camera_link After this change drivers can be further extended to not fail, if they don't get platform data, but to use defaults. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c index cf9dc12..4c86028 100644 --- a/arch/sh/boards/mach-ap325rxa/setup.c +++ b/arch/sh/boards/mach-ap325rxa/setup.c @@ -324,12 +324,14 @@ static struct soc_camera_platform_info camera_info = { .bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8, .set_capture = camera_set_capture, - .link = { - .bus_id = 0, - .add_device = ap325rxa_camera_add, - .del_device = ap325rxa_camera_del, - .module_name = "soc_camera_platform", - }, +}; + +struct soc_camera_link camera_link = { + .bus_id = 0, + .add_device = ap325rxa_camera_add, + .del_device = ap325rxa_camera_del, + .module_name = "soc_camera_platform", + .priv = &camera_info, }; static void dummy_release(struct device *dev) @@ -347,7 +349,7 @@ static struct platform_device camera_device = { static int ap325rxa_camera_add(struct soc_camera_link *icl, struct device *dev) { - if (icl != &camera_info.link || camera_probe() <= 0) + if (icl != &camera_link || camera_probe() <= 0) return -ENODEV; camera_info.dev = dev; @@ -357,7 +359,7 @@ static int ap325rxa_camera_add(struct soc_camera_link *icl, static void ap325rxa_camera_del(struct soc_camera_link *icl) { - if (icl != &camera_info.link) + if (icl != &camera_link) return; platform_device_unregister(&camera_device); @@ -470,13 +472,15 @@ static struct ov772x_camera_info ov7725_info = { .buswidth = SOCAM_DATAWIDTH_8, .flags = OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP, .edgectrl = OV772X_AUTO_EDGECTRL(0xf, 0), - .link = { - .bus_id = 0, - .power = ov7725_power, - .board_info = &ap325rxa_i2c_camera[0], - .i2c_adapter_id = 0, - .module_name = "ov772x", - }, +}; + +static struct soc_camera_link ov7725_link = { + .bus_id = 0, + .power = ov7725_power, + .board_info = &ap325rxa_i2c_camera[0], + .i2c_adapter_id = 0, + .module_name = "ov772x", + .priv = &ov7725_info, }; static struct platform_device ap325rxa_camera[] = { @@ -484,13 +488,13 @@ static struct platform_device ap325rxa_camera[] = { .name = "soc-camera-pdrv", .id = 0, .dev = { - .platform_data = &ov7725_info.link, + .platform_data = &ov7725_link, }, }, { .name = "soc-camera-pdrv", .id = 1, .dev = { - .platform_data = &camera_info.link, + .platform_data = &camera_link, }, }, }; diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c index 9099b6d..507c77b 100644 --- a/arch/sh/boards/mach-migor/setup.c +++ b/arch/sh/boards/mach-migor/setup.c @@ -432,23 +432,27 @@ static struct i2c_board_info migor_i2c_camera[] = { static struct ov772x_camera_info ov7725_info = { .buswidth = SOCAM_DATAWIDTH_8, - .link = { - .power = ov7725_power, - .board_info = &migor_i2c_camera[0], - .i2c_adapter_id = 0, - .module_name = "ov772x", - }, +}; + +static struct soc_camera_link ov7725_link = { + .power = ov7725_power, + .board_info = &migor_i2c_camera[0], + .i2c_adapter_id = 0, + .module_name = "ov772x", + .priv = &ov7725_info, }; static struct tw9910_video_info tw9910_info = { .buswidth = SOCAM_DATAWIDTH_8, .mpout = TW9910_MPO_FIELD, - .link = { - .power = tw9910_power, - .board_info = &migor_i2c_camera[1], - .i2c_adapter_id = 0, - .module_name = "tw9910", - } +}; + +static struct soc_camera_link tw9910_link = { + .power = tw9910_power, + .board_info = &migor_i2c_camera[1], + .i2c_adapter_id = 0, + .module_name = "tw9910", + .priv = &tw9910_info, }; static struct platform_device migor_camera[] = { @@ -456,13 +460,13 @@ static struct platform_device migor_camera[] = { .name = "soc-camera-pdrv", .id = 0, .dev = { - .platform_data = &ov7725_info.link, + .platform_data = &ov7725_link, }, }, { .name = "soc-camera-pdrv", .id = 1, .dev = { - .platform_data = &tw9910_info.link, + .platform_data = &tw9910_link, }, }, }; diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 2052293..dcb690c 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c @@ -1143,10 +1143,10 @@ static int ov772x_probe(struct i2c_client *client, } icl = to_soc_camera_link(icd); - if (!icl) + if (!icl || !icl->priv) return -EINVAL; - info = container_of(icl, struct ov772x_camera_info, link); + info = icl->priv; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { dev_err(&adapter->dev, diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 3cb9ba6..35373d8 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c @@ -955,10 +955,10 @@ static int tw9910_probe(struct i2c_client *client, } icl = to_soc_camera_link(icd); - if (!icl) + if (!icl || !icl->priv) return -EINVAL; - info = container_of(icl, struct tw9910_video_info, link); + info = icl->priv; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { dev_err(&client->dev, @@ -976,7 +976,7 @@ static int tw9910_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops); icd->ops = &tw9910_ops; - icd->iface = info->link.bus_id; + icd->iface = icl->bus_id; ret = tw9910_video_probe(icd, client); if (ret) { diff --git a/include/media/ov772x.h b/include/media/ov772x.h index 37bcd09..14c77ef 100644 --- a/include/media/ov772x.h +++ b/include/media/ov772x.h @@ -55,7 +55,6 @@ struct ov772x_edge_ctrl { struct ov772x_camera_info { unsigned long buswidth; unsigned long flags; - struct soc_camera_link link; struct ov772x_edge_ctrl edgectrl; }; diff --git a/include/media/soc_camera_platform.h b/include/media/soc_camera_platform.h index bb70401..88b3b57 100644 --- a/include/media/soc_camera_platform.h +++ b/include/media/soc_camera_platform.h @@ -23,7 +23,6 @@ struct soc_camera_platform_info { unsigned long bus_param; struct device *dev; int (*set_capture)(struct soc_camera_platform_info *info, int enable); - struct soc_camera_link link; }; #endif /* __SOC_CAMERA_H__ */ diff --git a/include/media/tw9910.h b/include/media/tw9910.h index 73231e7..5e2895a 100644 --- a/include/media/tw9910.h +++ b/include/media/tw9910.h @@ -32,7 +32,6 @@ enum tw9910_mpout_pin { struct tw9910_video_info { unsigned long buswidth; enum tw9910_mpout_pin mpout; - struct soc_camera_link link; }; -- cgit v0.10.2 From 35b23b522696118b5ec5b84ba6846ee96aa2743e Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 11 Dec 2009 11:34:20 -0300 Subject: V4L/DVB (13651): sh_mobile_ceu_camera: document the scaling and cropping algorithm The sh_mobile_ceu_camera driver implements an advanced algorithm, combining scaling and cropping on the client and on the host. Due to its complexity the algorithm deserves separate documentation. create mode 100644 Documentation/video4linux/sh_mobile_ceu_camera.txt Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/sh_mobile_ceu_camera.txt b/Documentation/video4linux/sh_mobile_ceu_camera.txt new file mode 100644 index 0000000..2ae1634 --- /dev/null +++ b/Documentation/video4linux/sh_mobile_ceu_camera.txt @@ -0,0 +1,157 @@ + Cropping and Scaling algorithm, used in the sh_mobile_ceu_camera driver + ======================================================================= + +Terminology +----------- + +sensor scales: horizontal and vertical scales, configured by the sensor driver +host scales: -"- host driver +combined scales: sensor_scale * host_scale + + +Generic scaling / cropping scheme +--------------------------------- + +-1-- +| +-2-- -\ +| --\ +| --\ ++-5-- -\ -- -3-- +| ---\ +| --- -4-- -\ +| -\ +| - -6-- +| +| - -6'- +| -/ +| --- -4'- -/ +| ---/ ++-5'- -/ +| -- -3'- +| --/ +| --/ +-2'- -/ +| +| +-1'- + +Produced by user requests: + +S_CROP(left / top = (5) - (1), width / height = (5') - (5)) +S_FMT(width / height = (6') - (6)) + +Here: + +(1) to (1') - whole max width or height +(1) to (2) - sensor cropped left or top +(2) to (2') - sensor cropped width or height +(3) to (3') - sensor scale +(3) to (4) - CEU cropped left or top +(4) to (4') - CEU cropped width or height +(5) to (5') - reverse sensor scale applied to CEU cropped width or height +(2) to (5) - reverse sensor scale applied to CEU cropped left or top +(6) to (6') - CEU scale - user window + + +S_FMT +----- + +Do not touch input rectangle - it is already optimal. + +1. Calculate current sensor scales: + + scale_s = ((3') - (3)) / ((2') - (2)) + +2. Calculate "effective" input crop (sensor subwindow) - CEU crop scaled back at +current sensor scales onto input window - this is user S_CROP: + + width_u = (5') - (5) = ((4') - (4)) * scale_s + +3. Calculate new combined scales from "effective" input window to requested user +window: + + scale_comb = width_u / ((6') - (6)) + +4. Calculate sensor output window by applying combined scales to real input +window: + + width_s_out = ((2') - (2)) / scale_comb + +5. Apply iterative sensor S_FMT for sensor output window. + + subdev->video_ops->s_fmt(.width = width_s_out) + +6. Retrieve sensor output window (g_fmt) + +7. Calculate new sensor scales: + + scale_s_new = ((3')_new - (3)_new) / ((2') - (2)) + +8. Calculate new CEU crop - apply sensor scales to previously calculated +"effective" crop: + + width_ceu = (4')_new - (4)_new = width_u / scale_s_new + left_ceu = (4)_new - (3)_new = ((5) - (2)) / scale_s_new + +9. Use CEU cropping to crop to the new window: + + ceu_crop(.width = width_ceu, .left = left_ceu) + +10. Use CEU scaling to scale to the requested user window: + + scale_ceu = width_ceu / width + + +S_CROP +------ + +If old scale applied to new crop is invalid produce nearest new scale possible + +1. Calculate current combined scales. + + scale_comb = (((4') - (4)) / ((6') - (6))) * (((2') - (2)) / ((3') - (3))) + +2. Apply iterative sensor S_CROP for new input window. + +3. If old combined scales applied to new crop produce an impossible user window, +adjust scales to produce nearest possible window. + + width_u_out = ((5') - (5)) / scale_comb + + if (width_u_out > max) + scale_comb = ((5') - (5)) / max; + else if (width_u_out < min) + scale_comb = ((5') - (5)) / min; + +4. Issue G_CROP to retrieve actual input window. + +5. Using actual input window and calculated combined scales calculate sensor +target output window. + + width_s_out = ((3') - (3)) = ((2') - (2)) / scale_comb + +6. Apply iterative S_FMT for new sensor target output window. + +7. Issue G_FMT to retrieve the actual sensor output window. + +8. Calculate sensor scales. + + scale_s = ((3') - (3)) / ((2') - (2)) + +9. Calculate sensor output subwindow to be cropped on CEU by applying sensor +scales to the requested window. + + width_ceu = ((5') - (5)) / scale_s + +10. Use CEU cropping for above calculated window. + +11. Calculate CEU scales from sensor scales from results of (10) and user window +from (3) + + scale_ceu = calc_scale(((5') - (5)), &width_u_out) + +12. Apply CEU scales. + +-- +Author: Guennadi Liakhovetski -- cgit v0.10.2 From 6d74e5f361bdacfdcfe14220868d562368aaadc2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 11 Dec 2009 11:34:50 -0300 Subject: V4L/DVB (13652): tw9910: Add revision control Also fix a badly chosen macro name. Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 35373d8..e3a4942 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c @@ -29,7 +29,7 @@ #include #define GET_ID(val) ((val & 0xF8) >> 3) -#define GET_ReV(val) (val & 0x07) +#define GET_REV(val) (val & 0x07) /* * register offset @@ -225,6 +225,7 @@ struct tw9910_priv { struct v4l2_subdev subdev; struct tw9910_video_info *info; const struct tw9910_scale_ctrl *scale; + u32 revision; }; /* @@ -575,8 +576,11 @@ static int tw9910_enum_input(struct soc_camera_device *icd, static int tw9910_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *id) { + struct i2c_client *client = sd->priv; + struct tw9910_priv *priv = to_tw9910(client); + id->ident = V4L2_IDENT_TW9910; - id->revision = 0; + id->revision = priv->revision; return 0; } @@ -886,16 +890,18 @@ static int tw9910_video_probe(struct soc_camera_device *icd, * So far only revisions 0 and 1 have been seen */ val = i2c_smbus_read_byte_data(client, ID); + priv->revision = GET_REV(val); if (0x0B != GET_ID(val) || - 0x01 < GET_ReV(val)) { + 0x01 < priv->revision) { dev_err(&client->dev, - "Product ID error %x:%x\n", GET_ID(val), GET_ReV(val)); + "Product ID error %x:%x\n", + GET_ID(val), priv->revision); return -ENODEV; } dev_info(&client->dev, - "tw9910 Product ID %0x:%0x\n", GET_ID(val), GET_ReV(val)); + "tw9910 Product ID %0x:%0x\n", GET_ID(val), priv->revision); icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL; icd->vdev->current_norm = V4L2_STD_NTSC; -- cgit v0.10.2 From 88a67c51dfc649c18fc8828970cb4fd09d1871b5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 11 Dec 2009 11:34:50 -0300 Subject: V4L/DVB (13653): tw9910: simplify chip ID calculation Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index e3a4942..3d8a45f 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c @@ -863,7 +863,7 @@ static int tw9910_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { struct tw9910_priv *priv = to_tw9910(client); - s32 val; + s32 id; /* * We must have a parent by now. And it cannot be a wrong one. @@ -889,19 +889,20 @@ static int tw9910_video_probe(struct soc_camera_device *icd, * check and show Product ID * So far only revisions 0 and 1 have been seen */ - val = i2c_smbus_read_byte_data(client, ID); - priv->revision = GET_REV(val); + id = i2c_smbus_read_byte_data(client, ID); + priv->revision = GET_REV(id); + id = GET_ID(id); - if (0x0B != GET_ID(val) || + if (0x0B != id || 0x01 < priv->revision) { dev_err(&client->dev, "Product ID error %x:%x\n", - GET_ID(val), priv->revision); + id, priv->revision); return -ENODEV; } dev_info(&client->dev, - "tw9910 Product ID %0x:%0x\n", GET_ID(val), priv->revision); + "tw9910 Product ID %0x:%0x\n", id, priv->revision); icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL; icd->vdev->current_norm = V4L2_STD_NTSC; -- cgit v0.10.2 From 06f292e4806fcec2e7b2356c41241f5b6c4e3afb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 11 Dec 2009 11:34:50 -0300 Subject: V4L/DVB (13654): tw9910: Tri-state pins when idle Tri-state all pins when not streaming to save power. Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 3d8a45f..80b214e 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c @@ -152,7 +152,10 @@ /* 1 : non-auto */ #define VSCTL 0x08 /* 1 : Vertical out ctrl by DVALID */ /* 0 : Vertical out ctrl by HACTIVE and DVALID */ -#define OEN 0x04 /* Output Enable together with TRI_SEL. */ +#define OEN_TRI_SEL_MASK 0x07 +#define OEN_TRI_SEL_ALL_ON 0x00 /* Enable output for Rev0/Rev1 */ +#define OEN_TRI_SEL_ALL_OFF_r0 0x06 /* All tri-stated for Rev0 */ +#define OEN_TRI_SEL_ALL_OFF_r1 0x07 /* All tri-stated for Rev1 */ /* OUTCTR1 */ #define VSP_LO 0x00 /* 0 : VS pin output polarity is active low */ @@ -236,7 +239,6 @@ struct tw9910_priv { static const struct regval_list tw9910_default_regs[] = { - { OPFORM, 0x00 }, { OUTCTR1, VSP_LO | VSSL_VVALID | HSP_HI | HSSL_HSYNC }, ENDMARKER, }; @@ -519,20 +521,35 @@ static int tw9910_s_stream(struct v4l2_subdev *sd, int enable) struct i2c_client *client = sd->priv; struct tw9910_priv *priv = to_tw9910(client); - if (!enable) - return 0; + u8 val; - if (!priv->scale) { - dev_err(&client->dev, "norm select error\n"); - return -EPERM; - } + if (!enable) { + switch (priv->revision) { + case 0: + val = OEN_TRI_SEL_ALL_OFF_r0; + break; + case 1: + val = OEN_TRI_SEL_ALL_OFF_r1; + break; + default: + dev_err(&client->dev, "un-supported revision\n"); + return -EINVAL; + } + } else { + val = OEN_TRI_SEL_ALL_ON; - dev_dbg(&client->dev, "%s %dx%d\n", - priv->scale->name, - priv->scale->width, - priv->scale->height); + if (!priv->scale) { + dev_err(&client->dev, "norm select error\n"); + return -EPERM; + } - return 0; + dev_dbg(&client->dev, "%s %dx%d\n", + priv->scale->name, + priv->scale->width, + priv->scale->height); + } + + return tw9910_mask_set(client, OPFORM, OEN_TRI_SEL_MASK, val); } static int tw9910_set_bus_param(struct soc_camera_device *icd, -- cgit v0.10.2 From 607e5ad8d596495341fa0a13e0a23121ee6053b6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 11 Dec 2009 11:34:50 -0300 Subject: V4L/DVB (13655): tw9910: Add power control Power down internal blocks when not streaming. Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 80b214e..c21aced 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c @@ -181,6 +181,14 @@ * but all register content remain unchanged. * This bit is self-resetting. */ +#define ACNTL1_PDN_MASK 0x0e +#define CLK_PDN 0x08 /* system clock power down */ +#define Y_PDN 0x04 /* Luma ADC power down */ +#define C_PDN 0x02 /* Chroma ADC power down */ + +/* ACNTL2 */ +#define ACNTL2_PDN_MASK 0x40 +#define PLL_PDN 0x40 /* PLL power down */ /* VBICNTL */ @@ -478,10 +486,31 @@ static int tw9910_mask_set(struct i2c_client *client, u8 command, static void tw9910_reset(struct i2c_client *client) { - i2c_smbus_write_byte_data(client, ACNTL1, SRESET); + tw9910_mask_set(client, ACNTL1, SRESET, SRESET); msleep(1); } +static int tw9910_power(struct i2c_client *client, int enable) +{ + int ret; + u8 acntl1; + u8 acntl2; + + if (enable) { + acntl1 = 0; + acntl2 = 0; + } else { + acntl1 = CLK_PDN | Y_PDN | C_PDN; + acntl2 = PLL_PDN; + } + + ret = tw9910_mask_set(client, ACNTL1, ACNTL1_PDN_MASK, acntl1); + if (ret < 0) + return ret; + + return tw9910_mask_set(client, ACNTL2, ACNTL2_PDN_MASK, acntl2); +} + static const struct tw9910_scale_ctrl* tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height) { @@ -520,8 +549,8 @@ static int tw9910_s_stream(struct v4l2_subdev *sd, int enable) { struct i2c_client *client = sd->priv; struct tw9910_priv *priv = to_tw9910(client); - u8 val; + int ret; if (!enable) { switch (priv->revision) { @@ -549,7 +578,11 @@ static int tw9910_s_stream(struct v4l2_subdev *sd, int enable) priv->scale->height); } - return tw9910_mask_set(client, OPFORM, OEN_TRI_SEL_MASK, val); + ret = tw9910_mask_set(client, OPFORM, OEN_TRI_SEL_MASK, val); + if (ret < 0) + return ret; + + return tw9910_power(client, enable); } static int tw9910_set_bus_param(struct soc_camera_device *icd, -- cgit v0.10.2 From 207970838186b2606896b03f590b89b13570a727 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 11 Dec 2009 11:34:51 -0300 Subject: V4L/DVB (13656): tw9910: tw9910_set_hsync clean up tw9910_set_hsync should use tw9910_mask_set to set bits 2-0 Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index c21aced..2256ba6 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c @@ -371,6 +371,19 @@ static struct tw9910_priv *to_tw9910(const struct i2c_client *client) subdev); } +static int tw9910_mask_set(struct i2c_client *client, u8 command, + u8 mask, u8 set) +{ + s32 val = i2c_smbus_read_byte_data(client, command); + if (val < 0) + return val; + + val &= ~mask; + val |= set & mask; + + return i2c_smbus_write_byte_data(client, command, val); +} + static int tw9910_set_scale(struct i2c_client *client, const struct tw9910_scale_ctrl *scale) { @@ -445,14 +458,9 @@ static int tw9910_set_hsync(struct i2c_client *client, return ret; /* bit 2 - 0 */ - ret = i2c_smbus_read_byte_data(client, HSLOWCTL); - if (ret < 0) - return ret; - - ret = i2c_smbus_write_byte_data(client, HSLOWCTL, - (ret & 0x88) | - (hsync->start & 0x0007) << 4 | - (hsync->end & 0x0007)); + ret = tw9910_mask_set(client, HSLOWCTL, 0x77, + (hsync->start & 0x0007) << 4 | + (hsync->end & 0x0007)); return ret; } @@ -471,19 +479,6 @@ static int tw9910_write_array(struct i2c_client *client, return 0; } -static int tw9910_mask_set(struct i2c_client *client, u8 command, - u8 mask, u8 set) -{ - s32 val = i2c_smbus_read_byte_data(client, command); - if (val < 0) - return val; - - val &= ~mask; - val |= set & mask; - - return i2c_smbus_write_byte_data(client, command, val); -} - static void tw9910_reset(struct i2c_client *client) { tw9910_mask_set(client, ACNTL1, SRESET, SRESET); -- cgit v0.10.2 From faa582610d87edf3ae1d07710a8f7e11c105686c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 11 Dec 2009 11:34:51 -0300 Subject: V4L/DVB (13657): tw9910: Add revision control to tw9910_set_hsync Bits 10-3 of hsync control are the same for Rev0 and Rev1, but only Rev1 also has bits 2-0 for hsync. Account for this difference and also fix a register name. Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 2256ba6..8ec1031 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c @@ -117,7 +117,7 @@ #define LCTL24 0x68 #define LCTL25 0x69 #define LCTL26 0x6A -#define HSGEGIN 0x6B +#define HSBEGIN 0x6B #define HSEND 0x6C #define OVSDLY 0x6D #define OVSEND 0x6E @@ -443,10 +443,11 @@ static int tw9910_set_cropping(struct i2c_client *client, static int tw9910_set_hsync(struct i2c_client *client, const struct tw9910_hsync_ctrl *hsync) { + struct tw9910_priv *priv = to_tw9910(client); int ret; /* bit 10 - 3 */ - ret = i2c_smbus_write_byte_data(client, HSGEGIN, + ret = i2c_smbus_write_byte_data(client, HSBEGIN, (hsync->start & 0x07F8) >> 3); if (ret < 0) return ret; @@ -457,10 +458,12 @@ static int tw9910_set_hsync(struct i2c_client *client, if (ret < 0) return ret; + /* So far only revisions 0 and 1 have been seen */ /* bit 2 - 0 */ - ret = tw9910_mask_set(client, HSLOWCTL, 0x77, - (hsync->start & 0x0007) << 4 | - (hsync->end & 0x0007)); + if (1 == priv->revision) + ret = tw9910_mask_set(client, HSLOWCTL, 0x77, + (hsync->start & 0x0007) << 4 | + (hsync->end & 0x0007)); return ret; } -- cgit v0.10.2 From 9a74251d8bee7a25fee89a0be3ccea73e01c1a05 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 11 Dec 2009 11:41:28 -0300 Subject: V4L/DVB (13658): v4l: add a media-bus API for configuring v4l2 subdev pixel and frame formats Video subdevices, like cameras, decoders, connect to video bridges over specialised busses. Data is being transferred over these busses in various formats, which only loosely correspond to fourcc codes, describing how video data is stored in RAM. This is not a one-to-one correspondence, therefore we cannot use fourcc codes to configure subdevice output data formats. This patch adds codes for several such on-the-bus formats and an API, similar to the familiar .s_fmt(), .g_fmt(), .try_fmt(), .enum_fmt() API for configuring those codes. After all users of the old API in struct v4l2_subdev_video_ops are converted, it will be removed. Also add helper routines to support generic pass-through mode for the soc-camera framework. create mode 100644 drivers/media/video/soc_mediabus.c create mode 100644 include/media/soc_mediabus.h create mode 100644 include/media/v4l2-mediabus.h Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 7a2dcc3..e7bc8da 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -149,7 +149,7 @@ obj-$(CONFIG_VIDEO_VIVI) += vivi.o obj-$(CONFIG_VIDEO_CX23885) += cx23885/ obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.o -obj-$(CONFIG_SOC_CAMERA) += soc_camera.o +obj-$(CONFIG_SOC_CAMERA) += soc_camera.o soc_mediabus.o obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o # soc-camera host drivers have to be linked after camera drivers obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o diff --git a/drivers/media/video/soc_mediabus.c b/drivers/media/video/soc_mediabus.c new file mode 100644 index 0000000..f8d5c87 --- /dev/null +++ b/drivers/media/video/soc_mediabus.c @@ -0,0 +1,157 @@ +/* + * soc-camera media bus helper routines + * + * Copyright (C) 2009, Guennadi Liakhovetski + * + * 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 + +#define MBUS_IDX(f) (V4L2_MBUS_FMT_ ## f - V4L2_MBUS_FMT_FIXED - 1) + +static const struct soc_mbus_pixelfmt mbus_fmt[] = { + [MBUS_IDX(YUYV8_2X8_LE)] = { + .fourcc = V4L2_PIX_FMT_YUYV, + .name = "YUYV", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_LE, + }, [MBUS_IDX(YVYU8_2X8_LE)] = { + .fourcc = V4L2_PIX_FMT_YVYU, + .name = "YVYU", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_LE, + }, [MBUS_IDX(YUYV8_2X8_BE)] = { + .fourcc = V4L2_PIX_FMT_UYVY, + .name = "UYVY", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_LE, + }, [MBUS_IDX(YVYU8_2X8_BE)] = { + .fourcc = V4L2_PIX_FMT_VYUY, + .name = "VYUY", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_LE, + }, [MBUS_IDX(RGB555_2X8_PADHI_LE)] = { + .fourcc = V4L2_PIX_FMT_RGB555, + .name = "RGB555", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_LE, + }, [MBUS_IDX(RGB555_2X8_PADHI_BE)] = { + .fourcc = V4L2_PIX_FMT_RGB555X, + .name = "RGB555X", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_LE, + }, [MBUS_IDX(RGB565_2X8_LE)] = { + .fourcc = V4L2_PIX_FMT_RGB565, + .name = "RGB565", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_LE, + }, [MBUS_IDX(RGB565_2X8_BE)] = { + .fourcc = V4L2_PIX_FMT_RGB565X, + .name = "RGB565X", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_LE, + }, [MBUS_IDX(SBGGR8_1X8)] = { + .fourcc = V4L2_PIX_FMT_SBGGR8, + .name = "Bayer 8 BGGR", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_NONE, + .order = SOC_MBUS_ORDER_LE, + }, [MBUS_IDX(SBGGR10_1X10)] = { + .fourcc = V4L2_PIX_FMT_SBGGR10, + .name = "Bayer 10 BGGR", + .bits_per_sample = 10, + .packing = SOC_MBUS_PACKING_EXTEND16, + .order = SOC_MBUS_ORDER_LE, + }, [MBUS_IDX(GREY8_1X8)] = { + .fourcc = V4L2_PIX_FMT_GREY, + .name = "Grey", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_NONE, + .order = SOC_MBUS_ORDER_LE, + }, [MBUS_IDX(Y10_1X10)] = { + .fourcc = V4L2_PIX_FMT_Y10, + .name = "Grey 10bit", + .bits_per_sample = 10, + .packing = SOC_MBUS_PACKING_EXTEND16, + .order = SOC_MBUS_ORDER_LE, + }, [MBUS_IDX(SBGGR10_2X8_PADHI_LE)] = { + .fourcc = V4L2_PIX_FMT_SBGGR10, + .name = "Bayer 10 BGGR", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_LE, + }, [MBUS_IDX(SBGGR10_2X8_PADLO_LE)] = { + .fourcc = V4L2_PIX_FMT_SBGGR10, + .name = "Bayer 10 BGGR", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADLO, + .order = SOC_MBUS_ORDER_LE, + }, [MBUS_IDX(SBGGR10_2X8_PADHI_BE)] = { + .fourcc = V4L2_PIX_FMT_SBGGR10, + .name = "Bayer 10 BGGR", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_BE, + }, [MBUS_IDX(SBGGR10_2X8_PADLO_BE)] = { + .fourcc = V4L2_PIX_FMT_SBGGR10, + .name = "Bayer 10 BGGR", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADLO, + .order = SOC_MBUS_ORDER_BE, + }, +}; + +s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf) +{ + switch (mf->packing) { + case SOC_MBUS_PACKING_NONE: + return width * mf->bits_per_sample / 8; + case SOC_MBUS_PACKING_2X8_PADHI: + case SOC_MBUS_PACKING_2X8_PADLO: + case SOC_MBUS_PACKING_EXTEND16: + return width * 2; + } + return -EINVAL; +} +EXPORT_SYMBOL(soc_mbus_bytes_per_line); + +const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc( + enum v4l2_mbus_pixelcode code) +{ + if ((unsigned int)(code - V4L2_MBUS_FMT_FIXED) > ARRAY_SIZE(mbus_fmt)) + return NULL; + return mbus_fmt + code - V4L2_MBUS_FMT_FIXED - 1; +} +EXPORT_SYMBOL(soc_mbus_get_fmtdesc); + +static int __init soc_mbus_init(void) +{ + return 0; +} + +static void __exit soc_mbus_exit(void) +{ +} + +module_init(soc_mbus_init); +module_exit(soc_mbus_exit); + +MODULE_DESCRIPTION("soc-camera media bus interface"); +MODULE_AUTHOR("Guennadi Liakhovetski "); +MODULE_LICENSE("GPL v2"); diff --git a/include/media/soc_mediabus.h b/include/media/soc_mediabus.h new file mode 100644 index 0000000..037cd7b --- /dev/null +++ b/include/media/soc_mediabus.h @@ -0,0 +1,65 @@ +/* + * SoC-camera Media Bus API extensions + * + * Copyright (C) 2009, Guennadi Liakhovetski + * + * 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. + */ + +#ifndef SOC_MEDIABUS_H +#define SOC_MEDIABUS_H + +#include + +#include + +/** + * enum soc_mbus_packing - data packing types on the media-bus + * @SOC_MBUS_PACKING_NONE: no packing, bit-for-bit transfer to RAM + * @SOC_MBUS_PACKING_2X8_PADHI: 16 bits transferred in 2 8-bit samples, in the + * possibly incomplete byte high bits are padding + * @SOC_MBUS_PACKING_2X8_PADLO: as above, but low bits are padding + * @SOC_MBUS_PACKING_EXTEND16: sample width (e.g., 10 bits) has to be extended + * to 16 bits + */ +enum soc_mbus_packing { + SOC_MBUS_PACKING_NONE, + SOC_MBUS_PACKING_2X8_PADHI, + SOC_MBUS_PACKING_2X8_PADLO, + SOC_MBUS_PACKING_EXTEND16, +}; + +/** + * enum soc_mbus_order - sample order on the media bus + * @SOC_MBUS_ORDER_LE: least significant sample first + * @SOC_MBUS_ORDER_BE: most significant sample first + */ +enum soc_mbus_order { + SOC_MBUS_ORDER_LE, + SOC_MBUS_ORDER_BE, +}; + +/** + * struct soc_mbus_pixelfmt - Data format on the media bus + * @name: Name of the format + * @fourcc: Fourcc code, that will be obtained if the data is + * stored in memory in the following way: + * @packing: Type of sample-packing, that has to be used + * @order: Sample order when storing in memory + * @bits_per_sample: How many bits the bridge has to sample + */ +struct soc_mbus_pixelfmt { + const char *name; + u32 fourcc; + enum soc_mbus_packing packing; + enum soc_mbus_order order; + u8 bits_per_sample; +}; + +const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc( + enum v4l2_mbus_pixelcode code); +s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf); + +#endif diff --git a/include/media/v4l2-mediabus.h b/include/media/v4l2-mediabus.h new file mode 100644 index 0000000..0dbe02a --- /dev/null +++ b/include/media/v4l2-mediabus.h @@ -0,0 +1,61 @@ +/* + * Media Bus API header + * + * Copyright (C) 2009, Guennadi Liakhovetski + * + * 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. + */ + +#ifndef V4L2_MEDIABUS_H +#define V4L2_MEDIABUS_H + +/* + * These pixel codes uniquely identify data formats on the media bus. Mostly + * they correspond to similarly named V4L2_PIX_FMT_* formats, format 0 is + * reserved, V4L2_MBUS_FMT_FIXED shall be used by host-client pairs, where the + * data format is fixed. Additionally, "2X8" means that one pixel is transferred + * in two 8-bit samples, "BE" or "LE" specify in which order those samples are + * transferred over the bus: "LE" means that the least significant bits are + * transferred first, "BE" means that the most significant bits are transferred + * first, and "PADHI" and "PADLO" define which bits - low or high, in the + * incomplete high byte, are filled with padding bits. + */ +enum v4l2_mbus_pixelcode { + V4L2_MBUS_FMT_FIXED = 1, + V4L2_MBUS_FMT_YUYV8_2X8_LE, + V4L2_MBUS_FMT_YVYU8_2X8_LE, + V4L2_MBUS_FMT_YUYV8_2X8_BE, + V4L2_MBUS_FMT_YVYU8_2X8_BE, + V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, + V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE, + V4L2_MBUS_FMT_RGB565_2X8_LE, + V4L2_MBUS_FMT_RGB565_2X8_BE, + V4L2_MBUS_FMT_SBGGR8_1X8, + V4L2_MBUS_FMT_SBGGR10_1X10, + V4L2_MBUS_FMT_GREY8_1X8, + V4L2_MBUS_FMT_Y10_1X10, + V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, + V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE, + V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE, + V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE, +}; + +/** + * struct v4l2_mbus_framefmt - frame format on the media bus + * @width: frame width + * @height: frame height + * @code: data format code + * @field: used interlacing type + * @colorspace: colorspace of the data + */ +struct v4l2_mbus_framefmt { + __u32 width; + __u32 height; + enum v4l2_mbus_pixelcode code; + enum v4l2_field field; + enum v4l2_colorspace colorspace; +}; + +#endif diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index a128458..9ba99cd 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -22,6 +22,7 @@ #define _V4L2_SUBDEV_H #include +#include /* generic v4l2_device notify callback notification values */ #define V4L2_SUBDEV_IR_RX_NOTIFY _IOW('v', 0, u32) @@ -207,7 +208,7 @@ struct v4l2_subdev_audio_ops { s_std_output: set v4l2_std_id for video OUTPUT devices. This is ignored by video input devices. - s_crystal_freq: sets the frequency of the crystal used to generate the + s_crystal_freq: sets the frequency of the crystal used to generate the clocks in Hz. An extra flags field allows device specific configuration regarding clock frequency dividers, etc. If not used, then set flags to 0. If the frequency is not supported, then -EINVAL is returned. @@ -230,6 +231,13 @@ struct v4l2_subdev_audio_ops { g_dv_timings(): Get custom dv timings in the sub device. + enum_mbus_fmt: enumerate pixel formats, provided by a video data source + + g_mbus_fmt: get the current pixel format, provided by a video data source + + try_mbus_fmt: try to set a pixel format on a video data source + + s_mbus_fmt: set a pixel format on a video data source */ struct v4l2_subdev_video_ops { int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config); @@ -261,6 +269,14 @@ struct v4l2_subdev_video_ops { struct v4l2_dv_timings *timings); int (*g_dv_timings)(struct v4l2_subdev *sd, struct v4l2_dv_timings *timings); + int (*enum_mbus_fmt)(struct v4l2_subdev *sd, int index, + enum v4l2_mbus_pixelcode *code); + int (*g_mbus_fmt)(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *fmt); + int (*try_mbus_fmt)(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *fmt); + int (*s_mbus_fmt)(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *fmt); }; /** -- cgit v0.10.2 From 760697beca338599a65484389c7abbe54aedb664 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 11 Dec 2009 11:46:49 -0300 Subject: V4L/DVB (13659): soc-camera: convert to the new mediabus API Convert soc-camera core and all soc-camera drivers to the new mediabus API. This also takes soc-camera client drivers one step closer to also be usable with generic v4l2-subdev host drivers. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c index 4c86028..7a9f696 100644 --- a/arch/sh/boards/mach-ap325rxa/setup.c +++ b/arch/sh/boards/mach-ap325rxa/setup.c @@ -316,8 +316,9 @@ static struct soc_camera_platform_info camera_info = { .format_name = "UYVY", .format_depth = 16, .format = { - .pixelformat = V4L2_PIX_FMT_UYVY, + .code = V4L2_MBUS_FMT_YUYV8_2X8_BE, .colorspace = V4L2_COLORSPACE_SMPTE170M, + .field = V4L2_FIELD_NONE, .width = 640, .height = 480, }, diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index cc90660..b62c0bd 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -48,41 +48,46 @@ #define MT9M001_COLUMN_SKIP 20 #define MT9M001_ROW_SKIP 12 -static const struct soc_camera_data_format mt9m001_colour_formats[] = { +/* MT9M001 has only one fixed colorspace per pixelcode */ +struct mt9m001_datafmt { + enum v4l2_mbus_pixelcode code; + enum v4l2_colorspace colorspace; +}; + +/* Find a data format by a pixel code in an array */ +static const struct mt9m001_datafmt *mt9m001_find_datafmt( + enum v4l2_mbus_pixelcode code, const struct mt9m001_datafmt *fmt, + int n) +{ + int i; + for (i = 0; i < n; i++) + if (fmt[i].code == code) + return fmt + i; + + return NULL; +} + +static const struct mt9m001_datafmt mt9m001_colour_fmts[] = { /* * Order important: first natively supported, * second supported with a GPIO extender */ - { - .name = "Bayer (sRGB) 10 bit", - .depth = 10, - .fourcc = V4L2_PIX_FMT_SBGGR16, - .colorspace = V4L2_COLORSPACE_SRGB, - }, { - .name = "Bayer (sRGB) 8 bit", - .depth = 8, - .fourcc = V4L2_PIX_FMT_SBGGR8, - .colorspace = V4L2_COLORSPACE_SRGB, - } + {V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB}, + {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB}, }; -static const struct soc_camera_data_format mt9m001_monochrome_formats[] = { +static const struct mt9m001_datafmt mt9m001_monochrome_fmts[] = { /* Order important - see above */ - { - .name = "Monochrome 10 bit", - .depth = 10, - .fourcc = V4L2_PIX_FMT_Y16, - }, { - .name = "Monochrome 8 bit", - .depth = 8, - .fourcc = V4L2_PIX_FMT_GREY, - }, + {V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG}, + {V4L2_MBUS_FMT_GREY8_1X8, V4L2_COLORSPACE_JPEG}, }; struct mt9m001 { struct v4l2_subdev subdev; struct v4l2_rect rect; /* Sensor window */ - __u32 fourcc; + const struct mt9m001_datafmt *fmt; + const struct mt9m001_datafmt *fmts; + int num_fmts; int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ unsigned int gain; unsigned int exposure; @@ -209,8 +214,7 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) const u16 hblank = 9, vblank = 25; unsigned int total_h; - if (mt9m001->fourcc == V4L2_PIX_FMT_SBGGR8 || - mt9m001->fourcc == V4L2_PIX_FMT_SBGGR16) + if (mt9m001->fmts == mt9m001_colour_fmts) /* * Bayer format - even number of rows for simplicity, * but let the user play with the top row. @@ -290,32 +294,32 @@ static int mt9m001_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) return 0; } -static int mt9m001_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int mt9m001_g_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = sd->priv; struct mt9m001 *mt9m001 = to_mt9m001(client); - struct v4l2_pix_format *pix = &f->fmt.pix; - pix->width = mt9m001->rect.width; - pix->height = mt9m001->rect.height; - pix->pixelformat = mt9m001->fourcc; - pix->field = V4L2_FIELD_NONE; - pix->colorspace = V4L2_COLORSPACE_SRGB; + mf->width = mt9m001->rect.width; + mf->height = mt9m001->rect.height; + mf->code = mt9m001->fmt->code; + mf->colorspace = mt9m001->fmt->colorspace; + mf->field = V4L2_FIELD_NONE; return 0; } -static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int mt9m001_s_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = sd->priv; struct mt9m001 *mt9m001 = to_mt9m001(client); - struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_crop a = { .c = { .left = mt9m001->rect.left, .top = mt9m001->rect.top, - .width = pix->width, - .height = pix->height, + .width = mf->width, + .height = mf->height, }, }; int ret; @@ -323,28 +327,39 @@ static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) /* No support for scaling so far, just crop. TODO: use skipping */ ret = mt9m001_s_crop(sd, &a); if (!ret) { - pix->width = mt9m001->rect.width; - pix->height = mt9m001->rect.height; - mt9m001->fourcc = pix->pixelformat; + mf->width = mt9m001->rect.width; + mf->height = mt9m001->rect.height; + mt9m001->fmt = mt9m001_find_datafmt(mf->code, + mt9m001->fmts, mt9m001->num_fmts); + mf->colorspace = mt9m001->fmt->colorspace; } return ret; } -static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int mt9m001_try_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = sd->priv; struct mt9m001 *mt9m001 = to_mt9m001(client); - struct v4l2_pix_format *pix = &f->fmt.pix; + const struct mt9m001_datafmt *fmt; - v4l_bound_align_image(&pix->width, MT9M001_MIN_WIDTH, + v4l_bound_align_image(&mf->width, MT9M001_MIN_WIDTH, MT9M001_MAX_WIDTH, 1, - &pix->height, MT9M001_MIN_HEIGHT + mt9m001->y_skip_top, + &mf->height, MT9M001_MIN_HEIGHT + mt9m001->y_skip_top, MT9M001_MAX_HEIGHT + mt9m001->y_skip_top, 0, 0); - if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8 || - pix->pixelformat == V4L2_PIX_FMT_SBGGR16) - pix->height = ALIGN(pix->height - 1, 2); + if (mt9m001->fmts == mt9m001_colour_fmts) + mf->height = ALIGN(mf->height - 1, 2); + + fmt = mt9m001_find_datafmt(mf->code, mt9m001->fmts, + mt9m001->num_fmts); + if (!fmt) { + fmt = mt9m001->fmt; + mf->code = fmt->code; + } + + mf->colorspace = fmt->colorspace; return 0; } @@ -608,11 +623,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, case 0x8411: case 0x8421: mt9m001->model = V4L2_IDENT_MT9M001C12ST; - icd->formats = mt9m001_colour_formats; + mt9m001->fmts = mt9m001_colour_fmts; break; case 0x8431: mt9m001->model = V4L2_IDENT_MT9M001C12STM; - icd->formats = mt9m001_monochrome_formats; + mt9m001->fmts = mt9m001_monochrome_fmts; break; default: dev_err(&client->dev, @@ -620,7 +635,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, return -ENODEV; } - icd->num_formats = 0; + mt9m001->num_fmts = 0; /* * This is a 10bit sensor, so by default we only allow 10bit. @@ -633,14 +648,14 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, flags = SOCAM_DATAWIDTH_10; if (flags & SOCAM_DATAWIDTH_10) - icd->num_formats++; + mt9m001->num_fmts++; else - icd->formats++; + mt9m001->fmts++; if (flags & SOCAM_DATAWIDTH_8) - icd->num_formats++; + mt9m001->num_fmts++; - mt9m001->fourcc = icd->formats->fourcc; + mt9m001->fmt = &mt9m001->fmts[0]; dev_info(&client->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, data == 0x8431 ? "C12STM" : "C12ST"); @@ -686,14 +701,28 @@ static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = { #endif }; +static int mt9m001_enum_fmt(struct v4l2_subdev *sd, int index, + enum v4l2_mbus_pixelcode *code) +{ + struct i2c_client *client = sd->priv; + struct mt9m001 *mt9m001 = to_mt9m001(client); + + if ((unsigned int)index >= mt9m001->num_fmts) + return -EINVAL; + + *code = mt9m001->fmts[index].code; + return 0; +} + static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { .s_stream = mt9m001_s_stream, - .s_fmt = mt9m001_s_fmt, - .g_fmt = mt9m001_g_fmt, - .try_fmt = mt9m001_try_fmt, + .s_mbus_fmt = mt9m001_s_fmt, + .g_mbus_fmt = mt9m001_g_fmt, + .try_mbus_fmt = mt9m001_try_fmt, .s_crop = mt9m001_s_crop, .g_crop = mt9m001_g_crop, .cropcap = mt9m001_cropcap, + .enum_mbus_fmt = mt9m001_enum_fmt, }; static struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = { diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index 30db625..d35f536 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c @@ -123,23 +123,34 @@ #define MT9M111_MAX_HEIGHT 1024 #define MT9M111_MAX_WIDTH 1280 -#define COL_FMT(_name, _depth, _fourcc, _colorspace) \ - { .name = _name, .depth = _depth, .fourcc = _fourcc, \ - .colorspace = _colorspace } -#define RGB_FMT(_name, _depth, _fourcc) \ - COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_SRGB) -#define JPG_FMT(_name, _depth, _fourcc) \ - COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_JPEG) - -static const struct soc_camera_data_format mt9m111_colour_formats[] = { - JPG_FMT("CbYCrY 16 bit", 16, V4L2_PIX_FMT_UYVY), - JPG_FMT("CrYCbY 16 bit", 16, V4L2_PIX_FMT_VYUY), - JPG_FMT("YCbYCr 16 bit", 16, V4L2_PIX_FMT_YUYV), - JPG_FMT("YCrYCb 16 bit", 16, V4L2_PIX_FMT_YVYU), - RGB_FMT("RGB 565", 16, V4L2_PIX_FMT_RGB565), - RGB_FMT("RGB 555", 16, V4L2_PIX_FMT_RGB555), - RGB_FMT("Bayer (sRGB) 10 bit", 10, V4L2_PIX_FMT_SBGGR16), - RGB_FMT("Bayer (sRGB) 8 bit", 8, V4L2_PIX_FMT_SBGGR8), +/* MT9M111 has only one fixed colorspace per pixelcode */ +struct mt9m111_datafmt { + enum v4l2_mbus_pixelcode code; + enum v4l2_colorspace colorspace; +}; + +/* Find a data format by a pixel code in an array */ +static const struct mt9m111_datafmt *mt9m111_find_datafmt( + enum v4l2_mbus_pixelcode code, const struct mt9m111_datafmt *fmt, + int n) +{ + int i; + for (i = 0; i < n; i++) + if (fmt[i].code == code) + return fmt + i; + + return NULL; +} + +static const struct mt9m111_datafmt mt9m111_colour_fmts[] = { + {V4L2_MBUS_FMT_YUYV8_2X8_LE, V4L2_COLORSPACE_JPEG}, + {V4L2_MBUS_FMT_YVYU8_2X8_LE, V4L2_COLORSPACE_JPEG}, + {V4L2_MBUS_FMT_YUYV8_2X8_BE, V4L2_COLORSPACE_JPEG}, + {V4L2_MBUS_FMT_YVYU8_2X8_BE, V4L2_COLORSPACE_JPEG}, + {V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB}, + {V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB}, + {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB}, + {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB}, }; enum mt9m111_context { @@ -152,7 +163,7 @@ struct mt9m111 { int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */ enum mt9m111_context context; struct v4l2_rect rect; - u32 pixfmt; + const struct mt9m111_datafmt *fmt; unsigned int gain; unsigned char autoexposure; unsigned char datawidth; @@ -258,8 +269,8 @@ static int mt9m111_setup_rect(struct i2c_client *client, int width = rect->width; int height = rect->height; - if (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8 || - mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16) + if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 || + mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) is_raw_format = 1; else is_raw_format = 0; @@ -307,7 +318,8 @@ static int mt9m111_setup_pixfmt(struct i2c_client *client, u16 outfmt) static int mt9m111_setfmt_bayer8(struct i2c_client *client) { - return mt9m111_setup_pixfmt(client, MT9M111_OUTFMT_PROCESSED_BAYER); + return mt9m111_setup_pixfmt(client, MT9M111_OUTFMT_PROCESSED_BAYER | + MT9M111_OUTFMT_RGB); } static int mt9m111_setfmt_bayer10(struct i2c_client *client) @@ -401,8 +413,8 @@ static int mt9m111_make_rect(struct i2c_client *client, { struct mt9m111 *mt9m111 = to_mt9m111(client); - if (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8 || - mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16) { + if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 || + mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) { /* Bayer format - even size lengths */ rect->width = ALIGN(rect->width, 2); rect->height = ALIGN(rect->height, 2); @@ -460,120 +472,139 @@ static int mt9m111_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) return 0; } -static int mt9m111_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int mt9m111_g_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = sd->priv; struct mt9m111 *mt9m111 = to_mt9m111(client); - struct v4l2_pix_format *pix = &f->fmt.pix; - pix->width = mt9m111->rect.width; - pix->height = mt9m111->rect.height; - pix->pixelformat = mt9m111->pixfmt; - pix->field = V4L2_FIELD_NONE; - pix->colorspace = V4L2_COLORSPACE_SRGB; + mf->width = mt9m111->rect.width; + mf->height = mt9m111->rect.height; + mf->code = mt9m111->fmt->code; + mf->field = V4L2_FIELD_NONE; return 0; } -static int mt9m111_set_pixfmt(struct i2c_client *client, u32 pixfmt) +static int mt9m111_set_pixfmt(struct i2c_client *client, + enum v4l2_mbus_pixelcode code) { struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; - switch (pixfmt) { - case V4L2_PIX_FMT_SBGGR8: + switch (code) { + case V4L2_MBUS_FMT_SBGGR8_1X8: ret = mt9m111_setfmt_bayer8(client); break; - case V4L2_PIX_FMT_SBGGR16: + case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE: ret = mt9m111_setfmt_bayer10(client); break; - case V4L2_PIX_FMT_RGB555: + case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE: ret = mt9m111_setfmt_rgb555(client); break; - case V4L2_PIX_FMT_RGB565: + case V4L2_MBUS_FMT_RGB565_2X8_LE: ret = mt9m111_setfmt_rgb565(client); break; - case V4L2_PIX_FMT_UYVY: + case V4L2_MBUS_FMT_YUYV8_2X8_BE: mt9m111->swap_yuv_y_chromas = 0; mt9m111->swap_yuv_cb_cr = 0; ret = mt9m111_setfmt_yuv(client); break; - case V4L2_PIX_FMT_VYUY: + case V4L2_MBUS_FMT_YVYU8_2X8_BE: mt9m111->swap_yuv_y_chromas = 0; mt9m111->swap_yuv_cb_cr = 1; ret = mt9m111_setfmt_yuv(client); break; - case V4L2_PIX_FMT_YUYV: + case V4L2_MBUS_FMT_YUYV8_2X8_LE: mt9m111->swap_yuv_y_chromas = 1; mt9m111->swap_yuv_cb_cr = 0; ret = mt9m111_setfmt_yuv(client); break; - case V4L2_PIX_FMT_YVYU: + case V4L2_MBUS_FMT_YVYU8_2X8_LE: mt9m111->swap_yuv_y_chromas = 1; mt9m111->swap_yuv_cb_cr = 1; ret = mt9m111_setfmt_yuv(client); break; default: dev_err(&client->dev, "Pixel format not handled : %x\n", - pixfmt); + code); ret = -EINVAL; } - if (!ret) - mt9m111->pixfmt = pixfmt; - return ret; } -static int mt9m111_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int mt9m111_s_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = sd->priv; + const struct mt9m111_datafmt *fmt; struct mt9m111 *mt9m111 = to_mt9m111(client); - struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { .left = mt9m111->rect.left, .top = mt9m111->rect.top, - .width = pix->width, - .height = pix->height, + .width = mf->width, + .height = mf->height, }; int ret; + fmt = mt9m111_find_datafmt(mf->code, mt9m111_colour_fmts, + ARRAY_SIZE(mt9m111_colour_fmts)); + if (!fmt) + return -EINVAL; + dev_dbg(&client->dev, - "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", __func__, - pix->pixelformat, rect.left, rect.top, rect.width, rect.height); + "%s code=%x left=%d, top=%d, width=%d, height=%d\n", __func__, + mf->code, rect.left, rect.top, rect.width, rect.height); ret = mt9m111_make_rect(client, &rect); if (!ret) - ret = mt9m111_set_pixfmt(client, pix->pixelformat); - if (!ret) - mt9m111->rect = rect; + ret = mt9m111_set_pixfmt(client, mf->code); + if (!ret) { + mt9m111->rect = rect; + mt9m111->fmt = fmt; + mf->colorspace = fmt->colorspace; + } + return ret; } -static int mt9m111_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int mt9m111_try_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { - struct v4l2_pix_format *pix = &f->fmt.pix; - bool bayer = pix->pixelformat == V4L2_PIX_FMT_SBGGR8 || - pix->pixelformat == V4L2_PIX_FMT_SBGGR16; + struct i2c_client *client = sd->priv; + struct mt9m111 *mt9m111 = to_mt9m111(client); + const struct mt9m111_datafmt *fmt; + bool bayer = mf->code == V4L2_MBUS_FMT_SBGGR8_1X8 || + mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE; + + fmt = mt9m111_find_datafmt(mf->code, mt9m111_colour_fmts, + ARRAY_SIZE(mt9m111_colour_fmts)); + if (!fmt) { + fmt = mt9m111->fmt; + mf->code = fmt->code; + } /* * With Bayer format enforce even side lengths, but let the user play * with the starting pixel */ - if (pix->height > MT9M111_MAX_HEIGHT) - pix->height = MT9M111_MAX_HEIGHT; - else if (pix->height < 2) - pix->height = 2; + if (mf->height > MT9M111_MAX_HEIGHT) + mf->height = MT9M111_MAX_HEIGHT; + else if (mf->height < 2) + mf->height = 2; else if (bayer) - pix->height = ALIGN(pix->height, 2); + mf->height = ALIGN(mf->height, 2); - if (pix->width > MT9M111_MAX_WIDTH) - pix->width = MT9M111_MAX_WIDTH; - else if (pix->width < 2) - pix->width = 2; + if (mf->width > MT9M111_MAX_WIDTH) + mf->width = MT9M111_MAX_WIDTH; + else if (mf->width < 2) + mf->width = 2; else if (bayer) - pix->width = ALIGN(pix->width, 2); + mf->width = ALIGN(mf->width, 2); + + mf->colorspace = fmt->colorspace; return 0; } @@ -863,7 +894,7 @@ static int mt9m111_restore_state(struct i2c_client *client) struct mt9m111 *mt9m111 = to_mt9m111(client); mt9m111_set_context(client, mt9m111->context); - mt9m111_set_pixfmt(client, mt9m111->pixfmt); + mt9m111_set_pixfmt(client, mt9m111->fmt->code); mt9m111_setup_rect(client, &mt9m111->rect); mt9m111_set_flip(client, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS); mt9m111_set_flip(client, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); @@ -952,9 +983,6 @@ static int mt9m111_video_probe(struct soc_camera_device *icd, goto ei2c; } - icd->formats = mt9m111_colour_formats; - icd->num_formats = ARRAY_SIZE(mt9m111_colour_formats); - dev_info(&client->dev, "Detected a MT9M11x chip ID %x\n", data); ei2c: @@ -971,13 +999,24 @@ static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = { #endif }; +static int mt9m111_enum_fmt(struct v4l2_subdev *sd, int index, + enum v4l2_mbus_pixelcode *code) +{ + if ((unsigned int)index >= ARRAY_SIZE(mt9m111_colour_fmts)) + return -EINVAL; + + *code = mt9m111_colour_fmts[index].code; + return 0; +} + static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = { - .s_fmt = mt9m111_s_fmt, - .g_fmt = mt9m111_g_fmt, - .try_fmt = mt9m111_try_fmt, + .s_mbus_fmt = mt9m111_s_fmt, + .g_mbus_fmt = mt9m111_g_fmt, + .try_mbus_fmt = mt9m111_try_fmt, .s_crop = mt9m111_s_crop, .g_crop = mt9m111_g_crop, .cropcap = mt9m111_cropcap, + .enum_mbus_fmt = mt9m111_enum_fmt, }; static struct v4l2_subdev_ops mt9m111_subdev_ops = { @@ -1024,6 +1063,7 @@ static int mt9m111_probe(struct i2c_client *client, mt9m111->rect.top = MT9M111_MIN_DARK_ROWS; mt9m111->rect.width = MT9M111_MAX_WIDTH; mt9m111->rect.height = MT9M111_MAX_HEIGHT; + mt9m111->fmt = &mt9m111_colour_fmts[0]; ret = mt9m111_video_probe(icd, client); if (ret) { diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index e3f664f..69c227f 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c @@ -60,15 +60,6 @@ SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | \ SOCAM_MASTER | SOCAM_DATAWIDTH_10) -static const struct soc_camera_data_format mt9t031_colour_formats[] = { - { - .name = "Bayer (sRGB) 10 bit", - .depth = 10, - .fourcc = V4L2_PIX_FMT_SGRBG10, - .colorspace = V4L2_COLORSPACE_SRGB, - } -}; - struct mt9t031 { struct v4l2_subdev subdev; struct v4l2_rect rect; /* Sensor window */ @@ -378,27 +369,27 @@ static int mt9t031_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) return 0; } -static int mt9t031_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int mt9t031_g_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = sd->priv; struct mt9t031 *mt9t031 = to_mt9t031(client); - struct v4l2_pix_format *pix = &f->fmt.pix; - pix->width = mt9t031->rect.width / mt9t031->xskip; - pix->height = mt9t031->rect.height / mt9t031->yskip; - pix->pixelformat = V4L2_PIX_FMT_SGRBG10; - pix->field = V4L2_FIELD_NONE; - pix->colorspace = V4L2_COLORSPACE_SRGB; + mf->width = mt9t031->rect.width / mt9t031->xskip; + mf->height = mt9t031->rect.height / mt9t031->yskip; + mf->code = V4L2_MBUS_FMT_SBGGR10_1X10; + mf->colorspace = V4L2_COLORSPACE_SRGB; + mf->field = V4L2_FIELD_NONE; return 0; } -static int mt9t031_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int mt9t031_s_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = sd->priv; struct mt9t031 *mt9t031 = to_mt9t031(client); struct soc_camera_device *icd = client->dev.platform_data; - struct v4l2_pix_format *pix = &f->fmt.pix; u16 xskip, yskip; struct v4l2_rect rect = mt9t031->rect; @@ -406,8 +397,11 @@ static int mt9t031_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) * try_fmt has put width and height within limits. * S_FMT: use binning and skipping for scaling */ - xskip = mt9t031_skip(&rect.width, pix->width, MT9T031_MAX_WIDTH); - yskip = mt9t031_skip(&rect.height, pix->height, MT9T031_MAX_HEIGHT); + xskip = mt9t031_skip(&rect.width, mf->width, MT9T031_MAX_WIDTH); + yskip = mt9t031_skip(&rect.height, mf->height, MT9T031_MAX_HEIGHT); + + mf->code = V4L2_MBUS_FMT_SBGGR10_1X10; + mf->colorspace = V4L2_COLORSPACE_SRGB; /* mt9t031_set_params() doesn't change width and height */ return mt9t031_set_params(icd, &rect, xskip, yskip); @@ -417,13 +411,15 @@ static int mt9t031_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) * If a user window larger than sensor window is requested, we'll increase the * sensor window. */ -static int mt9t031_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int mt9t031_try_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { - struct v4l2_pix_format *pix = &f->fmt.pix; - v4l_bound_align_image( - &pix->width, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH, 1, - &pix->height, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT, 1, 0); + &mf->width, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH, 1, + &mf->height, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT, 1, 0); + + mf->code = V4L2_MBUS_FMT_SBGGR10_1X10; + mf->colorspace = V4L2_COLORSPACE_SRGB; return 0; } @@ -684,7 +680,6 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) */ static int mt9t031_video_probe(struct i2c_client *client) { - struct soc_camera_device *icd = client->dev.platform_data; struct mt9t031 *mt9t031 = to_mt9t031(client); s32 data; int ret; @@ -699,8 +694,6 @@ static int mt9t031_video_probe(struct i2c_client *client) switch (data) { case 0x1621: mt9t031->model = V4L2_IDENT_MT9T031; - icd->formats = mt9t031_colour_formats; - icd->num_formats = ARRAY_SIZE(mt9t031_colour_formats); break; default: dev_err(&client->dev, @@ -741,14 +734,25 @@ static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { #endif }; +static int mt9t031_enum_fmt(struct v4l2_subdev *sd, int index, + enum v4l2_mbus_pixelcode *code) +{ + if (index) + return -EINVAL; + + *code = V4L2_MBUS_FMT_SBGGR10_1X10; + return 0; +} + static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { .s_stream = mt9t031_s_stream, - .s_fmt = mt9t031_s_fmt, - .g_fmt = mt9t031_g_fmt, - .try_fmt = mt9t031_try_fmt, + .s_mbus_fmt = mt9t031_s_fmt, + .g_mbus_fmt = mt9t031_g_fmt, + .try_mbus_fmt = mt9t031_try_fmt, .s_crop = mt9t031_s_crop, .g_crop = mt9t031_g_crop, .cropcap = mt9t031_cropcap, + .enum_mbus_fmt = mt9t031_enum_fmt, }; static struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = { diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index f60a9a1..91df7ec 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -64,41 +64,46 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\""); #define MT9V022_COLUMN_SKIP 1 #define MT9V022_ROW_SKIP 4 -static const struct soc_camera_data_format mt9v022_colour_formats[] = { +/* MT9V022 has only one fixed colorspace per pixelcode */ +struct mt9v022_datafmt { + enum v4l2_mbus_pixelcode code; + enum v4l2_colorspace colorspace; +}; + +/* Find a data format by a pixel code in an array */ +static const struct mt9v022_datafmt *mt9v022_find_datafmt( + enum v4l2_mbus_pixelcode code, const struct mt9v022_datafmt *fmt, + int n) +{ + int i; + for (i = 0; i < n; i++) + if (fmt[i].code == code) + return fmt + i; + + return NULL; +} + +static const struct mt9v022_datafmt mt9v022_colour_fmts[] = { /* * Order important: first natively supported, * second supported with a GPIO extender */ - { - .name = "Bayer (sRGB) 10 bit", - .depth = 10, - .fourcc = V4L2_PIX_FMT_SBGGR16, - .colorspace = V4L2_COLORSPACE_SRGB, - }, { - .name = "Bayer (sRGB) 8 bit", - .depth = 8, - .fourcc = V4L2_PIX_FMT_SBGGR8, - .colorspace = V4L2_COLORSPACE_SRGB, - } + {V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB}, + {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB}, }; -static const struct soc_camera_data_format mt9v022_monochrome_formats[] = { +static const struct mt9v022_datafmt mt9v022_monochrome_fmts[] = { /* Order important - see above */ - { - .name = "Monochrome 10 bit", - .depth = 10, - .fourcc = V4L2_PIX_FMT_Y16, - }, { - .name = "Monochrome 8 bit", - .depth = 8, - .fourcc = V4L2_PIX_FMT_GREY, - }, + {V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG}, + {V4L2_MBUS_FMT_GREY8_1X8, V4L2_COLORSPACE_JPEG}, }; struct mt9v022 { struct v4l2_subdev subdev; struct v4l2_rect rect; /* Sensor window */ - __u32 fourcc; + const struct mt9v022_datafmt *fmt; + const struct mt9v022_datafmt *fmts; + int num_fmts; int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ u16 chip_control; unsigned short y_skip_top; /* Lines to skip at the top */ @@ -275,8 +280,7 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) int ret; /* Bayer format - even size lengths */ - if (mt9v022->fourcc == V4L2_PIX_FMT_SBGGR8 || - mt9v022->fourcc == V4L2_PIX_FMT_SBGGR16) { + if (mt9v022->fmts == mt9v022_colour_fmts) { rect.width = ALIGN(rect.width, 2); rect.height = ALIGN(rect.height, 2); /* Let the user play with the starting pixel */ @@ -354,32 +358,32 @@ static int mt9v022_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) return 0; } -static int mt9v022_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int mt9v022_g_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = sd->priv; struct mt9v022 *mt9v022 = to_mt9v022(client); - struct v4l2_pix_format *pix = &f->fmt.pix; - pix->width = mt9v022->rect.width; - pix->height = mt9v022->rect.height; - pix->pixelformat = mt9v022->fourcc; - pix->field = V4L2_FIELD_NONE; - pix->colorspace = V4L2_COLORSPACE_SRGB; + mf->width = mt9v022->rect.width; + mf->height = mt9v022->rect.height; + mf->code = mt9v022->fmt->code; + mf->colorspace = mt9v022->fmt->colorspace; + mf->field = V4L2_FIELD_NONE; return 0; } -static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int mt9v022_s_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = sd->priv; struct mt9v022 *mt9v022 = to_mt9v022(client); - struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_crop a = { .c = { .left = mt9v022->rect.left, .top = mt9v022->rect.top, - .width = pix->width, - .height = pix->height, + .width = mf->width, + .height = mf->height, }, }; int ret; @@ -388,14 +392,14 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) * The caller provides a supported format, as verified per call to * icd->try_fmt(), datawidth is from our supported format list */ - switch (pix->pixelformat) { - case V4L2_PIX_FMT_GREY: - case V4L2_PIX_FMT_Y16: + switch (mf->code) { + case V4L2_MBUS_FMT_GREY8_1X8: + case V4L2_MBUS_FMT_Y10_1X10: if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM) return -EINVAL; break; - case V4L2_PIX_FMT_SBGGR8: - case V4L2_PIX_FMT_SBGGR16: + case V4L2_MBUS_FMT_SBGGR8_1X8: + case V4L2_MBUS_FMT_SBGGR10_1X10: if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC) return -EINVAL; break; @@ -409,27 +413,39 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) /* No support for scaling on this camera, just crop. */ ret = mt9v022_s_crop(sd, &a); if (!ret) { - pix->width = mt9v022->rect.width; - pix->height = mt9v022->rect.height; - mt9v022->fourcc = pix->pixelformat; + mf->width = mt9v022->rect.width; + mf->height = mt9v022->rect.height; + mt9v022->fmt = mt9v022_find_datafmt(mf->code, + mt9v022->fmts, mt9v022->num_fmts); + mf->colorspace = mt9v022->fmt->colorspace; } return ret; } -static int mt9v022_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int mt9v022_try_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = sd->priv; struct mt9v022 *mt9v022 = to_mt9v022(client); - struct v4l2_pix_format *pix = &f->fmt.pix; - int align = pix->pixelformat == V4L2_PIX_FMT_SBGGR8 || - pix->pixelformat == V4L2_PIX_FMT_SBGGR16; + const struct mt9v022_datafmt *fmt; + int align = mf->code == V4L2_MBUS_FMT_SBGGR8_1X8 || + mf->code == V4L2_MBUS_FMT_SBGGR10_1X10; - v4l_bound_align_image(&pix->width, MT9V022_MIN_WIDTH, + v4l_bound_align_image(&mf->width, MT9V022_MIN_WIDTH, MT9V022_MAX_WIDTH, align, - &pix->height, MT9V022_MIN_HEIGHT + mt9v022->y_skip_top, + &mf->height, MT9V022_MIN_HEIGHT + mt9v022->y_skip_top, MT9V022_MAX_HEIGHT + mt9v022->y_skip_top, align, 0); + fmt = mt9v022_find_datafmt(mf->code, mt9v022->fmts, + mt9v022->num_fmts); + if (!fmt) { + fmt = mt9v022->fmt; + mf->code = fmt->code; + } + + mf->colorspace = fmt->colorspace; + return 0; } @@ -749,17 +765,17 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, !strcmp("color", sensor_type))) { ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; - icd->formats = mt9v022_colour_formats; + mt9v022->fmts = mt9v022_colour_fmts; } else { ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 0x11); mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; - icd->formats = mt9v022_monochrome_formats; + mt9v022->fmts = mt9v022_monochrome_fmts; } if (ret < 0) goto ei2c; - icd->num_formats = 0; + mt9v022->num_fmts = 0; /* * This is a 10bit sensor, so by default we only allow 10bit. @@ -772,14 +788,14 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, flags = SOCAM_DATAWIDTH_10; if (flags & SOCAM_DATAWIDTH_10) - icd->num_formats++; + mt9v022->num_fmts++; else - icd->formats++; + mt9v022->fmts++; if (flags & SOCAM_DATAWIDTH_8) - icd->num_formats++; + mt9v022->num_fmts++; - mt9v022->fourcc = icd->formats->fourcc; + mt9v022->fmt = &mt9v022->fmts[0]; dev_info(&client->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? @@ -823,14 +839,28 @@ static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = { #endif }; +static int mt9v022_enum_fmt(struct v4l2_subdev *sd, int index, + enum v4l2_mbus_pixelcode *code) +{ + struct i2c_client *client = sd->priv; + struct mt9v022 *mt9v022 = to_mt9v022(client); + + if ((unsigned int)index >= mt9v022->num_fmts) + return -EINVAL; + + *code = mt9v022->fmts[index].code; + return 0; +} + static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = { .s_stream = mt9v022_s_stream, - .s_fmt = mt9v022_s_fmt, - .g_fmt = mt9v022_g_fmt, - .try_fmt = mt9v022_try_fmt, + .s_mbus_fmt = mt9v022_s_fmt, + .g_mbus_fmt = mt9v022_g_fmt, + .try_mbus_fmt = mt9v022_try_fmt, .s_crop = mt9v022_s_crop, .g_crop = mt9v022_g_crop, .cropcap = mt9v022_cropcap, + .enum_mbus_fmt = mt9v022_enum_fmt, }; static struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = { diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c index 4c1a439..2ba14fb 100644 --- a/drivers/media/video/mx1_camera.c +++ b/drivers/media/video/mx1_camera.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -94,9 +95,9 @@ /* buffer for one video frame */ struct mx1_buffer { /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; - const struct soc_camera_data_format *fmt; - int inwork; + struct videobuf_buffer vb; + enum v4l2_mbus_pixelcode code; + int inwork; }; /* @@ -128,9 +129,13 @@ static int mx1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) { struct soc_camera_device *icd = vq->priv_data; + int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, + icd->current_fmt->host_fmt); - *size = icd->user_width * icd->user_height * - ((icd->current_fmt->depth + 7) >> 3); + if (bytes_per_line < 0) + return bytes_per_line; + + *size = bytes_per_line * icd->user_height; if (!*count) *count = 32; @@ -169,6 +174,11 @@ static int mx1_videobuf_prepare(struct videobuf_queue *vq, struct soc_camera_device *icd = vq->priv_data; struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb); int ret; + int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, + icd->current_fmt->host_fmt); + + if (bytes_per_line < 0) + return bytes_per_line; dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); @@ -184,18 +194,18 @@ static int mx1_videobuf_prepare(struct videobuf_queue *vq, */ buf->inwork = 1; - if (buf->fmt != icd->current_fmt || + if (buf->code != icd->current_fmt->code || vb->width != icd->user_width || vb->height != icd->user_height || vb->field != field) { - buf->fmt = icd->current_fmt; + buf->code = icd->current_fmt->code; vb->width = icd->user_width; vb->height = icd->user_height; vb->field = field; vb->state = VIDEOBUF_NEEDS_INIT; } - vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3); + vb->size = bytes_per_line * vb->height; if (0 != vb->baddr && vb->bsize < vb->size) { ret = -EINVAL; goto out; @@ -497,12 +507,10 @@ static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) /* MX1 supports only 8bit buswidth */ common_flags = soc_camera_bus_param_compatible(camera_flags, - CSI_BUS_FLAGS); + CSI_BUS_FLAGS); if (!common_flags) return -EINVAL; - icd->buswidth = 8; - /* Make choises, based on platform choice */ if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) && (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) { @@ -555,7 +563,8 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd, struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; - int ret; + struct v4l2_mbus_framefmt mf; + int ret, buswidth; xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { @@ -564,12 +573,33 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd, return -EINVAL; } - ret = v4l2_subdev_call(sd, video, s_fmt, f); - if (!ret) { - icd->buswidth = xlate->buswidth; - icd->current_fmt = xlate->host_fmt; + buswidth = xlate->host_fmt->bits_per_sample; + if (buswidth > 8) { + dev_warn(icd->dev.parent, + "bits-per-sample %d for format %x unsupported\n", + buswidth, pix->pixelformat); + return -EINVAL; } + mf.width = pix->width; + mf.height = pix->height; + mf.field = pix->field; + mf.colorspace = pix->colorspace; + mf.code = xlate->code; + + ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); + if (ret < 0) + return ret; + + if (mf.code != xlate->code) + return -EINVAL; + + pix->width = mf.width; + pix->height = mf.height; + pix->field = mf.field; + pix->colorspace = mf.colorspace; + icd->current_fmt = xlate; + return ret; } @@ -577,10 +607,36 @@ static int mx1_camera_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + const struct soc_camera_format_xlate *xlate; + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_mbus_framefmt mf; + int ret; /* TODO: limit to mx1 hardware capabilities */ + xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); + if (!xlate) { + dev_warn(icd->dev.parent, "Format %x not found\n", + pix->pixelformat); + return -EINVAL; + } + + mf.width = pix->width; + mf.height = pix->height; + mf.field = pix->field; + mf.colorspace = pix->colorspace; + mf.code = xlate->code; + /* limit to sensor capabilities */ - return v4l2_subdev_call(sd, video, try_fmt, f); + ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); + if (ret < 0) + return ret; + + pix->width = mf.width; + pix->height = mf.height; + pix->field = mf.field; + pix->colorspace = mf.colorspace; + + return 0; } static int mx1_camera_reqbufs(struct soc_camera_file *icf, diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index ae7d483..bd297f5 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -63,7 +64,7 @@ struct mx3_camera_buffer { /* common v4l buffer stuff -- must be first */ struct videobuf_buffer vb; - const struct soc_camera_data_format *fmt; + enum v4l2_mbus_pixelcode code; /* One descriptot per scatterlist (per frame) */ struct dma_async_tx_descriptor *txd; @@ -118,8 +119,6 @@ struct dma_chan_request { enum ipu_channel id; }; -static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt); - static u32 csi_reg_read(struct mx3_camera_dev *mx3, off_t reg) { return __raw_readl(mx3->base + reg); @@ -211,17 +210,16 @@ static int mx3_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; - /* - * bits-per-pixel (depth) as specified in camera's pixel format does - * not necessarily match what the camera interface writes to RAM, but - * it should be good enough for now. - */ - unsigned int bpp = DIV_ROUND_UP(icd->current_fmt->depth, 8); + int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, + icd->current_fmt->host_fmt); + + if (bytes_per_line < 0) + return bytes_per_line; if (!mx3_cam->idmac_channel[0]) return -EINVAL; - *size = icd->user_width * icd->user_height * bpp; + *size = bytes_per_line * icd->user_height; if (!*count) *count = 32; @@ -241,21 +239,26 @@ static int mx3_videobuf_prepare(struct videobuf_queue *vq, struct mx3_camera_dev *mx3_cam = ici->priv; struct mx3_camera_buffer *buf = container_of(vb, struct mx3_camera_buffer, vb); - /* current_fmt _must_ always be set */ - size_t new_size = icd->user_width * icd->user_height * - ((icd->current_fmt->depth + 7) >> 3); + size_t new_size; int ret; + int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, + icd->current_fmt->host_fmt); + + if (bytes_per_line < 0) + return bytes_per_line; + + new_size = bytes_per_line * icd->user_height; /* * I think, in buf_prepare you only have to protect global data, * the actual buffer is yours */ - if (buf->fmt != icd->current_fmt || + if (buf->code != icd->current_fmt->code || vb->width != icd->user_width || vb->height != icd->user_height || vb->field != field) { - buf->fmt = icd->current_fmt; + buf->code = icd->current_fmt->code; vb->width = icd->user_width; vb->height = icd->user_height; vb->field = field; @@ -348,13 +351,13 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq, struct dma_async_tx_descriptor *txd = buf->txd; struct idmac_channel *ichan = to_idmac_chan(txd->chan); struct idmac_video_param *video = &ichan->params.video; - const struct soc_camera_data_format *data_fmt = icd->current_fmt; dma_cookie_t cookie; + u32 fourcc = icd->current_fmt->host_fmt->fourcc; BUG_ON(!irqs_disabled()); /* This is the configuration of one sg-element */ - video->out_pixel_fmt = fourcc_to_ipu_pix(data_fmt->fourcc); + video->out_pixel_fmt = fourcc_to_ipu_pix(fourcc); video->out_width = icd->user_width; video->out_height = icd->user_height; video->out_stride = icd->user_width; @@ -568,28 +571,33 @@ static int test_platform_param(struct mx3_camera_dev *mx3_cam, * If requested data width is supported by the platform, use it or any * possible lower value - i.MX31 is smart enough to schift bits */ + if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15) + *flags |= SOCAM_DATAWIDTH_15 | SOCAM_DATAWIDTH_10 | + SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4; + else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10) + *flags |= SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8 | + SOCAM_DATAWIDTH_4; + else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8) + *flags |= SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4; + else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4) + *flags |= SOCAM_DATAWIDTH_4; + switch (buswidth) { case 15: - if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15)) + if (!(*flags & SOCAM_DATAWIDTH_15)) return -EINVAL; - *flags |= SOCAM_DATAWIDTH_15 | SOCAM_DATAWIDTH_10 | - SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4; break; case 10: - if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10)) + if (!(*flags & SOCAM_DATAWIDTH_10)) return -EINVAL; - *flags |= SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8 | - SOCAM_DATAWIDTH_4; break; case 8: - if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8)) + if (!(*flags & SOCAM_DATAWIDTH_8)) return -EINVAL; - *flags |= SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4; break; case 4: - if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4)) + if (!(*flags & SOCAM_DATAWIDTH_4)) return -EINVAL; - *flags |= SOCAM_DATAWIDTH_4; break; default: dev_warn(mx3_cam->soc_host.v4l2_dev.dev, @@ -638,91 +646,92 @@ static bool chan_filter(struct dma_chan *chan, void *arg) pdata->dma_dev == chan->device->dev; } -static const struct soc_camera_data_format mx3_camera_formats[] = { +static const struct soc_mbus_pixelfmt mx3_camera_formats[] = { { - .name = "Bayer (sRGB) 8 bit", - .depth = 8, - .fourcc = V4L2_PIX_FMT_SBGGR8, - .colorspace = V4L2_COLORSPACE_SRGB, + .fourcc = V4L2_PIX_FMT_SBGGR8, + .name = "Bayer BGGR (sRGB) 8 bit", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_NONE, + .order = SOC_MBUS_ORDER_LE, }, { - .name = "Monochrome 8 bit", - .depth = 8, - .fourcc = V4L2_PIX_FMT_GREY, - .colorspace = V4L2_COLORSPACE_JPEG, + .fourcc = V4L2_PIX_FMT_GREY, + .name = "Monochrome 8 bit", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_NONE, + .order = SOC_MBUS_ORDER_LE, }, }; -static bool buswidth_supported(struct soc_camera_host *ici, int depth) +/* This will be corrected as we get more formats */ +static bool mx3_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt) { - struct mx3_camera_dev *mx3_cam = ici->priv; - - switch (depth) { - case 4: - return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4); - case 8: - return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8); - case 10: - return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10); - case 15: - return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15); - } - return false; + return fmt->packing == SOC_MBUS_PACKING_NONE || + (fmt->bits_per_sample == 8 && + fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) || + (fmt->bits_per_sample > 8 && + fmt->packing == SOC_MBUS_PACKING_EXTEND16); } static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, struct soc_camera_format_xlate *xlate) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - int formats = 0, buswidth, ret; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct device *dev = icd->dev.parent; + int formats = 0, ret; + enum v4l2_mbus_pixelcode code; + const struct soc_mbus_pixelfmt *fmt; - buswidth = icd->formats[idx].depth; + ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code); + if (ret < 0) + /* No more formats */ + return 0; - if (!buswidth_supported(ici, buswidth)) + fmt = soc_mbus_get_fmtdesc(code); + if (!fmt) { + dev_err(icd->dev.parent, + "Invalid format code #%d: %d\n", idx, code); return 0; + } - ret = mx3_camera_try_bus_param(icd, buswidth); + /* This also checks support for the requested bits-per-sample */ + ret = mx3_camera_try_bus_param(icd, fmt->bits_per_sample); if (ret < 0) return 0; - switch (icd->formats[idx].fourcc) { - case V4L2_PIX_FMT_SGRBG10: + switch (code) { + case V4L2_MBUS_FMT_SBGGR10_1X10: formats++; if (xlate) { - xlate->host_fmt = &mx3_camera_formats[0]; - xlate->cam_fmt = icd->formats + idx; - xlate->buswidth = buswidth; + xlate->host_fmt = &mx3_camera_formats[0]; + xlate->code = code; xlate++; - dev_dbg(icd->dev.parent, - "Providing format %s using %s\n", - mx3_camera_formats[0].name, - icd->formats[idx].name); + dev_dbg(dev, "Providing format %s using code %d\n", + mx3_camera_formats[0].name, code); } - goto passthrough; - case V4L2_PIX_FMT_Y16: + break; + case V4L2_MBUS_FMT_Y10_1X10: formats++; if (xlate) { - xlate->host_fmt = &mx3_camera_formats[1]; - xlate->cam_fmt = icd->formats + idx; - xlate->buswidth = buswidth; + xlate->host_fmt = &mx3_camera_formats[1]; + xlate->code = code; xlate++; - dev_dbg(icd->dev.parent, - "Providing format %s using %s\n", - mx3_camera_formats[0].name, - icd->formats[idx].name); + dev_dbg(dev, "Providing format %s using code %d\n", + mx3_camera_formats[1].name, code); } + break; default: -passthrough: - /* Generic pass-through */ - formats++; - if (xlate) { - xlate->host_fmt = icd->formats + idx; - xlate->cam_fmt = icd->formats + idx; - xlate->buswidth = buswidth; - xlate++; - dev_dbg(icd->dev.parent, - "Providing format %s in pass-through mode\n", - icd->formats[idx].name); - } + if (!mx3_camera_packing_supported(fmt)) + return 0; + } + + /* Generic pass-through */ + formats++; + if (xlate) { + xlate->host_fmt = fmt; + xlate->code = code; + xlate++; + dev_dbg(dev, "Providing format %x in pass-through mode\n", + xlate->host_fmt->fourcc); } return formats; @@ -806,8 +815,7 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - struct v4l2_format f = {.type = V4L2_BUF_TYPE_VIDEO_CAPTURE}; - struct v4l2_pix_format *pix = &f.fmt.pix; + struct v4l2_mbus_framefmt mf; int ret; soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096); @@ -818,19 +826,19 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, return ret; /* The capture device might have changed its output */ - ret = v4l2_subdev_call(sd, video, g_fmt, &f); + ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); if (ret < 0) return ret; - if (pix->width & 7) { + if (mf.width & 7) { /* Ouch! We can only handle 8-byte aligned width... */ - stride_align(&pix->width); - ret = v4l2_subdev_call(sd, video, s_fmt, &f); + stride_align(&mf.width); + ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); if (ret < 0) return ret; } - if (pix->width != icd->user_width || pix->height != icd->user_height) { + if (mf.width != icd->user_width || mf.height != icd->user_height) { /* * We now know pixel formats and can decide upon DMA-channel(s) * So far only direct camera-to-memory is supported @@ -841,14 +849,14 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, return ret; } - configure_geometry(mx3_cam, pix->width, pix->height); + configure_geometry(mx3_cam, mf.width, mf.height); } dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n", - pix->width, pix->height); + mf.width, mf.height); - icd->user_width = pix->width; - icd->user_height = pix->height; + icd->user_width = mf.width; + icd->user_height = mf.height; return ret; } @@ -861,6 +869,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_mbus_framefmt mf; int ret; xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); @@ -885,11 +894,24 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, configure_geometry(mx3_cam, pix->width, pix->height); - ret = v4l2_subdev_call(sd, video, s_fmt, f); - if (!ret) { - icd->buswidth = xlate->buswidth; - icd->current_fmt = xlate->host_fmt; - } + mf.width = pix->width; + mf.height = pix->height; + mf.field = pix->field; + mf.colorspace = pix->colorspace; + mf.code = xlate->code; + + ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); + if (ret < 0) + return ret; + + if (mf.code != xlate->code) + return -EINVAL; + + pix->width = mf.width; + pix->height = mf.height; + pix->field = mf.field; + pix->colorspace = mf.colorspace; + icd->current_fmt = xlate; dev_dbg(icd->dev.parent, "Sensor set %dx%d\n", pix->width, pix->height); @@ -902,8 +924,8 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd, struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_mbus_framefmt mf; __u32 pixfmt = pix->pixelformat; - enum v4l2_field field; int ret; xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); @@ -918,23 +940,37 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd, if (pix->width > 4096) pix->width = 4096; - pix->bytesperline = pix->width * - DIV_ROUND_UP(xlate->host_fmt->depth, 8); + pix->bytesperline = soc_mbus_bytes_per_line(pix->width, + xlate->host_fmt); + if (pix->bytesperline < 0) + return pix->bytesperline; pix->sizeimage = pix->height * pix->bytesperline; - /* camera has to see its format, but the user the original one */ - pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ - ret = v4l2_subdev_call(sd, video, try_fmt, f); - pix->pixelformat = xlate->host_fmt->fourcc; + mf.width = pix->width; + mf.height = pix->height; + mf.field = pix->field; + mf.colorspace = pix->colorspace; + mf.code = xlate->code; - field = pix->field; + ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); + if (ret < 0) + return ret; - if (field == V4L2_FIELD_ANY) { + pix->width = mf.width; + pix->height = mf.height; + pix->colorspace = mf.colorspace; + + switch (mf.field) { + case V4L2_FIELD_ANY: pix->field = V4L2_FIELD_NONE; - } else if (field != V4L2_FIELD_NONE) { - dev_err(icd->dev.parent, "Field type %d unsupported.\n", field); - return -EINVAL; + break; + case V4L2_FIELD_NONE: + break; + default: + dev_err(icd->dev.parent, "Field type %d unsupported.\n", + mf.field); + ret = -EINVAL; } return ret; @@ -970,18 +1006,26 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) struct mx3_camera_dev *mx3_cam = ici->priv; unsigned long bus_flags, camera_flags, common_flags; u32 dw, sens_conf; - int ret = test_platform_param(mx3_cam, icd->buswidth, &bus_flags); + const struct soc_mbus_pixelfmt *fmt; + int buswidth; + int ret; const struct soc_camera_format_xlate *xlate; struct device *dev = icd->dev.parent; + fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code); + if (!fmt) + return -EINVAL; + + buswidth = fmt->bits_per_sample; + ret = test_platform_param(mx3_cam, buswidth, &bus_flags); + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { dev_warn(dev, "Format %x not found\n", pixfmt); return -EINVAL; } - dev_dbg(dev, "requested bus width %d bit: %d\n", - icd->buswidth, ret); + dev_dbg(dev, "requested bus width %d bit: %d\n", buswidth, ret); if (ret < 0) return ret; @@ -1082,7 +1126,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) sens_conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT; /* Just do what we're asked to do */ - switch (xlate->host_fmt->depth) { + switch (xlate->host_fmt->bits_per_sample) { case 4: dw = 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; break; diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index dcb690c..3a45e94 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c @@ -24,6 +24,7 @@ #include #include #include +#include #include /* @@ -382,7 +383,8 @@ struct regval_list { }; struct ov772x_color_format { - const struct soc_camera_data_format *format; + enum v4l2_mbus_pixelcode code; + enum v4l2_colorspace colorspace; u8 dsp3; u8 com3; u8 com7; @@ -399,7 +401,7 @@ struct ov772x_win_size { struct ov772x_priv { struct v4l2_subdev subdev; struct ov772x_camera_info *info; - const struct ov772x_color_format *fmt; + const struct ov772x_color_format *cfmt; const struct ov772x_win_size *win; int model; unsigned short flag_vflip:1; @@ -434,93 +436,57 @@ static const struct regval_list ov772x_vga_regs[] = { }; /* - * supported format list - */ - -#define SETFOURCC(type) .name = (#type), .fourcc = (V4L2_PIX_FMT_ ## type) -static const struct soc_camera_data_format ov772x_fmt_lists[] = { - { - SETFOURCC(YUYV), - .depth = 16, - .colorspace = V4L2_COLORSPACE_JPEG, - }, - { - SETFOURCC(YVYU), - .depth = 16, - .colorspace = V4L2_COLORSPACE_JPEG, - }, - { - SETFOURCC(UYVY), - .depth = 16, - .colorspace = V4L2_COLORSPACE_JPEG, - }, - { - SETFOURCC(RGB555), - .depth = 16, - .colorspace = V4L2_COLORSPACE_SRGB, - }, - { - SETFOURCC(RGB555X), - .depth = 16, - .colorspace = V4L2_COLORSPACE_SRGB, - }, - { - SETFOURCC(RGB565), - .depth = 16, - .colorspace = V4L2_COLORSPACE_SRGB, - }, - { - SETFOURCC(RGB565X), - .depth = 16, - .colorspace = V4L2_COLORSPACE_SRGB, - }, -}; - -/* - * color format list + * supported color format list */ static const struct ov772x_color_format ov772x_cfmts[] = { { - .format = &ov772x_fmt_lists[0], - .dsp3 = 0x0, - .com3 = SWAP_YUV, - .com7 = OFMT_YUV, + .code = V4L2_MBUS_FMT_YUYV8_2X8_LE, + .colorspace = V4L2_COLORSPACE_JPEG, + .dsp3 = 0x0, + .com3 = SWAP_YUV, + .com7 = OFMT_YUV, }, { - .format = &ov772x_fmt_lists[1], - .dsp3 = UV_ON, - .com3 = SWAP_YUV, - .com7 = OFMT_YUV, + .code = V4L2_MBUS_FMT_YVYU8_2X8_LE, + .colorspace = V4L2_COLORSPACE_JPEG, + .dsp3 = UV_ON, + .com3 = SWAP_YUV, + .com7 = OFMT_YUV, }, { - .format = &ov772x_fmt_lists[2], - .dsp3 = 0x0, - .com3 = 0x0, - .com7 = OFMT_YUV, + .code = V4L2_MBUS_FMT_YUYV8_2X8_BE, + .colorspace = V4L2_COLORSPACE_JPEG, + .dsp3 = 0x0, + .com3 = 0x0, + .com7 = OFMT_YUV, }, { - .format = &ov772x_fmt_lists[3], - .dsp3 = 0x0, - .com3 = SWAP_RGB, - .com7 = FMT_RGB555 | OFMT_RGB, + .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, + .colorspace = V4L2_COLORSPACE_SRGB, + .dsp3 = 0x0, + .com3 = SWAP_RGB, + .com7 = FMT_RGB555 | OFMT_RGB, }, { - .format = &ov772x_fmt_lists[4], - .dsp3 = 0x0, - .com3 = 0x0, - .com7 = FMT_RGB555 | OFMT_RGB, + .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE, + .colorspace = V4L2_COLORSPACE_SRGB, + .dsp3 = 0x0, + .com3 = 0x0, + .com7 = FMT_RGB555 | OFMT_RGB, }, { - .format = &ov772x_fmt_lists[5], - .dsp3 = 0x0, - .com3 = SWAP_RGB, - .com7 = FMT_RGB565 | OFMT_RGB, + .code = V4L2_MBUS_FMT_RGB565_2X8_LE, + .colorspace = V4L2_COLORSPACE_SRGB, + .dsp3 = 0x0, + .com3 = SWAP_RGB, + .com7 = FMT_RGB565 | OFMT_RGB, }, { - .format = &ov772x_fmt_lists[6], - .dsp3 = 0x0, - .com3 = 0x0, - .com7 = FMT_RGB565 | OFMT_RGB, + .code = V4L2_MBUS_FMT_RGB565_2X8_BE, + .colorspace = V4L2_COLORSPACE_SRGB, + .dsp3 = 0x0, + .com3 = 0x0, + .com7 = FMT_RGB565 | OFMT_RGB, }, }; @@ -642,15 +608,15 @@ static int ov772x_s_stream(struct v4l2_subdev *sd, int enable) return 0; } - if (!priv->win || !priv->fmt) { + if (!priv->win || !priv->cfmt) { dev_err(&client->dev, "norm or win select error\n"); return -EPERM; } ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); - dev_dbg(&client->dev, "format %s, win %s\n", - priv->fmt->format->name, priv->win->name); + dev_dbg(&client->dev, "format %d, win %s\n", + priv->cfmt->code, priv->win->name); return 0; } @@ -806,8 +772,8 @@ static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height) return win; } -static int ov772x_set_params(struct i2c_client *client, - u32 *width, u32 *height, u32 pixfmt) +static int ov772x_set_params(struct i2c_client *client, u32 *width, u32 *height, + enum v4l2_mbus_pixelcode code) { struct ov772x_priv *priv = to_ov772x(client); int ret = -EINVAL; @@ -817,14 +783,14 @@ static int ov772x_set_params(struct i2c_client *client, /* * select format */ - priv->fmt = NULL; + priv->cfmt = NULL; for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) { - if (pixfmt == ov772x_cfmts[i].format->fourcc) { - priv->fmt = ov772x_cfmts + i; + if (code == ov772x_cfmts[i].code) { + priv->cfmt = ov772x_cfmts + i; break; } } - if (!priv->fmt) + if (!priv->cfmt) goto ov772x_set_fmt_error; /* @@ -894,7 +860,7 @@ static int ov772x_set_params(struct i2c_client *client, /* * set DSP_CTRL3 */ - val = priv->fmt->dsp3; + val = priv->cfmt->dsp3; if (val) { ret = ov772x_mask_set(client, DSP_CTRL3, UV_MASK, val); @@ -905,7 +871,7 @@ static int ov772x_set_params(struct i2c_client *client, /* * set COM3 */ - val = priv->fmt->com3; + val = priv->cfmt->com3; if (priv->info->flags & OV772X_FLAG_VFLIP) val |= VFLIP_IMG; if (priv->info->flags & OV772X_FLAG_HFLIP) @@ -923,9 +889,9 @@ static int ov772x_set_params(struct i2c_client *client, /* * set COM7 */ - val = priv->win->com7_bit | priv->fmt->com7; + val = priv->win->com7_bit | priv->cfmt->com7; ret = ov772x_mask_set(client, - COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK), + COM7, SLCT_MASK | FMT_MASK | OFMT_MASK, val); if (ret < 0) goto ov772x_set_fmt_error; @@ -951,7 +917,7 @@ ov772x_set_fmt_error: ov772x_reset(client); priv->win = NULL; - priv->fmt = NULL; + priv->cfmt = NULL; return ret; } @@ -981,54 +947,79 @@ static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) return 0; } -static int ov772x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int ov772x_g_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = sd->priv; struct ov772x_priv *priv = to_ov772x(client); - struct v4l2_pix_format *pix = &f->fmt.pix; - if (!priv->win || !priv->fmt) { + if (!priv->win || !priv->cfmt) { u32 width = VGA_WIDTH, height = VGA_HEIGHT; int ret = ov772x_set_params(client, &width, &height, - V4L2_PIX_FMT_YUYV); + V4L2_MBUS_FMT_YUYV8_2X8_LE); if (ret < 0) return ret; } - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - pix->width = priv->win->width; - pix->height = priv->win->height; - pix->pixelformat = priv->fmt->format->fourcc; - pix->colorspace = priv->fmt->format->colorspace; - pix->field = V4L2_FIELD_NONE; + mf->width = priv->win->width; + mf->height = priv->win->height; + mf->code = priv->cfmt->code; + mf->colorspace = priv->cfmt->colorspace; + mf->field = V4L2_FIELD_NONE; return 0; } -static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int ov772x_s_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = sd->priv; - struct v4l2_pix_format *pix = &f->fmt.pix; + struct ov772x_priv *priv = to_ov772x(client); + int ret = ov772x_set_params(client, &mf->width, &mf->height, + mf->code); + + if (!ret) + mf->colorspace = priv->cfmt->colorspace; - return ov772x_set_params(client, &pix->width, &pix->height, - pix->pixelformat); + return ret; } static int ov772x_try_fmt(struct v4l2_subdev *sd, - struct v4l2_format *f) + struct v4l2_mbus_framefmt *mf) { - struct v4l2_pix_format *pix = &f->fmt.pix; + struct i2c_client *client = sd->priv; + struct ov772x_priv *priv = to_ov772x(client); const struct ov772x_win_size *win; + int i; /* * select suitable win */ - win = ov772x_select_win(pix->width, pix->height); + win = ov772x_select_win(mf->width, mf->height); + + mf->width = win->width; + mf->height = win->height; + mf->field = V4L2_FIELD_NONE; - pix->width = win->width; - pix->height = win->height; - pix->field = V4L2_FIELD_NONE; + for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) + if (mf->code == ov772x_cfmts[i].code) + break; + + if (i == ARRAY_SIZE(ov772x_cfmts)) { + /* Unsupported format requested. Propose either */ + if (priv->cfmt) { + /* the current one or */ + mf->colorspace = priv->cfmt->colorspace; + mf->code = priv->cfmt->code; + } else { + /* the default one */ + mf->colorspace = ov772x_cfmts[0].colorspace; + mf->code = ov772x_cfmts[0].code; + } + } else { + /* Also return the colorspace */ + mf->colorspace = ov772x_cfmts[i].colorspace; + } return 0; } @@ -1057,9 +1048,6 @@ static int ov772x_video_probe(struct soc_camera_device *icd, return -ENODEV; } - icd->formats = ov772x_fmt_lists; - icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists); - /* * check and show product ID and manufacturer ID */ @@ -1109,13 +1097,24 @@ static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = { #endif }; +static int ov772x_enum_fmt(struct v4l2_subdev *sd, int index, + enum v4l2_mbus_pixelcode *code) +{ + if ((unsigned int)index >= ARRAY_SIZE(ov772x_cfmts)) + return -EINVAL; + + *code = ov772x_cfmts[index].code; + return 0; +} + static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = { .s_stream = ov772x_s_stream, - .g_fmt = ov772x_g_fmt, - .s_fmt = ov772x_s_fmt, - .try_fmt = ov772x_try_fmt, + .g_mbus_fmt = ov772x_g_fmt, + .s_mbus_fmt = ov772x_s_fmt, + .try_mbus_fmt = ov772x_try_fmt, .cropcap = ov772x_cropcap, .g_crop = ov772x_g_crop, + .enum_mbus_fmt = ov772x_enum_fmt, }; static struct v4l2_subdev_ops ov772x_subdev_ops = { diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c index c81ae219..47bf60c 100644 --- a/drivers/media/video/ov9640.c +++ b/drivers/media/video/ov9640.c @@ -154,19 +154,10 @@ static const struct ov9640_reg ov9640_regs_rgb[] = { { OV9640_MTXS, 0x65 }, }; -/* - * TODO: this sensor also supports RGB555 and RGB565 formats, but support for - * them has not yet been sufficiently tested and so it is not included with - * this version of the driver. To test and debug these formats add two entries - * to the below array, see ov722x.c for an example. - */ -static const struct soc_camera_data_format ov9640_fmt_lists[] = { - { - .name = "UYVY", - .fourcc = V4L2_PIX_FMT_UYVY, - .depth = 16, - .colorspace = V4L2_COLORSPACE_JPEG, - }, +static enum v4l2_mbus_pixelcode ov9640_codes[] = { + V4L2_MBUS_FMT_YUYV8_2X8_BE, + V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, + V4L2_MBUS_FMT_RGB565_2X8_LE, }; static const struct v4l2_queryctrl ov9640_controls[] = { @@ -434,20 +425,22 @@ static void ov9640_res_roundup(u32 *width, u32 *height) } /* Prepare necessary register changes depending on color encoding */ -static void ov9640_alter_regs(u32 pixfmt, struct ov9640_reg_alt *alt) +static void ov9640_alter_regs(enum v4l2_mbus_pixelcode code, + struct ov9640_reg_alt *alt) { - switch (pixfmt) { - case V4L2_PIX_FMT_UYVY: + switch (code) { + default: + case V4L2_MBUS_FMT_YUYV8_2X8_BE: alt->com12 = OV9640_COM12_YUV_AVG; alt->com13 = OV9640_COM13_Y_DELAY_EN | OV9640_COM13_YUV_DLY(0x01); break; - case V4L2_PIX_FMT_RGB555: + case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE: alt->com7 = OV9640_COM7_RGB; alt->com13 = OV9640_COM13_RGB_AVG; alt->com15 = OV9640_COM15_RGB_555; break; - case V4L2_PIX_FMT_RGB565: + case V4L2_MBUS_FMT_RGB565_2X8_LE: alt->com7 = OV9640_COM7_RGB; alt->com13 = OV9640_COM13_RGB_AVG; alt->com15 = OV9640_COM15_RGB_565; @@ -456,8 +449,8 @@ static void ov9640_alter_regs(u32 pixfmt, struct ov9640_reg_alt *alt) } /* Setup registers according to resolution and color encoding */ -static int ov9640_write_regs(struct i2c_client *client, - u32 width, u32 pixfmt, struct ov9640_reg_alt *alts) +static int ov9640_write_regs(struct i2c_client *client, u32 width, + enum v4l2_mbus_pixelcode code, struct ov9640_reg_alt *alts) { const struct ov9640_reg *ov9640_regs, *matrix_regs; int ov9640_regs_len, matrix_regs_len; @@ -500,7 +493,7 @@ static int ov9640_write_regs(struct i2c_client *client, } /* select color matrix configuration for given color encoding */ - if (pixfmt == V4L2_PIX_FMT_UYVY) { + if (code == V4L2_MBUS_FMT_YUYV8_2X8_BE) { matrix_regs = ov9640_regs_yuv; matrix_regs_len = ARRAY_SIZE(ov9640_regs_yuv); } else { @@ -562,15 +555,17 @@ static int ov9640_prog_dflt(struct i2c_client *client) } /* set the format we will capture in */ -static int ov9640_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int ov9640_s_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = sd->priv; - struct v4l2_pix_format *pix = &f->fmt.pix; struct ov9640_reg_alt alts = {0}; + enum v4l2_colorspace cspace; + enum v4l2_mbus_pixelcode code = mf->code; int ret; - ov9640_res_roundup(&pix->width, &pix->height); - ov9640_alter_regs(pix->pixelformat, &alts); + ov9640_res_roundup(&mf->width, &mf->height); + ov9640_alter_regs(mf->code, &alts); ov9640_reset(client); @@ -578,19 +573,57 @@ static int ov9640_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) if (ret) return ret; - return ov9640_write_regs(client, pix->width, pix->pixelformat, &alts); + switch (code) { + case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE: + case V4L2_MBUS_FMT_RGB565_2X8_LE: + cspace = V4L2_COLORSPACE_SRGB; + break; + default: + code = V4L2_MBUS_FMT_YUYV8_2X8_BE; + case V4L2_MBUS_FMT_YUYV8_2X8_BE: + cspace = V4L2_COLORSPACE_JPEG; + } + + ret = ov9640_write_regs(client, mf->width, code, &alts); + if (!ret) { + mf->code = code; + mf->colorspace = cspace; + } + + return ret; } -static int ov9640_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int ov9640_try_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { - struct v4l2_pix_format *pix = &f->fmt.pix; + ov9640_res_roundup(&mf->width, &mf->height); - ov9640_res_roundup(&pix->width, &pix->height); - pix->field = V4L2_FIELD_NONE; + mf->field = V4L2_FIELD_NONE; + + switch (mf->code) { + case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE: + case V4L2_MBUS_FMT_RGB565_2X8_LE: + mf->colorspace = V4L2_COLORSPACE_SRGB; + break; + default: + mf->code = V4L2_MBUS_FMT_YUYV8_2X8_BE; + case V4L2_MBUS_FMT_YUYV8_2X8_BE: + mf->colorspace = V4L2_COLORSPACE_JPEG; + } return 0; } +static int ov9640_enum_fmt(struct v4l2_subdev *sd, int index, + enum v4l2_mbus_pixelcode *code) +{ + if ((unsigned int)index >= ARRAY_SIZE(ov9640_codes)) + return -EINVAL; + + *code = ov9640_codes[index]; + return 0; +} + static int ov9640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { a->c.left = 0; @@ -637,9 +670,6 @@ static int ov9640_video_probe(struct soc_camera_device *icd, goto err; } - icd->formats = ov9640_fmt_lists; - icd->num_formats = ARRAY_SIZE(ov9640_fmt_lists); - /* * check and show product ID and manufacturer ID */ @@ -702,11 +732,12 @@ static struct v4l2_subdev_core_ops ov9640_core_ops = { }; static struct v4l2_subdev_video_ops ov9640_video_ops = { - .s_stream = ov9640_s_stream, - .s_fmt = ov9640_s_fmt, - .try_fmt = ov9640_try_fmt, - .cropcap = ov9640_cropcap, - .g_crop = ov9640_g_crop, + .s_stream = ov9640_s_stream, + .s_mbus_fmt = ov9640_s_fmt, + .try_mbus_fmt = ov9640_try_fmt, + .enum_mbus_fmt = ov9640_enum_fmt, + .cropcap = ov9640_cropcap, + .g_crop = ov9640_g_crop, }; diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index f063f59..294f860 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -32,6 +32,7 @@ #include #include #include +#include #include @@ -183,16 +184,12 @@ struct pxa_cam_dma { /* buffer for one video frame */ struct pxa_buffer { /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; - - const struct soc_camera_data_format *fmt; - + struct videobuf_buffer vb; + enum v4l2_mbus_pixelcode code; /* our descriptor lists for Y, U and V channels */ - struct pxa_cam_dma dmas[3]; - - int inwork; - - enum pxa_camera_active_dma active_dma; + struct pxa_cam_dma dmas[3]; + int inwork; + enum pxa_camera_active_dma active_dma; }; struct pxa_camera_dev { @@ -243,11 +240,15 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) { struct soc_camera_device *icd = vq->priv_data; + int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, + icd->current_fmt->host_fmt); + + if (bytes_per_line < 0) + return bytes_per_line; dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); - *size = roundup(icd->user_width * icd->user_height * - ((icd->current_fmt->depth + 7) >> 3), 8); + *size = bytes_per_line * icd->user_height; if (0 == *count) *count = 32; @@ -433,6 +434,11 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); int ret; int size_y, size_u = 0, size_v = 0; + int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, + icd->current_fmt->host_fmt); + + if (bytes_per_line < 0) + return bytes_per_line; dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); @@ -456,18 +462,18 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, */ buf->inwork = 1; - if (buf->fmt != icd->current_fmt || + if (buf->code != icd->current_fmt->code || vb->width != icd->user_width || vb->height != icd->user_height || vb->field != field) { - buf->fmt = icd->current_fmt; + buf->code = icd->current_fmt->code; vb->width = icd->user_width; vb->height = icd->user_height; vb->field = field; vb->state = VIDEOBUF_NEEDS_INIT; } - vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3); + vb->size = bytes_per_line * vb->height; if (0 != vb->baddr && vb->bsize < vb->size) { ret = -EINVAL; goto out; @@ -1157,9 +1163,15 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; unsigned long bus_flags, camera_flags, common_flags; - int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags); + const struct soc_mbus_pixelfmt *fmt; + int ret; struct pxa_cam *cam = icd->host_priv; + fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code); + if (!fmt) + return -EINVAL; + + ret = test_platform_param(pcdev, fmt->bits_per_sample, &bus_flags); if (ret < 0) return ret; @@ -1223,59 +1235,49 @@ static int pxa_camera_try_bus_param(struct soc_camera_device *icd, return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL; } -static const struct soc_camera_data_format pxa_camera_formats[] = { +static const struct soc_mbus_pixelfmt pxa_camera_formats[] = { { - .name = "Planar YUV422 16 bit", - .depth = 16, - .fourcc = V4L2_PIX_FMT_YUV422P, - .colorspace = V4L2_COLORSPACE_JPEG, + .fourcc = V4L2_PIX_FMT_YUV422P, + .name = "Planar YUV422 16 bit", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_LE, }, }; -static bool buswidth_supported(struct soc_camera_device *icd, int depth) +/* This will be corrected as we get more formats */ +static bool pxa_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct pxa_camera_dev *pcdev = ici->priv; - - switch (depth) { - case 8: - return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8); - case 9: - return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9); - case 10: - return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10); - } - return false; -} - -static int required_buswidth(const struct soc_camera_data_format *fmt) -{ - switch (fmt->fourcc) { - case V4L2_PIX_FMT_UYVY: - case V4L2_PIX_FMT_VYUY: - case V4L2_PIX_FMT_YUYV: - case V4L2_PIX_FMT_YVYU: - case V4L2_PIX_FMT_RGB565: - case V4L2_PIX_FMT_RGB555: - return 8; - default: - return fmt->depth; - } + return fmt->packing == SOC_MBUS_PACKING_NONE || + (fmt->bits_per_sample == 8 && + fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) || + (fmt->bits_per_sample > 8 && + fmt->packing == SOC_MBUS_PACKING_EXTEND16); } static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, struct soc_camera_format_xlate *xlate) { + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct device *dev = icd->dev.parent; - int formats = 0, buswidth, ret; + int formats = 0, ret; struct pxa_cam *cam; + enum v4l2_mbus_pixelcode code; + const struct soc_mbus_pixelfmt *fmt; - buswidth = required_buswidth(icd->formats + idx); + ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code); + if (ret < 0) + /* No more formats */ + return 0; - if (!buswidth_supported(icd, buswidth)) + fmt = soc_mbus_get_fmtdesc(code); + if (!fmt) { + dev_err(dev, "Invalid format code #%d: %d\n", idx, code); return 0; + } - ret = pxa_camera_try_bus_param(icd, buswidth); + /* This also checks support for the requested bits-per-sample */ + ret = pxa_camera_try_bus_param(icd, fmt->bits_per_sample); if (ret < 0) return 0; @@ -1289,45 +1291,40 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, cam = icd->host_priv; } - switch (icd->formats[idx].fourcc) { - case V4L2_PIX_FMT_UYVY: + switch (code) { + case V4L2_MBUS_FMT_YUYV8_2X8_BE: formats++; if (xlate) { - xlate->host_fmt = &pxa_camera_formats[0]; - xlate->cam_fmt = icd->formats + idx; - xlate->buswidth = buswidth; + xlate->host_fmt = &pxa_camera_formats[0]; + xlate->code = code; xlate++; - dev_dbg(dev, "Providing format %s using %s\n", - pxa_camera_formats[0].name, - icd->formats[idx].name); + dev_dbg(dev, "Providing format %s using code %d\n", + pxa_camera_formats[0].name, code); } - case V4L2_PIX_FMT_VYUY: - case V4L2_PIX_FMT_YUYV: - case V4L2_PIX_FMT_YVYU: - case V4L2_PIX_FMT_RGB565: - case V4L2_PIX_FMT_RGB555: - formats++; - if (xlate) { - xlate->host_fmt = icd->formats + idx; - xlate->cam_fmt = icd->formats + idx; - xlate->buswidth = buswidth; - xlate++; + case V4L2_MBUS_FMT_YVYU8_2X8_BE: + case V4L2_MBUS_FMT_YUYV8_2X8_LE: + case V4L2_MBUS_FMT_YVYU8_2X8_LE: + case V4L2_MBUS_FMT_RGB565_2X8_LE: + case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE: + if (xlate) dev_dbg(dev, "Providing format %s packed\n", - icd->formats[idx].name); - } + fmt->name); break; default: - /* Generic pass-through */ - formats++; - if (xlate) { - xlate->host_fmt = icd->formats + idx; - xlate->cam_fmt = icd->formats + idx; - xlate->buswidth = icd->formats[idx].depth; - xlate++; + if (!pxa_camera_packing_supported(fmt)) + return 0; + if (xlate) dev_dbg(dev, "Providing format %s in pass-through mode\n", - icd->formats[idx].name); - } + fmt->name); + } + + /* Generic pass-through */ + formats++; + if (xlate) { + xlate->host_fmt = fmt; + xlate->code = code; + xlate++; } return formats; @@ -1339,11 +1336,11 @@ static void pxa_camera_put_formats(struct soc_camera_device *icd) icd->host_priv = NULL; } -static int pxa_camera_check_frame(struct v4l2_pix_format *pix) +static int pxa_camera_check_frame(u32 width, u32 height) { /* limit to pxa hardware capabilities */ - return pix->height < 32 || pix->height > 2048 || pix->width < 48 || - pix->width > 2048 || (pix->width & 0x01); + return height < 32 || height > 2048 || width < 48 || width > 2048 || + (width & 0x01); } static int pxa_camera_set_crop(struct soc_camera_device *icd, @@ -1358,9 +1355,9 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, .master_clock = pcdev->mclk, .pixel_clock_max = pcdev->ciclk / 4, }; - struct v4l2_format f; - struct v4l2_pix_format *pix = &f.fmt.pix, pix_tmp; + struct v4l2_mbus_framefmt mf; struct pxa_cam *cam = icd->host_priv; + u32 fourcc = icd->current_fmt->host_fmt->fourcc; int ret; /* If PCLK is used to latch data from the sensor, check sense */ @@ -1377,27 +1374,23 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, return ret; } - f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - ret = v4l2_subdev_call(sd, video, g_fmt, &f); + ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); if (ret < 0) return ret; - pix_tmp = *pix; - if (pxa_camera_check_frame(pix)) { + if (pxa_camera_check_frame(mf.width, mf.height)) { /* * Camera cropping produced a frame beyond our capabilities. * FIXME: just extract a subframe, that we can process. */ - v4l_bound_align_image(&pix->width, 48, 2048, 1, - &pix->height, 32, 2048, 0, - icd->current_fmt->fourcc == V4L2_PIX_FMT_YUV422P ? - 4 : 0); - ret = v4l2_subdev_call(sd, video, s_fmt, &f); + v4l_bound_align_image(&mf.width, 48, 2048, 1, + &mf.height, 32, 2048, 0, + fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0); + ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); if (ret < 0) return ret; - if (pxa_camera_check_frame(pix)) { + if (pxa_camera_check_frame(mf.width, mf.height)) { dev_warn(icd->dev.parent, "Inconsistent state. Use S_FMT to repair\n"); return -EINVAL; @@ -1414,10 +1407,10 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, recalculate_fifo_timeout(pcdev, sense.pixel_clock); } - icd->user_width = pix->width; - icd->user_height = pix->height; + icd->user_width = mf.width; + icd->user_height = mf.height; - pxa_camera_setup_cicr(icd, cam->flags, icd->current_fmt->fourcc); + pxa_camera_setup_cicr(icd, cam->flags, fourcc); return ret; } @@ -1429,14 +1422,13 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, struct pxa_camera_dev *pcdev = ici->priv; struct device *dev = icd->dev.parent; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - const struct soc_camera_data_format *cam_fmt = NULL; const struct soc_camera_format_xlate *xlate = NULL; struct soc_camera_sense sense = { .master_clock = pcdev->mclk, .pixel_clock_max = pcdev->ciclk / 4, }; struct v4l2_pix_format *pix = &f->fmt.pix; - struct v4l2_format cam_f = *f; + struct v4l2_mbus_framefmt mf; int ret; xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); @@ -1445,26 +1437,31 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, return -EINVAL; } - cam_fmt = xlate->cam_fmt; - /* If PCLK is used to latch data from the sensor, check sense */ if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) + /* The caller holds a mutex. */ icd->sense = &sense; - cam_f.fmt.pix.pixelformat = cam_fmt->fourcc; - ret = v4l2_subdev_call(sd, video, s_fmt, &cam_f); - cam_f.fmt.pix.pixelformat = pix->pixelformat; - *pix = cam_f.fmt.pix; + mf.width = pix->width; + mf.height = pix->height; + mf.field = pix->field; + mf.colorspace = pix->colorspace; + mf.code = xlate->code; + + ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); + + if (mf.code != xlate->code) + return -EINVAL; icd->sense = NULL; if (ret < 0) { dev_warn(dev, "Failed to configure for format %x\n", pix->pixelformat); - } else if (pxa_camera_check_frame(pix)) { + } else if (pxa_camera_check_frame(mf.width, mf.height)) { dev_warn(dev, "Camera driver produced an unsupported frame %dx%d\n", - pix->width, pix->height); + mf.width, mf.height); ret = -EINVAL; } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { @@ -1476,10 +1473,14 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, recalculate_fifo_timeout(pcdev, sense.pixel_clock); } - if (!ret) { - icd->buswidth = xlate->buswidth; - icd->current_fmt = xlate->host_fmt; - } + if (ret < 0) + return ret; + + pix->width = mf.width; + pix->height = mf.height; + pix->field = mf.field; + pix->colorspace = mf.colorspace; + icd->current_fmt = xlate; return ret; } @@ -1487,17 +1488,16 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, static int pxa_camera_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_mbus_framefmt mf; __u32 pixfmt = pix->pixelformat; - enum v4l2_field field; int ret; xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pixfmt); + dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); return -EINVAL; } @@ -1511,22 +1511,36 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, &pix->height, 32, 2048, 0, pixfmt == V4L2_PIX_FMT_YUV422P ? 4 : 0); - pix->bytesperline = pix->width * - DIV_ROUND_UP(xlate->host_fmt->depth, 8); + pix->bytesperline = soc_mbus_bytes_per_line(pix->width, + xlate->host_fmt); + if (pix->bytesperline < 0) + return pix->bytesperline; pix->sizeimage = pix->height * pix->bytesperline; - /* camera has to see its format, but the user the original one */ - pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ - ret = v4l2_subdev_call(sd, video, try_fmt, f); - pix->pixelformat = pixfmt; + mf.width = pix->width; + mf.height = pix->height; + mf.field = pix->field; + mf.colorspace = pix->colorspace; + mf.code = xlate->code; - field = pix->field; + ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); + if (ret < 0) + return ret; - if (field == V4L2_FIELD_ANY) { - pix->field = V4L2_FIELD_NONE; - } else if (field != V4L2_FIELD_NONE) { - dev_err(icd->dev.parent, "Field type %d unsupported.\n", field); + pix->width = mf.width; + pix->height = mf.height; + pix->colorspace = mf.colorspace; + + switch (mf.field) { + case V4L2_FIELD_ANY: + case V4L2_FIELD_NONE: + pix->field = V4L2_FIELD_NONE; + break; + default: + /* TODO: support interlaced at least in pass-through mode */ + dev_err(icd->dev.parent, "Field type %d unsupported.\n", + mf.field); return -EINVAL; } diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c index 373f2a3..7b08bff 100644 --- a/drivers/media/video/rj54n1cb0c.c +++ b/drivers/media/video/rj54n1cb0c.c @@ -16,6 +16,7 @@ #include #include #include +#include #define RJ54N1_DEV_CODE 0x0400 #define RJ54N1_DEV_CODE2 0x0401 @@ -85,18 +86,35 @@ /* I2C addresses: 0x50, 0x51, 0x60, 0x61 */ -static const struct soc_camera_data_format rj54n1_colour_formats[] = { - { - .name = "YUYV", - .depth = 16, - .fourcc = V4L2_PIX_FMT_YUYV, - .colorspace = V4L2_COLORSPACE_JPEG, - }, { - .name = "RGB565", - .depth = 16, - .fourcc = V4L2_PIX_FMT_RGB565, - .colorspace = V4L2_COLORSPACE_SRGB, - } +/* RJ54N1CB0C has only one fixed colorspace per pixelcode */ +struct rj54n1_datafmt { + enum v4l2_mbus_pixelcode code; + enum v4l2_colorspace colorspace; +}; + +/* Find a data format by a pixel code in an array */ +static const struct rj54n1_datafmt *rj54n1_find_datafmt( + enum v4l2_mbus_pixelcode code, const struct rj54n1_datafmt *fmt, + int n) +{ + int i; + for (i = 0; i < n; i++) + if (fmt[i].code == code) + return fmt + i; + + return NULL; +} + +static const struct rj54n1_datafmt rj54n1_colour_fmts[] = { + {V4L2_MBUS_FMT_YUYV8_2X8_LE, V4L2_COLORSPACE_JPEG}, + {V4L2_MBUS_FMT_YVYU8_2X8_LE, V4L2_COLORSPACE_JPEG}, + {V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB}, + {V4L2_MBUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB}, + {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB}, + {V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE, V4L2_COLORSPACE_SRGB}, + {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB}, + {V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE, V4L2_COLORSPACE_SRGB}, + {V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB}, }; struct rj54n1_clock_div { @@ -109,12 +127,12 @@ struct rj54n1_clock_div { struct rj54n1 { struct v4l2_subdev subdev; + const struct rj54n1_datafmt *fmt; struct v4l2_rect rect; /* Sensor window */ unsigned short width; /* Output window */ unsigned short height; unsigned short resize; /* Sensor * 1024 / resize = Output */ struct rj54n1_clock_div clk_div; - u32 fourcc; unsigned short scale; u8 bank; }; @@ -440,6 +458,16 @@ static int reg_write_multiple(struct i2c_client *client, return 0; } +static int rj54n1_enum_fmt(struct v4l2_subdev *sd, int index, + enum v4l2_mbus_pixelcode *code) +{ + if ((unsigned int)index >= ARRAY_SIZE(rj54n1_colour_fmts)) + return -EINVAL; + + *code = rj54n1_colour_fmts[index].code; + return 0; +} + static int rj54n1_s_stream(struct v4l2_subdev *sd, int enable) { /* TODO: start / stop streaming */ @@ -527,16 +555,17 @@ static int rj54n1_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) return 0; } -static int rj54n1_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int rj54n1_g_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = sd->priv; struct rj54n1 *rj54n1 = to_rj54n1(client); - struct v4l2_pix_format *pix = &f->fmt.pix; - pix->pixelformat = rj54n1->fourcc; - pix->field = V4L2_FIELD_NONE; - pix->width = rj54n1->width; - pix->height = rj54n1->height; + mf->code = rj54n1->fmt->code; + mf->colorspace = rj54n1->fmt->colorspace; + mf->field = V4L2_FIELD_NONE; + mf->width = rj54n1->width; + mf->height = rj54n1->height; return 0; } @@ -787,26 +816,44 @@ static int rj54n1_reg_init(struct i2c_client *client) } /* FIXME: streaming output only up to 800x600 is functional */ -static int rj54n1_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int rj54n1_try_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { - struct v4l2_pix_format *pix = &f->fmt.pix; + struct i2c_client *client = sd->priv; + struct rj54n1 *rj54n1 = to_rj54n1(client); + const struct rj54n1_datafmt *fmt; + int align = mf->code == V4L2_MBUS_FMT_SBGGR10_1X10 || + mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE || + mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE || + mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE || + mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE; + + dev_dbg(&client->dev, "%s: code = %d, width = %u, height = %u\n", + __func__, mf->code, mf->width, mf->height); + + fmt = rj54n1_find_datafmt(mf->code, rj54n1_colour_fmts, + ARRAY_SIZE(rj54n1_colour_fmts)); + if (!fmt) { + fmt = rj54n1->fmt; + mf->code = fmt->code; + } - pix->field = V4L2_FIELD_NONE; + mf->field = V4L2_FIELD_NONE; + mf->colorspace = fmt->colorspace; - if (pix->width > 800) - pix->width = 800; - if (pix->height > 600) - pix->height = 600; + v4l_bound_align_image(&mf->width, 112, RJ54N1_MAX_WIDTH, align, + &mf->height, 84, RJ54N1_MAX_HEIGHT, align, 0); return 0; } -static int rj54n1_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int rj54n1_s_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = sd->priv; struct rj54n1 *rj54n1 = to_rj54n1(client); - struct v4l2_pix_format *pix = &f->fmt.pix; - unsigned int output_w, output_h, + const struct rj54n1_datafmt *fmt; + unsigned int output_w, output_h, max_w, max_h, input_w = rj54n1->rect.width, input_h = rj54n1->rect.height; int ret; @@ -814,7 +861,7 @@ static int rj54n1_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) * The host driver can call us without .try_fmt(), so, we have to take * care ourseleves */ - ret = rj54n1_try_fmt(sd, f); + ret = rj54n1_try_fmt(sd, mf); /* * Verify if the sensor has just been powered on. TODO: replace this @@ -832,49 +879,101 @@ static int rj54n1_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) } /* RA_SEL_UL is only relevant for raw modes, ignored otherwise. */ - switch (pix->pixelformat) { - case V4L2_PIX_FMT_YUYV: + switch (mf->code) { + case V4L2_MBUS_FMT_YUYV8_2X8_LE: ret = reg_write(client, RJ54N1_OUT_SEL, 0); if (!ret) ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8); break; - case V4L2_PIX_FMT_RGB565: + case V4L2_MBUS_FMT_YVYU8_2X8_LE: + ret = reg_write(client, RJ54N1_OUT_SEL, 0); + if (!ret) + ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8); + break; + case V4L2_MBUS_FMT_RGB565_2X8_LE: ret = reg_write(client, RJ54N1_OUT_SEL, 0x11); if (!ret) ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8); break; + case V4L2_MBUS_FMT_RGB565_2X8_BE: + ret = reg_write(client, RJ54N1_OUT_SEL, 0x11); + if (!ret) + ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8); + break; + case V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE: + ret = reg_write(client, RJ54N1_OUT_SEL, 4); + if (!ret) + ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8); + if (!ret) + ret = reg_write(client, RJ54N1_RA_SEL_UL, 0); + break; + case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE: + ret = reg_write(client, RJ54N1_OUT_SEL, 4); + if (!ret) + ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8); + if (!ret) + ret = reg_write(client, RJ54N1_RA_SEL_UL, 8); + break; + case V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE: + ret = reg_write(client, RJ54N1_OUT_SEL, 4); + if (!ret) + ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8); + if (!ret) + ret = reg_write(client, RJ54N1_RA_SEL_UL, 0); + break; + case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE: + ret = reg_write(client, RJ54N1_OUT_SEL, 4); + if (!ret) + ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8); + if (!ret) + ret = reg_write(client, RJ54N1_RA_SEL_UL, 8); + break; + case V4L2_MBUS_FMT_SBGGR10_1X10: + ret = reg_write(client, RJ54N1_OUT_SEL, 5); + break; default: ret = -EINVAL; } + /* Special case: a raw mode with 10 bits of data per clock tick */ + if (!ret) + ret = reg_set(client, RJ54N1_OCLK_SEL_EN, + (mf->code == V4L2_MBUS_FMT_SBGGR10_1X10) << 1, 2); + if (ret < 0) return ret; - /* Supported scales 1:1 - 1:16 */ - if (pix->width < input_w / 16) - pix->width = input_w / 16; - if (pix->height < input_h / 16) - pix->height = input_h / 16; + /* Supported scales 1:1 >= scale > 1:16 */ + max_w = mf->width * (16 * 1024 - 1) / 1024; + if (input_w > max_w) + input_w = max_w; + max_h = mf->height * (16 * 1024 - 1) / 1024; + if (input_h > max_h) + input_h = max_h; - output_w = pix->width; - output_h = pix->height; + output_w = mf->width; + output_h = mf->height; ret = rj54n1_sensor_scale(sd, &input_w, &input_h, &output_w, &output_h); if (ret < 0) return ret; - rj54n1->fourcc = pix->pixelformat; + fmt = rj54n1_find_datafmt(mf->code, rj54n1_colour_fmts, + ARRAY_SIZE(rj54n1_colour_fmts)); + + rj54n1->fmt = fmt; rj54n1->resize = ret; rj54n1->rect.width = input_w; rj54n1->rect.height = input_h; rj54n1->width = output_w; rj54n1->height = output_h; - pix->width = output_w; - pix->height = output_h; - pix->field = V4L2_FIELD_NONE; + mf->width = output_w; + mf->height = output_h; + mf->field = V4L2_FIELD_NONE; + mf->colorspace = fmt->colorspace; - return ret; + return 0; } static int rj54n1_g_chip_ident(struct v4l2_subdev *sd, @@ -1054,9 +1153,10 @@ static struct v4l2_subdev_core_ops rj54n1_subdev_core_ops = { static struct v4l2_subdev_video_ops rj54n1_subdev_video_ops = { .s_stream = rj54n1_s_stream, - .s_fmt = rj54n1_s_fmt, - .g_fmt = rj54n1_g_fmt, - .try_fmt = rj54n1_try_fmt, + .s_mbus_fmt = rj54n1_s_fmt, + .g_mbus_fmt = rj54n1_g_fmt, + .try_mbus_fmt = rj54n1_try_fmt, + .enum_mbus_fmt = rj54n1_enum_fmt, .g_crop = rj54n1_g_crop, .cropcap = rj54n1_cropcap, }; @@ -1153,7 +1253,7 @@ static int rj54n1_probe(struct i2c_client *client, rj54n1->rect.height = RJ54N1_MAX_HEIGHT; rj54n1->width = RJ54N1_MAX_WIDTH; rj54n1->height = RJ54N1_MAX_HEIGHT; - rj54n1->fourcc = V4L2_PIX_FMT_YUYV; + rj54n1->fmt = &rj54n1_colour_fmts[0]; rj54n1->resize = 1024; ret = rj54n1_video_probe(icd, client); @@ -1164,9 +1264,6 @@ static int rj54n1_probe(struct i2c_client *client, return ret; } - icd->formats = rj54n1_colour_formats; - icd->num_formats = ARRAY_SIZE(rj54n1_colour_formats); - return ret; } diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 2a38e1d..273ad34 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -38,6 +38,8 @@ #include #include #include +#include +#include /* register offsets for sh7722 / sh7723 */ @@ -85,7 +87,7 @@ /* per video frame buffer */ struct sh_mobile_ceu_buffer { struct videobuf_buffer vb; /* v4l buffer must be first */ - const struct soc_camera_data_format *fmt; + enum v4l2_mbus_pixelcode code; }; struct sh_mobile_ceu_dev { @@ -114,8 +116,8 @@ struct sh_mobile_ceu_cam { struct v4l2_rect ceu_rect; unsigned int cam_width; unsigned int cam_height; - const struct soc_camera_data_format *extra_fmt; - const struct soc_camera_data_format *camera_fmt; + const struct soc_mbus_pixelfmt *extra_fmt; + enum v4l2_mbus_pixelcode code; }; static unsigned long make_bus_param(struct sh_mobile_ceu_dev *pcdev) @@ -197,10 +199,13 @@ static int sh_mobile_ceu_videobuf_setup(struct videobuf_queue *vq, struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; - int bytes_per_pixel = (icd->current_fmt->depth + 7) >> 3; + int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, + icd->current_fmt->host_fmt); - *size = PAGE_ALIGN(icd->user_width * icd->user_height * - bytes_per_pixel); + if (bytes_per_line < 0) + return bytes_per_line; + + *size = PAGE_ALIGN(bytes_per_line * icd->user_height); if (0 == *count) *count = 2; @@ -284,7 +289,7 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) ceu_write(pcdev, CDBYR, phys_addr_bottom); } - switch (icd->current_fmt->fourcc) { + switch (icd->current_fmt->host_fmt->fourcc) { case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: case V4L2_PIX_FMT_NV16: @@ -311,8 +316,13 @@ static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq, { struct soc_camera_device *icd = vq->priv_data; struct sh_mobile_ceu_buffer *buf; + int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, + icd->current_fmt->host_fmt); int ret; + if (bytes_per_line < 0) + return bytes_per_line; + buf = container_of(vb, struct sh_mobile_ceu_buffer, vb); dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, @@ -331,18 +341,18 @@ static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq, BUG_ON(NULL == icd->current_fmt); - if (buf->fmt != icd->current_fmt || + if (buf->code != icd->current_fmt->code || vb->width != icd->user_width || vb->height != icd->user_height || vb->field != field) { - buf->fmt = icd->current_fmt; + buf->code = icd->current_fmt->code; vb->width = icd->user_width; vb->height = icd->user_height; vb->field = field; vb->state = VIDEOBUF_NEEDS_INIT; } - vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3); + vb->size = vb->height * bytes_per_line; if (0 != vb->baddr && vb->bsize < vb->size) { ret = -EINVAL; goto out; @@ -564,19 +574,30 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, in_width *= 2; left_offset *= 2; } - width = cdwdr_width = out_width; + width = out_width; + cdwdr_width = out_width; } else { - unsigned int w_factor = (icd->current_fmt->depth + 7) >> 3; + int bytes_per_line = soc_mbus_bytes_per_line(out_width, + icd->current_fmt->host_fmt); + unsigned int w_factor; - width = out_width * w_factor / 2; + width = out_width; - if (!pcdev->is_16bit) - w_factor *= 2; + switch (icd->current_fmt->host_fmt->packing) { + case SOC_MBUS_PACKING_2X8_PADHI: + w_factor = 2; + break; + default: + w_factor = 1; + } - in_width = rect->width * w_factor / 2; - left_offset = left_offset * w_factor / 2; + in_width = rect->width * w_factor; + left_offset = left_offset * w_factor; - cdwdr_width = width * 2; + if (bytes_per_line < 0) + cdwdr_width = out_width; + else + cdwdr_width = bytes_per_line; } height = out_height; @@ -673,24 +694,24 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, value = 0x00000010; /* data fetch by default */ yuv_lineskip = 0; - switch (icd->current_fmt->fourcc) { + switch (icd->current_fmt->host_fmt->fourcc) { case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: yuv_lineskip = 1; /* skip for NV12/21, no skip for NV16/61 */ /* fall-through */ case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: - switch (cam->camera_fmt->fourcc) { - case V4L2_PIX_FMT_UYVY: + switch (cam->code) { + case V4L2_MBUS_FMT_YUYV8_2X8_BE: value = 0x00000000; /* Cb0, Y0, Cr0, Y1 */ break; - case V4L2_PIX_FMT_VYUY: + case V4L2_MBUS_FMT_YVYU8_2X8_BE: value = 0x00000100; /* Cr0, Y0, Cb0, Y1 */ break; - case V4L2_PIX_FMT_YUYV: + case V4L2_MBUS_FMT_YUYV8_2X8_LE: value = 0x00000200; /* Y0, Cb0, Y1, Cr0 */ break; - case V4L2_PIX_FMT_YVYU: + case V4L2_MBUS_FMT_YVYU8_2X8_LE: value = 0x00000300; /* Y0, Cr0, Y1, Cb0 */ break; default: @@ -698,8 +719,8 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, } } - if (icd->current_fmt->fourcc == V4L2_PIX_FMT_NV21 || - icd->current_fmt->fourcc == V4L2_PIX_FMT_NV61) + if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV21 || + icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV61) value ^= 0x00000100; /* swap U, V to change from NV1x->NVx1 */ value |= common_flags & SOCAM_VSYNC_ACTIVE_LOW ? 1 << 1 : 0; @@ -746,7 +767,8 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, return 0; } -static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd) +static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd, + unsigned char buswidth) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; @@ -755,48 +777,75 @@ static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd) camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, make_bus_param(pcdev)); - if (!common_flags) + if (!common_flags || buswidth > 16 || + (buswidth > 8 && !(common_flags & SOCAM_DATAWIDTH_16))) return -EINVAL; return 0; } -static const struct soc_camera_data_format sh_mobile_ceu_formats[] = { - { - .name = "NV12", - .depth = 12, - .fourcc = V4L2_PIX_FMT_NV12, - .colorspace = V4L2_COLORSPACE_JPEG, - }, - { - .name = "NV21", - .depth = 12, - .fourcc = V4L2_PIX_FMT_NV21, - .colorspace = V4L2_COLORSPACE_JPEG, - }, - { - .name = "NV16", - .depth = 16, - .fourcc = V4L2_PIX_FMT_NV16, - .colorspace = V4L2_COLORSPACE_JPEG, - }, +static const struct soc_mbus_pixelfmt sh_mobile_ceu_formats[] = { { - .name = "NV61", - .depth = 16, - .fourcc = V4L2_PIX_FMT_NV61, - .colorspace = V4L2_COLORSPACE_JPEG, + .fourcc = V4L2_PIX_FMT_NV12, + .name = "NV12", + .bits_per_sample = 12, + .packing = SOC_MBUS_PACKING_NONE, + .order = SOC_MBUS_ORDER_LE, + }, { + .fourcc = V4L2_PIX_FMT_NV21, + .name = "NV21", + .bits_per_sample = 12, + .packing = SOC_MBUS_PACKING_NONE, + .order = SOC_MBUS_ORDER_LE, + }, { + .fourcc = V4L2_PIX_FMT_NV16, + .name = "NV16", + .bits_per_sample = 16, + .packing = SOC_MBUS_PACKING_NONE, + .order = SOC_MBUS_ORDER_LE, + }, { + .fourcc = V4L2_PIX_FMT_NV61, + .name = "NV61", + .bits_per_sample = 16, + .packing = SOC_MBUS_PACKING_NONE, + .order = SOC_MBUS_ORDER_LE, }, }; +/* This will be corrected as we get more formats */ +static bool sh_mobile_ceu_packing_supported(const struct soc_mbus_pixelfmt *fmt) +{ + return fmt->packing == SOC_MBUS_PACKING_NONE || + (fmt->bits_per_sample == 8 && + fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) || + (fmt->bits_per_sample > 8 && + fmt->packing == SOC_MBUS_PACKING_EXTEND16); +} + static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, struct soc_camera_format_xlate *xlate) { + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct device *dev = icd->dev.parent; int ret, k, n; int formats = 0; struct sh_mobile_ceu_cam *cam; + enum v4l2_mbus_pixelcode code; + const struct soc_mbus_pixelfmt *fmt; - ret = sh_mobile_ceu_try_bus_param(icd); + ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code); + if (ret < 0) + /* No more formats */ + return 0; + + fmt = soc_mbus_get_fmtdesc(code); + if (!fmt) { + dev_err(icd->dev.parent, + "Invalid format code #%d: %d\n", idx, code); + return -EINVAL; + } + + ret = sh_mobile_ceu_try_bus_param(icd, fmt->bits_per_sample); if (ret < 0) return 0; @@ -814,13 +863,13 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, if (!idx) cam->extra_fmt = NULL; - switch (icd->formats[idx].fourcc) { - case V4L2_PIX_FMT_UYVY: - case V4L2_PIX_FMT_VYUY: - case V4L2_PIX_FMT_YUYV: - case V4L2_PIX_FMT_YVYU: + switch (code) { + case V4L2_MBUS_FMT_YUYV8_2X8_BE: + case V4L2_MBUS_FMT_YVYU8_2X8_BE: + case V4L2_MBUS_FMT_YUYV8_2X8_LE: + case V4L2_MBUS_FMT_YVYU8_2X8_LE: if (cam->extra_fmt) - goto add_single_format; + break; /* * Our case is simple so far: for any of the above four camera @@ -831,32 +880,31 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, * the host_priv pointer and check whether the format you're * going to add now is already there. */ - cam->extra_fmt = (void *)sh_mobile_ceu_formats; + cam->extra_fmt = sh_mobile_ceu_formats; n = ARRAY_SIZE(sh_mobile_ceu_formats); formats += n; for (k = 0; xlate && k < n; k++) { - xlate->host_fmt = &sh_mobile_ceu_formats[k]; - xlate->cam_fmt = icd->formats + idx; - xlate->buswidth = icd->formats[idx].depth; + xlate->host_fmt = &sh_mobile_ceu_formats[k]; + xlate->code = code; xlate++; - dev_dbg(dev, "Providing format %s using %s\n", - sh_mobile_ceu_formats[k].name, - icd->formats[idx].name); + dev_dbg(dev, "Providing format %s using code %d\n", + sh_mobile_ceu_formats[k].name, code); } + break; default: -add_single_format: - /* Generic pass-through */ - formats++; - if (xlate) { - xlate->host_fmt = icd->formats + idx; - xlate->cam_fmt = icd->formats + idx; - xlate->buswidth = icd->formats[idx].depth; - xlate++; - dev_dbg(dev, - "Providing format %s in pass-through mode\n", - icd->formats[idx].name); - } + if (!sh_mobile_ceu_packing_supported(fmt)) + return 0; + } + + /* Generic pass-through */ + formats++; + if (xlate) { + xlate->host_fmt = fmt; + xlate->code = code; + xlate++; + dev_dbg(dev, "Providing format %s in pass-through mode\n", + xlate->host_fmt->name); } return formats; @@ -1036,17 +1084,15 @@ static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, static int get_camera_scales(struct v4l2_subdev *sd, struct v4l2_rect *rect, unsigned int *scale_h, unsigned int *scale_v) { - struct v4l2_format f; + struct v4l2_mbus_framefmt mf; int ret; - f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - ret = v4l2_subdev_call(sd, video, g_fmt, &f); + ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); if (ret < 0) return ret; - *scale_h = calc_generic_scale(rect->width, f.fmt.pix.width); - *scale_v = calc_generic_scale(rect->height, f.fmt.pix.height); + *scale_h = calc_generic_scale(rect->width, mf.width); + *scale_v = calc_generic_scale(rect->height, mf.height); return 0; } @@ -1061,32 +1107,29 @@ static int get_camera_subwin(struct soc_camera_device *icd, if (!ceu_rect->width) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct device *dev = icd->dev.parent; - struct v4l2_format f; - struct v4l2_pix_format *pix = &f.fmt.pix; + struct v4l2_mbus_framefmt mf; int ret; /* First time */ - f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - ret = v4l2_subdev_call(sd, video, g_fmt, &f); + ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); if (ret < 0) return ret; - dev_geo(dev, "camera fmt %ux%u\n", pix->width, pix->height); + dev_geo(dev, "camera fmt %ux%u\n", mf.width, mf.height); - if (pix->width > 2560) { + if (mf.width > 2560) { ceu_rect->width = 2560; - ceu_rect->left = (pix->width - 2560) / 2; + ceu_rect->left = (mf.width - 2560) / 2; } else { - ceu_rect->width = pix->width; + ceu_rect->width = mf.width; ceu_rect->left = 0; } - if (pix->height > 1920) { + if (mf.height > 1920) { ceu_rect->height = 1920; - ceu_rect->top = (pix->height - 1920) / 2; + ceu_rect->top = (mf.height - 1920) / 2; } else { - ceu_rect->height = pix->height; + ceu_rect->height = mf.height; ceu_rect->top = 0; } @@ -1103,13 +1146,12 @@ static int get_camera_subwin(struct soc_camera_device *icd, return 0; } -static int client_s_fmt(struct soc_camera_device *icd, struct v4l2_format *f, - bool ceu_can_scale) +static int client_s_fmt(struct soc_camera_device *icd, + struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct device *dev = icd->dev.parent; - struct v4l2_pix_format *pix = &f->fmt.pix; - unsigned int width = pix->width, height = pix->height, tmp_w, tmp_h; + unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h; unsigned int max_width, max_height; struct v4l2_cropcap cap; int ret; @@ -1123,29 +1165,29 @@ static int client_s_fmt(struct soc_camera_device *icd, struct v4l2_format *f, max_width = min(cap.bounds.width, 2560); max_height = min(cap.bounds.height, 1920); - ret = v4l2_subdev_call(sd, video, s_fmt, f); + ret = v4l2_subdev_call(sd, video, s_mbus_fmt, mf); if (ret < 0) return ret; - dev_geo(dev, "camera scaled to %ux%u\n", pix->width, pix->height); + dev_geo(dev, "camera scaled to %ux%u\n", mf->width, mf->height); - if ((width == pix->width && height == pix->height) || !ceu_can_scale) + if ((width == mf->width && height == mf->height) || !ceu_can_scale) return 0; /* Camera set a format, but geometry is not precise, try to improve */ - tmp_w = pix->width; - tmp_h = pix->height; + tmp_w = mf->width; + tmp_h = mf->height; /* width <= max_width && height <= max_height - guaranteed by try_fmt */ while ((width > tmp_w || height > tmp_h) && tmp_w < max_width && tmp_h < max_height) { tmp_w = min(2 * tmp_w, max_width); tmp_h = min(2 * tmp_h, max_height); - pix->width = tmp_w; - pix->height = tmp_h; - ret = v4l2_subdev_call(sd, video, s_fmt, f); + mf->width = tmp_w; + mf->height = tmp_h; + ret = v4l2_subdev_call(sd, video, s_mbus_fmt, mf); dev_geo(dev, "Camera scaled to %ux%u\n", - pix->width, pix->height); + mf->width, mf->height); if (ret < 0) { /* This shouldn't happen */ dev_err(dev, "Client failed to set format: %d\n", ret); @@ -1163,27 +1205,26 @@ static int client_s_fmt(struct soc_camera_device *icd, struct v4l2_format *f, */ static int client_scale(struct soc_camera_device *icd, struct v4l2_rect *rect, struct v4l2_rect *sub_rect, struct v4l2_rect *ceu_rect, - struct v4l2_format *f, bool ceu_can_scale) + struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct sh_mobile_ceu_cam *cam = icd->host_priv; struct device *dev = icd->dev.parent; - struct v4l2_format f_tmp = *f; - struct v4l2_pix_format *pix_tmp = &f_tmp.fmt.pix; + struct v4l2_mbus_framefmt mf_tmp = *mf; unsigned int scale_h, scale_v; int ret; /* 5. Apply iterative camera S_FMT for camera user window. */ - ret = client_s_fmt(icd, &f_tmp, ceu_can_scale); + ret = client_s_fmt(icd, &mf_tmp, ceu_can_scale); if (ret < 0) return ret; dev_geo(dev, "5: camera scaled to %ux%u\n", - pix_tmp->width, pix_tmp->height); + mf_tmp.width, mf_tmp.height); /* 6. Retrieve camera output window (g_fmt) */ - /* unneeded - it is already in "f_tmp" */ + /* unneeded - it is already in "mf_tmp" */ /* 7. Calculate new camera scales. */ ret = get_camera_scales(sd, rect, &scale_h, &scale_v); @@ -1192,10 +1233,11 @@ static int client_scale(struct soc_camera_device *icd, struct v4l2_rect *rect, dev_geo(dev, "7: camera scales %u:%u\n", scale_h, scale_v); - cam->cam_width = pix_tmp->width; - cam->cam_height = pix_tmp->height; - f->fmt.pix.width = pix_tmp->width; - f->fmt.pix.height = pix_tmp->height; + cam->cam_width = mf_tmp.width; + cam->cam_height = mf_tmp.height; + mf->width = mf_tmp.width; + mf->height = mf_tmp.height; + mf->colorspace = mf_tmp.colorspace; /* * 8. Calculate new CEU crop - apply camera scales to previously @@ -1259,8 +1301,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, struct v4l2_rect *cam_rect = &cam_crop.c, *ceu_rect = &cam->ceu_rect; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct device *dev = icd->dev.parent; - struct v4l2_format f; - struct v4l2_pix_format *pix = &f.fmt.pix; + struct v4l2_mbus_framefmt mf; unsigned int scale_comb_h, scale_comb_v, scale_ceu_h, scale_ceu_v, out_width, out_height; u32 capsr, cflcr; @@ -1309,25 +1350,24 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, * 5. Using actual input window and calculated combined scales calculate * camera target output window. */ - pix->width = scale_down(cam_rect->width, scale_comb_h); - pix->height = scale_down(cam_rect->height, scale_comb_v); + mf.width = scale_down(cam_rect->width, scale_comb_h); + mf.height = scale_down(cam_rect->height, scale_comb_v); - dev_geo(dev, "5: camera target %ux%u\n", pix->width, pix->height); + dev_geo(dev, "5: camera target %ux%u\n", mf.width, mf.height); /* 6. - 9. */ - pix->pixelformat = cam->camera_fmt->fourcc; - pix->colorspace = cam->camera_fmt->colorspace; + mf.code = cam->code; + mf.field = pcdev->is_interlaced ? V4L2_FIELD_INTERLACED : + V4L2_FIELD_NONE; capsr = capture_save_reset(pcdev); dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); /* Make relative to camera rectangle */ - rect->left -= cam_rect->left; - rect->top -= cam_rect->top; + rect->left -= cam_rect->left; + rect->top -= cam_rect->top; - f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - ret = client_scale(icd, cam_rect, rect, ceu_rect, &f, + ret = client_scale(icd, cam_rect, rect, ceu_rect, &mf, pcdev->image_mode && !pcdev->is_interlaced); dev_geo(dev, "6-9: %d\n", ret); @@ -1375,8 +1415,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, struct sh_mobile_ceu_dev *pcdev = ici->priv; struct sh_mobile_ceu_cam *cam = icd->host_priv; struct v4l2_pix_format *pix = &f->fmt.pix; - struct v4l2_format cam_f = *f; - struct v4l2_pix_format *cam_pix = &cam_f.fmt.pix; + struct v4l2_mbus_framefmt mf; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct device *dev = icd->dev.parent; __u32 pixfmt = pix->pixelformat; @@ -1445,9 +1484,11 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, * 4. Calculate camera output window by applying combined scales to real * input window. */ - cam_pix->width = scale_down(cam_rect->width, scale_h); - cam_pix->height = scale_down(cam_rect->height, scale_v); - cam_pix->pixelformat = xlate->cam_fmt->fourcc; + mf.width = scale_down(cam_rect->width, scale_h); + mf.height = scale_down(cam_rect->height, scale_v); + mf.field = pix->field; + mf.colorspace = pix->colorspace; + mf.code = xlate->code; switch (pixfmt) { case V4L2_PIX_FMT_NV12: @@ -1460,11 +1501,10 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, image_mode = false; } - dev_geo(dev, "4: camera output %ux%u\n", - cam_pix->width, cam_pix->height); + dev_geo(dev, "4: camera output %ux%u\n", mf.width, mf.height); /* 5. - 9. */ - ret = client_scale(icd, cam_rect, &cam_subrect, &ceu_rect, &cam_f, + ret = client_scale(icd, cam_rect, &cam_subrect, &ceu_rect, &mf, image_mode && !is_interlaced); dev_geo(dev, "5-9: client scale %d\n", ret); @@ -1472,37 +1512,48 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, /* Done with the camera. Now see if we can improve the result */ dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n", - ret, cam_pix->width, cam_pix->height, pix->width, pix->height); + ret, mf.width, mf.height, pix->width, pix->height); if (ret < 0) return ret; + if (mf.code != xlate->code) + return -EINVAL; + /* 10. Use CEU scaling to scale to the requested user window. */ /* We cannot scale up */ - if (pix->width > cam_pix->width) - pix->width = cam_pix->width; + if (pix->width > mf.width) + pix->width = mf.width; if (pix->width > ceu_rect.width) pix->width = ceu_rect.width; - if (pix->height > cam_pix->height) - pix->height = cam_pix->height; + if (pix->height > mf.height) + pix->height = mf.height; if (pix->height > ceu_rect.height) pix->height = ceu_rect.height; - /* Let's rock: scale pix->{width x height} down to width x height */ - scale_h = calc_scale(ceu_rect.width, &pix->width); - scale_v = calc_scale(ceu_rect.height, &pix->height); + pix->colorspace = mf.colorspace; + + if (image_mode) { + /* Scale pix->{width x height} down to width x height */ + scale_h = calc_scale(ceu_rect.width, &pix->width); + scale_v = calc_scale(ceu_rect.height, &pix->height); + + pcdev->cflcr = scale_h | (scale_v << 16); + } else { + pix->width = ceu_rect.width; + pix->height = ceu_rect.height; + scale_h = scale_v = 0; + pcdev->cflcr = 0; + } dev_geo(dev, "10: W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", ceu_rect.width, scale_h, pix->width, ceu_rect.height, scale_v, pix->height); - pcdev->cflcr = scale_h | (scale_v << 16); - - icd->buswidth = xlate->buswidth; - icd->current_fmt = xlate->host_fmt; - cam->camera_fmt = xlate->cam_fmt; - cam->ceu_rect = ceu_rect; + cam->code = xlate->code; + cam->ceu_rect = ceu_rect; + icd->current_fmt = xlate; pcdev->is_interlaced = is_interlaced; pcdev->image_mode = image_mode; @@ -1516,6 +1567,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct v4l2_mbus_framefmt mf; __u32 pixfmt = pix->pixelformat; int width, height; int ret; @@ -1534,18 +1586,27 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, width = pix->width; height = pix->height; - pix->bytesperline = pix->width * - DIV_ROUND_UP(xlate->host_fmt->depth, 8); - pix->sizeimage = pix->height * pix->bytesperline; - - pix->pixelformat = xlate->cam_fmt->fourcc; + pix->bytesperline = soc_mbus_bytes_per_line(width, xlate->host_fmt); + if (pix->bytesperline < 0) + return pix->bytesperline; + pix->sizeimage = height * pix->bytesperline; /* limit to sensor capabilities */ - ret = v4l2_subdev_call(sd, video, try_fmt, f); - pix->pixelformat = pixfmt; + mf.width = pix->width; + mf.height = pix->height; + mf.field = pix->field; + mf.code = xlate->code; + mf.colorspace = pix->colorspace; + + ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); if (ret < 0) return ret; + pix->width = mf.width; + pix->height = mf.height; + pix->field = mf.field; + pix->colorspace = mf.colorspace; + switch (pixfmt) { case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: @@ -1554,21 +1615,25 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, /* FIXME: check against rect_max after converting soc-camera */ /* We can scale precisely, need a bigger image from camera */ if (pix->width < width || pix->height < height) { - int tmp_w = pix->width, tmp_h = pix->height; - pix->width = 2560; - pix->height = 1920; - ret = v4l2_subdev_call(sd, video, try_fmt, f); + /* + * We presume, the sensor behaves sanely, i.e., if + * requested a bigger rectangle, it will not return a + * smaller one. + */ + mf.width = 2560; + mf.height = 1920; + ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); if (ret < 0) { /* Shouldn't actually happen... */ dev_err(icd->dev.parent, - "FIXME: try_fmt() returned %d\n", ret); - pix->width = tmp_w; - pix->height = tmp_h; + "FIXME: client try_fmt() = %d\n", ret); + return ret; } } - if (pix->width > width) + /* We will scale exactly */ + if (mf.width > width) pix->width = width; - if (pix->height > height) + if (mf.height > height) pix->height = height; } @@ -1663,7 +1728,7 @@ static int sh_mobile_ceu_set_ctrl(struct soc_camera_device *icd, switch (ctrl->id) { case V4L2_CID_SHARPNESS: - switch (icd->current_fmt->fourcc) { + switch (icd->current_fmt->host_fmt->fourcc) { case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: case V4L2_PIX_FMT_NV16: diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 5fdedc7..6b3fbcc 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -31,6 +31,7 @@ #include #include #include +#include /* Default to VGA resolution */ #define DEFAULT_WIDTH 640 @@ -40,18 +41,6 @@ static LIST_HEAD(hosts); static LIST_HEAD(devices); static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ -const struct soc_camera_data_format *soc_camera_format_by_fourcc( - struct soc_camera_device *icd, unsigned int fourcc) -{ - unsigned int i; - - for (i = 0; i < icd->num_formats; i++) - if (icd->formats[i].fourcc == fourcc) - return icd->formats + i; - return NULL; -} -EXPORT_SYMBOL(soc_camera_format_by_fourcc); - const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( struct soc_camera_device *icd, unsigned int fourcc) { @@ -207,21 +196,26 @@ static int soc_camera_dqbuf(struct file *file, void *priv, /* Always entered with .video_lock held */ static int soc_camera_init_user_formats(struct soc_camera_device *icd) { + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - int i, fmts = 0, ret; + int i, fmts = 0, raw_fmts = 0, ret; + enum v4l2_mbus_pixelcode code; + + while (!v4l2_subdev_call(sd, video, enum_mbus_fmt, raw_fmts, &code)) + raw_fmts++; if (!ici->ops->get_formats) /* * Fallback mode - the host will have to serve all * sensor-provided formats one-to-one to the user */ - fmts = icd->num_formats; + fmts = raw_fmts; else /* * First pass - only count formats this host-sensor * configuration can provide */ - for (i = 0; i < icd->num_formats; i++) { + for (i = 0; i < raw_fmts; i++) { ret = ici->ops->get_formats(icd, i, NULL); if (ret < 0) return ret; @@ -242,11 +236,12 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) /* Second pass - actually fill data formats */ fmts = 0; - for (i = 0; i < icd->num_formats; i++) + for (i = 0; i < raw_fmts; i++) if (!ici->ops->get_formats) { - icd->user_formats[i].host_fmt = icd->formats + i; - icd->user_formats[i].cam_fmt = icd->formats + i; - icd->user_formats[i].buswidth = icd->formats[i].depth; + v4l2_subdev_call(sd, video, enum_mbus_fmt, i, &code); + icd->user_formats[i].host_fmt = + soc_mbus_get_fmtdesc(code); + icd->user_formats[i].code = code; } else { ret = ici->ops->get_formats(icd, i, &icd->user_formats[fmts]); @@ -255,7 +250,7 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) fmts += ret; } - icd->current_fmt = icd->user_formats[0].host_fmt; + icd->current_fmt = &icd->user_formats[0]; return 0; @@ -281,7 +276,7 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd) #define pixfmtstr(x) (x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, \ ((x) >> 24) & 0xff -/* Called with .vb_lock held */ +/* Called with .vb_lock held, or from the first open(2), see comment there */ static int soc_camera_set_fmt(struct soc_camera_file *icf, struct v4l2_format *f) { @@ -302,7 +297,7 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, if (ret < 0) { return ret; } else if (!icd->current_fmt || - icd->current_fmt->fourcc != pix->pixelformat) { + icd->current_fmt->host_fmt->fourcc != pix->pixelformat) { dev_err(&icd->dev, "Host driver hasn't set up current format correctly!\n"); return -EINVAL; @@ -310,6 +305,7 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, icd->user_width = pix->width; icd->user_height = pix->height; + icd->colorspace = pix->colorspace; icf->vb_vidq.field = icd->field = pix->field; @@ -369,8 +365,9 @@ static int soc_camera_open(struct file *file) .width = icd->user_width, .height = icd->user_height, .field = icd->field, - .pixelformat = icd->current_fmt->fourcc, - .colorspace = icd->current_fmt->colorspace, + .colorspace = icd->colorspace, + .pixelformat = + icd->current_fmt->host_fmt->fourcc, }, }; @@ -390,7 +387,12 @@ static int soc_camera_open(struct file *file) goto eiciadd; } - /* Try to configure with default parameters */ + /* + * Try to configure with default parameters. Notice: this is the + * very first open, so, we cannot race against other calls, + * apart from someone else calling open() simultaneously, but + * .video_lock is protecting us against it. + */ ret = soc_camera_set_fmt(icf, &f); if (ret < 0) goto esfmt; @@ -534,7 +536,7 @@ static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - const struct soc_camera_data_format *format; + const struct soc_mbus_pixelfmt *format; WARN_ON(priv != file->private_data); @@ -543,7 +545,8 @@ static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv, format = icd->user_formats[f->index].host_fmt; - strlcpy(f->description, format->name, sizeof(f->description)); + if (format->name) + strlcpy(f->description, format->name, sizeof(f->description)); f->pixelformat = format->fourcc; return 0; } @@ -560,12 +563,15 @@ static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv, pix->width = icd->user_width; pix->height = icd->user_height; pix->field = icf->vb_vidq.field; - pix->pixelformat = icd->current_fmt->fourcc; - pix->bytesperline = pix->width * - DIV_ROUND_UP(icd->current_fmt->depth, 8); + pix->pixelformat = icd->current_fmt->host_fmt->fourcc; + pix->bytesperline = soc_mbus_bytes_per_line(pix->width, + icd->current_fmt->host_fmt); + pix->colorspace = icd->colorspace; + if (pix->bytesperline < 0) + return pix->bytesperline; pix->sizeimage = pix->height * pix->bytesperline; dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n", - icd->current_fmt->fourcc); + icd->current_fmt->host_fmt->fourcc); return 0; } @@ -894,7 +900,7 @@ static int soc_camera_probe(struct device *dev) struct soc_camera_link *icl = to_soc_camera_link(icd); struct device *control = NULL; struct v4l2_subdev *sd; - struct v4l2_format f = {.type = V4L2_BUF_TYPE_VIDEO_CAPTURE}; + struct v4l2_mbus_framefmt mf; int ret; dev_info(dev, "Probing %s\n", dev_name(dev)); @@ -965,9 +971,11 @@ static int soc_camera_probe(struct device *dev) /* Try to improve our guess of a reasonable window format */ sd = soc_camera_to_subdev(icd); - if (!v4l2_subdev_call(sd, video, g_fmt, &f)) { - icd->user_width = f.fmt.pix.width; - icd->user_height = f.fmt.pix.height; + if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) { + icd->user_width = mf.width; + icd->user_height = mf.height; + icd->colorspace = mf.colorspace; + icd->field = mf.field; } /* Do we have to sysfs_remove_link() before device_unregister()? */ diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c index c7c9151..10b003a 100644 --- a/drivers/media/video/soc_camera_platform.c +++ b/drivers/media/video/soc_camera_platform.c @@ -22,7 +22,6 @@ struct soc_camera_platform_priv { struct v4l2_subdev subdev; - struct soc_camera_data_format format; }; static struct soc_camera_platform_priv *get_priv(struct platform_device *pdev) @@ -58,36 +57,36 @@ soc_camera_platform_query_bus_param(struct soc_camera_device *icd) } static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd, - struct v4l2_format *f) + struct v4l2_mbus_framefmt *mf) { struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); - struct v4l2_pix_format *pix = &f->fmt.pix; - pix->width = p->format.width; - pix->height = p->format.height; + mf->width = p->format.width; + mf->height = p->format.height; + mf->code = p->format.code; + mf->colorspace = p->format.colorspace; + return 0; } -static void soc_camera_platform_video_probe(struct soc_camera_device *icd, - struct platform_device *pdev) +static struct v4l2_subdev_core_ops platform_subdev_core_ops; + +static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, int index, + enum v4l2_mbus_pixelcode *code) { - struct soc_camera_platform_priv *priv = get_priv(pdev); - struct soc_camera_platform_info *p = pdev->dev.platform_data; + struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); - priv->format.name = p->format_name; - priv->format.depth = p->format_depth; - priv->format.fourcc = p->format.pixelformat; - priv->format.colorspace = p->format.colorspace; + if (index) + return -EINVAL; - icd->formats = &priv->format; - icd->num_formats = 1; + *code = p->format.code; + return 0; } -static struct v4l2_subdev_core_ops platform_subdev_core_ops; - static struct v4l2_subdev_video_ops platform_subdev_video_ops = { .s_stream = soc_camera_platform_s_stream, - .try_fmt = soc_camera_platform_try_fmt, + .try_mbus_fmt = soc_camera_platform_try_fmt, + .enum_mbus_fmt = soc_camera_platform_enum_fmt, }; static struct v4l2_subdev_ops platform_subdev_ops = { @@ -128,12 +127,10 @@ static int soc_camera_platform_probe(struct platform_device *pdev) /* Set the control device reference */ dev_set_drvdata(&icd->dev, &pdev->dev); - icd->ops = &soc_camera_platform_ops; + icd->ops = &soc_camera_platform_ops; ici = to_soc_camera_host(icd->dev.parent); - soc_camera_platform_video_probe(icd, pdev); - v4l2_subdev_init(&priv->subdev, &platform_subdev_ops); v4l2_set_subdevdata(&priv->subdev, p); strncpy(priv->subdev.name, dev_name(&pdev->dev), V4L2_SUBDEV_NAME_SIZE); diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 8ec1031..341d0e0 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c @@ -251,15 +251,6 @@ static const struct regval_list tw9910_default_regs[] = ENDMARKER, }; -static const struct soc_camera_data_format tw9910_color_fmt[] = { - { - .name = "VYUY", - .fourcc = V4L2_PIX_FMT_VYUY, - .depth = 16, - .colorspace = V4L2_COLORSPACE_SMPTE170M, - } -}; - static const struct tw9910_scale_ctrl tw9910_ntsc_scales[] = { { .name = "NTSC SQ", @@ -814,11 +805,11 @@ static int tw9910_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) return 0; } -static int tw9910_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int tw9910_g_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = sd->priv; struct tw9910_priv *priv = to_tw9910(client); - struct v4l2_pix_format *pix = &f->fmt.pix; if (!priv->scale) { int ret; @@ -835,74 +826,76 @@ static int tw9910_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) return ret; } - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - pix->width = priv->scale->width; - pix->height = priv->scale->height; - pix->pixelformat = V4L2_PIX_FMT_VYUY; - pix->colorspace = V4L2_COLORSPACE_SMPTE170M; - pix->field = V4L2_FIELD_INTERLACED; + mf->width = priv->scale->width; + mf->height = priv->scale->height; + mf->code = V4L2_MBUS_FMT_YVYU8_2X8_BE; + mf->colorspace = V4L2_COLORSPACE_JPEG; + mf->field = V4L2_FIELD_INTERLACED; return 0; } -static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int tw9910_s_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = sd->priv; struct tw9910_priv *priv = to_tw9910(client); - struct v4l2_pix_format *pix = &f->fmt.pix; /* See tw9910_s_crop() - no proper cropping support */ struct v4l2_crop a = { .c = { .left = 0, .top = 0, - .width = pix->width, - .height = pix->height, + .width = mf->width, + .height = mf->height, }, }; - int i, ret; + int ret; + + WARN_ON(mf->field != V4L2_FIELD_ANY && + mf->field != V4L2_FIELD_INTERLACED); /* * check color format */ - for (i = 0; i < ARRAY_SIZE(tw9910_color_fmt); i++) - if (pix->pixelformat == tw9910_color_fmt[i].fourcc) - break; - - if (i == ARRAY_SIZE(tw9910_color_fmt)) + if (mf->code != V4L2_MBUS_FMT_YVYU8_2X8_BE) return -EINVAL; + mf->colorspace = V4L2_COLORSPACE_JPEG; + ret = tw9910_s_crop(sd, &a); if (!ret) { - pix->width = priv->scale->width; - pix->height = priv->scale->height; + mf->width = priv->scale->width; + mf->height = priv->scale->height; } return ret; } -static int tw9910_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +static int tw9910_try_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = sd->priv; struct soc_camera_device *icd = client->dev.platform_data; - struct v4l2_pix_format *pix = &f->fmt.pix; const struct tw9910_scale_ctrl *scale; - if (V4L2_FIELD_ANY == pix->field) { - pix->field = V4L2_FIELD_INTERLACED; - } else if (V4L2_FIELD_INTERLACED != pix->field) { - dev_err(&client->dev, "Field type invalid.\n"); + if (V4L2_FIELD_ANY == mf->field) { + mf->field = V4L2_FIELD_INTERLACED; + } else if (V4L2_FIELD_INTERLACED != mf->field) { + dev_err(&client->dev, "Field type %d invalid.\n", mf->field); return -EINVAL; } + mf->code = V4L2_MBUS_FMT_YVYU8_2X8_BE; + mf->colorspace = V4L2_COLORSPACE_JPEG; + /* * select suitable norm */ - scale = tw9910_select_norm(icd, pix->width, pix->height); + scale = tw9910_select_norm(icd, mf->width, mf->height); if (!scale) return -EINVAL; - pix->width = scale->width; - pix->height = scale->height; + mf->width = scale->width; + mf->height = scale->height; return 0; } @@ -930,9 +923,6 @@ static int tw9910_video_probe(struct soc_camera_device *icd, return -ENODEV; } - icd->formats = tw9910_color_fmt; - icd->num_formats = ARRAY_SIZE(tw9910_color_fmt); - /* * check and show Product ID * So far only revisions 0 and 1 have been seen @@ -973,14 +963,25 @@ static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = { #endif }; +static int tw9910_enum_fmt(struct v4l2_subdev *sd, int index, + enum v4l2_mbus_pixelcode *code) +{ + if (index) + return -EINVAL; + + *code = V4L2_MBUS_FMT_YVYU8_2X8_BE; + return 0; +} + static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = { .s_stream = tw9910_s_stream, - .g_fmt = tw9910_g_fmt, - .s_fmt = tw9910_s_fmt, - .try_fmt = tw9910_try_fmt, + .g_mbus_fmt = tw9910_g_fmt, + .s_mbus_fmt = tw9910_s_fmt, + .try_mbus_fmt = tw9910_try_fmt, .cropcap = tw9910_cropcap, .g_crop = tw9910_g_crop, .s_crop = tw9910_s_crop, + .enum_mbus_fmt = tw9910_enum_fmt, }; static struct v4l2_subdev_ops tw9910_subdev_ops = { diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 831efff..dcc5b86 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -24,15 +24,13 @@ struct soc_camera_device { struct device *pdev; /* Platform device */ s32 user_width; s32 user_height; + enum v4l2_colorspace colorspace; unsigned char iface; /* Host number */ unsigned char devnum; /* Device number per host */ - unsigned char buswidth; /* See comment in .c */ struct soc_camera_sense *sense; /* See comment in struct definition */ struct soc_camera_ops *ops; struct video_device *vdev; - const struct soc_camera_data_format *current_fmt; - const struct soc_camera_data_format *formats; - int num_formats; + const struct soc_camera_format_xlate *current_fmt; struct soc_camera_format_xlate *user_formats; int num_user_formats; enum v4l2_field field; /* Preserve field over close() */ @@ -161,23 +159,13 @@ static inline struct v4l2_subdev *soc_camera_to_subdev( int soc_camera_host_register(struct soc_camera_host *ici); void soc_camera_host_unregister(struct soc_camera_host *ici); -const struct soc_camera_data_format *soc_camera_format_by_fourcc( - struct soc_camera_device *icd, unsigned int fourcc); const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( struct soc_camera_device *icd, unsigned int fourcc); -struct soc_camera_data_format { - const char *name; - unsigned int depth; - __u32 fourcc; - enum v4l2_colorspace colorspace; -}; - /** * struct soc_camera_format_xlate - match between host and sensor formats - * @cam_fmt: sensor format provided by the sensor - * @host_fmt: host format after host translation from cam_fmt - * @buswidth: bus width for this format + * @code: code of a sensor provided format + * @host_fmt: host format after host translation from code * * Host and sensor translation structure. Used in table of host and sensor * formats matchings in soc_camera_device. A host can override the generic list @@ -185,9 +173,8 @@ struct soc_camera_data_format { * format setup. */ struct soc_camera_format_xlate { - const struct soc_camera_data_format *cam_fmt; - const struct soc_camera_data_format *host_fmt; - unsigned char buswidth; + enum v4l2_mbus_pixelcode code; + const struct soc_mbus_pixelfmt *host_fmt; }; struct soc_camera_ops { diff --git a/include/media/soc_camera_platform.h b/include/media/soc_camera_platform.h index 88b3b57..0ecefe2 100644 --- a/include/media/soc_camera_platform.h +++ b/include/media/soc_camera_platform.h @@ -19,7 +19,7 @@ struct device; struct soc_camera_platform_info { const char *format_name; unsigned long format_depth; - struct v4l2_pix_format format; + struct v4l2_mbus_framefmt format; unsigned long bus_param; struct device *dev; int (*set_capture)(struct soc_camera_platform_info *info, int enable); -- cgit v0.10.2 From a6b5f2008a3d54b5f5350a01121b718dd6bfead7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 11 Dec 2009 11:53:45 -0300 Subject: V4L/DVB (13661): rj54n1cb0c: Add cropping, auto white balance, restrict sizes, add platform data It has been experimentally found out, that the sensor only supports up to 512x384 video output and also has some restrictions on minimum scale. We disable non-working size ranges until, maybe, someone finds out how to properly set them up. Also add cropping support, an auto white balance control, platform data to specify master clock frequency and polarity of the IOCTL pin. create mode 100644 include/media/rj54n1cb0c.h Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c index 87438d6..9038d76 100644 --- a/arch/sh/boards/mach-kfr2r09/setup.c +++ b/arch/sh/boards/mach-kfr2r09/setup.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include