summaryrefslogtreecommitdiff
path: root/drivers/video/b2r2/b2r2_node_gen.c
blob: 1f48bac6fe7d40ffcc7234339132a328c1470874 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/*
 * Copyright (C) ST-Ericsson SA 2010
 *
 * ST-Ericsson B2R2 node generator
 *
 * Author: Robert Fekete <robert.fekete@stericsson.com>
 * Author: Paul Wannback
 * for ST-Ericsson.
 *
 * License terms: GNU General Public License (GPL), version 2.
 */

#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <asm/dma-mapping.h>
#include "b2r2_internal.h"

static void free_nodes(struct b2r2_control *cont,
		struct b2r2_node *first_node)
{
	struct b2r2_node *node = first_node;
	int no_of_nodes = 0;

	while (node) {
		no_of_nodes++;
		node = node->next;
	}

	dma_free_coherent(cont->dev,
			no_of_nodes * sizeof(struct b2r2_node),
			first_node,
			first_node->physical_address -
			offsetof(struct b2r2_node, node));
}

struct b2r2_node *b2r2_blt_alloc_nodes(struct b2r2_control *cont,
		int no_of_nodes)
{
	u32 physical_address;
	struct b2r2_node *nodes;
	struct b2r2_node *tmpnode;

	if (no_of_nodes <= 0) {
		dev_err(cont->dev, "%s: Wrong number of nodes (%d)",
				__func__, no_of_nodes);
		return NULL;
	}

	/* Allocate the memory */
	nodes = (struct b2r2_node *) dma_alloc_coherent(cont->dev,
			no_of_nodes * sizeof(struct b2r2_node),
			&physical_address, GFP_DMA | GFP_KERNEL);

	if (nodes == NULL) {
		dev_err(cont->dev,
				"%s: Failed to alloc memory for nodes",
				__func__);
		return NULL;
	}

	/* Build the linked list */
	tmpnode = nodes;
	physical_address += offsetof(struct b2r2_node, node);
	while (no_of_nodes--) {
		tmpnode->physical_address = physical_address;
		if (no_of_nodes)
			tmpnode->next = tmpnode + 1;
		else
			tmpnode->next = NULL;

		tmpnode++;
		physical_address += sizeof(struct b2r2_node);
	}

	return nodes;
}

void b2r2_blt_free_nodes(struct b2r2_control *cont,
		struct b2r2_node *first_node)
{
	free_nodes(cont, first_node);
}