2 * SMI PCIe driver for DVBSky cards.
4 * Copyright (C) 2014 Max nibble <nibble.max@gmail.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
19 #define SMI_SAMPLE_PERIOD 83
20 #define SMI_SAMPLE_IDLEMIN (10000 / SMI_SAMPLE_PERIOD)
22 static void smi_ir_enableInterrupt(struct smi_rc
*ir
)
24 struct smi_dev
*dev
= ir
->dev
;
26 smi_write(MSI_INT_ENA_SET
, IR_X_INT
);
29 static void smi_ir_disableInterrupt(struct smi_rc
*ir
)
31 struct smi_dev
*dev
= ir
->dev
;
33 smi_write(MSI_INT_ENA_CLR
, IR_X_INT
);
36 static void smi_ir_clearInterrupt(struct smi_rc
*ir
)
38 struct smi_dev
*dev
= ir
->dev
;
40 smi_write(MSI_INT_STATUS_CLR
, IR_X_INT
);
43 static void smi_ir_stop(struct smi_rc
*ir
)
45 struct smi_dev
*dev
= ir
->dev
;
47 smi_ir_disableInterrupt(ir
);
48 smi_clear(IR_Init_Reg
, rbIRen
);
51 static void smi_raw_process(struct rc_dev
*rc_dev
, const u8
*buffer
,
54 struct ir_raw_event rawir
= {};
57 for (cnt
= 0; cnt
< length
; cnt
++) {
58 if (buffer
[cnt
] & 0x7f) {
59 rawir
.pulse
= (buffer
[cnt
] & 0x80) == 0;
60 rawir
.duration
= ((buffer
[cnt
] & 0x7f) +
61 (rawir
.pulse
? 0 : -1)) *
62 rc_dev
->rx_resolution
;
63 ir_raw_event_store_with_filter(rc_dev
, &rawir
);
68 static void smi_ir_decode(struct smi_rc
*ir
)
70 struct smi_dev
*dev
= ir
->dev
;
71 struct rc_dev
*rc_dev
= ir
->rc_dev
;
72 u32 dwIRControl
, dwIRData
;
73 u8 index
, ucIRCount
, readLoop
;
75 dwIRControl
= smi_read(IR_Init_Reg
);
77 if (dwIRControl
& rbIRVld
) {
78 ucIRCount
= (u8
) smi_read(IR_Data_Cnt
);
80 readLoop
= ucIRCount
/4;
83 for (index
= 0; index
< readLoop
; index
++) {
84 dwIRData
= smi_read(IR_DATA_BUFFER_BASE
+ (index
* 4));
86 ir
->irData
[index
*4 + 0] = (u8
)(dwIRData
);
87 ir
->irData
[index
*4 + 1] = (u8
)(dwIRData
>> 8);
88 ir
->irData
[index
*4 + 2] = (u8
)(dwIRData
>> 16);
89 ir
->irData
[index
*4 + 3] = (u8
)(dwIRData
>> 24);
91 smi_raw_process(rc_dev
, ir
->irData
, ucIRCount
);
92 smi_set(IR_Init_Reg
, rbIRVld
);
95 if (dwIRControl
& rbIRhighidle
) {
96 struct ir_raw_event rawir
= {};
99 rawir
.duration
= US_TO_NS(SMI_SAMPLE_PERIOD
*
101 ir_raw_event_store_with_filter(rc_dev
, &rawir
);
102 smi_set(IR_Init_Reg
, rbIRhighidle
);
105 ir_raw_event_handle(rc_dev
);
108 /* ir functions call by main driver.*/
109 int smi_ir_irq(struct smi_rc
*ir
, u32 int_status
)
113 if (int_status
& IR_X_INT
) {
114 smi_ir_disableInterrupt(ir
);
115 smi_ir_clearInterrupt(ir
);
117 smi_ir_enableInterrupt(ir
);
123 void smi_ir_start(struct smi_rc
*ir
)
125 struct smi_dev
*dev
= ir
->dev
;
127 smi_write(IR_Idle_Cnt_Low
,
128 (((SMI_SAMPLE_PERIOD
- 1) & 0xFFFF) << 16) |
129 (SMI_SAMPLE_IDLEMIN
& 0xFFFF));
131 smi_set(IR_Init_Reg
, rbIRen
| rbIRhighidle
);
133 smi_ir_enableInterrupt(ir
);
136 int smi_ir_init(struct smi_dev
*dev
)
139 struct rc_dev
*rc_dev
;
140 struct smi_rc
*ir
= &dev
->ir
;
142 rc_dev
= rc_allocate_device(RC_DRIVER_IR_RAW
);
146 /* init input device */
147 snprintf(ir
->device_name
, sizeof(ir
->device_name
), "IR (%s)",
149 snprintf(ir
->input_phys
, sizeof(ir
->input_phys
), "pci-%s/ir0",
150 pci_name(dev
->pci_dev
));
152 rc_dev
->allowed_protocols
= RC_PROTO_BIT_ALL_IR_DECODER
;
153 rc_dev
->driver_name
= "SMI_PCIe";
154 rc_dev
->input_phys
= ir
->input_phys
;
155 rc_dev
->device_name
= ir
->device_name
;
156 rc_dev
->input_id
.bustype
= BUS_PCI
;
157 rc_dev
->input_id
.version
= 1;
158 rc_dev
->input_id
.vendor
= dev
->pci_dev
->subsystem_vendor
;
159 rc_dev
->input_id
.product
= dev
->pci_dev
->subsystem_device
;
160 rc_dev
->dev
.parent
= &dev
->pci_dev
->dev
;
162 rc_dev
->map_name
= dev
->info
->rc_map
;
163 rc_dev
->timeout
= MS_TO_NS(100);
164 rc_dev
->rx_resolution
= US_TO_NS(SMI_SAMPLE_PERIOD
);
169 smi_ir_disableInterrupt(ir
);
171 ret
= rc_register_device(rc_dev
);
177 rc_free_device(rc_dev
);
181 void smi_ir_exit(struct smi_dev
*dev
)
183 struct smi_rc
*ir
= &dev
->ir
;
184 struct rc_dev
*rc_dev
= ir
->rc_dev
;
187 rc_unregister_device(rc_dev
);