Re: Re: [PATCH 1/1] SMI PCIe driver for DVBSky cards

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

 



Hello,

Just find a minor issue to do "smi_ir_exit".

Best Regards,
Max

On 2015-05-15 00:06:33, Mauro Carvalho Chehab <mchehab@xxxxxxxxxxxxxxx> wrote:
>Em Fri, 13 Mar 2015 00:09:23 +0100
>Dirk Nehring <dnehring@xxxxxxx> escreveu:
>
>> ported from the manufacturer's source tree, available from
>> http://dvbsky.net/download/linux/media_build-bst-150211.tar.gz
>
>The better would be if the author of the remote controller support
>to send us the patch or to reply us with his SOB.
>
>Max,
>
>Could you please take care of it?
>
>Thanks!
>Mauro
>
>> 
>> Signed-off-by: Dirk Nehring <dnehring@xxxxxxx>
>> ---
>>  drivers/media/pci/smipcie/Kconfig                  |   1 +
>>  drivers/media/pci/smipcie/Makefile                 |   3 +
>>  drivers/media/pci/smipcie/smipcie-ir.c             | 233 +++++++++++++++++++++
>>  .../pci/smipcie/{smipcie.c => smipcie-main.c}      |  14 +-
>>  drivers/media/pci/smipcie/smipcie.h                |  19 ++
>>  5 files changed, 269 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/media/pci/smipcie/smipcie-ir.c
>>  rename drivers/media/pci/smipcie/{smipcie.c => smipcie-main.c} (99%)
>> 
>> diff --git a/drivers/media/pci/smipcie/Kconfig b/drivers/media/pci/smipcie/Kconfig
>> index c8de53f..c24641e 100644
>> --- a/drivers/media/pci/smipcie/Kconfig
>> +++ b/drivers/media/pci/smipcie/Kconfig
>> @@ -7,6 +7,7 @@ config DVB_SMIPCIE
>>  	select MEDIA_TUNER_M88TS2022 if MEDIA_SUBDRV_AUTOSELECT
>>  	select MEDIA_TUNER_M88RS6000T if MEDIA_SUBDRV_AUTOSELECT
>>  	select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
>> +	depends on RC_CORE
>>  	help
>>  	  Support for cards with SMI PCIe bridge:
>>  	  - DVBSky S950 V3
>> diff --git a/drivers/media/pci/smipcie/Makefile b/drivers/media/pci/smipcie/Makefile
>> index be55481..013bc3f 100644
>> --- a/drivers/media/pci/smipcie/Makefile
>> +++ b/drivers/media/pci/smipcie/Makefile
>> @@ -1,3 +1,6 @@
>> +
>> +smipcie-objs	:= smipcie-main.o smipcie-ir.o
>> +
>>  obj-$(CONFIG_DVB_SMIPCIE) += smipcie.o
>>  
>>  ccflags-y += -Idrivers/media/tuners
>> diff --git a/drivers/media/pci/smipcie/smipcie-ir.c b/drivers/media/pci/smipcie/smipcie-ir.c
>> new file mode 100644
>> index 0000000..2a32746
>> --- /dev/null
>> +++ b/drivers/media/pci/smipcie/smipcie-ir.c
>> @@ -0,0 +1,233 @@
>> +/*
>> + * SMI PCIe driver for DVBSky cards.
>> + *
>> + * Copyright (C) 2014 Max nibble <nibble.max@xxxxxxxxx>
>> + *
>> + *    This program is free software; 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.
>> + */
>> +
>> +#include "smipcie.h"
>> +
>> +static void smi_ir_enableInterrupt(struct smi_rc *ir)
>> +{
>> +	struct smi_dev *dev = ir->dev;
>> +
>> +	smi_write(MSI_INT_ENA_SET, IR_X_INT);
>> +}
>> +
>> +static void smi_ir_disableInterrupt(struct smi_rc *ir)
>> +{
>> +	struct smi_dev *dev = ir->dev;
>> +
>> +	smi_write(MSI_INT_ENA_CLR, IR_X_INT);
>> +}
>> +
>> +static void smi_ir_clearInterrupt(struct smi_rc *ir)
>> +{
>> +	struct smi_dev *dev = ir->dev;
>> +
>> +	smi_write(MSI_INT_STATUS_CLR, IR_X_INT);
>> +}
>> +
>> +static void smi_ir_stop(struct smi_rc *ir)
>> +{
>> +	struct smi_dev *dev = ir->dev;
>> +
>> +	smi_ir_disableInterrupt(ir);
>> +	smi_clear(IR_Init_Reg, 0x80);
>> +}
>> +
>> +#define BITS_PER_COMMAND 14
>> +#define GROUPS_PER_BIT	 2
>> +#define IR_RC5_MIN_BIT	36
>> +#define IR_RC5_MAX_BIT	52
>> +static u32 smi_decode_rc5(u8 *pData, u8 size)
>> +{
>> +	u8 index, current_bit, bit_count;
>> +	u8 group_array[BITS_PER_COMMAND * GROUPS_PER_BIT + 4];
>> +	u8 group_index = 0;
>> +	u32 command = 0xFFFFFFFF;
>> +
>> +	group_array[group_index++] = 1;
>> +
>> +	for (index = 0; index < size; index++) {
>> +
>> +		current_bit = (pData[index] & 0x80) ? 1 : 0;
>> +		bit_count = pData[index] & 0x7f;
>> +
>> +		if ((current_bit == 1) && (bit_count >= 2*IR_RC5_MAX_BIT + 1)) {
>> +			goto process_code;
>> +		} else if ((bit_count >= IR_RC5_MIN_BIT) &&
>> +			   (bit_count <= IR_RC5_MAX_BIT)) {
>> +				group_array[group_index++] = current_bit;
>> +		} else if ((bit_count > IR_RC5_MAX_BIT) &&
>> +			   (bit_count <= 2*IR_RC5_MAX_BIT)) {
>> +				group_array[group_index++] = current_bit;
>> +				group_array[group_index++] = current_bit;
>> +		} else {
>> +			goto invalid_timing;
>> +		}
>> +		if (group_index >= BITS_PER_COMMAND*GROUPS_PER_BIT)
>> +			goto process_code;
>> +
>> +		 if ((group_index == BITS_PER_COMMAND*GROUPS_PER_BIT - 1)
>> +			&& (group_array[group_index-1] == 0)) {
>> +			group_array[group_index++] = 1;
>> +			goto process_code;
>> +		}
>> +	}
>> +
>> +process_code:
>> +	if (group_index == (BITS_PER_COMMAND*GROUPS_PER_BIT-1))
>> +		group_array[group_index++] = 1;
>> +
>> +	if (group_index == BITS_PER_COMMAND*GROUPS_PER_BIT) {
>> +		command = 0;
>> +		for (index = 0; index < (BITS_PER_COMMAND*GROUPS_PER_BIT);
>> +		     index = index + 2) {
>> +			if ((group_array[index] == 1) &&
>> +			    (group_array[index+1] == 0)) {
>> +				command |= (1 << (BITS_PER_COMMAND -
>> +						   (index/2) - 1));
>> +			} else if ((group_array[index] == 0) &&
>> +				   (group_array[index+1] == 1)) {
>> +				/* */
>> +
>> +			} else {
>> +				command = 0xFFFFFFFF;
>> +				goto invalid_timing;
>> +			}
>> +		}
>> +	}
>> +
>> +invalid_timing:
>> +	return command;
>> +}
>> +
>> +static void smi_ir_decode(struct work_struct *work)
>> +{
>> +	struct smi_rc *ir = container_of(work, struct smi_rc, work);
>> +	struct smi_dev *dev = ir->dev;
>> +	struct rc_dev *rc_dev = ir->rc_dev;
>> +	u32 dwIRControl, dwIRData, dwIRCode, scancode;
>> +	u8 index, ucIRCount, readLoop, rc5_command, rc5_system, toggle;
>> +
>> +	dwIRControl = smi_read(IR_Init_Reg);
>> +	if (dwIRControl & rbIRVld) {
>> +		ucIRCount = (u8) smi_read(IR_Data_Cnt);
>> +
>> +		if (ucIRCount < 4)
>> +			goto end_ir_decode;
>> +
>> +		readLoop = ucIRCount/4;
>> +		if (ucIRCount % 4)
>> +			readLoop += 1;
>> +		for (index = 0; index < readLoop; index++) {
>> +			dwIRData = smi_read(IR_DATA_BUFFER_BASE + (index*4));
>> +
>> +			ir->irData[index*4 + 0] = (u8)(dwIRData);
>> +			ir->irData[index*4 + 1] = (u8)(dwIRData >> 8);
>> +			ir->irData[index*4 + 2] = (u8)(dwIRData >> 16);
>> +			ir->irData[index*4 + 3] = (u8)(dwIRData >> 24);
>> +		}
>> +		dwIRCode = smi_decode_rc5(ir->irData, ucIRCount);
>> +
>> +		if (dwIRCode != 0xFFFFFFFF) {
>> +			rc5_command = dwIRCode & 0x3F;
>> +			rc5_system = (dwIRCode & 0x7C0) >> 6;
>> +			toggle = (dwIRCode & 0x800) ? 1 : 0;
>> +			scancode = rc5_system << 8 | rc5_command;
>> +			rc_keydown(rc_dev, RC_TYPE_RC5, scancode, toggle);
>> +		}
>> +	}
>> +end_ir_decode:
>> +	smi_set(IR_Init_Reg, 0x04);
>> +	smi_ir_enableInterrupt(ir);
>> +}
>> +
>> +/* ir functions call by main driver.*/
>> +int smi_ir_irq(struct smi_rc *ir, u32 int_status)
>> +{
>> +	int handled = 0;
>> +
>> +	if (int_status & IR_X_INT) {
>> +		smi_ir_disableInterrupt(ir);
>> +		smi_ir_clearInterrupt(ir);
>> +		schedule_work(&ir->work);
>> +		handled = 1;
>> +	}
>> +	return handled;
>> +}
>> +
>> +void smi_ir_start(struct smi_rc *ir)
>> +{
>> +	struct smi_dev *dev = ir->dev;
>> +
>> +	smi_write(IR_Idle_Cnt_Low, 0x00140070);
>> +	msleep(20);
>> +	smi_set(IR_Init_Reg, 0x90);
>> +
>> +	smi_ir_enableInterrupt(ir);
>> +}
>> +
>> +int smi_ir_init(struct smi_dev *dev)
>> +{
>> +	int ret;
>> +	struct rc_dev *rc_dev;
>> +	struct smi_rc *ir = &dev->ir;
>> +
>> +	rc_dev = rc_allocate_device();
>> +	if (!rc_dev)
>> +		return -ENOMEM;
>> +
>> +	/* init input device */
>> +	snprintf(ir->input_name, sizeof(ir->input_name), "IR (%s)",
>> +		 dev->info->name);
>> +	snprintf(ir->input_phys, sizeof(ir->input_phys), "pci-%s/ir0",
>> +		 pci_name(dev->pci_dev));
>> +
>> +	rc_dev->driver_name = "SMI_PCIe";
>> +	rc_dev->input_phys = ir->input_phys;
>> +	rc_dev->input_name = ir->input_name;
>> +	rc_dev->input_id.bustype = BUS_PCI;
>> +	rc_dev->input_id.version = 1;
>> +	rc_dev->input_id.vendor = dev->pci_dev->subsystem_vendor;
>> +	rc_dev->input_id.product = dev->pci_dev->subsystem_device;
>> +	rc_dev->dev.parent = &dev->pci_dev->dev;
>> +
>> +	rc_dev->driver_type = RC_DRIVER_SCANCODE;
>> +	rc_dev->map_name = RC_MAP_DVBSKY;
>> +
>> +	ir->rc_dev = rc_dev;
>> +	ir->dev = dev;
>> +
>> +	INIT_WORK(&ir->work, smi_ir_decode);
>> +	smi_ir_disableInterrupt(ir);
>> +
>> +	ret = rc_register_device(rc_dev);
>> +	if (ret)
>> +		goto ir_err;
>> +
>> +	return 0;
>> +ir_err:
>> +	rc_free_device(rc_dev);
>> +	return ret;
>> +}
>> +
>> +void smi_ir_exit(struct smi_dev *dev)
>> +{
>> +	struct smi_rc *ir = &dev->ir;
>> +	struct rc_dev *rc_dev = ir->rc_dev;
>> +
>> +	smi_ir_stop(ir);
>> +	rc_unregister_device(rc_dev);
>> +	ir->rc_dev = NULL;
>> +}
>> diff --git a/drivers/media/pci/smipcie/smipcie.c b/drivers/media/pci/smipcie/smipcie-main.c
>> similarity index 99%
>> rename from drivers/media/pci/smipcie/smipcie.c
>> rename to drivers/media/pci/smipcie/smipcie-main.c
>> index 36c8ed7..88f3268 100644
>> --- a/drivers/media/pci/smipcie/smipcie.c
>> +++ b/drivers/media/pci/smipcie/smipcie-main.c
>> @@ -472,6 +472,7 @@ static irqreturn_t smi_irq_handler(int irq, void *dev_id)
>>  
>>  	u32 intr_status = smi_read(MSI_INT_STATUS);
>>  
>> +	struct smi_rc *ir = &dev->ir;
>>  	/* ts0 interrupt.*/
>>  	if (dev->info->ts_0)
>>  		handled += smi_port_irq(port0, intr_status);
>> @@ -484,6 +485,9 @@ static irqreturn_t smi_irq_handler(int irq, void *dev_id)
>>  }
>>  
>>  static struct i2c_client *smi_add_i2c_client(struct i2c_adapter *adapter,
>> +	/* ir interrupt.*/
>> +	handled += smi_ir_irq(ir, intr_status);
>> +
>>  			struct i2c_board_info *info)
>>  {
>>  	struct i2c_client *client;
>> @@ -994,6 +998,10 @@ static int smi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>>  			goto err_del_port0_attach;
>>  	}
>>  
>> +	ret = smi_ir_init(dev);
>> +	if (ret < 0)
>> +		goto err_del_port1_attach;
>> +
>>  #ifdef CONFIG_PCI_MSI /* to do msi interrupt.???*/
>>  	if (pci_msi_enabled())
>>  		ret = pci_enable_msi(dev->pci_dev);
>> @@ -1004,10 +1012,13 @@ static int smi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>>  	ret = request_irq(dev->pci_dev->irq, smi_irq_handler,
>>  			   IRQF_SHARED, "SMI_PCIE", dev);
>>  	if (ret < 0)
>> -		goto err_del_port1_attach;
>> +		goto err_del_ir;
>>  
>> +	smi_ir_start(&dev->ir);
>>  	return 0;
>>  
>> +err_del_ir:
>> +	smi_ir_exit(dev);
>>  err_del_port1_attach:
>>  	if (dev->info->ts_1)
>>  		smi_port_detach(&dev->ts_port[1]);
>> @@ -1016,6 +1027,7 @@ err_del_port0_attach:
>>  		smi_port_detach(&dev->ts_port[0]);
>>  err_del_i2c_adaptor:
>>  	smi_i2c_exit(dev);
>> +	smi_ir_exit(dev);

no need to do "smi_ir_exit" again.
It should place in "static void smi_remove(struct pci_dev *pdev)" function.

>>  err_pci_iounmap:
>>  	iounmap(dev->lmmio);
>>  err_kfree:
>> diff --git a/drivers/media/pci/smipcie/smipcie.h b/drivers/media/pci/smipcie/smipcie.h
>> index 10cdf20..68cdda2 100644
>> --- a/drivers/media/pci/smipcie/smipcie.h
>> +++ b/drivers/media/pci/smipcie/smipcie.h
>> @@ -234,6 +234,17 @@ struct smi_cfg_info {
>>  	int fe_1;
>>  };
>>  
>> +struct smi_rc {
>> +	struct smi_dev *dev;
>> +	struct rc_dev *rc_dev;
>> +	char input_phys[64];
>> +	char input_name[64];
>> +	struct work_struct work;
>> +	u8 irData[256];
>> +
>> +	int users;
>> +};
>> +
>>  struct smi_port {
>>  	struct smi_dev *dev;
>>  	int idx;
>> @@ -284,6 +295,9 @@ struct smi_dev {
>>  	/* i2c */
>>  	struct i2c_adapter i2c_bus[2];
>>  	struct i2c_algo_bit_data i2c_bit[2];
>> +
>> +	/* ir */
>> +	struct smi_rc ir;
>>  };
>>  
>>  #define smi_read(reg)             readl(dev->lmmio + ((reg)>>2))
>> @@ -296,4 +310,9 @@ struct smi_dev {
>>  #define smi_set(reg, bit)          smi_andor((reg), (bit), (bit))
>>  #define smi_clear(reg, bit)        smi_andor((reg), (bit), 0)
>>  
>> +int smi_ir_irq(struct smi_rc *ir, u32 int_status);
>> +void smi_ir_start(struct smi_rc *ir);
>> +void smi_ir_exit(struct smi_dev *dev);
>> +int smi_ir_init(struct smi_dev *dev);
>> +
>>  #endif /* #ifndef _SMI_PCIE_H_ */

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