xref: /haiku/src/add-ons/kernel/drivers/audio/ac97/auich/io.c (revision 1b8f7f13a3dc70e0e903cb94248220b40b732204)
1 /*
2  * Auich BeOS Driver for Intel Southbridge audio
3  *
4  * Copyright (c) 2003, Jerome Duval (jerome.duval@free.fr)
5  *
6  * Original code : BeOS Driver for Intel ICH AC'97 Link interface
7  * Copyright (c) 2002, Marcus Overhagen <marcus@overhagen.de>
8  *
9  * All rights reserved.
10  * Redistribution and use in source and binary forms, with or without modification,
11  * are permitted provided that the following conditions are met:
12  *
13  * - Redistributions of source code must retain the above copyright notice,
14  *   this list of conditions and the following disclaimer.
15  * - Redistributions in binary form must reproduce the above copyright notice,
16  *   this list of conditions and the following disclaimer in the documentation
17  *   and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  */
31 #include <KernelExport.h>
32 #include <OS.h>
33 #include "io.h"
34 #include "auichreg.h"
35 #include "debug.h"
36 #include <PCI.h>
37 
38 extern pci_module_info  *pci;
39 
40 uint8
41 auich_reg_read_8(device_config *config, int regno)
42 {
43 	ASSERT(regno >= 0);
44 	ASSERT(((config->type & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63);
45 	if (config->type & TYPE_ICH4)
46 		return *(uint8 *)(((char *)config->log_mbbar) + regno);
47 	else
48 		return pci->read_io_8(config->nabmbar + regno);
49 }
50 
51 uint16
52 auich_reg_read_16(device_config *config, int regno)
53 {
54 	ASSERT(regno >= 0);
55 	ASSERT(((config->type & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63);
56 	if (config->type & TYPE_ICH4)
57 		return *(uint16 *)(((char *)config->log_mbbar) + regno);
58 	else
59 		return pci->read_io_16(config->nabmbar + regno);
60 }
61 
62 uint32
63 auich_reg_read_32(device_config *config, int regno)
64 {
65 	ASSERT(regno >= 0);
66 	ASSERT(((config->type & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63);
67 	if (config->type & TYPE_ICH4)
68 		return *(uint32 *)(((char *)config->log_mbbar) + regno);
69 	else
70 		return pci->read_io_32(config->nabmbar + regno);
71 }
72 
73 void
74 auich_reg_write_8(device_config *config, int regno, uint8 value)
75 {
76 	ASSERT(regno >= 0);
77 	ASSERT(((config->type & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63);
78 	if (config->type & TYPE_ICH4)
79 		*(uint8 *)(((char *)config->log_mbbar) + regno) = value;
80 	else
81 		pci->write_io_8(config->nabmbar + regno, value);
82 }
83 
84 void
85 auich_reg_write_16(device_config *config, int regno, uint16 value)
86 {
87 	ASSERT(regno >= 0);
88 	ASSERT(((config->type & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63);
89 	if (config->type & TYPE_ICH4)
90 		*(uint16 *)(((char *)config->log_mbbar) + regno) = value;
91 	else
92 		pci->write_io_16(config->nabmbar + regno, value);
93 }
94 
95 void
96 auich_reg_write_32(device_config *config, int regno, uint32 value)
97 {
98 	ASSERT(regno >= 0);
99 	ASSERT(((config->type & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63);
100 	if (config->type & TYPE_ICH4)
101 		*(uint32 *)(((char *)config->log_mbbar) + regno) = value;
102 	else
103 		pci->write_io_32(config->nabmbar + regno, value);
104 }
105 
106 /* codec */
107 static int
108 auich_codec_wait(device_config *config)
109 {
110 	int i;
111 	for (i = 0; i < 1100; i++) {
112 		if ((auich_reg_read_8(config, AUICH_REG_ACC_SEMA) & 0x01) == 0)
113 			return B_OK;
114 		if (i > 100)
115 			snooze(10);
116 	}
117 	return B_TIMED_OUT;
118 }
119 
120 uint16
121 auich_codec_read(device_config *config, int regno)
122 {
123 	ASSERT(regno >= 0);
124 	ASSERT(((config->type & TYPE_ICH4) != 0 && regno <= 511) || regno <= 255);
125 	if(auich_codec_wait(config)!=B_OK) {
126 		PRINT(("codec busy (2)\n"));
127 		return -1;
128 	}
129 
130 	if (config->type & TYPE_ICH4)
131 		return *(uint16 *)(((char *)config->log_mmbar) + regno);
132 	else
133 		return pci->read_io_16(config->nambar + regno);
134 }
135 
136 void
137 auich_codec_write(device_config *config, int regno, uint16 value)
138 {
139 	ASSERT(regno >= 0);
140 	ASSERT(((config->type & TYPE_ICH4) != 0 && regno <= 511) || regno <= 255);
141 	if(auich_codec_wait(config)!=B_OK) {
142 		PRINT(("codec busy (4)\n"));
143 		return;
144 	}
145 	if (config->type & TYPE_ICH4)
146 		*(uint16 *)(((char *)config->log_mmbar) + regno) = value;
147 	else
148 		pci->write_io_16(config->nambar + regno, value);
149 }
150