xref: /haiku/src/add-ons/kernel/drivers/audio/ac97/auvia/io.c (revision 9eb55bc1d104b8fda80898f8b25c94d8000c8255)
1 /*
2  * Auvia BeOS Driver for Via VT82xx 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 "auviareg.h"
35 #include "debug.h"
36 
37 /*
38  * from BeOS R3 KernelExport.h
39  * should be replaced by PCI bus manager functions
40  */
41 uint8         read_io_8(int mapped_io_addr);
42 void          write_io_8(int mapped_io_addr, uint8 value);
43 uint16        read_io_16(int mapped_io_addr);
44 void          write_io_16(int mapped_io_addr, uint16 value);
45 uint32        read_io_32(int mapped_io_addr);
46 void          write_io_32(int mapped_io_addr, uint32 value);
47 
48 uint8
49 auvia_reg_read_8(device_config *config, int regno)
50 {
51 	return read_io_8(config->nabmbar + regno);
52 }
53 
54 uint16
55 auvia_reg_read_16(device_config *config, int regno)
56 {
57 	return read_io_16(config->nabmbar + regno);
58 }
59 
60 uint32
61 auvia_reg_read_32(device_config *config, int regno)
62 {
63 	return read_io_32(config->nabmbar + regno);
64 }
65 
66 void
67 auvia_reg_write_8(device_config *config, int regno, uint8 value)
68 {
69 	write_io_8(config->nabmbar + regno, value);
70 }
71 
72 void
73 auvia_reg_write_16(device_config *config, int regno, uint16 value)
74 {
75 	write_io_16(config->nabmbar + regno, value);
76 }
77 
78 void
79 auvia_reg_write_32(device_config *config, int regno, uint32 value)
80 {
81 	write_io_32(config->nabmbar + regno, value);
82 }
83 
84 /* codec */
85 
86 #define AUVIA_TIMEOUT 	200
87 
88 int
89 auvia_codec_waitready(device_config *config)
90 {
91 	int i;
92 
93 	/* poll until codec not busy */
94 	for(i=0; (i<AUVIA_TIMEOUT) && (read_io_32(config->nabmbar
95 		+ AUVIA_CODEC_CTL) & AUVIA_CODEC_BUSY) ; i++)
96 		snooze(1);
97 	if(i>=AUVIA_TIMEOUT) {
98 		//PRINT(("codec busy\n"));
99 		return B_ERROR;
100 	}
101 	return B_OK;
102 }
103 
104 int
105 auvia_codec_waitvalid(device_config *config)
106 {
107 	int i;
108 
109 	/* poll until codec valid */
110 	for(i=0; (i<AUVIA_TIMEOUT) && !(read_io_32(config->nabmbar
111 		+ AUVIA_CODEC_CTL) & AUVIA_CODEC_PRIVALID) ; i++)
112 		snooze(1);
113 	if(i>=AUVIA_TIMEOUT) {
114 		//PRINT(("codec invalid\n"));
115 		return B_ERROR;
116 	}
117 	return B_OK;
118 }
119 
120 uint16
121 auvia_codec_read(device_config *config, int regno)
122 {
123 	if(auvia_codec_waitready(config)!=B_OK) {
124 		PRINT(("codec busy (1)\n"));
125 		return -1;
126 	}
127 	write_io_32(config->nabmbar + AUVIA_CODEC_CTL,
128 		AUVIA_CODEC_PRIVALID | AUVIA_CODEC_READ | AUVIA_CODEC_INDEX(regno));
129 
130 	if(auvia_codec_waitready(config)!=B_OK) {
131 		PRINT(("codec busy (2)\n"));
132 		return -1;
133 	}
134 	if(auvia_codec_waitvalid(config)!=B_OK) {
135 		PRINT(("codec invalid (3)\n"));
136 		return -1;
137 	}
138 
139 	return read_io_16(config->nabmbar + AUVIA_CODEC_CTL);
140 }
141 
142 void
143 auvia_codec_write(device_config *config, int regno, uint16 value)
144 {
145 	if(auvia_codec_waitready(config)!=B_OK) {
146 		PRINT(("codec busy (4)\n"));
147 		return;
148 	}
149 	write_io_32(config->nabmbar + AUVIA_CODEC_CTL,
150 		AUVIA_CODEC_PRIVALID | AUVIA_CODEC_INDEX(regno) | value);
151 }
152