402 lines
8.2 KiB
C
Executable file
402 lines
8.2 KiB
C
Executable file
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Samsung Exynos SoC series dsp driver
|
|
*
|
|
* Copyright (c) 2019 Samsung Electronics Co., Ltd.
|
|
* http://www.samsung.com/
|
|
*/
|
|
|
|
#include "dl/dsp-rule-reader.h"
|
|
|
|
void dsp_type_print(struct dsp_type *type)
|
|
{
|
|
if (type->sign == SIGNED)
|
|
DL_BUF_STR("s");
|
|
else
|
|
DL_BUF_STR("u");
|
|
|
|
DL_BUF_STR("%d\n", type->bit_sz);
|
|
DL_PRINT_BUF(INFO);
|
|
}
|
|
|
|
void dsp_exp_binary_op(struct dsp_list_head *head, struct dsp_list_head *head1,
|
|
struct dsp_list_head *head2, char op)
|
|
{
|
|
struct dsp_exp_element *tmp = (struct dsp_exp_element *)dsp_dl_malloc(
|
|
sizeof(*tmp), "Exp elem");
|
|
|
|
tmp->type = EXP_OP;
|
|
tmp->op = op;
|
|
dsp_list_node_init(&tmp->list_node);
|
|
dsp_list_merge(head, head1, head2);
|
|
dsp_list_node_push_back(head, &tmp->list_node);
|
|
}
|
|
|
|
void dsp_exp_print(struct dsp_list_head *head)
|
|
{
|
|
struct dsp_list_node *node;
|
|
|
|
dsp_list_for_each(node, head) {
|
|
struct dsp_exp_element *element =
|
|
container_of(node, struct dsp_exp_element, list_node);
|
|
|
|
if (element->type == EXP_INTEGER)
|
|
DL_BUF_STR("%d ", element->integer);
|
|
|
|
if (element->type == EXP_OP)
|
|
DL_BUF_STR("%c ", element->op);
|
|
|
|
if (element->type == EXP_LINKER_VALUE) {
|
|
switch (element->linker_value) {
|
|
case ADDEND:
|
|
DL_BUF_STR("addend ");
|
|
break;
|
|
case BLOCK_ADDR_AR:
|
|
DL_BUF_STR("block_addr_AR ");
|
|
break;
|
|
case BLOCK_ADDR_BR:
|
|
DL_BUF_STR("block_addr_BR ");
|
|
break;
|
|
case ITEM_ADDR_AR:
|
|
DL_BUF_STR("item_addr_AR ");
|
|
break;
|
|
case ITEM_ADDR_BR:
|
|
DL_BUF_STR("item_addr_BR ");
|
|
break;
|
|
case ITEM_VALUE:
|
|
DL_BUF_STR("item_value ");
|
|
break;
|
|
case STORED_VALUE:
|
|
DL_BUF_STR("stored_value ");
|
|
break;
|
|
case SYMBOL_ADDR_AR:
|
|
DL_BUF_STR("symbol_addr_AR ");
|
|
break;
|
|
case SYMBOL_ADDR_BR:
|
|
DL_BUF_STR("symbol_addr_BR ");
|
|
break;
|
|
case SYMBOL_BLOCK_ADDR_AR:
|
|
DL_BUF_STR("symbol_block_addr_AR ");
|
|
break;
|
|
case SYMBOL_BLOCK_ADDR_BR:
|
|
DL_BUF_STR("symbol_block_addr_BR ");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
DL_BUF_STR("\n");
|
|
DL_PRINT_BUF(INFO);
|
|
}
|
|
|
|
int dsp_exp_import(struct dsp_exp_element *exp, struct dsp_dl_lib_file *file)
|
|
{
|
|
int ret;
|
|
|
|
ret = dsp_dl_lib_file_read((char *)exp, sizeof(*exp), file);
|
|
if (ret == -1) {
|
|
DL_ERROR("[%s] CHK_ERR\n", __func__);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void dsp_exp_free(struct dsp_list_head *head)
|
|
{
|
|
dsp_list_free(head, struct dsp_exp_element, list_node);
|
|
}
|
|
|
|
void dsp_bit_ext_print(enum dsp_bit_ext_type ext)
|
|
{
|
|
switch (ext) {
|
|
case BIT_ONE:
|
|
DL_BUF_STR("one ");
|
|
break;
|
|
case BIT_ZERO:
|
|
DL_BUF_STR("zero ");
|
|
break;
|
|
case BIT_SIGN:
|
|
DL_BUF_STR("sign ");
|
|
break;
|
|
case BIT_NONE:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void dsp_bit_slice_print(struct dsp_list_head *head)
|
|
{
|
|
struct dsp_list_node *node;
|
|
|
|
dsp_list_for_each(node, head) {
|
|
struct dsp_bit_slice *elem =
|
|
container_of(node, struct dsp_bit_slice, list_node);
|
|
|
|
if (elem->high == elem->low) {
|
|
DL_BUF_STR("[ ");
|
|
dsp_bit_ext_print(elem->h_ext);
|
|
DL_BUF_STR("%d ", elem->high);
|
|
dsp_bit_ext_print(elem->l_ext);
|
|
DL_BUF_STR("]@%d ", elem->value);
|
|
} else {
|
|
DL_BUF_STR("[");
|
|
dsp_bit_ext_print(elem->h_ext);
|
|
DL_BUF_STR("%d..%d", elem->high, elem->low);
|
|
dsp_bit_ext_print(elem->l_ext);
|
|
DL_BUF_STR("]");
|
|
DL_BUF_STR("@%d ", elem->value);
|
|
}
|
|
}
|
|
DL_BUF_STR("\n");
|
|
DL_PRINT_BUF(INFO);
|
|
}
|
|
|
|
int dsp_bit_slice_import(struct dsp_bit_slice *bs, struct dsp_dl_lib_file *file)
|
|
{
|
|
int ret;
|
|
|
|
ret = dsp_dl_lib_file_read((char *)bs, sizeof(*bs), file);
|
|
if (ret == -1) {
|
|
DL_ERROR("[%s] CHK_ERR\n", __func__);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void dsp_bit_slice_free(struct dsp_list_head *head)
|
|
{
|
|
dsp_list_free(head, struct dsp_bit_slice, list_node);
|
|
}
|
|
|
|
void dsp_pos_print(struct dsp_list_head *head)
|
|
{
|
|
struct dsp_list_node *node;
|
|
|
|
dsp_list_for_each(node, head) {
|
|
struct dsp_pos *elem =
|
|
container_of(node, struct dsp_pos, list_node);
|
|
|
|
if (elem->type == BIT_POS)
|
|
DL_INFO("@%d\n", elem->bit_pos);
|
|
else
|
|
dsp_bit_slice_print(&elem->bit_slice_list);
|
|
}
|
|
}
|
|
|
|
int dsp_pos_import(struct dsp_pos *pos, struct dsp_dl_lib_file *file)
|
|
{
|
|
int ret, idx;
|
|
|
|
ret = dsp_dl_lib_file_read((char *)pos, sizeof(*pos), file);
|
|
if (ret == -1) {
|
|
DL_ERROR("[%s] CHK_ERR\n", __func__);
|
|
return -1;
|
|
}
|
|
|
|
if (pos->type == BIT_SLICE_LIST) {
|
|
int list_num = pos->bit_slice_list.num;
|
|
|
|
dsp_list_head_init(&pos->bit_slice_list);
|
|
|
|
for (idx = 0; idx < list_num; idx++) {
|
|
struct dsp_bit_slice *bs =
|
|
(struct dsp_bit_slice *)dsp_dl_malloc(
|
|
sizeof(*bs),
|
|
"Bit slice");
|
|
|
|
dsp_bit_slice_import(bs, file);
|
|
dsp_list_node_init(&bs->list_node);
|
|
dsp_list_node_push_back(&pos->bit_slice_list,
|
|
&bs->list_node);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void dsp_pos_free(struct dsp_list_head *head)
|
|
{
|
|
struct dsp_list_node *cur, *next;
|
|
|
|
cur = head->next;
|
|
|
|
while (cur != NULL) {
|
|
struct dsp_pos *pos =
|
|
container_of(cur, struct dsp_pos, list_node);
|
|
|
|
next = cur->next;
|
|
|
|
if (pos->type == BIT_SLICE_LIST)
|
|
dsp_bit_slice_free(&pos->bit_slice_list);
|
|
|
|
dsp_dl_free(pos);
|
|
cur = next;
|
|
}
|
|
}
|
|
|
|
void dsp_cont_print(struct dsp_cont *cont)
|
|
{
|
|
if (cont->inst_num > 1)
|
|
DL_BUF_STR("[%d]", cont->inst_num);
|
|
|
|
dsp_type_print(&cont->type);
|
|
}
|
|
|
|
void dsp_range_print(enum dsp_range_type ran)
|
|
{
|
|
if (ran == RANGE_STRICT)
|
|
DL_BUF_STR("strict\n");
|
|
else if (ran == RANGE_NOSTRICT)
|
|
DL_BUF_STR("nostrict\n");
|
|
|
|
DL_PRINT_BUF(INFO);
|
|
}
|
|
|
|
void dsp_reloc_rule_print(struct dsp_reloc_rule *rule)
|
|
{
|
|
DL_INFO("Reloc rule[%d]\n", rule->idx);
|
|
DL_INFO("Exp:\n");
|
|
dsp_exp_print(&rule->exp);
|
|
|
|
DL_BUF_STR("Type: ");
|
|
dsp_type_print(&rule->type);
|
|
|
|
DL_INFO("Pos(%d):\n", rule->pos_list.num);
|
|
dsp_pos_print(&rule->pos_list);
|
|
|
|
DL_BUF_STR("Cont: ");
|
|
dsp_cont_print(&rule->cont);
|
|
|
|
DL_BUF_STR("Range: ");
|
|
dsp_range_print(rule->range_chk);
|
|
}
|
|
|
|
int dsp_reloc_rule_import(struct dsp_reloc_rule *rule,
|
|
struct dsp_dl_lib_file *file)
|
|
{
|
|
int ret;
|
|
int list_num, idx;
|
|
|
|
ret = dsp_dl_lib_file_read((char *)rule, sizeof(*rule), file);
|
|
if (ret == -1) {
|
|
DL_ERROR("[%s] CHK_ERR\n", __func__);
|
|
return -1;
|
|
}
|
|
|
|
list_num = rule->exp.num;
|
|
dsp_list_head_init(&rule->exp);
|
|
|
|
for (idx = 0; idx < list_num; idx++) {
|
|
struct dsp_exp_element *exp =
|
|
(struct dsp_exp_element *)
|
|
dsp_dl_malloc(
|
|
sizeof(*exp),
|
|
"Exp elem");
|
|
|
|
ret = dsp_exp_import(exp, file);
|
|
|
|
if (ret == -1) {
|
|
DL_ERROR("[%s] CHK_ERR\n", __func__);
|
|
return -1;
|
|
}
|
|
|
|
dsp_list_node_init(&exp->list_node);
|
|
dsp_list_node_push_back(&rule->exp, &exp->list_node);
|
|
}
|
|
|
|
list_num = rule->pos_list.num;
|
|
dsp_list_head_init(&rule->pos_list);
|
|
|
|
for (idx = 0; idx < list_num; idx++) {
|
|
struct dsp_pos *pos = (struct dsp_pos *)dsp_dl_malloc(
|
|
sizeof(*pos), "Pos");
|
|
|
|
ret = dsp_pos_import(pos, file);
|
|
|
|
if (ret == -1) {
|
|
DL_ERROR("[%s] CHK_ERR\n", __func__);
|
|
return -1;
|
|
}
|
|
|
|
dsp_list_node_init(&pos->list_node);
|
|
dsp_list_node_push_back(&rule->pos_list, &pos->list_node);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void dsp_reloc_rule_free(struct dsp_reloc_rule *rule)
|
|
{
|
|
dsp_exp_free(&rule->exp);
|
|
dsp_pos_free(&rule->pos_list);
|
|
}
|
|
|
|
void dsp_reloc_rule_list_print(struct dsp_reloc_rule_list *list)
|
|
{
|
|
int idx;
|
|
|
|
DL_INFO(DL_BORDER);
|
|
DL_INFO("Reloc rules\n");
|
|
|
|
for (idx = 0; idx < list->cnt; idx++) {
|
|
dsp_reloc_rule_print(list->list[idx]);
|
|
DL_INFO("\n");
|
|
}
|
|
}
|
|
|
|
int dsp_reloc_rule_list_import(struct dsp_reloc_rule_list *list,
|
|
struct dsp_dl_lib_file *file)
|
|
{
|
|
int ret;
|
|
char magic[4];
|
|
int idx;
|
|
|
|
DL_DEBUG("Rule list import\n");
|
|
|
|
dsp_dl_lib_file_reset(file);
|
|
ret = dsp_dl_lib_file_read(magic, sizeof(char) * 4, file);
|
|
if (ret == -1) {
|
|
DL_ERROR("[%s] CHK_ERR\n", __func__);
|
|
return -1;
|
|
}
|
|
|
|
if (magic[0] != 'R' || magic[1] != 'U' || magic[2] != 'L' ||
|
|
magic[3] != 'E') {
|
|
DL_ERROR("Magic number is incorrect\n");
|
|
return -1;
|
|
}
|
|
|
|
ret = dsp_dl_lib_file_read((char *)&list->cnt, sizeof(int), file);
|
|
if (ret == -1) {
|
|
DL_ERROR("[%s] CHK_ERR\n", __func__);
|
|
return -1;
|
|
}
|
|
|
|
if (list->cnt > RULE_MAX) {
|
|
DL_ERROR("Rule list count(%d) is over RULE_MAX(%d)\n",
|
|
list->cnt, RULE_MAX);
|
|
return -1;
|
|
}
|
|
DL_DEBUG("Rule list count %d\n", list->cnt);
|
|
|
|
for (idx = 0; idx < list->cnt; idx++) {
|
|
list->list[idx] = (struct dsp_reloc_rule *)dsp_dl_malloc(
|
|
sizeof(*list->list[idx]),
|
|
"Reloc rule");
|
|
dsp_reloc_rule_import(list->list[idx], file);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void dsp_reloc_rule_list_free(struct dsp_reloc_rule_list *list)
|
|
{
|
|
int idx;
|
|
|
|
for (idx = 0; idx < list->cnt; idx++) {
|
|
struct dsp_reloc_rule *rule = list->list[idx];
|
|
|
|
dsp_reloc_rule_free(rule);
|
|
dsp_dl_free(rule);
|
|
}
|
|
}
|