1 /*
2  * Support for Intel Camera Imaging ISP subsystem.
3  * Copyright (c) 2015, Intel Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  */
14 
15 #include "system_global.h"
16 
17 #include "assert_support.h"
18 #include "platform_support.h"
19 #include "ia_css_isys.h"
20 #include "ibuf_ctrl_rmgr.h"
21 
22 static ibuf_rsrc_t	ibuf_rsrc;
23 
24 static ibuf_handle_t *getHandle(uint16_t index)
25 {
26 	ibuf_handle_t *handle = NULL;
27 
28 	if (index < MAX_IBUF_HANDLES)
29 		handle = &ibuf_rsrc.handles[index];
30 	return handle;
31 }
32 
33 void ia_css_isys_ibuf_rmgr_init(void)
34 {
35 	memset(&ibuf_rsrc, 0, sizeof(ibuf_rsrc));
36 	ibuf_rsrc.free_size = MAX_INPUT_BUFFER_SIZE;
37 }
38 
39 void ia_css_isys_ibuf_rmgr_uninit(void)
40 {
41 	memset(&ibuf_rsrc, 0, sizeof(ibuf_rsrc));
42 	ibuf_rsrc.free_size = MAX_INPUT_BUFFER_SIZE;
43 }
44 
45 bool ia_css_isys_ibuf_rmgr_acquire(
46     u32	size,
47     uint32_t	*start_addr)
48 {
49 	bool retval = false;
50 	bool input_buffer_found = false;
51 	u32 aligned_size;
52 	ibuf_handle_t *handle = NULL;
53 	u16 i;
54 
55 	assert(start_addr);
56 	assert(size > 0);
57 
58 	aligned_size = (size + (IBUF_ALIGN - 1)) & ~(IBUF_ALIGN - 1);
59 
60 	/* Check if there is an available un-used handle with the size
61 	 * that will fulfill the request.
62 	 */
63 	if (ibuf_rsrc.num_active < ibuf_rsrc.num_allocated) {
64 		for (i = 0; i < ibuf_rsrc.num_allocated; i++) {
65 			handle = getHandle(i);
66 			if (!handle->active) {
67 				if (handle->size >= aligned_size) {
68 					handle->active = true;
69 					input_buffer_found = true;
70 					ibuf_rsrc.num_active++;
71 					break;
72 				}
73 			}
74 		}
75 	}
76 
77 	if (!input_buffer_found) {
78 		/* There were no available handles that fulfilled the
79 		 * request. Allocate a new handle with the requested size.
80 		 */
81 		if ((ibuf_rsrc.num_allocated < MAX_IBUF_HANDLES) &&
82 		    (ibuf_rsrc.free_size >= aligned_size)) {
83 			handle = getHandle(ibuf_rsrc.num_allocated);
84 			handle->start_addr	= ibuf_rsrc.free_start_addr;
85 			handle->size		= aligned_size;
86 			handle->active		= true;
87 
88 			ibuf_rsrc.free_start_addr += aligned_size;
89 			ibuf_rsrc.free_size -= aligned_size;
90 			ibuf_rsrc.num_active++;
91 			ibuf_rsrc.num_allocated++;
92 
93 			input_buffer_found = true;
94 		}
95 	}
96 
97 	if (input_buffer_found && handle) {
98 		*start_addr = handle->start_addr;
99 		retval = true;
100 	}
101 
102 	return retval;
103 }
104 
105 void ia_css_isys_ibuf_rmgr_release(
106     uint32_t	*start_addr)
107 {
108 	u16 i;
109 	ibuf_handle_t *handle = NULL;
110 
111 	assert(start_addr);
112 
113 	for (i = 0; i < ibuf_rsrc.num_allocated; i++) {
114 		handle = getHandle(i);
115 		if (handle->active && handle->start_addr == *start_addr) {
116 			handle->active = false;
117 			ibuf_rsrc.num_active--;
118 			break;
119 		}
120 	}
121 }
122