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