1 /*********************************************************************
2 * dsp.c - dsp patch manager library
4 * Copyright (C) 2000 Rui Sousa
5 *********************************************************************
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the Free
18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
20 *********************************************************************
26 #include <sys/ioctl.h>
27 #include <sys/soundcard.h>
30 #include "../emu10k1-include/dsp.h"
31 #include "../emu10k1-include/list.h"
33 #include "../emu10k1-include/internal.h"
35 __u32 addr_change
[0x400];
37 __s32 constants
[CONSTANTS_SIZE
] = {
63 /* these should have better names (and probably dependent on the card model) */
64 char dsp_in_name
[DSP_NUM_INPUTS
][DSP_LINE_NAME_SIZE
] =
65 { "Pcm L", "Pcm R", "fx2", "fx3", "Pcm1 L", "Pcm1 R", "fx6", "fx7",
66 "fx8", "fx9", "fx10", "fx11", "fx12", "fx13", "fx14", "fx15",
67 "Analog L", "Analog R", "CD-Spdif L", "CD-Spdif R", "in2l", "in2r", "Opt. Spdif L", "Opt. Spdif R",
68 "Line2/Mic2 L", "Line2/Mic2 R", "RCA Spdif L", "RCA Spdif R","RCA Aux L", "RCA Aux R", "in7l", "in7r"
70 char dsp_out_name
[DSP_NUM_OUTPUTS
][DSP_LINE_NAME_SIZE
] =
71 { "Front L", "Front R", "Digital L", "Digital R", "Digital Center", "Digital LFE", "Phones L", "Phones R",
72 "Rear L", "Rear R", "ADC Rec L", "ADC Rec R", "Mic Rec", "out6r", "out7l", "out7r",
73 "out8l", "Analog Center", "Analog LFE", "out9r", "out10l", "out10r", "out11l", "out11r",
74 "out12l", "out12r", "out13l", "out13r", "out14l", "out14r", "out15l", "out15r"
76 char dsp_stereo_in_name
[DSP_NUM_INPUTS
/2][DSP_LINE_NAME_SIZE
] =
77 { "Pcm", "fx2-3", "Pcm1", "fx6-7",
78 "fx8-9", "fx10-11", "fx12-13", "fx14-15",
79 "Analog", "CD-Spdif", "in2", "Opt. Spdif",
80 "Line2/Mic2", "RCA Spdif","RCA Aux", "in7"
82 char dsp_stereo_out_name
[DSP_NUM_OUTPUTS
/2][DSP_LINE_NAME_SIZE
] =
83 { "Front", "Digital", "Digital Ctr/lfe", "Phones",
84 "Rear", "ADC Rec", "out6", "out7",
85 "out8", "out9", "out10", "out11",
86 "out12", "out13", "out14", "out15"
88 char *oss_mixer_name
[SOUND_MIXER_NRDEVICES
] = SOUND_DEVICE_NAMES
;
91 int find_control_gpr_addr(struct dsp_patch_manager
*mgr
, const char *patch_name
, const char *gpr_name
)
93 struct dsp_rpatch
*rpatch
;
94 struct dsp_patch
*patch
;
95 struct list_head
*entry
;
96 char s
[DSP_PATCH_NAME_SIZE
+ 4];
100 list_for_each(entry
, &mgr
->ipatch_list
) {
101 patch
= list_entry(entry
, struct dsp_patch
, list
);
103 sprintf(s
, "%s %d", patch
->name
, patch
->id
);
105 sprintf(s
, "%s", patch
->name
);
107 if (!strcmp(s
, patch_name
)) {
108 gpr_used
= patch
->gpr_used
;
114 rpatch
= &mgr
->rpatch
;
115 if (!strcmp(rpatch
->name
, patch_name
)) {
116 gpr_used
= rpatch
->gpr_used
;
121 list_for_each(entry
, &mgr
->opatch_list
) {
122 patch
= list_entry(entry
, struct dsp_patch
, list
);
124 sprintf(s
, "%s %d", patch
->name
, patch
->id
);
126 sprintf(s
, "%s", patch
->name
);
128 if (!strcmp(s
, patch_name
)) {
129 gpr_used
= patch
->gpr_used
;
138 for (i
= 0; i
< DSP_NUM_GPRS
; i
++) {
139 if ((mgr
->gpr
[i
].type
== GPR_TYPE_CONTROL
)
140 && test_bit(i
, gpr_used
)
141 && !strcmp(mgr
->gpr
[i
].name
, gpr_name
))
148 int get_constant_gpr(struct dsp_patch_manager
*mgr
, __s32 val
, __u32
* used
)
152 for (i
= 0; i
< CONSTANTS_SIZE
; i
++)
153 /* if it's a hardwired constant use it */
154 if (constants
[i
] == val
)
155 return CONSTANTS_BASE
+ i
;
157 for (i
= 0; i
< DSP_NUM_GPRS
; i
++) {
158 /* see if he have this global gpr already */
159 if (mgr
->gpr
[i
].type
== GPR_TYPE_CONSTANT
&& mgr
->gpr
[i
].value
== val
&& mgr
->gpr
[i
].usage
< 255)
163 for (i
= 0; i
< DSP_NUM_GPRS
; i
++) {
164 /* assign a new free GPR */
165 if (mgr
->gpr
[i
].type
== GPR_TYPE_NULL
){
172 fprintf(stderr
, "get_constant_gpr(): no available gprs\n");
177 if (!test_and_set_bit(i
, used
)) {
178 mgr
->gpr
[i
].type
= GPR_TYPE_CONSTANT
;
179 mgr
->gpr
[i
].addr
= i
;
181 mgr
->gpr
[i
].value
= val
;
187 int get_dynamic_gpr(struct dsp_patch_manager
*mgr
, __u32
* used
)
191 for (i
= 0; i
< DSP_NUM_GPRS
; i
++) {
192 /* overlap DYNAMIC gprs from different patches */
193 if ((mgr
->gpr
[i
].type
== GPR_TYPE_DYNAMIC
)
194 && !test_bit(i
, used
) && mgr
->gpr
[i
].usage
< 255)
198 for (i
= 0; i
< DSP_NUM_GPRS
; i
++) {
199 /* assign a new free GPR */
200 if (mgr
->gpr
[i
].type
== GPR_TYPE_NULL
){
208 fprintf(stderr
, "get_dynamic_gpr(): no available gprs\n");
214 mgr
->gpr
[i
].type
= GPR_TYPE_DYNAMIC
;
215 mgr
->gpr
[i
].addr
= i
;
221 int get_static_gpr(struct dsp_patch_manager
*mgr
, __s32 val
, __u32
* used
)
225 /* these can't be shared so just get a new one */
226 for (i
= 0; i
< DSP_NUM_GPRS
; i
++) {
228 if (mgr
->gpr
[i
].type
== GPR_TYPE_NULL
)
232 fprintf(stderr
, "get_static_gpr(): no available gprs\n");
238 mgr
->gpr
[i
].type
= GPR_TYPE_STATIC
;
239 mgr
->gpr
[i
].addr
= i
;
241 mgr
->gpr
[i
].value
= val
;
246 /* We don't match IO gprs here, we just don't waste any (maximum of 2 per line) */
247 int get_io_gpr(struct dsp_patch_manager
*mgr
, int line
, int type
, __u32
* used
, __u32
* input
)
253 /* return an already allocated one (but not in use by this patch */
254 if (mgr
->io
[line
][0] >= 0) {
255 if (!test_bit(mgr
->io
[line
][0], used
)) {
256 i
= mgr
->io
[line
][0];
261 if (mgr
->io
[line
][1] >= 0) {
262 if (!test_bit(mgr
->io
[line
][1], used
)) {
263 i
= mgr
->io
[line
][1];
269 for (i
= 0; i
< DSP_NUM_GPRS
; i
++) {
270 if (mgr
->gpr
[i
].type
== GPR_TYPE_NULL
) {
272 if (mgr
->io
[line
][0] < 0)
273 mgr
->io
[line
][0] = i
;
274 else if (mgr
->io
[line
][1] < 0)
275 mgr
->io
[line
][1] = i
;
277 fprintf(stderr
, "get_io_gpr(): more than two io gprs per line\n");
284 fprintf(stderr
, "get_io_gpr(): no available gprs\n");
290 if (type
== GPR_INPUT
)
293 mgr
->gpr
[i
].type
= GPR_TYPE_IO
;
294 mgr
->gpr
[i
].addr
= i
;
295 mgr
->gpr
[i
].line
= line
;
297 mgr
->gpr
[i
].value
= 0;
302 int get_control_gpr(struct dsp_patch_manager
*mgr
, __s32 val
, __s32 min
, __s32 max
,
303 const char *name
, __u32
* used
, const char *patch_name
)
307 //if another instance of same patch is loaded, we'll use it's control gpr:
309 if( (i
=find_control_gpr_addr(mgr
, patch_name
, name
)) != -1){
310 mgr
->gpr
[i
-GPR_BASE
].usage
++;
311 set_bit(i
-GPR_BASE
, used
);
315 for (i
= 0; i
< DSP_NUM_GPRS
; i
++) {
317 if (mgr
->gpr
[i
].type
== GPR_TYPE_NULL
){
319 mgr
->gpr
[i
].mixer_id
= SOUND_MIXER_NONE
;
324 fprintf(stderr
, "get_control_gpr(): no available gprs\n");
330 mgr
->gpr
[i
].type
= GPR_TYPE_CONTROL
;
331 mgr
->gpr
[i
].addr
= i
;
332 mgr
->gpr
[i
].value
= val
;
333 mgr
->gpr
[i
].min_val
= min
;
334 mgr
->gpr
[i
].max_val
= max
;
336 strncpy(mgr
->gpr
[i
].name
, name
, DSP_GPR_NAME_SIZE
);
337 mgr
->gpr
[i
].name
[DSP_GPR_NAME_SIZE
- 1] = '\0';
342 /* get an already allocated gpr by address */
343 int get_gpr(struct dsp_patch_manager
*mgr
, int addr
, __u32
* used
)
345 if (test_bit(addr
, used
))
346 return GPR_BASE
+ addr
;
348 if (mgr
->gpr
[addr
].type
== GPR_TYPE_NULL
)
351 if (mgr
->gpr
[addr
].usage
== 1 && mgr
->gpr
[addr
].type
== GPR_TYPE_STATIC
)
354 if (mgr
->gpr
[addr
].usage
== 255)
358 mgr
->gpr
[addr
].usage
++;
361 return GPR_BASE
+ addr
;
364 int free_gpr(struct dsp_patch_manager
*mgr
, int addr
, __u32
* used
)
366 if (!test_bit(addr
, used
))
369 clear_bit(addr
, used
);
371 mgr
->gpr
[addr
].usage
--;
373 if (mgr
->gpr
[addr
].usage
== 0) {
374 if (mgr
->gpr
[addr
].type
== GPR_TYPE_IO
) {
375 if (mgr
->io
[mgr
->gpr
[addr
].line
][0] == addr
)
376 mgr
->io
[mgr
->gpr
[addr
].line
][0] = -1;
378 mgr
->io
[mgr
->gpr
[addr
].line
][1] = -1;
381 mgr
->gpr
[addr
].type
= GPR_TYPE_NULL
;
387 static void free_all_gprs(struct dsp_patch_manager
*mgr
, __u32
* used
)
391 for (i
= 0; i
< DSP_NUM_GPRS
; i
++)
392 free_gpr(mgr
, i
, used
);
397 /* returns 1 if the code contains a particular address (val) */
398 static int search_code(struct dsp_patch
*patch
, int val
)
402 for (i
= 0; i
< patch
->code_size
/ 2; i
++)
403 if (((patch
->code
[i
* 2 + 1] >> 10) & 0x3ff) == val
||
404 (patch
->code
[i
* 2 + 1] & 0x3ff) == val
||
405 ((patch
->code
[i
* 2] >> 10) & 0x3ff) == val
|| (patch
->code
[i
* 2] & 0x3ff) == val
)
411 void init_io_gprs_table(struct dsp_patch_manager
*mgr
)
415 for (i
= 0; i
< DSP_NUM_INPUTS
; i
++) {
420 /* construct table of possible io gprs for each line */
421 for (i
= 0; i
< DSP_NUM_GPRS
; i
++)
422 if (mgr
->gpr
[i
].type
== GPR_TYPE_IO
) {
423 line
= mgr
->gpr
[i
].line
& 0x3f;
424 if (mgr
->io
[line
][0] == -1)
425 mgr
->io
[line
][0] = mgr
->gpr
[i
].addr
;
426 else if (mgr
->io
[line
][1] == -1)
427 mgr
->io
[line
][1] = mgr
->gpr
[i
].addr
;
429 fprintf(stderr
, "init_io_gprs_table(): more than 2 io gprs\n");
437 void determine_io(struct dsp_patch_manager
*mgr
, struct dsp_patch
*patch
)
442 for (i
=0;i
<DSP_NUM_INPUTS
;i
++){
443 if(test_bit(i
,&patch
->input
)){
444 gpr0
= mgr
->io
[i
][0];
445 gpr1
= mgr
->io
[i
][1];
446 /* determine patch input */
447 if (gpr0
!= -1 && test_bit(gpr0
, patch
->gpr_input
))
448 patch
->in_gprs
[i
] = GPR_BASE
+ gpr0
;
449 else if (gpr1
!= -1 && test_bit(gpr1
, patch
->gpr_input
))
450 patch
->in_gprs
[i
] = GPR_BASE
+ gpr1
;
451 else if (search_code(patch
, i
))
452 patch
->in_gprs
[i
] = i
;
454 patch
->in_gprs
[i
] = -1;
458 for(i
=0;i
<DSP_NUM_OUTPUTS
;i
++){
459 if(test_bit(i
,&patch
->output
)){
461 gpr0
= mgr
->io
[i
][0];
462 gpr1
= mgr
->io
[i
][1];
464 /* determine patch output */
465 if (gpr0
!= -1 && test_bit(gpr0
, patch
->gpr_used
) && !test_bit(gpr0
, patch
->gpr_input
))
466 patch
->out_gprs
[i
] = GPR_BASE
+ gpr0
;
467 else if (gpr1
!= -1 && test_bit(gpr1
, patch
->gpr_used
) && !test_bit(gpr1
, patch
->gpr_input
))
468 patch
->out_gprs
[i
] = GPR_BASE
+ gpr1
;
469 else if (search_code(patch
, OUTPUT_BASE
+ i
))
470 patch
->out_gprs
[i
] = OUTPUT_BASE
+ i
;
472 patch
->out_gprs
[i
] = -1;
477 void init_addr_change_table(__u32
* table
, __u32 min
, __u32 max
)
481 for (i
= min
; i
< max
; i
++)
486 void search_and_replace(__u32
* code
, __u32 size
, __u32
* table
, __u32 min
, __u32 max
)
491 for (i
= 0; i
< size
; i
++) {
492 operand
[0] = code
[i
] & 0x000003ff;
493 operand
[1] = (code
[i
] & 0x000ffc00) >> 10;
495 if (operand
[0] < max
&& operand
[0] >= min
)
496 operand
[0] = table
[operand
[0] - min
];
498 if (operand
[1] < max
&& operand
[1] >= min
)
499 operand
[1] = table
[operand
[1] - min
];
501 code
[i
] = (code
[i
] & ~0x000fffff) | ((operand
[1] & 0x3ff) << 10)
502 | (operand
[0] & 0x3ff);
508 int dsp_find_patch(struct dsp_patch_manager
*mgr
, const char *name
, struct dsp_patch
**patch_in
)
510 struct dsp_patch
*patch
;
511 struct list_head
*entry
;
512 char s
[DSP_PATCH_NAME_SIZE
+ 4];
514 list_for_each(entry
, &mgr
->ipatch_list
) {
515 patch
= list_entry(entry
, struct dsp_patch
, list
);
517 sprintf(s
, "%s %d", patch
->name
, patch
->id
);
519 sprintf(s
, "%s", patch
->name
);
521 if (!strcmp(s
, name
)) {
527 list_for_each(entry
, &mgr
->opatch_list
) {
528 patch
= list_entry(entry
, struct dsp_patch
, list
);
531 sprintf(s
, "%s %d", patch
->name
, patch
->id
);
533 sprintf(s
, "%s", patch
->name
);
535 if (!strcmp(s
, name
)){
544 int dsp_unload_patch(struct dsp_patch_manager
*mgr
, const char *name
)
546 struct dsp_patch
*patch
;
552 if(dsp_find_patch(mgr
, name
, &patch
) < 0 )
555 list_del(&patch
->list
);
556 free_all_gprs(mgr
, patch
->gpr_used
);
557 mgr
->code_free_start
-= patch
->code_size
;
558 mgr
->traml_efree_start
-= patch
->traml_esize
;
559 mgr
->traml_ifree_start
-= patch
->traml_isize
;
560 mgr
->tramb_efree_start
-= patch
->tramb_esize
;
561 mgr
->tramb_ifree_start
-= patch
->tramb_isize
;
562 free(patch
->traml_iaddr
);
563 free(patch
->traml_eaddr
);
570 int dsp_set_patch_name(struct dsp_patch_manager
*mgr
, const char *patch
, const char *new)
575 int dsp_set_control_gpr_value(struct dsp_patch_manager
*mgr
, const char *patch
, const char *gpr
, __s32 val
)
577 struct mixer_private_ioctl ctl
;
581 addr
= find_control_gpr_addr(mgr
, patch
, gpr
);
587 if (val
> mgr
->gpr
[addr
].max_val
)
588 val
= mgr
->gpr
[addr
].max_val
;
589 else if (val
< mgr
->gpr
[addr
].min_val
)
590 val
= mgr
->gpr
[addr
].min_val
;
592 mgr
->gpr
[addr
].value
= val
;
596 ctl
.cmd
= CMD_SETCTLGPR
;
597 memcpy((char *) ctl
.val
, patch
, DSP_PATCH_NAME_SIZE
);
598 memcpy((char *) ctl
.val
+ DSP_PATCH_NAME_SIZE
, gpr
, DSP_PATCH_NAME_SIZE
);
599 memcpy((char *) ctl
.val
+ 2 * DSP_PATCH_NAME_SIZE
, &val
, sizeof(__s32
));
601 ret
= ioctl(mgr
->mixer_fd
, SOUND_MIXER_PRIVATE3
, &ctl
);
603 perror("SOUND_MIXER_PRIVATE3");
610 int dsp_get_control_gpr_value(struct dsp_patch_manager
*mgr
, const char *patch
, const char *gpr
, __s32
* val
)
612 struct mixer_private_ioctl ctl
;
617 addr
= find_control_gpr_addr(mgr
, patch
, gpr
);
623 *val
= mgr
->gpr
[addr
].value
;
626 ctl
.cmd
= CMD_GETCTLGPR
;
627 memcpy(ctl
.val
, patch
, DSP_PATCH_NAME_SIZE
);
628 memcpy((char *) ctl
.val
+ DSP_PATCH_NAME_SIZE
, gpr
, DSP_PATCH_NAME_SIZE
);
630 ret
= ioctl(mgr
->mixer_fd
, SOUND_MIXER_PRIVATE3
, &ctl
);
632 perror("SOUND_MIXER_PRIVATE3");
636 *val
= (__s32
) ctl
.val
[0];
642 static void construct_input_buffer(struct dsp_patch_manager
*mgr
, __u32
* operand
, __u32
* buffer_code
,
648 for (i
= 1; i
< 3; i
++)
649 if (operand
[i
] < OUTPUT_BASE
&& operand
[i
+ 1] < OUTPUT_BASE
&&
650 addr_change
[operand
[i
]] < OUTPUT_BASE
&& addr_change
[operand
[i
+ 1]] < OUTPUT_BASE
) {
651 addr
= get_dynamic_gpr(mgr
, mgr
->rpatch
.gpr_used
);
652 addr_change
[operand
[i
]] = addr
;
653 buffer_code
[*buffer_size
+ 1] = 0x6 << 20 | addr
<< 10 | operand
[i
];
654 buffer_code
[*buffer_size
] = 0x40 << 10 | 0x40;
659 int construct_routing(struct dsp_patch_manager
*mgr
)
661 struct dsp_rpatch
*rpatch
;
662 struct list_head
*entry
;
663 struct dsp_patch
*patch
;
664 __u32 op
, operand
[4];
665 char name
[DSP_GPR_NAME_SIZE
];
666 __u32 buffer_code
[DSP_NUM_INPUTS
* 2];
672 /* release io and dynamic gprs of the routing patch */
673 for (i
= 0; i
< DSP_NUM_GPRS
; i
++)
674 if (test_bit(i
, mgr
->rpatch
.gpr_used
) &&
675 (mgr
->gpr
[i
].type
== GPR_TYPE_IO
||
676 mgr
->gpr
[i
].type
== GPR_TYPE_DYNAMIC
)) free_gpr(mgr
, i
, mgr
->rpatch
.gpr_used
);
678 rpatch
= &mgr
->rpatch
;
680 for (i
= 0; i
< DSP_NUM_INPUTS
; i
++)
681 if (rpatch
->in
[i
] >= GPR_BASE
) {
682 get_gpr(mgr
, rpatch
->in
[i
] - GPR_BASE
, rpatch
->gpr_used
);
683 set_bit(rpatch
->in
[i
] - GPR_BASE
, rpatch
->gpr_input
);
686 for (i
= 0; i
< DSP_NUM_OUTPUTS
; i
++)
690 mgr
->code_free_start
-= rpatch
->code_size
;
691 rpatch
->code_size
= 0;
693 init_addr_change_table(addr_change
, 0, OUTPUT_BASE
);
695 for (i
= 0; i
< DSP_NUM_OUTPUTS
; i
++) {
696 if (mgr
->rpatch
.route
[i
] != 0 || mgr
->rpatch
.route_v
[i
] != 0) {
702 while (route
< DSP_NUM_INPUTS
|| route_v
< DSP_NUM_INPUTS
) {
704 /* find next active route */
705 while (!test_bit(route
, &mgr
->rpatch
.route
[i
])
706 && route
< DSP_NUM_INPUTS
)
709 while (!test_bit(route_v
, &mgr
->rpatch
.route_v
[i
])
710 && route_v
< DSP_NUM_INPUTS
)
713 /* a complete op and there are more arguments */
714 if (j
== 4 && (route
< DSP_NUM_INPUTS
|| route_v
< DSP_NUM_INPUTS
)) {
715 /* if we need an output gpr use it also for temporary storage */
716 if (rpatch
->out
[i
] < 0)
718 get_io_gpr(mgr
, i
, GPR_OUTPUT
, rpatch
->gpr_used
, rpatch
->gpr_input
);
720 if (rpatch
->out
[i
] < 0)
723 operand
[0] = rpatch
->out
[i
];
725 rpatch
->code
[rpatch
->code_size
+ 1] = op
<< 20 | operand
[0] << 10 | operand
[1];
728 rpatch
->code
[rpatch
->code_size
] = operand
[2] << 10 | operand
[3];
730 rpatch
->code_size
+= 2;
732 construct_input_buffer(mgr
, operand
, buffer_code
, &buffer_size
);
735 operand
[1] = rpatch
->out
[i
];
739 if ((j
== 2 || route
>= DSP_NUM_INPUTS
) && route_v
< DSP_NUM_INPUTS
) {
743 operand
[2] = rpatch
->in
[route_v
];
745 sprintf(name
, "Vol %s:%s", dsp_in_name
[route_v
], dsp_out_name
[i
]);
747 /* find control gpr for this route */
748 /* if there isn't any create one */
749 addr
= find_control_gpr_addr(mgr
, rpatch
->name
, name
);
752 get_control_gpr(mgr
, 0x7fffffff, 0, 0x7fffffff,
753 name
, rpatch
->gpr_used
, NULL
);
763 } else if (route
< DSP_NUM_INPUTS
) {
764 operand
[j
++] = rpatch
->in
[route
];
772 addr
= rpatch
->out
[i
];
773 rpatch
->out
[i
] = OUTPUT_BASE
+ i
;
775 list_for_each(entry
, &mgr
->opatch_list
) {
777 patch
= list_entry(entry
, struct dsp_patch
, list
);
778 //Reminder: check this to make sure its ok:
779 if(patch_uses_output(patch
,i
)){
781 if (patch
->in_gprs
[i
] > 0) {
783 rpatch
->out
[i
] = get_io_gpr(mgr
, i
,
784 GPR_OUTPUT
, rpatch
->gpr_used
,
787 rpatch
->out
[i
] = addr
;
794 operand
[0] = rpatch
->out
[i
];
796 rpatch
->code
[rpatch
->code_size
+ 1] = op
<< 20 | operand
[0] << 10 | operand
[1];
798 rpatch
->code
[rpatch
->code_size
] = operand
[2] << 10 | operand
[3];
799 rpatch
->code_size
+= 2;
801 construct_input_buffer(mgr
, operand
, buffer_code
, &buffer_size
);
805 search_and_replace(rpatch
->code
, rpatch
->code_size
, addr_change
, 0, OUTPUT_BASE
);
807 if (buffer_size
+ rpatch
->code_size
> DSP_CODE_SIZE
) {
808 fprintf(stderr
, "routing patch to big\n");
812 memmove(rpatch
->code
+ buffer_size
, rpatch
->code
, rpatch
->code_size
* sizeof(__u32
));
813 memcpy(rpatch
->code
, buffer_code
, buffer_size
* sizeof(__u32
));
814 rpatch
->code_size
+= buffer_size
;
815 mgr
->code_free_start
+= rpatch
->code_size
;
817 if (mgr
->code_free_start
> DSP_CODE_SIZE
) {
818 fprintf(stderr
, "no free dsp code memory\n");
826 int get_input_name(const char *input
)
830 for (i
= 0; i
< DSP_NUM_INPUTS
; i
++)
831 if (!strcasecmp(input
, dsp_in_name
[i
]))
837 int get_output_name(const char *output
)
841 for (i
= 0; i
< DSP_NUM_OUTPUTS
; i
++)
842 if (!strcasecmp(output
, dsp_out_name
[i
]))
848 int get_stereo_input_name(const char *input
)
852 for (i
= 0; i
< DSP_NUM_INPUTS
/2; i
++)
853 if (!strcasecmp(input
, dsp_stereo_in_name
[i
]))
858 int get_stereo_output_name(const char *output
)
862 for (i
= 0; i
< DSP_NUM_OUTPUTS
/2; i
++)
863 if (!strcasecmp(output
, dsp_stereo_out_name
[i
]))
868 static int get_stereo_route_name(struct dsp_patch_manager
*mgr
, const char *name
, int *in1
, int *in2
, int *out1
, int *out2
)
870 char route_name
[2 *DSP_LINE_NAME_SIZE
+2],*out_ptr
;
873 strcpy(route_name
,name
);
874 strtok_r(route_name
,":" , &out_ptr
);
876 if((ret
= get_input_name(route_name
)) >= 0){
879 }else if((ret
= get_stereo_input_name(route_name
)) >= 0){
885 if((ret
= get_output_name(out_ptr
)) >= 0){
888 }else if ( (ret
= get_stereo_output_name(out_ptr
)) >= 0 ){
898 static int get_route_name(struct dsp_patch_manager
*mgr
, const char *name
, int *in
, int *out
)
900 char route_name
[2 * DSP_LINE_NAME_SIZE
+ 2];
902 for (*in
= 0; *in
< DSP_NUM_INPUTS
; (*in
)++)
903 for (*out
= 0; *out
< DSP_NUM_OUTPUTS
; (*out
)++) {
904 sprintf(route_name
, "%s:%s", dsp_in_name
[*in
], dsp_out_name
[*out
]);
905 if (!strcmp(name
, route_name
))
912 int dsp_check_input(struct dsp_patch_manager
*mgr
, int in
)
914 struct dsp_rpatch
*rpatch
= &mgr
->rpatch
;
917 if (in
< 0 || in
> DSP_NUM_INPUTS
)
920 for (i
= 0; i
< DSP_NUM_OUTPUTS
; i
++)
921 if (test_bit(in
, &rpatch
->route
[i
]) || test_bit(in
, &rpatch
->route_v
[i
]))
927 int dsp_check_input_name(struct dsp_patch_manager
*mgr
, const char *input
)
931 in
= get_input_name(input
);
932 return dsp_check_input(mgr
, in
);
935 int dsp_check_output(struct dsp_patch_manager
*mgr
, int out
)
937 struct dsp_rpatch
*rpatch
= &mgr
->rpatch
;
939 if (out
< 0 || out
> DSP_NUM_OUTPUTS
)
942 if (rpatch
->route
[out
] || rpatch
->route_v
[out
])
948 int dsp_check_output_name(struct dsp_patch_manager
*mgr
, const char *output
)
952 out
= get_output_name(output
);
953 return dsp_check_output(mgr
, out
);
956 int dsp_check_route(struct dsp_patch_manager
*mgr
, int in
, int out
)
958 struct dsp_rpatch
*rpatch
= &mgr
->rpatch
;
960 if (in
< 0 || in
> DSP_NUM_INPUTS
|| out
< 0 || out
> DSP_NUM_OUTPUTS
)
963 if (test_bit(in
, &rpatch
->route
[out
]) || test_bit(in
, &rpatch
->route_v
[out
]))
969 int dsp_check_route_volume(struct dsp_patch_manager
*mgr
, int in
, int out
)
971 struct dsp_rpatch
*rpatch
= &mgr
->rpatch
;
973 if (in
< 0 || in
> DSP_NUM_INPUTS
|| out
< 0 || out
> DSP_NUM_OUTPUTS
)
976 if (test_bit(in
, &rpatch
->route_v
[out
]))
982 int dsp_check_route_name(struct dsp_patch_manager
*mgr
, const char *name
)
986 get_route_name(mgr
, name
, &in
, &out
);
987 return dsp_check_route(mgr
, in
, out
);
990 int dsp_input_unused( struct list_head
*list
, int line
)
992 struct list_head
*entry
;
993 struct dsp_patch
*patch
;
995 list_for_each(entry
, list
) {
996 patch
= list_entry(entry
, struct dsp_patch
, list
);
997 if (test_bit(line
,&patch
->input
))
1003 int dsp_output_unused( struct list_head
*list
, int line
)
1005 struct list_head
*entry
;
1006 struct dsp_patch
*patch
;
1008 list_for_each(entry
, list
) {
1009 patch
= list_entry(entry
, struct dsp_patch
, list
);
1010 if (test_bit(line
,&patch
->output
))
1017 int dsp_del_route(struct dsp_patch_manager
*mgr
, int in
, int out
)
1019 struct dsp_rpatch
*rpatch
= &mgr
->rpatch
;
1020 char s
[2 * DSP_LINE_NAME_SIZE
+ 5];
1024 if (in
< 0 || in
> DSP_NUM_INPUTS
|| out
< 0 || out
> DSP_NUM_OUTPUTS
)
1030 if (test_and_clear_bit(in
, &rpatch
->route
[out
])) {
1031 /* don't remove the route if it is the last one connected to a dsp program */
1032 if ( ( rpatch
->route
[out
] || rpatch
->route_v
[out
] || dsp_output_unused(&mgr
->opatch_list
,out
) )) {
1034 if (dsp_input_unused(&mgr
->ipatch_list
,in
))
1040 for (i
= 0; i
< DSP_NUM_OUTPUTS
; i
++)
1041 if ( test_bit(in
, &rpatch
->route
[i
]) || test_bit(in
, &rpatch
->route_v
[i
]))
1045 set_bit(in
, &rpatch
->route
[out
]);
1047 } else if (test_and_clear_bit(in
, &rpatch
->route_v
[out
])) {
1048 sprintf(s
, "Vol %s:%s", dsp_in_name
[in
], dsp_out_name
[out
]);
1049 addr
= find_control_gpr_addr(mgr
, rpatch
->name
, s
) - GPR_BASE
;
1053 if (rpatch
->route_v
[out
] || rpatch
->route
[out
] ||dsp_output_unused(&mgr
->opatch_list
,out
)) {
1055 if (dsp_input_unused(&mgr
->ipatch_list
,in
)){
1056 free_gpr(mgr
, addr
, rpatch
->gpr_used
);
1060 for (i
= 0; i
< DSP_NUM_OUTPUTS
; i
++)
1061 if (test_bit(in
, &rpatch
->route
[i
]) || test_bit(in
, &rpatch
->route_v
[i
])) {
1062 free_gpr(mgr
, addr
, rpatch
->gpr_used
);
1067 set_bit(in
, &rpatch
->route_v
[out
]);
1074 int dsp_del_route_name(struct dsp_patch_manager
*mgr
, const char *name
)
1076 int in1
, in2
, out1
, out2
, ret
;
1078 if(!get_stereo_route_name(mgr
, name
, &in1
, &in2
, &out1
, &out2
)){
1079 if((ret
=dsp_del_route(mgr
, in1
, out1
)))
1081 if(in2
<0 && out2
>0 )
1082 return dsp_del_route(mgr
, in1
, out2
);
1085 return dsp_del_route(mgr
, in2
, out2
);
1087 return dsp_del_route(mgr
, in2
, out1
);
1094 int dsp_add_route(struct dsp_patch_manager
*mgr
, int in
, int out
)
1096 struct dsp_rpatch
*rpatch
= &mgr
->rpatch
;
1097 char s
[2 * DSP_LINE_NAME_SIZE
+ 5];
1100 if (in
< 0 || in
> DSP_NUM_INPUTS
|| out
< 0 || out
> DSP_NUM_OUTPUTS
)
1106 set_bit(in
, &rpatch
->route
[out
]);
1108 if (test_bit(in
, &rpatch
->route_v
[out
])) {
1109 sprintf(s
, "Vol %s:%s", dsp_in_name
[in
], dsp_out_name
[out
]);
1110 addr
= find_control_gpr_addr(mgr
, rpatch
->name
, s
) - GPR_BASE
;
1114 free_gpr(mgr
, addr
, rpatch
->gpr_used
);
1115 clear_bit(in
, &rpatch
->route_v
[out
]);
1121 int dsp_add_route_name(struct dsp_patch_manager
*mgr
, const char *name
)
1123 int in1
, in2
, out1
, out2
, ret
;
1125 if(!get_stereo_route_name(mgr
, name
, &in1
, &in2
, &out1
, &out2
)){
1127 if((ret
=dsp_add_route(mgr
, in1
, out1
)))
1129 if(in2
<0 && out2
>0 )
1130 return dsp_add_route(mgr
, in1
, out2
);
1133 return dsp_add_route(mgr
, in2
, out2
);
1135 return dsp_add_route(mgr
, in2
, out1
);
1144 int dsp_add_route_v(struct dsp_patch_manager
*mgr
, int in
, int out
)
1146 char gpr_name
[DSP_GPR_NAME_SIZE
];
1148 if (in
< 0 || in
> DSP_NUM_INPUTS
|| out
< 0 || out
> DSP_NUM_OUTPUTS
)
1154 if (!test_and_set_bit(in
, &mgr
->rpatch
.route_v
[out
])) {
1155 sprintf(gpr_name
, "Vol %s:%s", dsp_in_name
[in
], dsp_out_name
[out
]);
1156 if (get_control_gpr(mgr
, 0x7fffffff, 0, 0x7fffffff, gpr_name
, mgr
->rpatch
.gpr_used
, NULL
) < 0)
1160 clear_bit(in
, &mgr
->rpatch
.route
[out
]);
1164 int dsp_add_route_v_name(struct dsp_patch_manager
*mgr
, const char *name
)
1166 int in1
, in2
, out1
, out2
, ret
;
1168 if(!get_stereo_route_name(mgr
, name
, &in1
, &in2
, &out1
, &out2
)){
1170 if((ret
=dsp_add_route_v(mgr
, in1
, out1
)))
1172 if(in2
<0 && out2
>0 )
1173 return dsp_add_route_v(mgr
, in1
, out2
);
1176 return dsp_add_route_v(mgr
, in2
, out2
);
1178 return dsp_add_route_v(mgr
, in2
, out1
);
1185 void dsp_print_inputs_name(void)
1189 printf("Inputs:\n");
1191 for (i
= 0; i
< DSP_NUM_INPUTS
; i
++)
1192 printf(" %s\n", dsp_in_name
[i
]);
1194 void dsp_print_outputs_name(void)
1198 printf("Outputs:\n");
1200 for (i
= 0; i
< DSP_NUM_OUTPUTS
; i
++)
1201 printf(" %s\n", dsp_out_name
[i
]);
1204 int dsp_set_oss_control_gpr(struct dsp_patch_manager
*mgr
, const char *patch_name
, const char *gpr_name
, const char *mixer_name
)
1206 int addr
, i
, mix
, ch
;
1208 static char channel_name
[2][3] = { "_l", "_r" };
1210 for (mix
= 0; mix
< SOUND_MIXER_NRDEVICES
; mix
++) {
1211 i
= strlen(oss_mixer_name
[mix
]);
1213 if (strncmp(mixer_name
, oss_mixer_name
[mix
], i
) == 0) {
1215 if (mixer_name
[i
] == '\0')
1218 for (; ch
< 2; ch
++) {
1219 if (strcmp(&mixer_name
[i
], channel_name
[ch
]) == 0)
1231 for (i
= 0; i
< DSP_NUM_GPRS
; i
++) {
1232 if ((mgr
->gpr
[i
].mixer_id
== mix
) &&
1233 (mgr
->gpr
[i
].mixer_ch
== ch
))
1234 mgr
->gpr
[i
].mixer_id
= SOUND_MIXER_NONE
;
1237 if((*patch_name
==0) &&(*gpr_name
==0))
1240 addr
= find_control_gpr_addr(mgr
, patch_name
, gpr_name
);
1242 mgr
->gpr
[addr
- GPR_BASE
].mixer_id
= mix
;
1243 mgr
->gpr
[addr
- GPR_BASE
].mixer_ch
= ch
;
1249 void dsp_unload_all(struct dsp_patch_manager
*mgr
)
1253 for (i
= 0; i
< DSP_NUM_INPUTS
; i
++)
1254 INIT_LIST_HEAD(&mgr
->ipatch_list
);
1256 for (i
= 0; i
< DSP_NUM_OUTPUTS
; i
++)
1257 INIT_LIST_HEAD(&mgr
->opatch_list
);
1259 mgr
->traml_efree_start
= 0;
1260 mgr
->traml_ifree_start
= 0;
1262 mgr
->tramb_efree_start
= 0;
1263 mgr
->tramb_ifree_start
= 0;
1265 mgr
->code_free_start
= 0;
1266 mgr
->icode_free_start
= DSP_CODE_SIZE
;
1268 memset(&mgr
->rpatch
, 0, sizeof(struct dsp_rpatch
));
1269 strcpy(mgr
->rpatch
.name
, "Routing");
1270 mgr
->rpatch
.code
= (__u32
*) malloc(DSP_CODE_SIZE
* sizeof(__u32
));
1272 for (i
= 0; i
< DSP_NUM_GPRS
; i
++){
1273 mgr
->gpr
[i
].type
= GPR_TYPE_NULL
;
1274 mgr
->gpr
[i
].usage
=0;
1277 init_io_gprs_table(mgr
);