xref: /openbmc/linux/sound/pci/ctxfi/ctsrc.c (revision 25aa8e9f)
15765e78eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2a08b9f2fSAditya Srivastava /*
38cc72361SWai Yew CHAY  * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
48cc72361SWai Yew CHAY  *
58cc72361SWai Yew CHAY  * @File	ctsrc.c
68cc72361SWai Yew CHAY  *
78cc72361SWai Yew CHAY  * @Brief
88cc72361SWai Yew CHAY  * This file contains the implementation of the Sample Rate Convertor
98cc72361SWai Yew CHAY  * resource management object.
108cc72361SWai Yew CHAY  *
118cc72361SWai Yew CHAY  * @Author	Liu Chun
128cc72361SWai Yew CHAY  * @Date 	May 13 2008
138cc72361SWai Yew CHAY  */
148cc72361SWai Yew CHAY 
158cc72361SWai Yew CHAY #include "ctsrc.h"
168cc72361SWai Yew CHAY #include "cthardware.h"
178cc72361SWai Yew CHAY #include <linux/slab.h>
188cc72361SWai Yew CHAY 
19391e6914SMaarten Lankhorst #define SRC_RESOURCE_NUM	256
208cc72361SWai Yew CHAY #define SRCIMP_RESOURCE_NUM	256
218cc72361SWai Yew CHAY 
228cc72361SWai Yew CHAY static unsigned int conj_mask;
238cc72361SWai Yew CHAY 
248cc72361SWai Yew CHAY static int src_default_config_memrd(struct src *src);
258cc72361SWai Yew CHAY static int src_default_config_memwr(struct src *src);
268cc72361SWai Yew CHAY static int src_default_config_arcrw(struct src *src);
278cc72361SWai Yew CHAY 
288cc72361SWai Yew CHAY static int (*src_default_config[3])(struct src *) = {
298cc72361SWai Yew CHAY 	[MEMRD] = src_default_config_memrd,
308cc72361SWai Yew CHAY 	[MEMWR] = src_default_config_memwr,
318cc72361SWai Yew CHAY 	[ARCRW] = src_default_config_arcrw
328cc72361SWai Yew CHAY };
338cc72361SWai Yew CHAY 
src_set_state(struct src * src,unsigned int state)348cc72361SWai Yew CHAY static int src_set_state(struct src *src, unsigned int state)
358cc72361SWai Yew CHAY {
36514eef9cSTakashi Iwai 	struct hw *hw;
378cc72361SWai Yew CHAY 
38514eef9cSTakashi Iwai 	hw = src->rsc.hw;
398cc72361SWai Yew CHAY 	hw->src_set_state(src->rsc.ctrl_blk, state);
408cc72361SWai Yew CHAY 
418cc72361SWai Yew CHAY 	return 0;
428cc72361SWai Yew CHAY }
438cc72361SWai Yew CHAY 
src_set_bm(struct src * src,unsigned int bm)448cc72361SWai Yew CHAY static int src_set_bm(struct src *src, unsigned int bm)
458cc72361SWai Yew CHAY {
46514eef9cSTakashi Iwai 	struct hw *hw;
478cc72361SWai Yew CHAY 
48514eef9cSTakashi Iwai 	hw = src->rsc.hw;
498cc72361SWai Yew CHAY 	hw->src_set_bm(src->rsc.ctrl_blk, bm);
508cc72361SWai Yew CHAY 
518cc72361SWai Yew CHAY 	return 0;
528cc72361SWai Yew CHAY }
538cc72361SWai Yew CHAY 
src_set_sf(struct src * src,unsigned int sf)548cc72361SWai Yew CHAY static int src_set_sf(struct src *src, unsigned int sf)
558cc72361SWai Yew CHAY {
56514eef9cSTakashi Iwai 	struct hw *hw;
578cc72361SWai Yew CHAY 
58514eef9cSTakashi Iwai 	hw = src->rsc.hw;
598cc72361SWai Yew CHAY 	hw->src_set_sf(src->rsc.ctrl_blk, sf);
608cc72361SWai Yew CHAY 
618cc72361SWai Yew CHAY 	return 0;
628cc72361SWai Yew CHAY }
638cc72361SWai Yew CHAY 
src_set_pm(struct src * src,unsigned int pm)648cc72361SWai Yew CHAY static int src_set_pm(struct src *src, unsigned int pm)
658cc72361SWai Yew CHAY {
66514eef9cSTakashi Iwai 	struct hw *hw;
678cc72361SWai Yew CHAY 
68514eef9cSTakashi Iwai 	hw = src->rsc.hw;
698cc72361SWai Yew CHAY 	hw->src_set_pm(src->rsc.ctrl_blk, pm);
708cc72361SWai Yew CHAY 
718cc72361SWai Yew CHAY 	return 0;
728cc72361SWai Yew CHAY }
738cc72361SWai Yew CHAY 
src_set_rom(struct src * src,unsigned int rom)748cc72361SWai Yew CHAY static int src_set_rom(struct src *src, unsigned int rom)
758cc72361SWai Yew CHAY {
76514eef9cSTakashi Iwai 	struct hw *hw;
778cc72361SWai Yew CHAY 
78514eef9cSTakashi Iwai 	hw = src->rsc.hw;
798cc72361SWai Yew CHAY 	hw->src_set_rom(src->rsc.ctrl_blk, rom);
808cc72361SWai Yew CHAY 
818cc72361SWai Yew CHAY 	return 0;
828cc72361SWai Yew CHAY }
838cc72361SWai Yew CHAY 
src_set_vo(struct src * src,unsigned int vo)848cc72361SWai Yew CHAY static int src_set_vo(struct src *src, unsigned int vo)
858cc72361SWai Yew CHAY {
86514eef9cSTakashi Iwai 	struct hw *hw;
878cc72361SWai Yew CHAY 
88514eef9cSTakashi Iwai 	hw = src->rsc.hw;
898cc72361SWai Yew CHAY 	hw->src_set_vo(src->rsc.ctrl_blk, vo);
908cc72361SWai Yew CHAY 
918cc72361SWai Yew CHAY 	return 0;
928cc72361SWai Yew CHAY }
938cc72361SWai Yew CHAY 
src_set_st(struct src * src,unsigned int st)948cc72361SWai Yew CHAY static int src_set_st(struct src *src, unsigned int st)
958cc72361SWai Yew CHAY {
96514eef9cSTakashi Iwai 	struct hw *hw;
978cc72361SWai Yew CHAY 
98514eef9cSTakashi Iwai 	hw = src->rsc.hw;
998cc72361SWai Yew CHAY 	hw->src_set_st(src->rsc.ctrl_blk, st);
1008cc72361SWai Yew CHAY 
1018cc72361SWai Yew CHAY 	return 0;
1028cc72361SWai Yew CHAY }
1038cc72361SWai Yew CHAY 
src_set_bp(struct src * src,unsigned int bp)1048cc72361SWai Yew CHAY static int src_set_bp(struct src *src, unsigned int bp)
1058cc72361SWai Yew CHAY {
106514eef9cSTakashi Iwai 	struct hw *hw;
1078cc72361SWai Yew CHAY 
108514eef9cSTakashi Iwai 	hw = src->rsc.hw;
1098cc72361SWai Yew CHAY 	hw->src_set_bp(src->rsc.ctrl_blk, bp);
1108cc72361SWai Yew CHAY 
1118cc72361SWai Yew CHAY 	return 0;
1128cc72361SWai Yew CHAY }
1138cc72361SWai Yew CHAY 
src_set_cisz(struct src * src,unsigned int cisz)1148cc72361SWai Yew CHAY static int src_set_cisz(struct src *src, unsigned int cisz)
1158cc72361SWai Yew CHAY {
116514eef9cSTakashi Iwai 	struct hw *hw;
1178cc72361SWai Yew CHAY 
118514eef9cSTakashi Iwai 	hw = src->rsc.hw;
1198cc72361SWai Yew CHAY 	hw->src_set_cisz(src->rsc.ctrl_blk, cisz);
1208cc72361SWai Yew CHAY 
1218cc72361SWai Yew CHAY 	return 0;
1228cc72361SWai Yew CHAY }
1238cc72361SWai Yew CHAY 
src_set_ca(struct src * src,unsigned int ca)1248cc72361SWai Yew CHAY static int src_set_ca(struct src *src, unsigned int ca)
1258cc72361SWai Yew CHAY {
126514eef9cSTakashi Iwai 	struct hw *hw;
1278cc72361SWai Yew CHAY 
128514eef9cSTakashi Iwai 	hw = src->rsc.hw;
1298cc72361SWai Yew CHAY 	hw->src_set_ca(src->rsc.ctrl_blk, ca);
1308cc72361SWai Yew CHAY 
1318cc72361SWai Yew CHAY 	return 0;
1328cc72361SWai Yew CHAY }
1338cc72361SWai Yew CHAY 
src_set_sa(struct src * src,unsigned int sa)1348cc72361SWai Yew CHAY static int src_set_sa(struct src *src, unsigned int sa)
1358cc72361SWai Yew CHAY {
136514eef9cSTakashi Iwai 	struct hw *hw;
1378cc72361SWai Yew CHAY 
138514eef9cSTakashi Iwai 	hw = src->rsc.hw;
1398cc72361SWai Yew CHAY 	hw->src_set_sa(src->rsc.ctrl_blk, sa);
1408cc72361SWai Yew CHAY 
1418cc72361SWai Yew CHAY 	return 0;
1428cc72361SWai Yew CHAY }
1438cc72361SWai Yew CHAY 
src_set_la(struct src * src,unsigned int la)1448cc72361SWai Yew CHAY static int src_set_la(struct src *src, unsigned int la)
1458cc72361SWai Yew CHAY {
146514eef9cSTakashi Iwai 	struct hw *hw;
1478cc72361SWai Yew CHAY 
148514eef9cSTakashi Iwai 	hw = src->rsc.hw;
1498cc72361SWai Yew CHAY 	hw->src_set_la(src->rsc.ctrl_blk, la);
1508cc72361SWai Yew CHAY 
1518cc72361SWai Yew CHAY 	return 0;
1528cc72361SWai Yew CHAY }
1538cc72361SWai Yew CHAY 
src_set_pitch(struct src * src,unsigned int pitch)1548cc72361SWai Yew CHAY static int src_set_pitch(struct src *src, unsigned int pitch)
1558cc72361SWai Yew CHAY {
156514eef9cSTakashi Iwai 	struct hw *hw;
1578cc72361SWai Yew CHAY 
158514eef9cSTakashi Iwai 	hw = src->rsc.hw;
1598cc72361SWai Yew CHAY 	hw->src_set_pitch(src->rsc.ctrl_blk, pitch);
1608cc72361SWai Yew CHAY 
1618cc72361SWai Yew CHAY 	return 0;
1628cc72361SWai Yew CHAY }
1638cc72361SWai Yew CHAY 
src_set_clear_zbufs(struct src * src)1648cc72361SWai Yew CHAY static int src_set_clear_zbufs(struct src *src)
1658cc72361SWai Yew CHAY {
166514eef9cSTakashi Iwai 	struct hw *hw;
1678cc72361SWai Yew CHAY 
168514eef9cSTakashi Iwai 	hw = src->rsc.hw;
1698cc72361SWai Yew CHAY 	hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1);
1708cc72361SWai Yew CHAY 
1718cc72361SWai Yew CHAY 	return 0;
1728cc72361SWai Yew CHAY }
1738cc72361SWai Yew CHAY 
src_commit_write(struct src * src)1748cc72361SWai Yew CHAY static int src_commit_write(struct src *src)
1758cc72361SWai Yew CHAY {
176514eef9cSTakashi Iwai 	struct hw *hw;
177514eef9cSTakashi Iwai 	int i;
1788cc72361SWai Yew CHAY 	unsigned int dirty = 0;
1798cc72361SWai Yew CHAY 
180514eef9cSTakashi Iwai 	hw = src->rsc.hw;
1818cc72361SWai Yew CHAY 	src->rsc.ops->master(&src->rsc);
1828cc72361SWai Yew CHAY 	if (src->rsc.msr > 1) {
1838cc72361SWai Yew CHAY 		/* Save dirty flags for conjugate resource programming */
1848cc72361SWai Yew CHAY 		dirty = hw->src_get_dirty(src->rsc.ctrl_blk) & conj_mask;
1858cc72361SWai Yew CHAY 	}
1868cc72361SWai Yew CHAY 	hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
1878cc72361SWai Yew CHAY 						src->rsc.ctrl_blk);
1888cc72361SWai Yew CHAY 
1898cc72361SWai Yew CHAY 	/* Program conjugate parameter mixer resources */
1908cc72361SWai Yew CHAY 	if (MEMWR == src->mode)
1918cc72361SWai Yew CHAY 		return 0;
1928cc72361SWai Yew CHAY 
1938cc72361SWai Yew CHAY 	for (i = 1; i < src->rsc.msr; i++) {
1948cc72361SWai Yew CHAY 		src->rsc.ops->next_conj(&src->rsc);
1958cc72361SWai Yew CHAY 		hw->src_set_dirty(src->rsc.ctrl_blk, dirty);
1968cc72361SWai Yew CHAY 		hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
1978cc72361SWai Yew CHAY 							src->rsc.ctrl_blk);
1988cc72361SWai Yew CHAY 	}
1998cc72361SWai Yew CHAY 	src->rsc.ops->master(&src->rsc);
2008cc72361SWai Yew CHAY 
2018cc72361SWai Yew CHAY 	return 0;
2028cc72361SWai Yew CHAY }
2038cc72361SWai Yew CHAY 
src_get_ca(struct src * src)2048cc72361SWai Yew CHAY static int src_get_ca(struct src *src)
2058cc72361SWai Yew CHAY {
206514eef9cSTakashi Iwai 	struct hw *hw;
2078cc72361SWai Yew CHAY 
208514eef9cSTakashi Iwai 	hw = src->rsc.hw;
2098cc72361SWai Yew CHAY 	return hw->src_get_ca(hw, src->rsc.ops->index(&src->rsc),
2108cc72361SWai Yew CHAY 						src->rsc.ctrl_blk);
2118cc72361SWai Yew CHAY }
2128cc72361SWai Yew CHAY 
src_init(struct src * src)2138cc72361SWai Yew CHAY static int src_init(struct src *src)
2148cc72361SWai Yew CHAY {
2158cc72361SWai Yew CHAY 	src_default_config[src->mode](src);
2168cc72361SWai Yew CHAY 
2178cc72361SWai Yew CHAY 	return 0;
2188cc72361SWai Yew CHAY }
2198cc72361SWai Yew CHAY 
src_next_interleave(struct src * src)2208cc72361SWai Yew CHAY static struct src *src_next_interleave(struct src *src)
2218cc72361SWai Yew CHAY {
2228cc72361SWai Yew CHAY 	return src->intlv;
2238cc72361SWai Yew CHAY }
2248cc72361SWai Yew CHAY 
src_default_config_memrd(struct src * src)2258cc72361SWai Yew CHAY static int src_default_config_memrd(struct src *src)
2268cc72361SWai Yew CHAY {
2278cc72361SWai Yew CHAY 	struct hw *hw = src->rsc.hw;
228514eef9cSTakashi Iwai 	unsigned int rsr, msr;
2298cc72361SWai Yew CHAY 
2308cc72361SWai Yew CHAY 	hw->src_set_state(src->rsc.ctrl_blk, SRC_STATE_OFF);
2318cc72361SWai Yew CHAY 	hw->src_set_bm(src->rsc.ctrl_blk, 1);
2328cc72361SWai Yew CHAY 	for (rsr = 0, msr = src->rsc.msr; msr > 1; msr >>= 1)
2338cc72361SWai Yew CHAY 		rsr++;
2348cc72361SWai Yew CHAY 
2358cc72361SWai Yew CHAY 	hw->src_set_rsr(src->rsc.ctrl_blk, rsr);
2368cc72361SWai Yew CHAY 	hw->src_set_sf(src->rsc.ctrl_blk, SRC_SF_S16);
2378cc72361SWai Yew CHAY 	hw->src_set_wr(src->rsc.ctrl_blk, 0);
2388cc72361SWai Yew CHAY 	hw->src_set_pm(src->rsc.ctrl_blk, 0);
2398cc72361SWai Yew CHAY 	hw->src_set_rom(src->rsc.ctrl_blk, 0);
2408cc72361SWai Yew CHAY 	hw->src_set_vo(src->rsc.ctrl_blk, 0);
2418cc72361SWai Yew CHAY 	hw->src_set_st(src->rsc.ctrl_blk, 0);
2428cc72361SWai Yew CHAY 	hw->src_set_ilsz(src->rsc.ctrl_blk, src->multi - 1);
2438cc72361SWai Yew CHAY 	hw->src_set_cisz(src->rsc.ctrl_blk, 0x80);
2448cc72361SWai Yew CHAY 	hw->src_set_sa(src->rsc.ctrl_blk, 0x0);
2458cc72361SWai Yew CHAY 	hw->src_set_la(src->rsc.ctrl_blk, 0x1000);
2468cc72361SWai Yew CHAY 	hw->src_set_ca(src->rsc.ctrl_blk, 0x80);
2478cc72361SWai Yew CHAY 	hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000);
2488cc72361SWai Yew CHAY 	hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1);
2498cc72361SWai Yew CHAY 
2508cc72361SWai Yew CHAY 	src->rsc.ops->master(&src->rsc);
2518cc72361SWai Yew CHAY 	hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
2528cc72361SWai Yew CHAY 						src->rsc.ctrl_blk);
2538cc72361SWai Yew CHAY 
2548cc72361SWai Yew CHAY 	for (msr = 1; msr < src->rsc.msr; msr++) {
2558cc72361SWai Yew CHAY 		src->rsc.ops->next_conj(&src->rsc);
2568cc72361SWai Yew CHAY 		hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000);
2578cc72361SWai Yew CHAY 		hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
2588cc72361SWai Yew CHAY 							src->rsc.ctrl_blk);
2598cc72361SWai Yew CHAY 	}
2608cc72361SWai Yew CHAY 	src->rsc.ops->master(&src->rsc);
2618cc72361SWai Yew CHAY 
2628cc72361SWai Yew CHAY 	return 0;
2638cc72361SWai Yew CHAY }
2648cc72361SWai Yew CHAY 
src_default_config_memwr(struct src * src)2658cc72361SWai Yew CHAY static int src_default_config_memwr(struct src *src)
2668cc72361SWai Yew CHAY {
2678cc72361SWai Yew CHAY 	struct hw *hw = src->rsc.hw;
2688cc72361SWai Yew CHAY 
2698cc72361SWai Yew CHAY 	hw->src_set_state(src->rsc.ctrl_blk, SRC_STATE_OFF);
2708cc72361SWai Yew CHAY 	hw->src_set_bm(src->rsc.ctrl_blk, 1);
2718cc72361SWai Yew CHAY 	hw->src_set_rsr(src->rsc.ctrl_blk, 0);
2728cc72361SWai Yew CHAY 	hw->src_set_sf(src->rsc.ctrl_blk, SRC_SF_S16);
2738cc72361SWai Yew CHAY 	hw->src_set_wr(src->rsc.ctrl_blk, 1);
2748cc72361SWai Yew CHAY 	hw->src_set_pm(src->rsc.ctrl_blk, 0);
2758cc72361SWai Yew CHAY 	hw->src_set_rom(src->rsc.ctrl_blk, 0);
2768cc72361SWai Yew CHAY 	hw->src_set_vo(src->rsc.ctrl_blk, 0);
2778cc72361SWai Yew CHAY 	hw->src_set_st(src->rsc.ctrl_blk, 0);
2788cc72361SWai Yew CHAY 	hw->src_set_ilsz(src->rsc.ctrl_blk, 0);
2798cc72361SWai Yew CHAY 	hw->src_set_cisz(src->rsc.ctrl_blk, 0x80);
2808cc72361SWai Yew CHAY 	hw->src_set_sa(src->rsc.ctrl_blk, 0x0);
2818cc72361SWai Yew CHAY 	hw->src_set_la(src->rsc.ctrl_blk, 0x1000);
2828cc72361SWai Yew CHAY 	hw->src_set_ca(src->rsc.ctrl_blk, 0x80);
2838cc72361SWai Yew CHAY 	hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000);
2848cc72361SWai Yew CHAY 	hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1);
2858cc72361SWai Yew CHAY 
2868cc72361SWai Yew CHAY 	src->rsc.ops->master(&src->rsc);
2878cc72361SWai Yew CHAY 	hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
2888cc72361SWai Yew CHAY 						src->rsc.ctrl_blk);
2898cc72361SWai Yew CHAY 
2908cc72361SWai Yew CHAY 	return 0;
2918cc72361SWai Yew CHAY }
2928cc72361SWai Yew CHAY 
src_default_config_arcrw(struct src * src)2938cc72361SWai Yew CHAY static int src_default_config_arcrw(struct src *src)
2948cc72361SWai Yew CHAY {
2958cc72361SWai Yew CHAY 	struct hw *hw = src->rsc.hw;
296514eef9cSTakashi Iwai 	unsigned int rsr, msr;
2978cc72361SWai Yew CHAY 	unsigned int dirty;
2988cc72361SWai Yew CHAY 
2998cc72361SWai Yew CHAY 	hw->src_set_state(src->rsc.ctrl_blk, SRC_STATE_OFF);
3008cc72361SWai Yew CHAY 	hw->src_set_bm(src->rsc.ctrl_blk, 0);
3018cc72361SWai Yew CHAY 	for (rsr = 0, msr = src->rsc.msr; msr > 1; msr >>= 1)
3028cc72361SWai Yew CHAY 		rsr++;
3038cc72361SWai Yew CHAY 
3048cc72361SWai Yew CHAY 	hw->src_set_rsr(src->rsc.ctrl_blk, rsr);
3058cc72361SWai Yew CHAY 	hw->src_set_sf(src->rsc.ctrl_blk, SRC_SF_F32);
3068cc72361SWai Yew CHAY 	hw->src_set_wr(src->rsc.ctrl_blk, 0);
3078cc72361SWai Yew CHAY 	hw->src_set_pm(src->rsc.ctrl_blk, 0);
3088cc72361SWai Yew CHAY 	hw->src_set_rom(src->rsc.ctrl_blk, 0);
3098cc72361SWai Yew CHAY 	hw->src_set_vo(src->rsc.ctrl_blk, 0);
3108cc72361SWai Yew CHAY 	hw->src_set_st(src->rsc.ctrl_blk, 0);
3118cc72361SWai Yew CHAY 	hw->src_set_ilsz(src->rsc.ctrl_blk, 0);
3128cc72361SWai Yew CHAY 	hw->src_set_cisz(src->rsc.ctrl_blk, 0x80);
3138cc72361SWai Yew CHAY 	hw->src_set_sa(src->rsc.ctrl_blk, 0x0);
3148cc72361SWai Yew CHAY 	/*hw->src_set_sa(src->rsc.ctrl_blk, 0x100);*/
3158cc72361SWai Yew CHAY 	hw->src_set_la(src->rsc.ctrl_blk, 0x1000);
3168cc72361SWai Yew CHAY 	/*hw->src_set_la(src->rsc.ctrl_blk, 0x03ffffe0);*/
3178cc72361SWai Yew CHAY 	hw->src_set_ca(src->rsc.ctrl_blk, 0x80);
3188cc72361SWai Yew CHAY 	hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000);
3198cc72361SWai Yew CHAY 	hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1);
3208cc72361SWai Yew CHAY 
3218cc72361SWai Yew CHAY 	dirty = hw->src_get_dirty(src->rsc.ctrl_blk);
3228cc72361SWai Yew CHAY 	src->rsc.ops->master(&src->rsc);
3238cc72361SWai Yew CHAY 	for (msr = 0; msr < src->rsc.msr; msr++) {
3248cc72361SWai Yew CHAY 		hw->src_set_dirty(src->rsc.ctrl_blk, dirty);
3258cc72361SWai Yew CHAY 		hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc),
3268cc72361SWai Yew CHAY 							src->rsc.ctrl_blk);
3278cc72361SWai Yew CHAY 		src->rsc.ops->next_conj(&src->rsc);
3288cc72361SWai Yew CHAY 	}
3298cc72361SWai Yew CHAY 	src->rsc.ops->master(&src->rsc);
3308cc72361SWai Yew CHAY 
3318cc72361SWai Yew CHAY 	return 0;
3328cc72361SWai Yew CHAY }
3338cc72361SWai Yew CHAY 
33443f2cdebSJulia Lawall static const struct src_rsc_ops src_rsc_ops = {
3358cc72361SWai Yew CHAY 	.set_state		= src_set_state,
3368cc72361SWai Yew CHAY 	.set_bm			= src_set_bm,
3378cc72361SWai Yew CHAY 	.set_sf			= src_set_sf,
3388cc72361SWai Yew CHAY 	.set_pm			= src_set_pm,
3398cc72361SWai Yew CHAY 	.set_rom		= src_set_rom,
3408cc72361SWai Yew CHAY 	.set_vo			= src_set_vo,
3418cc72361SWai Yew CHAY 	.set_st			= src_set_st,
3428cc72361SWai Yew CHAY 	.set_bp			= src_set_bp,
3438cc72361SWai Yew CHAY 	.set_cisz		= src_set_cisz,
3448cc72361SWai Yew CHAY 	.set_ca			= src_set_ca,
3458cc72361SWai Yew CHAY 	.set_sa			= src_set_sa,
3468cc72361SWai Yew CHAY 	.set_la			= src_set_la,
3478cc72361SWai Yew CHAY 	.set_pitch		= src_set_pitch,
3488cc72361SWai Yew CHAY 	.set_clr_zbufs		= src_set_clear_zbufs,
3498cc72361SWai Yew CHAY 	.commit_write		= src_commit_write,
3508cc72361SWai Yew CHAY 	.get_ca			= src_get_ca,
3518cc72361SWai Yew CHAY 	.init			= src_init,
3528cc72361SWai Yew CHAY 	.next_interleave	= src_next_interleave,
3538cc72361SWai Yew CHAY };
3548cc72361SWai Yew CHAY 
3558cc72361SWai Yew CHAY static int
src_rsc_init(struct src * src,u32 idx,const struct src_desc * desc,struct src_mgr * mgr)3568cc72361SWai Yew CHAY src_rsc_init(struct src *src, u32 idx,
3578cc72361SWai Yew CHAY 	     const struct src_desc *desc, struct src_mgr *mgr)
3588cc72361SWai Yew CHAY {
359514eef9cSTakashi Iwai 	int err;
360514eef9cSTakashi Iwai 	int i, n;
3618cc72361SWai Yew CHAY 	struct src *p;
3628cc72361SWai Yew CHAY 
3638cc72361SWai Yew CHAY 	n = (MEMRD == desc->mode) ? desc->multi : 1;
3648cc72361SWai Yew CHAY 	for (i = 0, p = src; i < n; i++, p++) {
3658cc72361SWai Yew CHAY 		err = rsc_init(&p->rsc, idx + i, SRC, desc->msr, mgr->mgr.hw);
3668cc72361SWai Yew CHAY 		if (err)
3678cc72361SWai Yew CHAY 			goto error1;
3688cc72361SWai Yew CHAY 
3698cc72361SWai Yew CHAY 		/* Initialize src specific rsc operations */
3708cc72361SWai Yew CHAY 		p->ops = &src_rsc_ops;
3718cc72361SWai Yew CHAY 		p->multi = (0 == i) ? desc->multi : 1;
3728cc72361SWai Yew CHAY 		p->mode = desc->mode;
3738cc72361SWai Yew CHAY 		src_default_config[desc->mode](p);
3748cc72361SWai Yew CHAY 		mgr->src_enable(mgr, p);
3758cc72361SWai Yew CHAY 		p->intlv = p + 1;
3768cc72361SWai Yew CHAY 	}
3778cc72361SWai Yew CHAY 	(--p)->intlv = NULL;	/* Set @intlv of the last SRC to NULL */
3788cc72361SWai Yew CHAY 
3798cc72361SWai Yew CHAY 	mgr->commit_write(mgr);
3808cc72361SWai Yew CHAY 
3818cc72361SWai Yew CHAY 	return 0;
3828cc72361SWai Yew CHAY 
3838cc72361SWai Yew CHAY error1:
3848cc72361SWai Yew CHAY 	for (i--, p--; i >= 0; i--, p--) {
3858cc72361SWai Yew CHAY 		mgr->src_disable(mgr, p);
3868cc72361SWai Yew CHAY 		rsc_uninit(&p->rsc);
3878cc72361SWai Yew CHAY 	}
3888cc72361SWai Yew CHAY 	mgr->commit_write(mgr);
3898cc72361SWai Yew CHAY 	return err;
3908cc72361SWai Yew CHAY }
3918cc72361SWai Yew CHAY 
src_rsc_uninit(struct src * src,struct src_mgr * mgr)3928cc72361SWai Yew CHAY static int src_rsc_uninit(struct src *src, struct src_mgr *mgr)
3938cc72361SWai Yew CHAY {
394514eef9cSTakashi Iwai 	int i, n;
3958cc72361SWai Yew CHAY 	struct src *p;
3968cc72361SWai Yew CHAY 
3978cc72361SWai Yew CHAY 	n = (MEMRD == src->mode) ? src->multi : 1;
3988cc72361SWai Yew CHAY 	for (i = 0, p = src; i < n; i++, p++) {
3998cc72361SWai Yew CHAY 		mgr->src_disable(mgr, p);
4008cc72361SWai Yew CHAY 		rsc_uninit(&p->rsc);
4018cc72361SWai Yew CHAY 		p->multi = 0;
4028cc72361SWai Yew CHAY 		p->ops = NULL;
4038cc72361SWai Yew CHAY 		p->mode = NUM_SRCMODES;
4048cc72361SWai Yew CHAY 		p->intlv = NULL;
4058cc72361SWai Yew CHAY 	}
4068cc72361SWai Yew CHAY 	mgr->commit_write(mgr);
4078cc72361SWai Yew CHAY 
4088cc72361SWai Yew CHAY 	return 0;
4098cc72361SWai Yew CHAY }
4108cc72361SWai Yew CHAY 
4118cc72361SWai Yew CHAY static int
get_src_rsc(struct src_mgr * mgr,const struct src_desc * desc,struct src ** rsrc)4128cc72361SWai Yew CHAY get_src_rsc(struct src_mgr *mgr, const struct src_desc *desc, struct src **rsrc)
4138cc72361SWai Yew CHAY {
4148cc72361SWai Yew CHAY 	unsigned int idx = SRC_RESOURCE_NUM;
415514eef9cSTakashi Iwai 	int err;
416514eef9cSTakashi Iwai 	struct src *src;
4178cc72361SWai Yew CHAY 	unsigned long flags;
4188cc72361SWai Yew CHAY 
4198cc72361SWai Yew CHAY 	*rsrc = NULL;
4208cc72361SWai Yew CHAY 
4218cc72361SWai Yew CHAY 	/* Check whether there are sufficient src resources to meet request. */
4228cc72361SWai Yew CHAY 	spin_lock_irqsave(&mgr->mgr_lock, flags);
4238cc72361SWai Yew CHAY 	if (MEMRD == desc->mode)
4248cc72361SWai Yew CHAY 		err = mgr_get_resource(&mgr->mgr, desc->multi, &idx);
4258cc72361SWai Yew CHAY 	else
4268cc72361SWai Yew CHAY 		err = mgr_get_resource(&mgr->mgr, 1, &idx);
4278cc72361SWai Yew CHAY 
4288cc72361SWai Yew CHAY 	spin_unlock_irqrestore(&mgr->mgr_lock, flags);
4298cc72361SWai Yew CHAY 	if (err) {
4300cae90a9SSudip Mukherjee 		dev_err(mgr->card->dev,
4310cae90a9SSudip Mukherjee 			"Can't meet SRC resource request!\n");
4328cc72361SWai Yew CHAY 		return err;
4338cc72361SWai Yew CHAY 	}
4348cc72361SWai Yew CHAY 
4358cc72361SWai Yew CHAY 	/* Allocate mem for master src resource */
4368cc72361SWai Yew CHAY 	if (MEMRD == desc->mode)
4371d5d37f4SThomas Meyer 		src = kcalloc(desc->multi, sizeof(*src), GFP_KERNEL);
4388cc72361SWai Yew CHAY 	else
4398cc72361SWai Yew CHAY 		src = kzalloc(sizeof(*src), GFP_KERNEL);
4408cc72361SWai Yew CHAY 
44135ebf6e7STakashi Iwai 	if (!src) {
4428cc72361SWai Yew CHAY 		err = -ENOMEM;
4438cc72361SWai Yew CHAY 		goto error1;
4448cc72361SWai Yew CHAY 	}
4458cc72361SWai Yew CHAY 
4468cc72361SWai Yew CHAY 	err = src_rsc_init(src, idx, desc, mgr);
4478cc72361SWai Yew CHAY 	if (err)
4488cc72361SWai Yew CHAY 		goto error2;
4498cc72361SWai Yew CHAY 
4508cc72361SWai Yew CHAY 	*rsrc = src;
4518cc72361SWai Yew CHAY 
4528cc72361SWai Yew CHAY 	return 0;
4538cc72361SWai Yew CHAY 
4548cc72361SWai Yew CHAY error2:
4558cc72361SWai Yew CHAY 	kfree(src);
4568cc72361SWai Yew CHAY error1:
4578cc72361SWai Yew CHAY 	spin_lock_irqsave(&mgr->mgr_lock, flags);
4588cc72361SWai Yew CHAY 	if (MEMRD == desc->mode)
4598cc72361SWai Yew CHAY 		mgr_put_resource(&mgr->mgr, desc->multi, idx);
4608cc72361SWai Yew CHAY 	else
4618cc72361SWai Yew CHAY 		mgr_put_resource(&mgr->mgr, 1, idx);
4628cc72361SWai Yew CHAY 
4638cc72361SWai Yew CHAY 	spin_unlock_irqrestore(&mgr->mgr_lock, flags);
4648cc72361SWai Yew CHAY 	return err;
4658cc72361SWai Yew CHAY }
4668cc72361SWai Yew CHAY 
put_src_rsc(struct src_mgr * mgr,struct src * src)4678cc72361SWai Yew CHAY static int put_src_rsc(struct src_mgr *mgr, struct src *src)
4688cc72361SWai Yew CHAY {
4698cc72361SWai Yew CHAY 	unsigned long flags;
4708cc72361SWai Yew CHAY 
4718cc72361SWai Yew CHAY 	spin_lock_irqsave(&mgr->mgr_lock, flags);
4728cc72361SWai Yew CHAY 	src->rsc.ops->master(&src->rsc);
4738cc72361SWai Yew CHAY 	if (MEMRD == src->mode)
4748cc72361SWai Yew CHAY 		mgr_put_resource(&mgr->mgr, src->multi,
4758cc72361SWai Yew CHAY 				 src->rsc.ops->index(&src->rsc));
4768cc72361SWai Yew CHAY 	else
4778cc72361SWai Yew CHAY 		mgr_put_resource(&mgr->mgr, 1, src->rsc.ops->index(&src->rsc));
4788cc72361SWai Yew CHAY 
4798cc72361SWai Yew CHAY 	spin_unlock_irqrestore(&mgr->mgr_lock, flags);
4808cc72361SWai Yew CHAY 	src_rsc_uninit(src, mgr);
4818cc72361SWai Yew CHAY 	kfree(src);
4828cc72361SWai Yew CHAY 
4838cc72361SWai Yew CHAY 	return 0;
4848cc72361SWai Yew CHAY }
4858cc72361SWai Yew CHAY 
src_enable_s(struct src_mgr * mgr,struct src * src)4868cc72361SWai Yew CHAY static int src_enable_s(struct src_mgr *mgr, struct src *src)
4878cc72361SWai Yew CHAY {
4888cc72361SWai Yew CHAY 	struct hw *hw = mgr->mgr.hw;
489514eef9cSTakashi Iwai 	int i;
4908cc72361SWai Yew CHAY 
4918cc72361SWai Yew CHAY 	src->rsc.ops->master(&src->rsc);
4928cc72361SWai Yew CHAY 	for (i = 0; i < src->rsc.msr; i++) {
4938cc72361SWai Yew CHAY 		hw->src_mgr_enbs_src(mgr->mgr.ctrl_blk,
4948cc72361SWai Yew CHAY 				     src->rsc.ops->index(&src->rsc));
4958cc72361SWai Yew CHAY 		src->rsc.ops->next_conj(&src->rsc);
4968cc72361SWai Yew CHAY 	}
4978cc72361SWai Yew CHAY 	src->rsc.ops->master(&src->rsc);
4988cc72361SWai Yew CHAY 
4998cc72361SWai Yew CHAY 	return 0;
5008cc72361SWai Yew CHAY }
5018cc72361SWai Yew CHAY 
src_enable(struct src_mgr * mgr,struct src * src)5028cc72361SWai Yew CHAY static int src_enable(struct src_mgr *mgr, struct src *src)
5038cc72361SWai Yew CHAY {
5048cc72361SWai Yew CHAY 	struct hw *hw = mgr->mgr.hw;
505514eef9cSTakashi Iwai 	int i;
5068cc72361SWai Yew CHAY 
5078cc72361SWai Yew CHAY 	src->rsc.ops->master(&src->rsc);
5088cc72361SWai Yew CHAY 	for (i = 0; i < src->rsc.msr; i++) {
5098cc72361SWai Yew CHAY 		hw->src_mgr_enb_src(mgr->mgr.ctrl_blk,
5108cc72361SWai Yew CHAY 				    src->rsc.ops->index(&src->rsc));
5118cc72361SWai Yew CHAY 		src->rsc.ops->next_conj(&src->rsc);
5128cc72361SWai Yew CHAY 	}
5138cc72361SWai Yew CHAY 	src->rsc.ops->master(&src->rsc);
5148cc72361SWai Yew CHAY 
5158cc72361SWai Yew CHAY 	return 0;
5168cc72361SWai Yew CHAY }
5178cc72361SWai Yew CHAY 
src_disable(struct src_mgr * mgr,struct src * src)5188cc72361SWai Yew CHAY static int src_disable(struct src_mgr *mgr, struct src *src)
5198cc72361SWai Yew CHAY {
5208cc72361SWai Yew CHAY 	struct hw *hw = mgr->mgr.hw;
521514eef9cSTakashi Iwai 	int i;
5228cc72361SWai Yew CHAY 
5238cc72361SWai Yew CHAY 	src->rsc.ops->master(&src->rsc);
5248cc72361SWai Yew CHAY 	for (i = 0; i < src->rsc.msr; i++) {
5258cc72361SWai Yew CHAY 		hw->src_mgr_dsb_src(mgr->mgr.ctrl_blk,
5268cc72361SWai Yew CHAY 				    src->rsc.ops->index(&src->rsc));
5278cc72361SWai Yew CHAY 		src->rsc.ops->next_conj(&src->rsc);
5288cc72361SWai Yew CHAY 	}
5298cc72361SWai Yew CHAY 	src->rsc.ops->master(&src->rsc);
5308cc72361SWai Yew CHAY 
5318cc72361SWai Yew CHAY 	return 0;
5328cc72361SWai Yew CHAY }
5338cc72361SWai Yew CHAY 
src_mgr_commit_write(struct src_mgr * mgr)5348cc72361SWai Yew CHAY static int src_mgr_commit_write(struct src_mgr *mgr)
5358cc72361SWai Yew CHAY {
5368cc72361SWai Yew CHAY 	struct hw *hw = mgr->mgr.hw;
5378cc72361SWai Yew CHAY 
5388cc72361SWai Yew CHAY 	hw->src_mgr_commit_write(hw, mgr->mgr.ctrl_blk);
5398cc72361SWai Yew CHAY 
5408cc72361SWai Yew CHAY 	return 0;
5418cc72361SWai Yew CHAY }
5428cc72361SWai Yew CHAY 
src_mgr_create(struct hw * hw,struct src_mgr ** rsrc_mgr)54366640898SSudip Mukherjee int src_mgr_create(struct hw *hw, struct src_mgr **rsrc_mgr)
5448cc72361SWai Yew CHAY {
545514eef9cSTakashi Iwai 	int err, i;
5468cc72361SWai Yew CHAY 	struct src_mgr *src_mgr;
5478cc72361SWai Yew CHAY 
5488cc72361SWai Yew CHAY 	*rsrc_mgr = NULL;
5498cc72361SWai Yew CHAY 	src_mgr = kzalloc(sizeof(*src_mgr), GFP_KERNEL);
55035ebf6e7STakashi Iwai 	if (!src_mgr)
5518cc72361SWai Yew CHAY 		return -ENOMEM;
5528cc72361SWai Yew CHAY 
5538cc72361SWai Yew CHAY 	err = rsc_mgr_init(&src_mgr->mgr, SRC, SRC_RESOURCE_NUM, hw);
5548cc72361SWai Yew CHAY 	if (err)
5558cc72361SWai Yew CHAY 		goto error1;
5568cc72361SWai Yew CHAY 
5578cc72361SWai Yew CHAY 	spin_lock_init(&src_mgr->mgr_lock);
558b6bfe86fSSudip Mukherjee 	conj_mask = hw->src_dirty_conj_mask();
5598cc72361SWai Yew CHAY 
5608cc72361SWai Yew CHAY 	src_mgr->get_src = get_src_rsc;
5618cc72361SWai Yew CHAY 	src_mgr->put_src = put_src_rsc;
5628cc72361SWai Yew CHAY 	src_mgr->src_enable_s = src_enable_s;
5638cc72361SWai Yew CHAY 	src_mgr->src_enable = src_enable;
5648cc72361SWai Yew CHAY 	src_mgr->src_disable = src_disable;
5658cc72361SWai Yew CHAY 	src_mgr->commit_write = src_mgr_commit_write;
566e5347f9aSSudip Mukherjee 	src_mgr->card = hw->card;
5678cc72361SWai Yew CHAY 
5688cc72361SWai Yew CHAY 	/* Disable all SRC resources. */
5698cc72361SWai Yew CHAY 	for (i = 0; i < 256; i++)
570b6bfe86fSSudip Mukherjee 		hw->src_mgr_dsb_src(src_mgr->mgr.ctrl_blk, i);
5718cc72361SWai Yew CHAY 
572b6bfe86fSSudip Mukherjee 	hw->src_mgr_commit_write(hw, src_mgr->mgr.ctrl_blk);
5738cc72361SWai Yew CHAY 
5748cc72361SWai Yew CHAY 	*rsrc_mgr = src_mgr;
5758cc72361SWai Yew CHAY 
5768cc72361SWai Yew CHAY 	return 0;
5778cc72361SWai Yew CHAY 
5788cc72361SWai Yew CHAY error1:
5798cc72361SWai Yew CHAY 	kfree(src_mgr);
5808cc72361SWai Yew CHAY 	return err;
5818cc72361SWai Yew CHAY }
5828cc72361SWai Yew CHAY 
src_mgr_destroy(struct src_mgr * src_mgr)5838cc72361SWai Yew CHAY int src_mgr_destroy(struct src_mgr *src_mgr)
5848cc72361SWai Yew CHAY {
5858cc72361SWai Yew CHAY 	rsc_mgr_uninit(&src_mgr->mgr);
5868cc72361SWai Yew CHAY 	kfree(src_mgr);
5878cc72361SWai Yew CHAY 
5888cc72361SWai Yew CHAY 	return 0;
5898cc72361SWai Yew CHAY }
5908cc72361SWai Yew CHAY 
5918cc72361SWai Yew CHAY /* SRCIMP resource manager operations */
5928cc72361SWai Yew CHAY 
srcimp_master(struct rsc * rsc)593*25aa8e9fSTakashi Iwai static void srcimp_master(struct rsc *rsc)
5948cc72361SWai Yew CHAY {
5958cc72361SWai Yew CHAY 	rsc->conj = 0;
596*25aa8e9fSTakashi Iwai 	rsc->idx = container_of(rsc, struct srcimp, rsc)->idx[0];
5978cc72361SWai Yew CHAY }
5988cc72361SWai Yew CHAY 
srcimp_next_conj(struct rsc * rsc)599*25aa8e9fSTakashi Iwai static void srcimp_next_conj(struct rsc *rsc)
6008cc72361SWai Yew CHAY {
6018cc72361SWai Yew CHAY 	rsc->conj++;
6028cc72361SWai Yew CHAY }
6038cc72361SWai Yew CHAY 
srcimp_index(const struct rsc * rsc)6048cc72361SWai Yew CHAY static int srcimp_index(const struct rsc *rsc)
6058cc72361SWai Yew CHAY {
6068cc72361SWai Yew CHAY 	return container_of(rsc, struct srcimp, rsc)->idx[rsc->conj];
6078cc72361SWai Yew CHAY }
6088cc72361SWai Yew CHAY 
60943f2cdebSJulia Lawall static const struct rsc_ops srcimp_basic_rsc_ops = {
6108cc72361SWai Yew CHAY 	.master		= srcimp_master,
6118cc72361SWai Yew CHAY 	.next_conj	= srcimp_next_conj,
6128cc72361SWai Yew CHAY 	.index		= srcimp_index,
6138cc72361SWai Yew CHAY 	.output_slot	= NULL,
6148cc72361SWai Yew CHAY };
6158cc72361SWai Yew CHAY 
srcimp_map(struct srcimp * srcimp,struct src * src,struct rsc * input)6168cc72361SWai Yew CHAY static int srcimp_map(struct srcimp *srcimp, struct src *src, struct rsc *input)
6178cc72361SWai Yew CHAY {
618514eef9cSTakashi Iwai 	struct imapper *entry;
619514eef9cSTakashi Iwai 	int i;
6208cc72361SWai Yew CHAY 
6218cc72361SWai Yew CHAY 	srcimp->rsc.ops->master(&srcimp->rsc);
6228cc72361SWai Yew CHAY 	src->rsc.ops->master(&src->rsc);
6238cc72361SWai Yew CHAY 	input->ops->master(input);
6248cc72361SWai Yew CHAY 
6258cc72361SWai Yew CHAY 	/* Program master and conjugate resources */
6268cc72361SWai Yew CHAY 	for (i = 0; i < srcimp->rsc.msr; i++) {
6278cc72361SWai Yew CHAY 		entry = &srcimp->imappers[i];
6288cc72361SWai Yew CHAY 		entry->slot = input->ops->output_slot(input);
6298cc72361SWai Yew CHAY 		entry->user = src->rsc.ops->index(&src->rsc);
6308cc72361SWai Yew CHAY 		entry->addr = srcimp->rsc.ops->index(&srcimp->rsc);
6318cc72361SWai Yew CHAY 		srcimp->mgr->imap_add(srcimp->mgr, entry);
6328cc72361SWai Yew CHAY 		srcimp->mapped |= (0x1 << i);
6338cc72361SWai Yew CHAY 
6348cc72361SWai Yew CHAY 		srcimp->rsc.ops->next_conj(&srcimp->rsc);
6358cc72361SWai Yew CHAY 		input->ops->next_conj(input);
6368cc72361SWai Yew CHAY 	}
6378cc72361SWai Yew CHAY 
6388cc72361SWai Yew CHAY 	srcimp->rsc.ops->master(&srcimp->rsc);
6398cc72361SWai Yew CHAY 	input->ops->master(input);
6408cc72361SWai Yew CHAY 
6418cc72361SWai Yew CHAY 	return 0;
6428cc72361SWai Yew CHAY }
6438cc72361SWai Yew CHAY 
srcimp_unmap(struct srcimp * srcimp)6448cc72361SWai Yew CHAY static int srcimp_unmap(struct srcimp *srcimp)
6458cc72361SWai Yew CHAY {
646514eef9cSTakashi Iwai 	int i;
6478cc72361SWai Yew CHAY 
6488cc72361SWai Yew CHAY 	/* Program master and conjugate resources */
6498cc72361SWai Yew CHAY 	for (i = 0; i < srcimp->rsc.msr; i++) {
6508cc72361SWai Yew CHAY 		if (srcimp->mapped & (0x1 << i)) {
6518cc72361SWai Yew CHAY 			srcimp->mgr->imap_delete(srcimp->mgr,
6528cc72361SWai Yew CHAY 						 &srcimp->imappers[i]);
6538cc72361SWai Yew CHAY 			srcimp->mapped &= ~(0x1 << i);
6548cc72361SWai Yew CHAY 		}
6558cc72361SWai Yew CHAY 	}
6568cc72361SWai Yew CHAY 
6578cc72361SWai Yew CHAY 	return 0;
6588cc72361SWai Yew CHAY }
6598cc72361SWai Yew CHAY 
66043f2cdebSJulia Lawall static const struct srcimp_rsc_ops srcimp_ops = {
6618cc72361SWai Yew CHAY 	.map = srcimp_map,
6628cc72361SWai Yew CHAY 	.unmap = srcimp_unmap
6638cc72361SWai Yew CHAY };
6648cc72361SWai Yew CHAY 
srcimp_rsc_init(struct srcimp * srcimp,const struct srcimp_desc * desc,struct srcimp_mgr * mgr)6658cc72361SWai Yew CHAY static int srcimp_rsc_init(struct srcimp *srcimp,
6668cc72361SWai Yew CHAY 			   const struct srcimp_desc *desc,
6678cc72361SWai Yew CHAY 			   struct srcimp_mgr *mgr)
6688cc72361SWai Yew CHAY {
669514eef9cSTakashi Iwai 	int err;
6708cc72361SWai Yew CHAY 
6718cc72361SWai Yew CHAY 	err = rsc_init(&srcimp->rsc, srcimp->idx[0],
6728cc72361SWai Yew CHAY 		       SRCIMP, desc->msr, mgr->mgr.hw);
6738cc72361SWai Yew CHAY 	if (err)
6748cc72361SWai Yew CHAY 		return err;
6758cc72361SWai Yew CHAY 
6768cc72361SWai Yew CHAY 	/* Reserve memory for imapper nodes */
6776396bb22SKees Cook 	srcimp->imappers = kcalloc(desc->msr, sizeof(struct imapper),
6788cc72361SWai Yew CHAY 				   GFP_KERNEL);
67935ebf6e7STakashi Iwai 	if (!srcimp->imappers) {
6808cc72361SWai Yew CHAY 		err = -ENOMEM;
6818cc72361SWai Yew CHAY 		goto error1;
6828cc72361SWai Yew CHAY 	}
6838cc72361SWai Yew CHAY 
6848cc72361SWai Yew CHAY 	/* Set srcimp specific operations */
6858cc72361SWai Yew CHAY 	srcimp->rsc.ops = &srcimp_basic_rsc_ops;
6868cc72361SWai Yew CHAY 	srcimp->ops = &srcimp_ops;
6878cc72361SWai Yew CHAY 	srcimp->mgr = mgr;
6888cc72361SWai Yew CHAY 
6898cc72361SWai Yew CHAY 	srcimp->rsc.ops->master(&srcimp->rsc);
6908cc72361SWai Yew CHAY 
6918cc72361SWai Yew CHAY 	return 0;
6928cc72361SWai Yew CHAY 
6938cc72361SWai Yew CHAY error1:
6948cc72361SWai Yew CHAY 	rsc_uninit(&srcimp->rsc);
6958cc72361SWai Yew CHAY 	return err;
6968cc72361SWai Yew CHAY }
6978cc72361SWai Yew CHAY 
srcimp_rsc_uninit(struct srcimp * srcimp)6988cc72361SWai Yew CHAY static int srcimp_rsc_uninit(struct srcimp *srcimp)
6998cc72361SWai Yew CHAY {
7008cc72361SWai Yew CHAY 	kfree(srcimp->imappers);
7018cc72361SWai Yew CHAY 	srcimp->imappers = NULL;
7028cc72361SWai Yew CHAY 	srcimp->ops = NULL;
7038cc72361SWai Yew CHAY 	srcimp->mgr = NULL;
7048cc72361SWai Yew CHAY 	rsc_uninit(&srcimp->rsc);
7058cc72361SWai Yew CHAY 
7068cc72361SWai Yew CHAY 	return 0;
7078cc72361SWai Yew CHAY }
7088cc72361SWai Yew CHAY 
get_srcimp_rsc(struct srcimp_mgr * mgr,const struct srcimp_desc * desc,struct srcimp ** rsrcimp)7098cc72361SWai Yew CHAY static int get_srcimp_rsc(struct srcimp_mgr *mgr,
7108cc72361SWai Yew CHAY 			  const struct srcimp_desc *desc,
7118cc72361SWai Yew CHAY 			  struct srcimp **rsrcimp)
7128cc72361SWai Yew CHAY {
713514eef9cSTakashi Iwai 	int err, i;
714514eef9cSTakashi Iwai 	unsigned int idx;
715514eef9cSTakashi Iwai 	struct srcimp *srcimp;
7168cc72361SWai Yew CHAY 	unsigned long flags;
7178cc72361SWai Yew CHAY 
7188cc72361SWai Yew CHAY 	*rsrcimp = NULL;
7198cc72361SWai Yew CHAY 
7208cc72361SWai Yew CHAY 	/* Allocate mem for SRCIMP resource */
7218cc72361SWai Yew CHAY 	srcimp = kzalloc(sizeof(*srcimp), GFP_KERNEL);
72268110661STakashi Iwai 	if (!srcimp)
72368110661STakashi Iwai 		return -ENOMEM;
7248cc72361SWai Yew CHAY 
7258cc72361SWai Yew CHAY 	/* Check whether there are sufficient SRCIMP resources. */
72668110661STakashi Iwai 	err = 0;
7278cc72361SWai Yew CHAY 	spin_lock_irqsave(&mgr->mgr_lock, flags);
7288cc72361SWai Yew CHAY 	for (i = 0; i < desc->msr; i++) {
7298cc72361SWai Yew CHAY 		err = mgr_get_resource(&mgr->mgr, 1, &idx);
7308cc72361SWai Yew CHAY 		if (err)
7318cc72361SWai Yew CHAY 			break;
7328cc72361SWai Yew CHAY 
7338cc72361SWai Yew CHAY 		srcimp->idx[i] = idx;
7348cc72361SWai Yew CHAY 	}
7358cc72361SWai Yew CHAY 	spin_unlock_irqrestore(&mgr->mgr_lock, flags);
7368cc72361SWai Yew CHAY 	if (err) {
7370cae90a9SSudip Mukherjee 		dev_err(mgr->card->dev,
7380cae90a9SSudip Mukherjee 			"Can't meet SRCIMP resource request!\n");
7398cc72361SWai Yew CHAY 		goto error1;
7408cc72361SWai Yew CHAY 	}
7418cc72361SWai Yew CHAY 
7428cc72361SWai Yew CHAY 	err = srcimp_rsc_init(srcimp, desc, mgr);
7438cc72361SWai Yew CHAY 	if (err)
7448cc72361SWai Yew CHAY 		goto error1;
7458cc72361SWai Yew CHAY 
7468cc72361SWai Yew CHAY 	*rsrcimp = srcimp;
7478cc72361SWai Yew CHAY 
7488cc72361SWai Yew CHAY 	return 0;
7498cc72361SWai Yew CHAY 
7508cc72361SWai Yew CHAY error1:
7518cc72361SWai Yew CHAY 	spin_lock_irqsave(&mgr->mgr_lock, flags);
7528cc72361SWai Yew CHAY 	for (i--; i >= 0; i--)
7538cc72361SWai Yew CHAY 		mgr_put_resource(&mgr->mgr, 1, srcimp->idx[i]);
7548cc72361SWai Yew CHAY 
7558cc72361SWai Yew CHAY 	spin_unlock_irqrestore(&mgr->mgr_lock, flags);
7568cc72361SWai Yew CHAY 	kfree(srcimp);
7578cc72361SWai Yew CHAY 	return err;
7588cc72361SWai Yew CHAY }
7598cc72361SWai Yew CHAY 
put_srcimp_rsc(struct srcimp_mgr * mgr,struct srcimp * srcimp)7608cc72361SWai Yew CHAY static int put_srcimp_rsc(struct srcimp_mgr *mgr, struct srcimp *srcimp)
7618cc72361SWai Yew CHAY {
7628cc72361SWai Yew CHAY 	unsigned long flags;
763514eef9cSTakashi Iwai 	int i;
7648cc72361SWai Yew CHAY 
7658cc72361SWai Yew CHAY 	spin_lock_irqsave(&mgr->mgr_lock, flags);
7668cc72361SWai Yew CHAY 	for (i = 0; i < srcimp->rsc.msr; i++)
7678cc72361SWai Yew CHAY 		mgr_put_resource(&mgr->mgr, 1, srcimp->idx[i]);
7688cc72361SWai Yew CHAY 
7698cc72361SWai Yew CHAY 	spin_unlock_irqrestore(&mgr->mgr_lock, flags);
7708cc72361SWai Yew CHAY 	srcimp_rsc_uninit(srcimp);
7718cc72361SWai Yew CHAY 	kfree(srcimp);
7728cc72361SWai Yew CHAY 
7738cc72361SWai Yew CHAY 	return 0;
7748cc72361SWai Yew CHAY }
7758cc72361SWai Yew CHAY 
srcimp_map_op(void * data,struct imapper * entry)7768cc72361SWai Yew CHAY static int srcimp_map_op(void *data, struct imapper *entry)
7778cc72361SWai Yew CHAY {
7788cc72361SWai Yew CHAY 	struct rsc_mgr *mgr = &((struct srcimp_mgr *)data)->mgr;
7798cc72361SWai Yew CHAY 	struct hw *hw = mgr->hw;
7808cc72361SWai Yew CHAY 
7818cc72361SWai Yew CHAY 	hw->srcimp_mgr_set_imaparc(mgr->ctrl_blk, entry->slot);
7828cc72361SWai Yew CHAY 	hw->srcimp_mgr_set_imapuser(mgr->ctrl_blk, entry->user);
7838cc72361SWai Yew CHAY 	hw->srcimp_mgr_set_imapnxt(mgr->ctrl_blk, entry->next);
7848cc72361SWai Yew CHAY 	hw->srcimp_mgr_set_imapaddr(mgr->ctrl_blk, entry->addr);
7858cc72361SWai Yew CHAY 	hw->srcimp_mgr_commit_write(mgr->hw, mgr->ctrl_blk);
7868cc72361SWai Yew CHAY 
7878cc72361SWai Yew CHAY 	return 0;
7888cc72361SWai Yew CHAY }
7898cc72361SWai Yew CHAY 
srcimp_imap_add(struct srcimp_mgr * mgr,struct imapper * entry)7908cc72361SWai Yew CHAY static int srcimp_imap_add(struct srcimp_mgr *mgr, struct imapper *entry)
7918cc72361SWai Yew CHAY {
7928cc72361SWai Yew CHAY 	unsigned long flags;
793514eef9cSTakashi Iwai 	int err;
7948cc72361SWai Yew CHAY 
7958cc72361SWai Yew CHAY 	spin_lock_irqsave(&mgr->imap_lock, flags);
7968cc72361SWai Yew CHAY 	if ((0 == entry->addr) && (mgr->init_imap_added)) {
7978cc72361SWai Yew CHAY 		input_mapper_delete(&mgr->imappers,
7988cc72361SWai Yew CHAY 				    mgr->init_imap, srcimp_map_op, mgr);
7998cc72361SWai Yew CHAY 		mgr->init_imap_added = 0;
8008cc72361SWai Yew CHAY 	}
8018cc72361SWai Yew CHAY 	err = input_mapper_add(&mgr->imappers, entry, srcimp_map_op, mgr);
8028cc72361SWai Yew CHAY 	spin_unlock_irqrestore(&mgr->imap_lock, flags);
8038cc72361SWai Yew CHAY 
8048cc72361SWai Yew CHAY 	return err;
8058cc72361SWai Yew CHAY }
8068cc72361SWai Yew CHAY 
srcimp_imap_delete(struct srcimp_mgr * mgr,struct imapper * entry)8078cc72361SWai Yew CHAY static int srcimp_imap_delete(struct srcimp_mgr *mgr, struct imapper *entry)
8088cc72361SWai Yew CHAY {
8098cc72361SWai Yew CHAY 	unsigned long flags;
810514eef9cSTakashi Iwai 	int err;
8118cc72361SWai Yew CHAY 
8128cc72361SWai Yew CHAY 	spin_lock_irqsave(&mgr->imap_lock, flags);
8138cc72361SWai Yew CHAY 	err = input_mapper_delete(&mgr->imappers, entry, srcimp_map_op, mgr);
8148cc72361SWai Yew CHAY 	if (list_empty(&mgr->imappers)) {
8158cc72361SWai Yew CHAY 		input_mapper_add(&mgr->imappers, mgr->init_imap,
8168cc72361SWai Yew CHAY 				 srcimp_map_op, mgr);
8178cc72361SWai Yew CHAY 		mgr->init_imap_added = 1;
8188cc72361SWai Yew CHAY 	}
8198cc72361SWai Yew CHAY 	spin_unlock_irqrestore(&mgr->imap_lock, flags);
8208cc72361SWai Yew CHAY 
8218cc72361SWai Yew CHAY 	return err;
8228cc72361SWai Yew CHAY }
8238cc72361SWai Yew CHAY 
srcimp_mgr_create(struct hw * hw,struct srcimp_mgr ** rsrcimp_mgr)82466640898SSudip Mukherjee int srcimp_mgr_create(struct hw *hw, struct srcimp_mgr **rsrcimp_mgr)
8258cc72361SWai Yew CHAY {
826514eef9cSTakashi Iwai 	int err;
8278cc72361SWai Yew CHAY 	struct srcimp_mgr *srcimp_mgr;
8288cc72361SWai Yew CHAY 	struct imapper *entry;
8298cc72361SWai Yew CHAY 
8308cc72361SWai Yew CHAY 	*rsrcimp_mgr = NULL;
8318cc72361SWai Yew CHAY 	srcimp_mgr = kzalloc(sizeof(*srcimp_mgr), GFP_KERNEL);
83235ebf6e7STakashi Iwai 	if (!srcimp_mgr)
8338cc72361SWai Yew CHAY 		return -ENOMEM;
8348cc72361SWai Yew CHAY 
8358cc72361SWai Yew CHAY 	err = rsc_mgr_init(&srcimp_mgr->mgr, SRCIMP, SRCIMP_RESOURCE_NUM, hw);
8368cc72361SWai Yew CHAY 	if (err)
8378cc72361SWai Yew CHAY 		goto error1;
8388cc72361SWai Yew CHAY 
8398cc72361SWai Yew CHAY 	spin_lock_init(&srcimp_mgr->mgr_lock);
8408cc72361SWai Yew CHAY 	spin_lock_init(&srcimp_mgr->imap_lock);
8418cc72361SWai Yew CHAY 	INIT_LIST_HEAD(&srcimp_mgr->imappers);
8428cc72361SWai Yew CHAY 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
84335ebf6e7STakashi Iwai 	if (!entry) {
8448cc72361SWai Yew CHAY 		err = -ENOMEM;
8458cc72361SWai Yew CHAY 		goto error2;
8468cc72361SWai Yew CHAY 	}
8478cc72361SWai Yew CHAY 	entry->slot = entry->addr = entry->next = entry->user = 0;
8488cc72361SWai Yew CHAY 	list_add(&entry->list, &srcimp_mgr->imappers);
8498cc72361SWai Yew CHAY 	srcimp_mgr->init_imap = entry;
8508cc72361SWai Yew CHAY 	srcimp_mgr->init_imap_added = 1;
8518cc72361SWai Yew CHAY 
8528cc72361SWai Yew CHAY 	srcimp_mgr->get_srcimp = get_srcimp_rsc;
8538cc72361SWai Yew CHAY 	srcimp_mgr->put_srcimp = put_srcimp_rsc;
8548cc72361SWai Yew CHAY 	srcimp_mgr->imap_add = srcimp_imap_add;
8558cc72361SWai Yew CHAY 	srcimp_mgr->imap_delete = srcimp_imap_delete;
856e5347f9aSSudip Mukherjee 	srcimp_mgr->card = hw->card;
8578cc72361SWai Yew CHAY 
8588cc72361SWai Yew CHAY 	*rsrcimp_mgr = srcimp_mgr;
8598cc72361SWai Yew CHAY 
8608cc72361SWai Yew CHAY 	return 0;
8618cc72361SWai Yew CHAY 
8628cc72361SWai Yew CHAY error2:
8638cc72361SWai Yew CHAY 	rsc_mgr_uninit(&srcimp_mgr->mgr);
8648cc72361SWai Yew CHAY error1:
8658cc72361SWai Yew CHAY 	kfree(srcimp_mgr);
8668cc72361SWai Yew CHAY 	return err;
8678cc72361SWai Yew CHAY }
8688cc72361SWai Yew CHAY 
srcimp_mgr_destroy(struct srcimp_mgr * srcimp_mgr)8698cc72361SWai Yew CHAY int srcimp_mgr_destroy(struct srcimp_mgr *srcimp_mgr)
8708cc72361SWai Yew CHAY {
8718cc72361SWai Yew CHAY 	unsigned long flags;
8728cc72361SWai Yew CHAY 
8738cc72361SWai Yew CHAY 	/* free src input mapper list */
8748cc72361SWai Yew CHAY 	spin_lock_irqsave(&srcimp_mgr->imap_lock, flags);
8758cc72361SWai Yew CHAY 	free_input_mapper_list(&srcimp_mgr->imappers);
8768cc72361SWai Yew CHAY 	spin_unlock_irqrestore(&srcimp_mgr->imap_lock, flags);
8778cc72361SWai Yew CHAY 
8788cc72361SWai Yew CHAY 	rsc_mgr_uninit(&srcimp_mgr->mgr);
8798cc72361SWai Yew CHAY 	kfree(srcimp_mgr);
8808cc72361SWai Yew CHAY 
8818cc72361SWai Yew CHAY 	return 0;
8828cc72361SWai Yew CHAY }
883