xref: /OK3568_Linux_fs/kernel/drivers/media/pci/smipcie/smipcie-ir.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * SMI PCIe driver for DVBSky cards.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2014 Max nibble <nibble.max@gmail.com>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include "smipcie.h"
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #define SMI_SAMPLE_PERIOD 83
11*4882a593Smuzhiyun #define SMI_SAMPLE_IDLEMIN (10000 / SMI_SAMPLE_PERIOD)
12*4882a593Smuzhiyun 
smi_ir_enableInterrupt(struct smi_rc * ir)13*4882a593Smuzhiyun static void smi_ir_enableInterrupt(struct smi_rc *ir)
14*4882a593Smuzhiyun {
15*4882a593Smuzhiyun 	struct smi_dev *dev = ir->dev;
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun 	smi_write(MSI_INT_ENA_SET, IR_X_INT);
18*4882a593Smuzhiyun }
19*4882a593Smuzhiyun 
smi_ir_disableInterrupt(struct smi_rc * ir)20*4882a593Smuzhiyun static void smi_ir_disableInterrupt(struct smi_rc *ir)
21*4882a593Smuzhiyun {
22*4882a593Smuzhiyun 	struct smi_dev *dev = ir->dev;
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun 	smi_write(MSI_INT_ENA_CLR, IR_X_INT);
25*4882a593Smuzhiyun }
26*4882a593Smuzhiyun 
smi_ir_clearInterrupt(struct smi_rc * ir)27*4882a593Smuzhiyun static void smi_ir_clearInterrupt(struct smi_rc *ir)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun 	struct smi_dev *dev = ir->dev;
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun 	smi_write(MSI_INT_STATUS_CLR, IR_X_INT);
32*4882a593Smuzhiyun }
33*4882a593Smuzhiyun 
smi_ir_stop(struct smi_rc * ir)34*4882a593Smuzhiyun static void smi_ir_stop(struct smi_rc *ir)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun 	struct smi_dev *dev = ir->dev;
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun 	smi_ir_disableInterrupt(ir);
39*4882a593Smuzhiyun 	smi_clear(IR_Init_Reg, rbIRen);
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun 
smi_raw_process(struct rc_dev * rc_dev,const u8 * buffer,const u8 length)42*4882a593Smuzhiyun static void smi_raw_process(struct rc_dev *rc_dev, const u8 *buffer,
43*4882a593Smuzhiyun 			    const u8 length)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun 	struct ir_raw_event rawir = {};
46*4882a593Smuzhiyun 	int cnt;
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	for (cnt = 0; cnt < length; cnt++) {
49*4882a593Smuzhiyun 		if (buffer[cnt] & 0x7f) {
50*4882a593Smuzhiyun 			rawir.pulse = (buffer[cnt] & 0x80) == 0;
51*4882a593Smuzhiyun 			rawir.duration = ((buffer[cnt] & 0x7f) +
52*4882a593Smuzhiyun 					 (rawir.pulse ? 0 : -1)) *
53*4882a593Smuzhiyun 					 rc_dev->rx_resolution;
54*4882a593Smuzhiyun 			ir_raw_event_store_with_filter(rc_dev, &rawir);
55*4882a593Smuzhiyun 		}
56*4882a593Smuzhiyun 	}
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun 
smi_ir_decode(struct smi_rc * ir)59*4882a593Smuzhiyun static void smi_ir_decode(struct smi_rc *ir)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun 	struct smi_dev *dev = ir->dev;
62*4882a593Smuzhiyun 	struct rc_dev *rc_dev = ir->rc_dev;
63*4882a593Smuzhiyun 	u32 control, data;
64*4882a593Smuzhiyun 	u8 index, ir_count, read_loop;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	control = smi_read(IR_Init_Reg);
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	dev_dbg(&rc_dev->dev, "ircontrol: 0x%08x\n", control);
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	if (control & rbIRVld) {
71*4882a593Smuzhiyun 		ir_count = (u8)smi_read(IR_Data_Cnt);
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 		dev_dbg(&rc_dev->dev, "ircount %d\n", ir_count);
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 		read_loop = ir_count / 4;
76*4882a593Smuzhiyun 		if (ir_count % 4)
77*4882a593Smuzhiyun 			read_loop += 1;
78*4882a593Smuzhiyun 		for (index = 0; index < read_loop; index++) {
79*4882a593Smuzhiyun 			data = smi_read(IR_DATA_BUFFER_BASE + (index * 4));
80*4882a593Smuzhiyun 			dev_dbg(&rc_dev->dev, "IRData 0x%08x\n", data);
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 			ir->irData[index * 4 + 0] = (u8)(data);
83*4882a593Smuzhiyun 			ir->irData[index * 4 + 1] = (u8)(data >> 8);
84*4882a593Smuzhiyun 			ir->irData[index * 4 + 2] = (u8)(data >> 16);
85*4882a593Smuzhiyun 			ir->irData[index * 4 + 3] = (u8)(data >> 24);
86*4882a593Smuzhiyun 		}
87*4882a593Smuzhiyun 		smi_raw_process(rc_dev, ir->irData, ir_count);
88*4882a593Smuzhiyun 	}
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	if (control & rbIRhighidle) {
91*4882a593Smuzhiyun 		struct ir_raw_event rawir = {};
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 		dev_dbg(&rc_dev->dev, "high idle\n");
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 		rawir.pulse = 0;
96*4882a593Smuzhiyun 		rawir.duration = SMI_SAMPLE_PERIOD * SMI_SAMPLE_IDLEMIN;
97*4882a593Smuzhiyun 		ir_raw_event_store_with_filter(rc_dev, &rawir);
98*4882a593Smuzhiyun 	}
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 	smi_set(IR_Init_Reg, rbIRVld);
101*4882a593Smuzhiyun 	ir_raw_event_handle(rc_dev);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun /* ir functions call by main driver.*/
smi_ir_irq(struct smi_rc * ir,u32 int_status)105*4882a593Smuzhiyun int smi_ir_irq(struct smi_rc *ir, u32 int_status)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun 	int handled = 0;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	if (int_status & IR_X_INT) {
110*4882a593Smuzhiyun 		smi_ir_disableInterrupt(ir);
111*4882a593Smuzhiyun 		smi_ir_clearInterrupt(ir);
112*4882a593Smuzhiyun 		smi_ir_decode(ir);
113*4882a593Smuzhiyun 		smi_ir_enableInterrupt(ir);
114*4882a593Smuzhiyun 		handled = 1;
115*4882a593Smuzhiyun 	}
116*4882a593Smuzhiyun 	return handled;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
smi_ir_start(struct smi_rc * ir)119*4882a593Smuzhiyun void smi_ir_start(struct smi_rc *ir)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun 	struct smi_dev *dev = ir->dev;
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	smi_write(IR_Idle_Cnt_Low,
124*4882a593Smuzhiyun 		  (((SMI_SAMPLE_PERIOD - 1) & 0xFFFF) << 16) |
125*4882a593Smuzhiyun 		  (SMI_SAMPLE_IDLEMIN & 0xFFFF));
126*4882a593Smuzhiyun 	msleep(20);
127*4882a593Smuzhiyun 	smi_set(IR_Init_Reg, rbIRen | rbIRhighidle);
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	smi_ir_enableInterrupt(ir);
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun 
smi_ir_init(struct smi_dev * dev)132*4882a593Smuzhiyun int smi_ir_init(struct smi_dev *dev)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun 	int ret;
135*4882a593Smuzhiyun 	struct rc_dev *rc_dev;
136*4882a593Smuzhiyun 	struct smi_rc *ir = &dev->ir;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	rc_dev = rc_allocate_device(RC_DRIVER_IR_RAW);
139*4882a593Smuzhiyun 	if (!rc_dev)
140*4882a593Smuzhiyun 		return -ENOMEM;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	/* init input device */
143*4882a593Smuzhiyun 	snprintf(ir->device_name, sizeof(ir->device_name), "IR (%s)",
144*4882a593Smuzhiyun 		 dev->info->name);
145*4882a593Smuzhiyun 	snprintf(ir->input_phys, sizeof(ir->input_phys), "pci-%s/ir0",
146*4882a593Smuzhiyun 		 pci_name(dev->pci_dev));
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	rc_dev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
149*4882a593Smuzhiyun 	rc_dev->driver_name = "SMI_PCIe";
150*4882a593Smuzhiyun 	rc_dev->input_phys = ir->input_phys;
151*4882a593Smuzhiyun 	rc_dev->device_name = ir->device_name;
152*4882a593Smuzhiyun 	rc_dev->input_id.bustype = BUS_PCI;
153*4882a593Smuzhiyun 	rc_dev->input_id.version = 1;
154*4882a593Smuzhiyun 	rc_dev->input_id.vendor = dev->pci_dev->subsystem_vendor;
155*4882a593Smuzhiyun 	rc_dev->input_id.product = dev->pci_dev->subsystem_device;
156*4882a593Smuzhiyun 	rc_dev->dev.parent = &dev->pci_dev->dev;
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	rc_dev->map_name = dev->info->rc_map;
159*4882a593Smuzhiyun 	rc_dev->timeout = SMI_SAMPLE_PERIOD * SMI_SAMPLE_IDLEMIN;
160*4882a593Smuzhiyun 	rc_dev->rx_resolution = SMI_SAMPLE_PERIOD;
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	ir->rc_dev = rc_dev;
163*4882a593Smuzhiyun 	ir->dev = dev;
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	smi_ir_disableInterrupt(ir);
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	ret = rc_register_device(rc_dev);
168*4882a593Smuzhiyun 	if (ret)
169*4882a593Smuzhiyun 		goto ir_err;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	return 0;
172*4882a593Smuzhiyun ir_err:
173*4882a593Smuzhiyun 	rc_free_device(rc_dev);
174*4882a593Smuzhiyun 	return ret;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun 
smi_ir_exit(struct smi_dev * dev)177*4882a593Smuzhiyun void smi_ir_exit(struct smi_dev *dev)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun 	struct smi_rc *ir = &dev->ir;
180*4882a593Smuzhiyun 	struct rc_dev *rc_dev = ir->rc_dev;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	rc_unregister_device(rc_dev);
183*4882a593Smuzhiyun 	smi_ir_stop(ir);
184*4882a593Smuzhiyun 	ir->rc_dev = NULL;
185*4882a593Smuzhiyun }
186