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]

 



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 ;)

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 */


-- 

Cheers,
Mauro
--
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