1/*
2 * BeOS Driver for Intel ICH AC'97 Link interface
3 *
4 * Copyright (C) 2002-2004, Marcus Overhagen <marcus@overhagen.de>
5 *
6 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without modification,
8 * are permitted provided that the following conditions are met:
9 *
10 * - Redistributions of source code must retain the above copyright notice,
11 *   this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright notice,
13 *   this list of conditions and the following disclaimer in the documentation
14 *   and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28#include <KernelExport.h>
29#include <OS.h>
30#include "debug.h"
31#include "hardware.h"
32#include "ichaudio.h"
33#include "io.h"
34
35status_t ich_codec_wait(ichaudio_cookie *cookie);
36
37uint8
38ich_reg_read_8(ichaudio_cookie *cookie, int regno)
39{
40	ASSERT(regno >= 0);
41	ASSERT(((cookie->flags & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63);
42	if (cookie->flags & TYPE_ICH4)
43		return *(uint8 *)((char *)cookie->mbbar + regno);
44	else
45		return cookie->pci->read_io_8(cookie->nabmbar + regno);
46}
47
48uint16
49ich_reg_read_16(ichaudio_cookie *cookie, int regno)
50{
51	ASSERT(regno >= 0);
52	ASSERT(((cookie->flags & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63);
53	if (cookie->flags & TYPE_ICH4)
54		return *(uint16 *)((char *)cookie->mbbar + regno);
55	else
56		return cookie->pci->read_io_16(cookie->nabmbar + regno);
57}
58
59uint32
60ich_reg_read_32(ichaudio_cookie *cookie, int regno)
61{
62	ASSERT(regno >= 0);
63	ASSERT(((cookie->flags & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63);
64
65	if (cookie->flags & TYPE_ICH4)
66		return *(uint32 *)((char *)cookie->mbbar + regno);
67	else
68		return cookie->pci->read_io_32(cookie->nabmbar + regno);
69}
70
71void
72ich_reg_write_8(ichaudio_cookie *cookie, int regno, uint8 value)
73{
74	ASSERT(regno >= 0);
75	ASSERT(((cookie->flags & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63);
76
77	if (cookie->flags & TYPE_ICH4)
78		*(uint8 *)((char *)cookie->mbbar + regno) = value;
79	else
80		cookie->pci->write_io_8(cookie->nabmbar + regno, value);
81}
82
83void
84ich_reg_write_16(ichaudio_cookie *cookie, int regno, uint16 value)
85{
86	ASSERT(regno >= 0);
87	ASSERT(((cookie->flags & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63);
88
89	if (cookie->flags & TYPE_ICH4)
90		*(uint16 *)((char *)cookie->mbbar + regno) = value;
91	else
92		cookie->pci->write_io_16(cookie->nabmbar + regno, value);
93}
94
95void
96ich_reg_write_32(ichaudio_cookie *cookie, int regno, uint32 value)
97{
98	ASSERT(regno >= 0);
99	ASSERT(((cookie->flags & TYPE_ICH4) != 0 && regno <= 255) || regno <= 63);
100
101	if (cookie->flags & TYPE_ICH4)
102		*(uint32 *)((char *)cookie->mbbar + regno) = value;
103	else
104		cookie->pci->write_io_32(cookie->nabmbar + regno, value);
105}
106
107status_t
108ich_codec_wait(ichaudio_cookie *cookie)
109{
110	int i;
111	for (i = 0; i < 1100; i++) {
112		if ((ich_reg_read_8(cookie, ICH_REG_ACC_SEMA) & 0x01) == 0)
113			return B_OK;
114		if (i > 100)
115			snooze(1);
116	}
117	return B_TIMED_OUT;
118}
119
120uint16
121ich_codec_read(void *_cookie, int regno)
122{
123	ichaudio_cookie *cookie = (ichaudio_cookie *)_cookie;
124
125	ASSERT(regno >= 0);
126	ASSERT((regno & 1) == 0);
127	ASSERT(((cookie->flags & TYPE_ICH4) != 0 && regno <= 511) || regno <= 255);
128
129	if (regno == 0x54) // intel uses 0x54 for GPIO access, we filter it!
130		return 0;
131	if (B_OK != ich_codec_wait(cookie))
132		PRINT(("semaphore timeout reading register %#x\n", regno));
133	if (cookie->flags & TYPE_ICH4)
134		return *(uint16 *)(((char *)cookie->mmbar) + regno);
135	else
136		return cookie->pci->read_io_16(cookie->nambar + regno);
137}
138
139void
140ich_codec_write(void *_cookie, int regno, uint16 value)
141{
142	ichaudio_cookie *cookie = (ichaudio_cookie *)_cookie;
143
144	ASSERT(regno >= 0);
145	ASSERT((regno & 1) == 0);
146	ASSERT(((cookie->flags & TYPE_ICH4) != 0 && regno <= 511) || regno <= 255);
147
148	if (regno == 0x54) // intel uses 0x54 for GPIO access, we filter it!
149		return;
150	if (B_OK != ich_codec_wait(cookie))
151		PRINT(("semaphore timeout writing register %#x\n", regno));
152	if (cookie->flags & TYPE_ICH4)
153		*(uint16 *)(((char *)cookie->mmbar) + regno) = value;
154	else
155		cookie->pci->write_io_16(cookie->nambar + regno, value);
156}
157