Re: [PATCH 3/6] em28xx: make remote controls of devices with external IR IC working again

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Am 04.01.2013 22:12, schrieb Mauro Carvalho Chehab:
> Em Fri, 28 Dec 2012 00:02:45 +0100
> Frank Schäfer <fschaefer.oss@xxxxxxxxxxxxxx> escreveu:
>
>> Tested with device "Terratec Cinergy 200 USB".
> Sorry, but this patch is completely wrong ;)

Completely wrong ? That's not helpful...
Please elaborate a bit more on this so that I can do things right next
time. ;)

Regards,
Frank

> The fix here is simple: just move the initialization to happen
> earlier.
>
> I'm posting it right now, together with a bunch of other fixes for
> I2C-based IR devices.
>
> Regards,
> Mauro
>> Signed-off-by: Frank Schäfer <fschaefer.oss@xxxxxxxxxxxxxx>
>> ---
>>  drivers/media/usb/em28xx/em28xx-cards.c |    9 +-
>>  drivers/media/usb/em28xx/em28xx-i2c.c   |    1 +
>>  drivers/media/usb/em28xx/em28xx-input.c |  142 +++++++++++++++++--------------
>>  3 Dateien geändert, 83 Zeilen hinzugefügt(+), 69 Zeilen entfernt(-)
>>
>> diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
>> index 40c3e45..3b226b1 100644
>> --- a/drivers/media/usb/em28xx/em28xx-cards.c
>> +++ b/drivers/media/usb/em28xx/em28xx-cards.c
>> @@ -488,6 +488,7 @@ struct em28xx_board em28xx_boards[] = {
>>  		.name         = "Terratec Cinergy 250 USB",
>>  		.tuner_type   = TUNER_LG_PAL_NEW_TAPC,
>>  		.has_ir_i2c   = 1,
>> +		.ir_codes     = RC_MAP_EM_TERRATEC,
>>  		.tda9887_conf = TDA9887_PRESENT,
>>  		.decoder      = EM28XX_SAA711X,
>>  		.input        = { {
>> @@ -508,6 +509,7 @@ struct em28xx_board em28xx_boards[] = {
>>  		.name         = "Pinnacle PCTV USB 2",
>>  		.tuner_type   = TUNER_LG_PAL_NEW_TAPC,
>>  		.has_ir_i2c   = 1,
>> +		.ir_codes     = RC_MAP_PINNACLE_GREY,
>>  		.tda9887_conf = TDA9887_PRESENT,
>>  		.decoder      = EM28XX_SAA711X,
>>  		.input        = { {
>> @@ -533,6 +535,7 @@ struct em28xx_board em28xx_boards[] = {
>>  		.decoder      = EM28XX_TVP5150,
>>  		.has_msp34xx  = 1,
>>  		.has_ir_i2c   = 1,
>> +		.ir_codes     = RC_MAP_HAUPPAUGE,
>>  		.input        = { {
>>  			.type     = EM28XX_VMUX_TELEVISION,
>>  			.vmux     = TVP5150_COMPOSITE0,
>> @@ -629,6 +632,7 @@ struct em28xx_board em28xx_boards[] = {
>>  		.valid        = EM28XX_BOARD_NOT_VALIDATED,
>>  		.tuner_type   = TUNER_PHILIPS_FM1216ME_MK3,
>>  		.has_ir_i2c   = 1,
>> +		.ir_codes     = RC_MAP_WINFAST_USBII_DELUXE,
>>  		.tvaudio_addr = 0x58,
>>  		.tda9887_conf = TDA9887_PRESENT |
>>  				TDA9887_PORT2_ACTIVE |
>> @@ -1222,6 +1226,7 @@ struct em28xx_board em28xx_boards[] = {
>>  		.name         = "Terratec Cinergy 200 USB",
>>  		.is_em2800    = 1,
>>  		.has_ir_i2c   = 1,
>> +		.ir_codes     = RC_MAP_EM_TERRATEC,
>>  		.tuner_type   = TUNER_LG_TALN,
>>  		.tda9887_conf = TDA9887_PRESENT,
>>  		.decoder      = EM28XX_SAA711X,
>> @@ -2912,7 +2917,7 @@ static void request_module_async(struct work_struct *work)
>>  
>>  	if (dev->board.has_dvb)
>>  		request_module("em28xx-dvb");
>> -	if (dev->board.ir_codes && !disable_ir)
>> +	if ((dev->board.ir_codes || dev->board.has_ir_i2c) && !disable_ir)
>>  		request_module("em28xx-rc");
>>  #endif /* CONFIG_MODULES */
>>  }
>> @@ -2935,8 +2940,6 @@ static void flush_request_modules(struct em28xx *dev)
>>  */
>>  void em28xx_release_resources(struct em28xx *dev)
>>  {
>> -	/*FIXME: I2C IR should be disconnected */
>> -
>>  	em28xx_release_analog_resources(dev);
>>  
>>  	em28xx_i2c_unregister(dev);
>> diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c
>> index 44533e4..39c5a3e 100644
>> --- a/drivers/media/usb/em28xx/em28xx-i2c.c
>> +++ b/drivers/media/usb/em28xx/em28xx-i2c.c
>> @@ -470,6 +470,7 @@ static struct i2c_client em28xx_client_template = {
>>  static char *i2c_devs[128] = {
>>  	[0x4a >> 1] = "saa7113h",
>>  	[0x52 >> 1] = "drxk",
>> +	[0x3e >> 1] = "remote IR sensor",
>>  	[0x60 >> 1] = "remote IR sensor",
>>  	[0x8e >> 1] = "remote IR sensor",
>>  	[0x86 >> 1] = "tda9887",
>> diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
>> index 3598221..631e252 100644
>> --- a/drivers/media/usb/em28xx/em28xx-input.c
>> +++ b/drivers/media/usb/em28xx/em28xx-input.c
>> @@ -5,6 +5,7 @@
>>  		      Markus Rechberger <mrechberger@xxxxxxxxx>
>>  		      Mauro Carvalho Chehab <mchehab@xxxxxxxxxxxxx>
>>  		      Sascha Sommer <saschasommer@xxxxxxxxxx>
>> +   Copyright (C) 2012 Frank Schäfer <fschaefer.oss@xxxxxxxxxxxxxx>
>>  
>>    This program is free software; you can redistribute it and/or modify
>>    it under the terms of the GNU General Public License as published by
>> @@ -34,6 +35,8 @@
>>  #define EM28XX_SBUTTON_QUERY_INTERVAL 500
>>  #define EM28XX_R0C_USBSUSP_SNAPSHOT 0x20
>>  
>> +#define EM28XX_RC_QUERY_INTERVAL 100
>> +
>>  static unsigned int ir_debug;
>>  module_param(ir_debug, int, 0644);
>>  MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
>> @@ -67,13 +70,14 @@ struct em28xx_IR {
>>  	char name[32];
>>  	char phys[32];
>>  
>> -	/* poll external decoder */
>>  	int polling;
>>  	struct delayed_work work;
>>  	unsigned int full_code:1;
>>  	unsigned int last_readcount;
>>  	u64 rc_type;
>>  
>> +	struct i2c_client *i2c_dev; /* external i2c IR receiver/decoder */
>> +
>>  	int  (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *);
>>  };
>>  
>> @@ -452,7 +456,7 @@ static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type)
>>  	}
>>  }
>>  
>> -static void em28xx_register_i2c_ir(struct em28xx *dev)
>> +static int em28xx_register_i2c_ir(struct em28xx *dev, struct rc_dev *rc_dev)
>>  {
>>  	/* Leadtek winfast tv USBII deluxe can find a non working IR-device */
>>  	/* at address 0x18, so if that address is needed for another board in */
>> @@ -470,30 +474,46 @@ static void em28xx_register_i2c_ir(struct em28xx *dev)
>>  	switch (dev->model) {
>>  	case EM2800_BOARD_TERRATEC_CINERGY_200:
>>  	case EM2820_BOARD_TERRATEC_CINERGY_250:
>> -		dev->init_data.ir_codes = RC_MAP_EM_TERRATEC;
>> -		dev->init_data.get_key = em28xx_get_key_terratec;
>>  		dev->init_data.name = "i2c IR (EM28XX Terratec)";
>> +		dev->init_data.type = RC_BIT_OTHER;
>> +		dev->init_data.get_key = em28xx_get_key_terratec;
>>  		break;
>>  	case EM2820_BOARD_PINNACLE_USB_2:
>> -		dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY;
>> -		dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey;
>>  		dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)";
>> +		dev->init_data.type = RC_BIT_OTHER;
>> +		dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey;
>>  		break;
>>  	case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
>> -		dev->init_data.ir_codes = RC_MAP_HAUPPAUGE;
>> -		dev->init_data.get_key = em28xx_get_key_em_haup;
>>  		dev->init_data.name = "i2c IR (EM2840 Hauppauge)";
>> +		dev->init_data.type = RC_BIT_RC5;
>> +		dev->init_data.get_key = em28xx_get_key_em_haup;
>>  		break;
>>  	case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE:
>> -		dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE;
>> -		dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe;
>>  		dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)";
>> +		dev->init_data.type = RC_BIT_OTHER;
>> +		dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe;
>>  		break;
>>  	}
>>  
>> -	if (dev->init_data.name)
>> +	if (dev->init_data.name && dev->board.ir_codes) {
>> +		dev->init_data.ir_codes = dev->board.ir_codes;
>> +		dev->init_data.polling_interval = EM28XX_RC_QUERY_INTERVAL;
>> +		dev->init_data.rc_dev = rc_dev;
>>  		info.platform_data = &dev->init_data;
>> -	i2c_new_probed_device(&dev->i2c_adap, &info, addr_list, NULL);
>> +	} else {
>> +		em28xx_warn("Unknown i2c remote control device.\n");
>> +		em28xx_warn("If the remote control doesn't work properly, please contact <linux-media@xxxxxxxxxxxxxxx>\n");
>> +	}
>> +
>> +	dev->ir->i2c_dev = i2c_new_probed_device(&dev->i2c_adap, &info, addr_list, NULL);
>> +	if (NULL == dev->ir->i2c_dev)
>> +		return -ENODEV;
>> +
>> +#if defined(CONFIG_MODULES) && defined(MODULE)
>> +	request_module("ir-kbd-i2c");
>> +#endif
>> +
>> +	return 0;
>>  }
>>  
>>  /**********************************************************
>> @@ -590,7 +610,7 @@ static int em28xx_ir_init(struct em28xx *dev)
>>  	int err = -ENOMEM;
>>  	u64 rc_type;
>>  
>> -	if (dev->board.ir_codes == NULL) {
>> +	if (dev->board.ir_codes == NULL && !dev->board.has_ir_i2c) {
>>  		/* No remote control support */
>>  		em28xx_warn("Remote control support is not available for "
>>  				"this card.\n");
>> @@ -607,68 +627,56 @@ static int em28xx_ir_init(struct em28xx *dev)
>>  	dev->ir = ir;
>>  	ir->rc = rc;
>>  
>> -	/*
>> -	 * em2874 supports more protocols. For now, let's just announce
>> -	 * the two protocols that were already tested
>> -	 */
>> -	rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC;
>> -	rc->priv = ir;
>> -	rc->change_protocol = em28xx_ir_change_protocol;
>> -	rc->open = em28xx_ir_start;
>> -	rc->close = em28xx_ir_stop;
>> -
>> -	switch (dev->chip_id) {
>> -	case CHIP_ID_EM2860:
>> -	case CHIP_ID_EM2883:
>> -		rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC;
>> -		break;
>> -	case CHIP_ID_EM2884:
>> -	case CHIP_ID_EM2874:
>> -	case CHIP_ID_EM28174:
>> -		rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC | RC_BIT_RC6_0;
>> -		break;
>> -	default:
>> -		err = -ENODEV;
>> -		goto error;
>> -	}
>> -
>> -	/* By default, keep protocol field untouched */
>> -	rc_type = RC_BIT_UNKNOWN;
>> -	err = em28xx_ir_change_protocol(rc, &rc_type);
>> -	if (err)
>> -		goto error;
>> -
>> -	/* This is how often we ask the chip for IR information */
>> -	ir->polling = 100; /* ms */
>> -
>> -	/* init input device */
>> -	snprintf(ir->name, sizeof(ir->name), "em28xx IR (%s)",
>> -						dev->name);
>> -
>> +	snprintf(ir->name, sizeof(ir->name), "em28xx IR (%s)", dev->name);
>>  	usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
>>  	strlcat(ir->phys, "/input0", sizeof(ir->phys));
>> +	ir->polling = EM28XX_RC_QUERY_INTERVAL;
>>  
>> -	rc->input_name = ir->name;
>> -	rc->input_phys = ir->phys;
>> -	rc->input_id.bustype = BUS_USB;
>>  	rc->input_id.version = 1;
>>  	rc->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
>>  	rc->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
>>  	rc->dev.parent = &dev->udev->dev;
>> -	rc->map_name = dev->board.ir_codes;
>>  	rc->driver_name = MODULE_NAME;
>>  
>> -	/* all done */
>> -	err = rc_register_device(rc);
>> -	if (err)
>> -		goto error;
>> -
>> -	em28xx_register_i2c_ir(dev);
>> +	if (dev->board.has_ir_i2c) {
>> +		err = em28xx_register_i2c_ir(dev, rc);
>> +		if (err < 0)
>> +			goto error;
>> +	} else {
>> +		switch (dev->chip_id) {
>> +		case CHIP_ID_EM2860:
>> +		case CHIP_ID_EM2883:
>> +			rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC;
>> +			break;
>> +		case CHIP_ID_EM2884:
>> +		case CHIP_ID_EM2874:
>> +		case CHIP_ID_EM28174:
>> +			rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC | RC_BIT_RC6_0;
>> +			break;
>> +		default:
>> +			err = -ENODEV;
>> +			goto error;
>> +		}
>> +		rc->priv = ir;
>> +		rc->change_protocol = em28xx_ir_change_protocol;
>> +		rc->open = em28xx_ir_start;
>> +		rc->close = em28xx_ir_stop;
>> +		rc->input_name = ir->name;
>> +		rc->input_phys = ir->phys;
>> +		rc->input_id.bustype = BUS_USB;
>> +		rc->map_name = dev->board.ir_codes;
>> +
>> +		/* By default, keep protocol field untouched */
>> +		rc_type = RC_BIT_UNKNOWN;
>> +		err = em28xx_ir_change_protocol(rc, &rc_type);
>> +		if (err)
>> +			goto error;
>> +
>> +		err = rc_register_device(rc);
>> +		if (err < 0)
>> +			goto error;
>> +	}
>>  
>> -#if defined(CONFIG_MODULES) && defined(MODULE)
>> -	if (dev->board.has_ir_i2c)
>> -		request_module("ir-kbd-i2c");
>> -#endif
>>  	if (dev->board.has_snapshot_button)
>>  		em28xx_register_snapshot_button(dev);
>>  
>> @@ -691,7 +699,9 @@ static int em28xx_ir_fini(struct em28xx *dev)
>>  	if (!ir)
>>  		return 0;
>>  
>> -	if (ir->rc)
>> +	if (ir->i2c_dev)
>> +		i2c_unregister_device(ir->i2c_dev);
>> +	else if (ir->rc)
>>  		rc_unregister_device(ir->rc);
>>  
>>  	/* done */

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux