xref: /openbmc/linux/sound/pci/ctxfi/ctimap.c (revision 514eef9c2a711b4c24b97bb456d39695a6fe1775)
18cc72361SWai Yew CHAY /**
28cc72361SWai Yew CHAY  * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
38cc72361SWai Yew CHAY  *
48cc72361SWai Yew CHAY  * This source file is released under GPL v2 license (no other versions).
58cc72361SWai Yew CHAY  * See the COPYING file included in the main directory of this source
68cc72361SWai Yew CHAY  * distribution for the license terms and conditions.
78cc72361SWai Yew CHAY  *
88cc72361SWai Yew CHAY  * @File	ctimap.c
98cc72361SWai Yew CHAY  *
108cc72361SWai Yew CHAY  * @Brief
118cc72361SWai Yew CHAY  * This file contains the implementation of generic input mapper operations
128cc72361SWai Yew CHAY  * for input mapper management.
138cc72361SWai Yew CHAY  *
148cc72361SWai Yew CHAY  * @Author	Liu Chun
158cc72361SWai Yew CHAY  * @Date 	May 23 2008
168cc72361SWai Yew CHAY  *
178cc72361SWai Yew CHAY  */
188cc72361SWai Yew CHAY 
198cc72361SWai Yew CHAY #include "ctimap.h"
208cc72361SWai Yew CHAY #include <linux/slab.h>
218cc72361SWai Yew CHAY 
228cc72361SWai Yew CHAY int input_mapper_add(struct list_head *mappers, struct imapper *entry,
238cc72361SWai Yew CHAY 		     int (*map_op)(void *, struct imapper *), void *data)
248cc72361SWai Yew CHAY {
258cc72361SWai Yew CHAY 	struct list_head *pos, *pre, *head;
268cc72361SWai Yew CHAY 	struct imapper *pre_ent, *pos_ent;
278cc72361SWai Yew CHAY 
288cc72361SWai Yew CHAY 	head = mappers;
298cc72361SWai Yew CHAY 
308cc72361SWai Yew CHAY 	if (list_empty(head)) {
318cc72361SWai Yew CHAY 		entry->next = entry->addr;
328cc72361SWai Yew CHAY 		map_op(data, entry);
338cc72361SWai Yew CHAY 		list_add(&entry->list, head);
348cc72361SWai Yew CHAY 		return 0;
358cc72361SWai Yew CHAY 	}
368cc72361SWai Yew CHAY 
378cc72361SWai Yew CHAY 	list_for_each(pos, head) {
388cc72361SWai Yew CHAY 		pos_ent = list_entry(pos, struct imapper, list);
398cc72361SWai Yew CHAY 		if (pos_ent->slot > entry->slot) {
408cc72361SWai Yew CHAY 			/* found a position in list */
418cc72361SWai Yew CHAY 			break;
428cc72361SWai Yew CHAY 		}
438cc72361SWai Yew CHAY 	}
448cc72361SWai Yew CHAY 
458cc72361SWai Yew CHAY 	if (pos != head) {
468cc72361SWai Yew CHAY 		pre = pos->prev;
478cc72361SWai Yew CHAY 		if (pre == head)
488cc72361SWai Yew CHAY 			pre = head->prev;
498cc72361SWai Yew CHAY 
508cc72361SWai Yew CHAY 		__list_add(&entry->list, pos->prev, pos);
518cc72361SWai Yew CHAY 	} else {
528cc72361SWai Yew CHAY 		pre = head->prev;
538cc72361SWai Yew CHAY 		pos = head->next;
548cc72361SWai Yew CHAY 		list_add_tail(&entry->list, head);
558cc72361SWai Yew CHAY 	}
568cc72361SWai Yew CHAY 
578cc72361SWai Yew CHAY 	pre_ent = list_entry(pre, struct imapper, list);
588cc72361SWai Yew CHAY 	pos_ent = list_entry(pos, struct imapper, list);
598cc72361SWai Yew CHAY 
608cc72361SWai Yew CHAY 	entry->next = pos_ent->addr;
618cc72361SWai Yew CHAY 	map_op(data, entry);
628cc72361SWai Yew CHAY 	pre_ent->next = entry->addr;
638cc72361SWai Yew CHAY 	map_op(data, pre_ent);
648cc72361SWai Yew CHAY 
658cc72361SWai Yew CHAY 	return 0;
668cc72361SWai Yew CHAY }
678cc72361SWai Yew CHAY 
688cc72361SWai Yew CHAY int input_mapper_delete(struct list_head *mappers, struct imapper *entry,
698cc72361SWai Yew CHAY 		     int (*map_op)(void *, struct imapper *), void *data)
708cc72361SWai Yew CHAY {
718cc72361SWai Yew CHAY 	struct list_head *next, *pre, *head;
728cc72361SWai Yew CHAY 	struct imapper *pre_ent, *next_ent;
738cc72361SWai Yew CHAY 
748cc72361SWai Yew CHAY 	head = mappers;
758cc72361SWai Yew CHAY 
768cc72361SWai Yew CHAY 	if (list_empty(head))
778cc72361SWai Yew CHAY 		return 0;
788cc72361SWai Yew CHAY 
798cc72361SWai Yew CHAY 	pre = (entry->list.prev == head) ? head->prev : entry->list.prev;
808cc72361SWai Yew CHAY 	next = (entry->list.next == head) ? head->next : entry->list.next;
818cc72361SWai Yew CHAY 
828cc72361SWai Yew CHAY 	if (pre == &entry->list) {
838cc72361SWai Yew CHAY 		/* entry is the only one node in mappers list */
848cc72361SWai Yew CHAY 		entry->next = entry->addr = entry->user = entry->slot = 0;
858cc72361SWai Yew CHAY 		map_op(data, entry);
868cc72361SWai Yew CHAY 		list_del(&entry->list);
878cc72361SWai Yew CHAY 		return 0;
888cc72361SWai Yew CHAY 	}
898cc72361SWai Yew CHAY 
908cc72361SWai Yew CHAY 	pre_ent = list_entry(pre, struct imapper, list);
918cc72361SWai Yew CHAY 	next_ent = list_entry(next, struct imapper, list);
928cc72361SWai Yew CHAY 
938cc72361SWai Yew CHAY 	pre_ent->next = next_ent->addr;
948cc72361SWai Yew CHAY 	map_op(data, pre_ent);
958cc72361SWai Yew CHAY 	list_del(&entry->list);
968cc72361SWai Yew CHAY 
978cc72361SWai Yew CHAY 	return 0;
988cc72361SWai Yew CHAY }
998cc72361SWai Yew CHAY 
1008cc72361SWai Yew CHAY void free_input_mapper_list(struct list_head *head)
1018cc72361SWai Yew CHAY {
102*514eef9cSTakashi Iwai 	struct imapper *entry;
103*514eef9cSTakashi Iwai 	struct list_head *pos;
1048cc72361SWai Yew CHAY 
1058cc72361SWai Yew CHAY 	while (!list_empty(head)) {
1068cc72361SWai Yew CHAY 		pos = head->next;
1078cc72361SWai Yew CHAY 		list_del(pos);
1088cc72361SWai Yew CHAY 		entry = list_entry(pos, struct imapper, list);
1098cc72361SWai Yew CHAY 		kfree(entry);
1108cc72361SWai Yew CHAY 	}
1118cc72361SWai Yew CHAY }
1128cc72361SWai Yew CHAY 
113