1 /*
2  * SMI PCIe driver for DVBSky cards.
3  *
4  * Copyright (C) 2014 Max nibble <nibble.max@gmail.com>
5  *
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.
10  *
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.
15  */
16 
17 #include "smipcie.h"
18 
19 #define SMI_SAMPLE_PERIOD 83
20 #define SMI_SAMPLE_IDLEMIN (10000 / SMI_SAMPLE_PERIOD)
21 
22 static void smi_ir_enableInterrupt(struct smi_rc *ir)
23 {
24 	struct smi_dev *dev = ir->dev;
25 
26 	smi_write(MSI_INT_ENA_SET, IR_X_INT);
27 }
28 
29 static void smi_ir_disableInterrupt(struct smi_rc *ir)
30 {
31 	struct smi_dev *dev = ir->dev;
32 
33 	smi_write(MSI_INT_ENA_CLR, IR_X_INT);
34 }
35 
36 static void smi_ir_clearInterrupt(struct smi_rc *ir)
37 {
38 	struct smi_dev *dev = ir->dev;
39 
40 	smi_write(MSI_INT_STATUS_CLR, IR_X_INT);
41 }
42 
43 static void smi_ir_stop(struct smi_rc *ir)
44 {
45 	struct smi_dev *dev = ir->dev;
46 
47 	smi_ir_disableInterrupt(ir);
48 	smi_clear(IR_Init_Reg, rbIRen);
49 }
50 
51 static void smi_raw_process(struct rc_dev *rc_dev, const u8 *buffer,
52 			    const u8 length)
53 {
54 	struct ir_raw_event rawir = {};
55 	int cnt;
56 
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);
64 		}
65 	}
66 }
67 
68 static void smi_ir_decode(struct smi_rc *ir)
69 {
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;
74 
75 	dwIRControl = smi_read(IR_Init_Reg);
76 
77 	if (dwIRControl & rbIRVld) {
78 		ucIRCount = (u8) smi_read(IR_Data_Cnt);
79 
80 		readLoop = ucIRCount/4;
81 		if (ucIRCount % 4)
82 			readLoop += 1;
83 		for (index = 0; index < readLoop; index++) {
84 			dwIRData = smi_read(IR_DATA_BUFFER_BASE + (index * 4));
85 
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);
90 		}
91 		smi_raw_process(rc_dev, ir->irData, ucIRCount);
92 		smi_set(IR_Init_Reg, rbIRVld);
93 	}
94 
95 	if (dwIRControl & rbIRhighidle) {
96 		struct ir_raw_event rawir = {};
97 
98 		rawir.pulse = 0;
99 		rawir.duration = US_TO_NS(SMI_SAMPLE_PERIOD *
100 					  SMI_SAMPLE_IDLEMIN);
101 		ir_raw_event_store_with_filter(rc_dev, &rawir);
102 		smi_set(IR_Init_Reg, rbIRhighidle);
103 	}
104 
105 	ir_raw_event_handle(rc_dev);
106 }
107 
108 /* ir functions call by main driver.*/
109 int smi_ir_irq(struct smi_rc *ir, u32 int_status)
110 {
111 	int handled = 0;
112 
113 	if (int_status & IR_X_INT) {
114 		smi_ir_disableInterrupt(ir);
115 		smi_ir_clearInterrupt(ir);
116 		smi_ir_decode(ir);
117 		smi_ir_enableInterrupt(ir);
118 		handled = 1;
119 	}
120 	return handled;
121 }
122 
123 void smi_ir_start(struct smi_rc *ir)
124 {
125 	struct smi_dev *dev = ir->dev;
126 
127 	smi_write(IR_Idle_Cnt_Low,
128 		  (((SMI_SAMPLE_PERIOD - 1) & 0xFFFF) << 16) |
129 		  (SMI_SAMPLE_IDLEMIN & 0xFFFF));
130 	msleep(20);
131 	smi_set(IR_Init_Reg, rbIRen | rbIRhighidle);
132 
133 	smi_ir_enableInterrupt(ir);
134 }
135 
136 int smi_ir_init(struct smi_dev *dev)
137 {
138 	int ret;
139 	struct rc_dev *rc_dev;
140 	struct smi_rc *ir = &dev->ir;
141 
142 	rc_dev = rc_allocate_device(RC_DRIVER_IR_RAW);
143 	if (!rc_dev)
144 		return -ENOMEM;
145 
146 	/* init input device */
147 	snprintf(ir->device_name, sizeof(ir->device_name), "IR (%s)",
148 		 dev->info->name);
149 	snprintf(ir->input_phys, sizeof(ir->input_phys), "pci-%s/ir0",
150 		 pci_name(dev->pci_dev));
151 
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;
161 
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);
165 
166 	ir->rc_dev = rc_dev;
167 	ir->dev = dev;
168 
169 	smi_ir_disableInterrupt(ir);
170 
171 	ret = rc_register_device(rc_dev);
172 	if (ret)
173 		goto ir_err;
174 
175 	return 0;
176 ir_err:
177 	rc_free_device(rc_dev);
178 	return ret;
179 }
180 
181 void smi_ir_exit(struct smi_dev *dev)
182 {
183 	struct smi_rc *ir = &dev->ir;
184 	struct rc_dev *rc_dev = ir->rc_dev;
185 
186 	smi_ir_stop(ir);
187 	rc_unregister_device(rc_dev);
188 	ir->rc_dev = NULL;
189 }
190