xref: /OK3568_Linux_fs/kernel/sound/pci/ctxfi/ctsrc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /**
3*4882a593Smuzhiyun  * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * @File	ctsrc.c
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * @Brief
8*4882a593Smuzhiyun  * This file contains the implementation of the Sample Rate Convertor
9*4882a593Smuzhiyun  * resource management object.
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * @Author	Liu Chun
12*4882a593Smuzhiyun  * @Date 	May 13 2008
13*4882a593Smuzhiyun  */
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #include "ctsrc.h"
16*4882a593Smuzhiyun #include "cthardware.h"
17*4882a593Smuzhiyun #include <linux/slab.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #define SRC_RESOURCE_NUM	256
20*4882a593Smuzhiyun #define SRCIMP_RESOURCE_NUM	256
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun static unsigned int conj_mask;
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun static int src_default_config_memrd(struct src *src);
25*4882a593Smuzhiyun static int src_default_config_memwr(struct src *src);
26*4882a593Smuzhiyun static int src_default_config_arcrw(struct src *src);
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun static int (*src_default_config[3])(struct src *) = {
29*4882a593Smuzhiyun 	[MEMRD] = src_default_config_memrd,
30*4882a593Smuzhiyun 	[MEMWR] = src_default_config_memwr,
31*4882a593Smuzhiyun 	[ARCRW] = src_default_config_arcrw
32*4882a593Smuzhiyun };
33*4882a593Smuzhiyun 
src_set_state(struct src * src,unsigned int state)34*4882a593Smuzhiyun static int src_set_state(struct src *src, unsigned int state)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun 	struct hw *hw;
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun 	hw = src->rsc.hw;
39*4882a593Smuzhiyun 	hw->src_set_state(src->rsc.ctrl_blk, state);
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 	return 0;
42*4882a593Smuzhiyun }
43*4882a593Smuzhiyun 
src_set_bm(struct src * src,unsigned int bm)44*4882a593Smuzhiyun static int src_set_bm(struct src *src, unsigned int bm)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun 	struct hw *hw;
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	hw = src->rsc.hw;
49*4882a593Smuzhiyun 	hw->src_set_bm(src->rsc.ctrl_blk, bm);
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	return 0;
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun 
src_set_sf(struct src * src,unsigned int sf)54*4882a593Smuzhiyun static int src_set_sf(struct src *src, unsigned int sf)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun 	struct hw *hw;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	hw = src->rsc.hw;
59*4882a593Smuzhiyun 	hw->src_set_sf(src->rsc.ctrl_blk, sf);
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 	return 0;
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun 
src_set_pm(struct src * src,unsigned int pm)64*4882a593Smuzhiyun static int src_set_pm(struct src *src, unsigned int pm)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun 	struct hw *hw;
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	hw = src->rsc.hw;
69*4882a593Smuzhiyun 	hw->src_set_pm(src->rsc.ctrl_blk, pm);
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 	return 0;
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun 
src_set_rom(struct src * src,unsigned int rom)74*4882a593Smuzhiyun static int src_set_rom(struct src *src, unsigned int rom)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun 	struct hw *hw;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	hw = src->rsc.hw;
79*4882a593Smuzhiyun 	hw->src_set_rom(src->rsc.ctrl_blk, rom);
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	return 0;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun 
src_set_vo(struct src * src,unsigned int vo)84*4882a593Smuzhiyun static int src_set_vo(struct src *src, unsigned int vo)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun 	struct hw *hw;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	hw = src->rsc.hw;
89*4882a593Smuzhiyun 	hw->src_set_vo(src->rsc.ctrl_blk, vo);
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	return 0;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
src_set_st(struct src * src,unsigned int st)94*4882a593Smuzhiyun static int src_set_st(struct src *src, unsigned int st)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	struct hw *hw;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	hw = src->rsc.hw;
99*4882a593Smuzhiyun 	hw->src_set_st(src->rsc.ctrl_blk, st);
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	return 0;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun 
src_set_bp(struct src * src,unsigned int bp)104*4882a593Smuzhiyun static int src_set_bp(struct src *src, unsigned int bp)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun 	struct hw *hw;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	hw = src->rsc.hw;
109*4882a593Smuzhiyun 	hw->src_set_bp(src->rsc.ctrl_blk, bp);
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	return 0;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun 
src_set_cisz(struct src * src,unsigned int cisz)114*4882a593Smuzhiyun static int src_set_cisz(struct src *src, unsigned int cisz)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun 	struct hw *hw;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	hw = src->rsc.hw;
119*4882a593Smuzhiyun 	hw->src_set_cisz(src->rsc.ctrl_blk, cisz);
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	return 0;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun 
src_set_ca(struct src * src,unsigned int ca)124*4882a593Smuzhiyun static int src_set_ca(struct src *src, unsigned int ca)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun 	struct hw *hw;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	hw = src->rsc.hw;
129*4882a593Smuzhiyun 	hw->src_set_ca(src->rsc.ctrl_blk, ca);
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	return 0;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun 
src_set_sa(struct src * src,unsigned int sa)134*4882a593Smuzhiyun static int src_set_sa(struct src *src, unsigned int sa)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun 	struct hw *hw;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	hw = src->rsc.hw;
139*4882a593Smuzhiyun 	hw->src_set_sa(src->rsc.ctrl_blk, sa);
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	return 0;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun 
src_set_la(struct src * src,unsigned int la)144*4882a593Smuzhiyun static int src_set_la(struct src *src, unsigned int la)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun 	struct hw *hw;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	hw = src->rsc.hw;
149*4882a593Smuzhiyun 	hw->src_set_la(src->rsc.ctrl_blk, la);
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	return 0;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun 
src_set_pitch(struct src * src,unsigned int pitch)154*4882a593Smuzhiyun static int src_set_pitch(struct src *src, unsigned int pitch)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun 	struct hw *hw;
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	hw = src->rsc.hw;
159*4882a593Smuzhiyun 	hw->src_set_pitch(src->rsc.ctrl_blk, pitch);
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	return 0;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
src_set_clear_zbufs(struct src * src)164*4882a593Smuzhiyun static int src_set_clear_zbufs(struct src *src)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	struct hw *hw;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	hw = src->rsc.hw;
169*4882a593Smuzhiyun 	hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1);
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	return 0;
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun 
src_commit_write(struct src * src)174*4882a593Smuzhiyun static int src_commit_write(struct src *src)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun 	struct hw *hw;
177*4882a593Smuzhiyun 	int i;
178*4882a593Smuzhiyun 	unsigned int dirty = 0;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	hw = src->rsc.hw;
181*4882a593Smuzhiyun 	src->rsc.ops->master(&src->rsc);
182*4882a593Smuzhiyun 	if (src->rsc.msr > 1) {
183*4882a593Smuzhiyun 		/* Save dirty flags for conjugate resource programming */
184*4882a593Smuzhiyun 		dirty = hw->src_get_dirty(src->rsc.ctrl_blk) & conj_mask;
185*4882a593Smuzhiyun 	}
186*4882a593Smuzhiyun 	hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
187*4882a593Smuzhiyun 						src->rsc.ctrl_blk);
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	/* Program conjugate parameter mixer resources */
190*4882a593Smuzhiyun 	if (MEMWR == src->mode)
191*4882a593Smuzhiyun 		return 0;
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	for (i = 1; i < src->rsc.msr; i++) {
194*4882a593Smuzhiyun 		src->rsc.ops->next_conj(&src->rsc);
195*4882a593Smuzhiyun 		hw->src_set_dirty(src->rsc.ctrl_blk, dirty);
196*4882a593Smuzhiyun 		hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
197*4882a593Smuzhiyun 							src->rsc.ctrl_blk);
198*4882a593Smuzhiyun 	}
199*4882a593Smuzhiyun 	src->rsc.ops->master(&src->rsc);
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	return 0;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun 
src_get_ca(struct src * src)204*4882a593Smuzhiyun static int src_get_ca(struct src *src)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun 	struct hw *hw;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	hw = src->rsc.hw;
209*4882a593Smuzhiyun 	return hw->src_get_ca(hw, src->rsc.ops->index(&src->rsc),
210*4882a593Smuzhiyun 						src->rsc.ctrl_blk);
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun 
src_init(struct src * src)213*4882a593Smuzhiyun static int src_init(struct src *src)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun 	src_default_config[src->mode](src);
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	return 0;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun 
src_next_interleave(struct src * src)220*4882a593Smuzhiyun static struct src *src_next_interleave(struct src *src)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun 	return src->intlv;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun 
src_default_config_memrd(struct src * src)225*4882a593Smuzhiyun static int src_default_config_memrd(struct src *src)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun 	struct hw *hw = src->rsc.hw;
228*4882a593Smuzhiyun 	unsigned int rsr, msr;
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	hw->src_set_state(src->rsc.ctrl_blk, SRC_STATE_OFF);
231*4882a593Smuzhiyun 	hw->src_set_bm(src->rsc.ctrl_blk, 1);
232*4882a593Smuzhiyun 	for (rsr = 0, msr = src->rsc.msr; msr > 1; msr >>= 1)
233*4882a593Smuzhiyun 		rsr++;
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	hw->src_set_rsr(src->rsc.ctrl_blk, rsr);
236*4882a593Smuzhiyun 	hw->src_set_sf(src->rsc.ctrl_blk, SRC_SF_S16);
237*4882a593Smuzhiyun 	hw->src_set_wr(src->rsc.ctrl_blk, 0);
238*4882a593Smuzhiyun 	hw->src_set_pm(src->rsc.ctrl_blk, 0);
239*4882a593Smuzhiyun 	hw->src_set_rom(src->rsc.ctrl_blk, 0);
240*4882a593Smuzhiyun 	hw->src_set_vo(src->rsc.ctrl_blk, 0);
241*4882a593Smuzhiyun 	hw->src_set_st(src->rsc.ctrl_blk, 0);
242*4882a593Smuzhiyun 	hw->src_set_ilsz(src->rsc.ctrl_blk, src->multi - 1);
243*4882a593Smuzhiyun 	hw->src_set_cisz(src->rsc.ctrl_blk, 0x80);
244*4882a593Smuzhiyun 	hw->src_set_sa(src->rsc.ctrl_blk, 0x0);
245*4882a593Smuzhiyun 	hw->src_set_la(src->rsc.ctrl_blk, 0x1000);
246*4882a593Smuzhiyun 	hw->src_set_ca(src->rsc.ctrl_blk, 0x80);
247*4882a593Smuzhiyun 	hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000);
248*4882a593Smuzhiyun 	hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1);
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	src->rsc.ops->master(&src->rsc);
251*4882a593Smuzhiyun 	hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
252*4882a593Smuzhiyun 						src->rsc.ctrl_blk);
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 	for (msr = 1; msr < src->rsc.msr; msr++) {
255*4882a593Smuzhiyun 		src->rsc.ops->next_conj(&src->rsc);
256*4882a593Smuzhiyun 		hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000);
257*4882a593Smuzhiyun 		hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
258*4882a593Smuzhiyun 							src->rsc.ctrl_blk);
259*4882a593Smuzhiyun 	}
260*4882a593Smuzhiyun 	src->rsc.ops->master(&src->rsc);
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	return 0;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun 
src_default_config_memwr(struct src * src)265*4882a593Smuzhiyun static int src_default_config_memwr(struct src *src)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun 	struct hw *hw = src->rsc.hw;
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	hw->src_set_state(src->rsc.ctrl_blk, SRC_STATE_OFF);
270*4882a593Smuzhiyun 	hw->src_set_bm(src->rsc.ctrl_blk, 1);
271*4882a593Smuzhiyun 	hw->src_set_rsr(src->rsc.ctrl_blk, 0);
272*4882a593Smuzhiyun 	hw->src_set_sf(src->rsc.ctrl_blk, SRC_SF_S16);
273*4882a593Smuzhiyun 	hw->src_set_wr(src->rsc.ctrl_blk, 1);
274*4882a593Smuzhiyun 	hw->src_set_pm(src->rsc.ctrl_blk, 0);
275*4882a593Smuzhiyun 	hw->src_set_rom(src->rsc.ctrl_blk, 0);
276*4882a593Smuzhiyun 	hw->src_set_vo(src->rsc.ctrl_blk, 0);
277*4882a593Smuzhiyun 	hw->src_set_st(src->rsc.ctrl_blk, 0);
278*4882a593Smuzhiyun 	hw->src_set_ilsz(src->rsc.ctrl_blk, 0);
279*4882a593Smuzhiyun 	hw->src_set_cisz(src->rsc.ctrl_blk, 0x80);
280*4882a593Smuzhiyun 	hw->src_set_sa(src->rsc.ctrl_blk, 0x0);
281*4882a593Smuzhiyun 	hw->src_set_la(src->rsc.ctrl_blk, 0x1000);
282*4882a593Smuzhiyun 	hw->src_set_ca(src->rsc.ctrl_blk, 0x80);
283*4882a593Smuzhiyun 	hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000);
284*4882a593Smuzhiyun 	hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1);
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	src->rsc.ops->master(&src->rsc);
287*4882a593Smuzhiyun 	hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
288*4882a593Smuzhiyun 						src->rsc.ctrl_blk);
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 	return 0;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun 
src_default_config_arcrw(struct src * src)293*4882a593Smuzhiyun static int src_default_config_arcrw(struct src *src)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun 	struct hw *hw = src->rsc.hw;
296*4882a593Smuzhiyun 	unsigned int rsr, msr;
297*4882a593Smuzhiyun 	unsigned int dirty;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	hw->src_set_state(src->rsc.ctrl_blk, SRC_STATE_OFF);
300*4882a593Smuzhiyun 	hw->src_set_bm(src->rsc.ctrl_blk, 0);
301*4882a593Smuzhiyun 	for (rsr = 0, msr = src->rsc.msr; msr > 1; msr >>= 1)
302*4882a593Smuzhiyun 		rsr++;
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	hw->src_set_rsr(src->rsc.ctrl_blk, rsr);
305*4882a593Smuzhiyun 	hw->src_set_sf(src->rsc.ctrl_blk, SRC_SF_F32);
306*4882a593Smuzhiyun 	hw->src_set_wr(src->rsc.ctrl_blk, 0);
307*4882a593Smuzhiyun 	hw->src_set_pm(src->rsc.ctrl_blk, 0);
308*4882a593Smuzhiyun 	hw->src_set_rom(src->rsc.ctrl_blk, 0);
309*4882a593Smuzhiyun 	hw->src_set_vo(src->rsc.ctrl_blk, 0);
310*4882a593Smuzhiyun 	hw->src_set_st(src->rsc.ctrl_blk, 0);
311*4882a593Smuzhiyun 	hw->src_set_ilsz(src->rsc.ctrl_blk, 0);
312*4882a593Smuzhiyun 	hw->src_set_cisz(src->rsc.ctrl_blk, 0x80);
313*4882a593Smuzhiyun 	hw->src_set_sa(src->rsc.ctrl_blk, 0x0);
314*4882a593Smuzhiyun 	/*hw->src_set_sa(src->rsc.ctrl_blk, 0x100);*/
315*4882a593Smuzhiyun 	hw->src_set_la(src->rsc.ctrl_blk, 0x1000);
316*4882a593Smuzhiyun 	/*hw->src_set_la(src->rsc.ctrl_blk, 0x03ffffe0);*/
317*4882a593Smuzhiyun 	hw->src_set_ca(src->rsc.ctrl_blk, 0x80);
318*4882a593Smuzhiyun 	hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000);
319*4882a593Smuzhiyun 	hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1);
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	dirty = hw->src_get_dirty(src->rsc.ctrl_blk);
322*4882a593Smuzhiyun 	src->rsc.ops->master(&src->rsc);
323*4882a593Smuzhiyun 	for (msr = 0; msr < src->rsc.msr; msr++) {
324*4882a593Smuzhiyun 		hw->src_set_dirty(src->rsc.ctrl_blk, dirty);
325*4882a593Smuzhiyun 		hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
326*4882a593Smuzhiyun 							src->rsc.ctrl_blk);
327*4882a593Smuzhiyun 		src->rsc.ops->next_conj(&src->rsc);
328*4882a593Smuzhiyun 	}
329*4882a593Smuzhiyun 	src->rsc.ops->master(&src->rsc);
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	return 0;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun static const struct src_rsc_ops src_rsc_ops = {
335*4882a593Smuzhiyun 	.set_state		= src_set_state,
336*4882a593Smuzhiyun 	.set_bm			= src_set_bm,
337*4882a593Smuzhiyun 	.set_sf			= src_set_sf,
338*4882a593Smuzhiyun 	.set_pm			= src_set_pm,
339*4882a593Smuzhiyun 	.set_rom		= src_set_rom,
340*4882a593Smuzhiyun 	.set_vo			= src_set_vo,
341*4882a593Smuzhiyun 	.set_st			= src_set_st,
342*4882a593Smuzhiyun 	.set_bp			= src_set_bp,
343*4882a593Smuzhiyun 	.set_cisz		= src_set_cisz,
344*4882a593Smuzhiyun 	.set_ca			= src_set_ca,
345*4882a593Smuzhiyun 	.set_sa			= src_set_sa,
346*4882a593Smuzhiyun 	.set_la			= src_set_la,
347*4882a593Smuzhiyun 	.set_pitch		= src_set_pitch,
348*4882a593Smuzhiyun 	.set_clr_zbufs		= src_set_clear_zbufs,
349*4882a593Smuzhiyun 	.commit_write		= src_commit_write,
350*4882a593Smuzhiyun 	.get_ca			= src_get_ca,
351*4882a593Smuzhiyun 	.init			= src_init,
352*4882a593Smuzhiyun 	.next_interleave	= src_next_interleave,
353*4882a593Smuzhiyun };
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun static int
src_rsc_init(struct src * src,u32 idx,const struct src_desc * desc,struct src_mgr * mgr)356*4882a593Smuzhiyun src_rsc_init(struct src *src, u32 idx,
357*4882a593Smuzhiyun 	     const struct src_desc *desc, struct src_mgr *mgr)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun 	int err;
360*4882a593Smuzhiyun 	int i, n;
361*4882a593Smuzhiyun 	struct src *p;
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 	n = (MEMRD == desc->mode) ? desc->multi : 1;
364*4882a593Smuzhiyun 	for (i = 0, p = src; i < n; i++, p++) {
365*4882a593Smuzhiyun 		err = rsc_init(&p->rsc, idx + i, SRC, desc->msr, mgr->mgr.hw);
366*4882a593Smuzhiyun 		if (err)
367*4882a593Smuzhiyun 			goto error1;
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 		/* Initialize src specific rsc operations */
370*4882a593Smuzhiyun 		p->ops = &src_rsc_ops;
371*4882a593Smuzhiyun 		p->multi = (0 == i) ? desc->multi : 1;
372*4882a593Smuzhiyun 		p->mode = desc->mode;
373*4882a593Smuzhiyun 		src_default_config[desc->mode](p);
374*4882a593Smuzhiyun 		mgr->src_enable(mgr, p);
375*4882a593Smuzhiyun 		p->intlv = p + 1;
376*4882a593Smuzhiyun 	}
377*4882a593Smuzhiyun 	(--p)->intlv = NULL;	/* Set @intlv of the last SRC to NULL */
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun 	mgr->commit_write(mgr);
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun 	return 0;
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun error1:
384*4882a593Smuzhiyun 	for (i--, p--; i >= 0; i--, p--) {
385*4882a593Smuzhiyun 		mgr->src_disable(mgr, p);
386*4882a593Smuzhiyun 		rsc_uninit(&p->rsc);
387*4882a593Smuzhiyun 	}
388*4882a593Smuzhiyun 	mgr->commit_write(mgr);
389*4882a593Smuzhiyun 	return err;
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun 
src_rsc_uninit(struct src * src,struct src_mgr * mgr)392*4882a593Smuzhiyun static int src_rsc_uninit(struct src *src, struct src_mgr *mgr)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun 	int i, n;
395*4882a593Smuzhiyun 	struct src *p;
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	n = (MEMRD == src->mode) ? src->multi : 1;
398*4882a593Smuzhiyun 	for (i = 0, p = src; i < n; i++, p++) {
399*4882a593Smuzhiyun 		mgr->src_disable(mgr, p);
400*4882a593Smuzhiyun 		rsc_uninit(&p->rsc);
401*4882a593Smuzhiyun 		p->multi = 0;
402*4882a593Smuzhiyun 		p->ops = NULL;
403*4882a593Smuzhiyun 		p->mode = NUM_SRCMODES;
404*4882a593Smuzhiyun 		p->intlv = NULL;
405*4882a593Smuzhiyun 	}
406*4882a593Smuzhiyun 	mgr->commit_write(mgr);
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun 	return 0;
409*4882a593Smuzhiyun }
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun static int
get_src_rsc(struct src_mgr * mgr,const struct src_desc * desc,struct src ** rsrc)412*4882a593Smuzhiyun get_src_rsc(struct src_mgr *mgr, const struct src_desc *desc, struct src **rsrc)
413*4882a593Smuzhiyun {
414*4882a593Smuzhiyun 	unsigned int idx = SRC_RESOURCE_NUM;
415*4882a593Smuzhiyun 	int err;
416*4882a593Smuzhiyun 	struct src *src;
417*4882a593Smuzhiyun 	unsigned long flags;
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	*rsrc = NULL;
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	/* Check whether there are sufficient src resources to meet request. */
422*4882a593Smuzhiyun 	spin_lock_irqsave(&mgr->mgr_lock, flags);
423*4882a593Smuzhiyun 	if (MEMRD == desc->mode)
424*4882a593Smuzhiyun 		err = mgr_get_resource(&mgr->mgr, desc->multi, &idx);
425*4882a593Smuzhiyun 	else
426*4882a593Smuzhiyun 		err = mgr_get_resource(&mgr->mgr, 1, &idx);
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	spin_unlock_irqrestore(&mgr->mgr_lock, flags);
429*4882a593Smuzhiyun 	if (err) {
430*4882a593Smuzhiyun 		dev_err(mgr->card->dev,
431*4882a593Smuzhiyun 			"Can't meet SRC resource request!\n");
432*4882a593Smuzhiyun 		return err;
433*4882a593Smuzhiyun 	}
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	/* Allocate mem for master src resource */
436*4882a593Smuzhiyun 	if (MEMRD == desc->mode)
437*4882a593Smuzhiyun 		src = kcalloc(desc->multi, sizeof(*src), GFP_KERNEL);
438*4882a593Smuzhiyun 	else
439*4882a593Smuzhiyun 		src = kzalloc(sizeof(*src), GFP_KERNEL);
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	if (!src) {
442*4882a593Smuzhiyun 		err = -ENOMEM;
443*4882a593Smuzhiyun 		goto error1;
444*4882a593Smuzhiyun 	}
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 	err = src_rsc_init(src, idx, desc, mgr);
447*4882a593Smuzhiyun 	if (err)
448*4882a593Smuzhiyun 		goto error2;
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	*rsrc = src;
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	return 0;
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun error2:
455*4882a593Smuzhiyun 	kfree(src);
456*4882a593Smuzhiyun error1:
457*4882a593Smuzhiyun 	spin_lock_irqsave(&mgr->mgr_lock, flags);
458*4882a593Smuzhiyun 	if (MEMRD == desc->mode)
459*4882a593Smuzhiyun 		mgr_put_resource(&mgr->mgr, desc->multi, idx);
460*4882a593Smuzhiyun 	else
461*4882a593Smuzhiyun 		mgr_put_resource(&mgr->mgr, 1, idx);
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	spin_unlock_irqrestore(&mgr->mgr_lock, flags);
464*4882a593Smuzhiyun 	return err;
465*4882a593Smuzhiyun }
466*4882a593Smuzhiyun 
put_src_rsc(struct src_mgr * mgr,struct src * src)467*4882a593Smuzhiyun static int put_src_rsc(struct src_mgr *mgr, struct src *src)
468*4882a593Smuzhiyun {
469*4882a593Smuzhiyun 	unsigned long flags;
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun 	spin_lock_irqsave(&mgr->mgr_lock, flags);
472*4882a593Smuzhiyun 	src->rsc.ops->master(&src->rsc);
473*4882a593Smuzhiyun 	if (MEMRD == src->mode)
474*4882a593Smuzhiyun 		mgr_put_resource(&mgr->mgr, src->multi,
475*4882a593Smuzhiyun 				 src->rsc.ops->index(&src->rsc));
476*4882a593Smuzhiyun 	else
477*4882a593Smuzhiyun 		mgr_put_resource(&mgr->mgr, 1, src->rsc.ops->index(&src->rsc));
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	spin_unlock_irqrestore(&mgr->mgr_lock, flags);
480*4882a593Smuzhiyun 	src_rsc_uninit(src, mgr);
481*4882a593Smuzhiyun 	kfree(src);
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	return 0;
484*4882a593Smuzhiyun }
485*4882a593Smuzhiyun 
src_enable_s(struct src_mgr * mgr,struct src * src)486*4882a593Smuzhiyun static int src_enable_s(struct src_mgr *mgr, struct src *src)
487*4882a593Smuzhiyun {
488*4882a593Smuzhiyun 	struct hw *hw = mgr->mgr.hw;
489*4882a593Smuzhiyun 	int i;
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	src->rsc.ops->master(&src->rsc);
492*4882a593Smuzhiyun 	for (i = 0; i < src->rsc.msr; i++) {
493*4882a593Smuzhiyun 		hw->src_mgr_enbs_src(mgr->mgr.ctrl_blk,
494*4882a593Smuzhiyun 				     src->rsc.ops->index(&src->rsc));
495*4882a593Smuzhiyun 		src->rsc.ops->next_conj(&src->rsc);
496*4882a593Smuzhiyun 	}
497*4882a593Smuzhiyun 	src->rsc.ops->master(&src->rsc);
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	return 0;
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun 
src_enable(struct src_mgr * mgr,struct src * src)502*4882a593Smuzhiyun static int src_enable(struct src_mgr *mgr, struct src *src)
503*4882a593Smuzhiyun {
504*4882a593Smuzhiyun 	struct hw *hw = mgr->mgr.hw;
505*4882a593Smuzhiyun 	int i;
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	src->rsc.ops->master(&src->rsc);
508*4882a593Smuzhiyun 	for (i = 0; i < src->rsc.msr; i++) {
509*4882a593Smuzhiyun 		hw->src_mgr_enb_src(mgr->mgr.ctrl_blk,
510*4882a593Smuzhiyun 				    src->rsc.ops->index(&src->rsc));
511*4882a593Smuzhiyun 		src->rsc.ops->next_conj(&src->rsc);
512*4882a593Smuzhiyun 	}
513*4882a593Smuzhiyun 	src->rsc.ops->master(&src->rsc);
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	return 0;
516*4882a593Smuzhiyun }
517*4882a593Smuzhiyun 
src_disable(struct src_mgr * mgr,struct src * src)518*4882a593Smuzhiyun static int src_disable(struct src_mgr *mgr, struct src *src)
519*4882a593Smuzhiyun {
520*4882a593Smuzhiyun 	struct hw *hw = mgr->mgr.hw;
521*4882a593Smuzhiyun 	int i;
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	src->rsc.ops->master(&src->rsc);
524*4882a593Smuzhiyun 	for (i = 0; i < src->rsc.msr; i++) {
525*4882a593Smuzhiyun 		hw->src_mgr_dsb_src(mgr->mgr.ctrl_blk,
526*4882a593Smuzhiyun 				    src->rsc.ops->index(&src->rsc));
527*4882a593Smuzhiyun 		src->rsc.ops->next_conj(&src->rsc);
528*4882a593Smuzhiyun 	}
529*4882a593Smuzhiyun 	src->rsc.ops->master(&src->rsc);
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 	return 0;
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun 
src_mgr_commit_write(struct src_mgr * mgr)534*4882a593Smuzhiyun static int src_mgr_commit_write(struct src_mgr *mgr)
535*4882a593Smuzhiyun {
536*4882a593Smuzhiyun 	struct hw *hw = mgr->mgr.hw;
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 	hw->src_mgr_commit_write(hw, mgr->mgr.ctrl_blk);
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 	return 0;
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun 
src_mgr_create(struct hw * hw,struct src_mgr ** rsrc_mgr)543*4882a593Smuzhiyun int src_mgr_create(struct hw *hw, struct src_mgr **rsrc_mgr)
544*4882a593Smuzhiyun {
545*4882a593Smuzhiyun 	int err, i;
546*4882a593Smuzhiyun 	struct src_mgr *src_mgr;
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun 	*rsrc_mgr = NULL;
549*4882a593Smuzhiyun 	src_mgr = kzalloc(sizeof(*src_mgr), GFP_KERNEL);
550*4882a593Smuzhiyun 	if (!src_mgr)
551*4882a593Smuzhiyun 		return -ENOMEM;
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	err = rsc_mgr_init(&src_mgr->mgr, SRC, SRC_RESOURCE_NUM, hw);
554*4882a593Smuzhiyun 	if (err)
555*4882a593Smuzhiyun 		goto error1;
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	spin_lock_init(&src_mgr->mgr_lock);
558*4882a593Smuzhiyun 	conj_mask = hw->src_dirty_conj_mask();
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 	src_mgr->get_src = get_src_rsc;
561*4882a593Smuzhiyun 	src_mgr->put_src = put_src_rsc;
562*4882a593Smuzhiyun 	src_mgr->src_enable_s = src_enable_s;
563*4882a593Smuzhiyun 	src_mgr->src_enable = src_enable;
564*4882a593Smuzhiyun 	src_mgr->src_disable = src_disable;
565*4882a593Smuzhiyun 	src_mgr->commit_write = src_mgr_commit_write;
566*4882a593Smuzhiyun 	src_mgr->card = hw->card;
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 	/* Disable all SRC resources. */
569*4882a593Smuzhiyun 	for (i = 0; i < 256; i++)
570*4882a593Smuzhiyun 		hw->src_mgr_dsb_src(src_mgr->mgr.ctrl_blk, i);
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun 	hw->src_mgr_commit_write(hw, src_mgr->mgr.ctrl_blk);
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 	*rsrc_mgr = src_mgr;
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun 	return 0;
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun error1:
579*4882a593Smuzhiyun 	kfree(src_mgr);
580*4882a593Smuzhiyun 	return err;
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun 
src_mgr_destroy(struct src_mgr * src_mgr)583*4882a593Smuzhiyun int src_mgr_destroy(struct src_mgr *src_mgr)
584*4882a593Smuzhiyun {
585*4882a593Smuzhiyun 	rsc_mgr_uninit(&src_mgr->mgr);
586*4882a593Smuzhiyun 	kfree(src_mgr);
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 	return 0;
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun 
591*4882a593Smuzhiyun /* SRCIMP resource manager operations */
592*4882a593Smuzhiyun 
srcimp_master(struct rsc * rsc)593*4882a593Smuzhiyun static void srcimp_master(struct rsc *rsc)
594*4882a593Smuzhiyun {
595*4882a593Smuzhiyun 	rsc->conj = 0;
596*4882a593Smuzhiyun 	rsc->idx = container_of(rsc, struct srcimp, rsc)->idx[0];
597*4882a593Smuzhiyun }
598*4882a593Smuzhiyun 
srcimp_next_conj(struct rsc * rsc)599*4882a593Smuzhiyun static void srcimp_next_conj(struct rsc *rsc)
600*4882a593Smuzhiyun {
601*4882a593Smuzhiyun 	rsc->conj++;
602*4882a593Smuzhiyun }
603*4882a593Smuzhiyun 
srcimp_index(const struct rsc * rsc)604*4882a593Smuzhiyun static int srcimp_index(const struct rsc *rsc)
605*4882a593Smuzhiyun {
606*4882a593Smuzhiyun 	return container_of(rsc, struct srcimp, rsc)->idx[rsc->conj];
607*4882a593Smuzhiyun }
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun static const struct rsc_ops srcimp_basic_rsc_ops = {
610*4882a593Smuzhiyun 	.master		= srcimp_master,
611*4882a593Smuzhiyun 	.next_conj	= srcimp_next_conj,
612*4882a593Smuzhiyun 	.index		= srcimp_index,
613*4882a593Smuzhiyun 	.output_slot	= NULL,
614*4882a593Smuzhiyun };
615*4882a593Smuzhiyun 
srcimp_map(struct srcimp * srcimp,struct src * src,struct rsc * input)616*4882a593Smuzhiyun static int srcimp_map(struct srcimp *srcimp, struct src *src, struct rsc *input)
617*4882a593Smuzhiyun {
618*4882a593Smuzhiyun 	struct imapper *entry;
619*4882a593Smuzhiyun 	int i;
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun 	srcimp->rsc.ops->master(&srcimp->rsc);
622*4882a593Smuzhiyun 	src->rsc.ops->master(&src->rsc);
623*4882a593Smuzhiyun 	input->ops->master(input);
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun 	/* Program master and conjugate resources */
626*4882a593Smuzhiyun 	for (i = 0; i < srcimp->rsc.msr; i++) {
627*4882a593Smuzhiyun 		entry = &srcimp->imappers[i];
628*4882a593Smuzhiyun 		entry->slot = input->ops->output_slot(input);
629*4882a593Smuzhiyun 		entry->user = src->rsc.ops->index(&src->rsc);
630*4882a593Smuzhiyun 		entry->addr = srcimp->rsc.ops->index(&srcimp->rsc);
631*4882a593Smuzhiyun 		srcimp->mgr->imap_add(srcimp->mgr, entry);
632*4882a593Smuzhiyun 		srcimp->mapped |= (0x1 << i);
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 		srcimp->rsc.ops->next_conj(&srcimp->rsc);
635*4882a593Smuzhiyun 		input->ops->next_conj(input);
636*4882a593Smuzhiyun 	}
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	srcimp->rsc.ops->master(&srcimp->rsc);
639*4882a593Smuzhiyun 	input->ops->master(input);
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun 	return 0;
642*4882a593Smuzhiyun }
643*4882a593Smuzhiyun 
srcimp_unmap(struct srcimp * srcimp)644*4882a593Smuzhiyun static int srcimp_unmap(struct srcimp *srcimp)
645*4882a593Smuzhiyun {
646*4882a593Smuzhiyun 	int i;
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 	/* Program master and conjugate resources */
649*4882a593Smuzhiyun 	for (i = 0; i < srcimp->rsc.msr; i++) {
650*4882a593Smuzhiyun 		if (srcimp->mapped & (0x1 << i)) {
651*4882a593Smuzhiyun 			srcimp->mgr->imap_delete(srcimp->mgr,
652*4882a593Smuzhiyun 						 &srcimp->imappers[i]);
653*4882a593Smuzhiyun 			srcimp->mapped &= ~(0x1 << i);
654*4882a593Smuzhiyun 		}
655*4882a593Smuzhiyun 	}
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun 	return 0;
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun static const struct srcimp_rsc_ops srcimp_ops = {
661*4882a593Smuzhiyun 	.map = srcimp_map,
662*4882a593Smuzhiyun 	.unmap = srcimp_unmap
663*4882a593Smuzhiyun };
664*4882a593Smuzhiyun 
srcimp_rsc_init(struct srcimp * srcimp,const struct srcimp_desc * desc,struct srcimp_mgr * mgr)665*4882a593Smuzhiyun static int srcimp_rsc_init(struct srcimp *srcimp,
666*4882a593Smuzhiyun 			   const struct srcimp_desc *desc,
667*4882a593Smuzhiyun 			   struct srcimp_mgr *mgr)
668*4882a593Smuzhiyun {
669*4882a593Smuzhiyun 	int err;
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun 	err = rsc_init(&srcimp->rsc, srcimp->idx[0],
672*4882a593Smuzhiyun 		       SRCIMP, desc->msr, mgr->mgr.hw);
673*4882a593Smuzhiyun 	if (err)
674*4882a593Smuzhiyun 		return err;
675*4882a593Smuzhiyun 
676*4882a593Smuzhiyun 	/* Reserve memory for imapper nodes */
677*4882a593Smuzhiyun 	srcimp->imappers = kcalloc(desc->msr, sizeof(struct imapper),
678*4882a593Smuzhiyun 				   GFP_KERNEL);
679*4882a593Smuzhiyun 	if (!srcimp->imappers) {
680*4882a593Smuzhiyun 		err = -ENOMEM;
681*4882a593Smuzhiyun 		goto error1;
682*4882a593Smuzhiyun 	}
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun 	/* Set srcimp specific operations */
685*4882a593Smuzhiyun 	srcimp->rsc.ops = &srcimp_basic_rsc_ops;
686*4882a593Smuzhiyun 	srcimp->ops = &srcimp_ops;
687*4882a593Smuzhiyun 	srcimp->mgr = mgr;
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun 	srcimp->rsc.ops->master(&srcimp->rsc);
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun 	return 0;
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun error1:
694*4882a593Smuzhiyun 	rsc_uninit(&srcimp->rsc);
695*4882a593Smuzhiyun 	return err;
696*4882a593Smuzhiyun }
697*4882a593Smuzhiyun 
srcimp_rsc_uninit(struct srcimp * srcimp)698*4882a593Smuzhiyun static int srcimp_rsc_uninit(struct srcimp *srcimp)
699*4882a593Smuzhiyun {
700*4882a593Smuzhiyun 	kfree(srcimp->imappers);
701*4882a593Smuzhiyun 	srcimp->imappers = NULL;
702*4882a593Smuzhiyun 	srcimp->ops = NULL;
703*4882a593Smuzhiyun 	srcimp->mgr = NULL;
704*4882a593Smuzhiyun 	rsc_uninit(&srcimp->rsc);
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun 	return 0;
707*4882a593Smuzhiyun }
708*4882a593Smuzhiyun 
get_srcimp_rsc(struct srcimp_mgr * mgr,const struct srcimp_desc * desc,struct srcimp ** rsrcimp)709*4882a593Smuzhiyun static int get_srcimp_rsc(struct srcimp_mgr *mgr,
710*4882a593Smuzhiyun 			  const struct srcimp_desc *desc,
711*4882a593Smuzhiyun 			  struct srcimp **rsrcimp)
712*4882a593Smuzhiyun {
713*4882a593Smuzhiyun 	int err, i;
714*4882a593Smuzhiyun 	unsigned int idx;
715*4882a593Smuzhiyun 	struct srcimp *srcimp;
716*4882a593Smuzhiyun 	unsigned long flags;
717*4882a593Smuzhiyun 
718*4882a593Smuzhiyun 	*rsrcimp = NULL;
719*4882a593Smuzhiyun 
720*4882a593Smuzhiyun 	/* Allocate mem for SRCIMP resource */
721*4882a593Smuzhiyun 	srcimp = kzalloc(sizeof(*srcimp), GFP_KERNEL);
722*4882a593Smuzhiyun 	if (!srcimp)
723*4882a593Smuzhiyun 		return -ENOMEM;
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun 	/* Check whether there are sufficient SRCIMP resources. */
726*4882a593Smuzhiyun 	err = 0;
727*4882a593Smuzhiyun 	spin_lock_irqsave(&mgr->mgr_lock, flags);
728*4882a593Smuzhiyun 	for (i = 0; i < desc->msr; i++) {
729*4882a593Smuzhiyun 		err = mgr_get_resource(&mgr->mgr, 1, &idx);
730*4882a593Smuzhiyun 		if (err)
731*4882a593Smuzhiyun 			break;
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun 		srcimp->idx[i] = idx;
734*4882a593Smuzhiyun 	}
735*4882a593Smuzhiyun 	spin_unlock_irqrestore(&mgr->mgr_lock, flags);
736*4882a593Smuzhiyun 	if (err) {
737*4882a593Smuzhiyun 		dev_err(mgr->card->dev,
738*4882a593Smuzhiyun 			"Can't meet SRCIMP resource request!\n");
739*4882a593Smuzhiyun 		goto error1;
740*4882a593Smuzhiyun 	}
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	err = srcimp_rsc_init(srcimp, desc, mgr);
743*4882a593Smuzhiyun 	if (err)
744*4882a593Smuzhiyun 		goto error1;
745*4882a593Smuzhiyun 
746*4882a593Smuzhiyun 	*rsrcimp = srcimp;
747*4882a593Smuzhiyun 
748*4882a593Smuzhiyun 	return 0;
749*4882a593Smuzhiyun 
750*4882a593Smuzhiyun error1:
751*4882a593Smuzhiyun 	spin_lock_irqsave(&mgr->mgr_lock, flags);
752*4882a593Smuzhiyun 	for (i--; i >= 0; i--)
753*4882a593Smuzhiyun 		mgr_put_resource(&mgr->mgr, 1, srcimp->idx[i]);
754*4882a593Smuzhiyun 
755*4882a593Smuzhiyun 	spin_unlock_irqrestore(&mgr->mgr_lock, flags);
756*4882a593Smuzhiyun 	kfree(srcimp);
757*4882a593Smuzhiyun 	return err;
758*4882a593Smuzhiyun }
759*4882a593Smuzhiyun 
put_srcimp_rsc(struct srcimp_mgr * mgr,struct srcimp * srcimp)760*4882a593Smuzhiyun static int put_srcimp_rsc(struct srcimp_mgr *mgr, struct srcimp *srcimp)
761*4882a593Smuzhiyun {
762*4882a593Smuzhiyun 	unsigned long flags;
763*4882a593Smuzhiyun 	int i;
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun 	spin_lock_irqsave(&mgr->mgr_lock, flags);
766*4882a593Smuzhiyun 	for (i = 0; i < srcimp->rsc.msr; i++)
767*4882a593Smuzhiyun 		mgr_put_resource(&mgr->mgr, 1, srcimp->idx[i]);
768*4882a593Smuzhiyun 
769*4882a593Smuzhiyun 	spin_unlock_irqrestore(&mgr->mgr_lock, flags);
770*4882a593Smuzhiyun 	srcimp_rsc_uninit(srcimp);
771*4882a593Smuzhiyun 	kfree(srcimp);
772*4882a593Smuzhiyun 
773*4882a593Smuzhiyun 	return 0;
774*4882a593Smuzhiyun }
775*4882a593Smuzhiyun 
srcimp_map_op(void * data,struct imapper * entry)776*4882a593Smuzhiyun static int srcimp_map_op(void *data, struct imapper *entry)
777*4882a593Smuzhiyun {
778*4882a593Smuzhiyun 	struct rsc_mgr *mgr = &((struct srcimp_mgr *)data)->mgr;
779*4882a593Smuzhiyun 	struct hw *hw = mgr->hw;
780*4882a593Smuzhiyun 
781*4882a593Smuzhiyun 	hw->srcimp_mgr_set_imaparc(mgr->ctrl_blk, entry->slot);
782*4882a593Smuzhiyun 	hw->srcimp_mgr_set_imapuser(mgr->ctrl_blk, entry->user);
783*4882a593Smuzhiyun 	hw->srcimp_mgr_set_imapnxt(mgr->ctrl_blk, entry->next);
784*4882a593Smuzhiyun 	hw->srcimp_mgr_set_imapaddr(mgr->ctrl_blk, entry->addr);
785*4882a593Smuzhiyun 	hw->srcimp_mgr_commit_write(mgr->hw, mgr->ctrl_blk);
786*4882a593Smuzhiyun 
787*4882a593Smuzhiyun 	return 0;
788*4882a593Smuzhiyun }
789*4882a593Smuzhiyun 
srcimp_imap_add(struct srcimp_mgr * mgr,struct imapper * entry)790*4882a593Smuzhiyun static int srcimp_imap_add(struct srcimp_mgr *mgr, struct imapper *entry)
791*4882a593Smuzhiyun {
792*4882a593Smuzhiyun 	unsigned long flags;
793*4882a593Smuzhiyun 	int err;
794*4882a593Smuzhiyun 
795*4882a593Smuzhiyun 	spin_lock_irqsave(&mgr->imap_lock, flags);
796*4882a593Smuzhiyun 	if ((0 == entry->addr) && (mgr->init_imap_added)) {
797*4882a593Smuzhiyun 		input_mapper_delete(&mgr->imappers,
798*4882a593Smuzhiyun 				    mgr->init_imap, srcimp_map_op, mgr);
799*4882a593Smuzhiyun 		mgr->init_imap_added = 0;
800*4882a593Smuzhiyun 	}
801*4882a593Smuzhiyun 	err = input_mapper_add(&mgr->imappers, entry, srcimp_map_op, mgr);
802*4882a593Smuzhiyun 	spin_unlock_irqrestore(&mgr->imap_lock, flags);
803*4882a593Smuzhiyun 
804*4882a593Smuzhiyun 	return err;
805*4882a593Smuzhiyun }
806*4882a593Smuzhiyun 
srcimp_imap_delete(struct srcimp_mgr * mgr,struct imapper * entry)807*4882a593Smuzhiyun static int srcimp_imap_delete(struct srcimp_mgr *mgr, struct imapper *entry)
808*4882a593Smuzhiyun {
809*4882a593Smuzhiyun 	unsigned long flags;
810*4882a593Smuzhiyun 	int err;
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun 	spin_lock_irqsave(&mgr->imap_lock, flags);
813*4882a593Smuzhiyun 	err = input_mapper_delete(&mgr->imappers, entry, srcimp_map_op, mgr);
814*4882a593Smuzhiyun 	if (list_empty(&mgr->imappers)) {
815*4882a593Smuzhiyun 		input_mapper_add(&mgr->imappers, mgr->init_imap,
816*4882a593Smuzhiyun 				 srcimp_map_op, mgr);
817*4882a593Smuzhiyun 		mgr->init_imap_added = 1;
818*4882a593Smuzhiyun 	}
819*4882a593Smuzhiyun 	spin_unlock_irqrestore(&mgr->imap_lock, flags);
820*4882a593Smuzhiyun 
821*4882a593Smuzhiyun 	return err;
822*4882a593Smuzhiyun }
823*4882a593Smuzhiyun 
srcimp_mgr_create(struct hw * hw,struct srcimp_mgr ** rsrcimp_mgr)824*4882a593Smuzhiyun int srcimp_mgr_create(struct hw *hw, struct srcimp_mgr **rsrcimp_mgr)
825*4882a593Smuzhiyun {
826*4882a593Smuzhiyun 	int err;
827*4882a593Smuzhiyun 	struct srcimp_mgr *srcimp_mgr;
828*4882a593Smuzhiyun 	struct imapper *entry;
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun 	*rsrcimp_mgr = NULL;
831*4882a593Smuzhiyun 	srcimp_mgr = kzalloc(sizeof(*srcimp_mgr), GFP_KERNEL);
832*4882a593Smuzhiyun 	if (!srcimp_mgr)
833*4882a593Smuzhiyun 		return -ENOMEM;
834*4882a593Smuzhiyun 
835*4882a593Smuzhiyun 	err = rsc_mgr_init(&srcimp_mgr->mgr, SRCIMP, SRCIMP_RESOURCE_NUM, hw);
836*4882a593Smuzhiyun 	if (err)
837*4882a593Smuzhiyun 		goto error1;
838*4882a593Smuzhiyun 
839*4882a593Smuzhiyun 	spin_lock_init(&srcimp_mgr->mgr_lock);
840*4882a593Smuzhiyun 	spin_lock_init(&srcimp_mgr->imap_lock);
841*4882a593Smuzhiyun 	INIT_LIST_HEAD(&srcimp_mgr->imappers);
842*4882a593Smuzhiyun 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
843*4882a593Smuzhiyun 	if (!entry) {
844*4882a593Smuzhiyun 		err = -ENOMEM;
845*4882a593Smuzhiyun 		goto error2;
846*4882a593Smuzhiyun 	}
847*4882a593Smuzhiyun 	entry->slot = entry->addr = entry->next = entry->user = 0;
848*4882a593Smuzhiyun 	list_add(&entry->list, &srcimp_mgr->imappers);
849*4882a593Smuzhiyun 	srcimp_mgr->init_imap = entry;
850*4882a593Smuzhiyun 	srcimp_mgr->init_imap_added = 1;
851*4882a593Smuzhiyun 
852*4882a593Smuzhiyun 	srcimp_mgr->get_srcimp = get_srcimp_rsc;
853*4882a593Smuzhiyun 	srcimp_mgr->put_srcimp = put_srcimp_rsc;
854*4882a593Smuzhiyun 	srcimp_mgr->imap_add = srcimp_imap_add;
855*4882a593Smuzhiyun 	srcimp_mgr->imap_delete = srcimp_imap_delete;
856*4882a593Smuzhiyun 	srcimp_mgr->card = hw->card;
857*4882a593Smuzhiyun 
858*4882a593Smuzhiyun 	*rsrcimp_mgr = srcimp_mgr;
859*4882a593Smuzhiyun 
860*4882a593Smuzhiyun 	return 0;
861*4882a593Smuzhiyun 
862*4882a593Smuzhiyun error2:
863*4882a593Smuzhiyun 	rsc_mgr_uninit(&srcimp_mgr->mgr);
864*4882a593Smuzhiyun error1:
865*4882a593Smuzhiyun 	kfree(srcimp_mgr);
866*4882a593Smuzhiyun 	return err;
867*4882a593Smuzhiyun }
868*4882a593Smuzhiyun 
srcimp_mgr_destroy(struct srcimp_mgr * srcimp_mgr)869*4882a593Smuzhiyun int srcimp_mgr_destroy(struct srcimp_mgr *srcimp_mgr)
870*4882a593Smuzhiyun {
871*4882a593Smuzhiyun 	unsigned long flags;
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun 	/* free src input mapper list */
874*4882a593Smuzhiyun 	spin_lock_irqsave(&srcimp_mgr->imap_lock, flags);
875*4882a593Smuzhiyun 	free_input_mapper_list(&srcimp_mgr->imappers);
876*4882a593Smuzhiyun 	spin_unlock_irqrestore(&srcimp_mgr->imap_lock, flags);
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun 	rsc_mgr_uninit(&srcimp_mgr->mgr);
879*4882a593Smuzhiyun 	kfree(srcimp_mgr);
880*4882a593Smuzhiyun 
881*4882a593Smuzhiyun 	return 0;
882*4882a593Smuzhiyun }
883