1/*
2 **********************************************************************
3 *     cardwi.c - PCM input HAL for emu10k1 driver
4 *     Copyright 1999, 2000 Creative Labs, Inc.
5 *
6 **********************************************************************
7 *
8 *     Date                 Author          Summary of changes
9 *     ----                 ------          ------------------
10 *     October 20, 1999     Bertrand Lee    base code release
11 *
12 **********************************************************************
13 *
14 *     This program is free software; you can redistribute it and/or
15 *     modify it under the terms of the GNU General Public License as
16 *     published by the Free Software Foundation; either version 2 of
17 *     the License, or (at your option) any later version.
18 *
19 *     This program is distributed in the hope that it will be useful,
20 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
21 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 *     GNU General Public License for more details.
23 *
24 *     You should have received a copy of the GNU General Public
25 *     License along with this program; if not, write to the Free
26 *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
27 *     USA.
28 *
29 **********************************************************************
30 */
31
32#include <linux/poll.h>
33#include "hwaccess.h"
34#include "timer.h"
35#include "recmgr.h"
36#include "audio.h"
37#include "cardwi.h"
38
39/**
40 * query_format - returns a valid sound format
41 *
42 * This function will return a valid sound format as close
43 * to the requested one as possible.
44 */
45static void query_format(int recsrc, struct wave_format *wave_fmt)
46{
47
48	switch (recsrc) {
49	case WAVERECORD_AC97:
50
51		if ((wave_fmt->channels != 1) && (wave_fmt->channels != 2))
52			wave_fmt->channels = 2;
53
54		if (wave_fmt->samplingrate >= (0xBB80 + 0xAC44) / 2)
55			wave_fmt->samplingrate = 0xBB80;
56		else if (wave_fmt->samplingrate >= (0xAC44 + 0x7D00) / 2)
57			wave_fmt->samplingrate = 0xAC44;
58		else if (wave_fmt->samplingrate >= (0x7D00 + 0x5DC0) / 2)
59			wave_fmt->samplingrate = 0x7D00;
60		else if (wave_fmt->samplingrate >= (0x5DC0 + 0x5622) / 2)
61			wave_fmt->samplingrate = 0x5DC0;
62		else if (wave_fmt->samplingrate >= (0x5622 + 0x3E80) / 2)
63			wave_fmt->samplingrate = 0x5622;
64		else if (wave_fmt->samplingrate >= (0x3E80 + 0x2B11) / 2)
65			wave_fmt->samplingrate = 0x3E80;
66		else if (wave_fmt->samplingrate >= (0x2B11 + 0x1F40) / 2)
67			wave_fmt->samplingrate = 0x2B11;
68		else
69			wave_fmt->samplingrate = 0x1F40;
70
71		switch (wave_fmt->id) {
72		case AFMT_S16_LE:
73			wave_fmt->bitsperchannel = 16;
74			break;
75		case AFMT_U8:
76			wave_fmt->bitsperchannel = 8;
77			break;
78		default:
79			wave_fmt->id = AFMT_S16_LE;
80			wave_fmt->bitsperchannel = 16;
81			break;
82		}
83
84		break;
85
86	/* these can't be changed from the original values */
87	case WAVERECORD_MIC:
88	case WAVERECORD_FX:
89		break;
90
91	default:
92		BUG();
93		break;
94	}
95
96	wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;
97	wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
98	wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
99	wave_fmt->bytespervoicesample = wave_fmt->bytespersample;
100}
101
102static int alloc_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
103{
104	buffer->addr = pci_alloc_consistent(card->pci_dev, buffer->size * buffer->cov,
105					    &buffer->dma_handle);
106	if (buffer->addr == NULL)
107		return -1;
108
109	return 0;
110}
111
112static void free_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
113{
114	if (buffer->addr != NULL)
115		pci_free_consistent(card->pci_dev, buffer->size * buffer->cov,
116				    buffer->addr, buffer->dma_handle);
117}
118
119int emu10k1_wavein_open(struct emu10k1_wavedevice *wave_dev)
120{
121	struct emu10k1_card *card = wave_dev->card;
122	struct wiinst *wiinst = wave_dev->wiinst;
123	struct wiinst **wiinst_tmp = NULL;
124	u16 delay;
125	unsigned long flags;
126
127	DPF(2, "emu10k1_wavein_open()\n");
128
129	switch (wiinst->recsrc) {
130	case WAVERECORD_AC97:
131		wiinst_tmp = &card->wavein.ac97;
132		break;
133	case WAVERECORD_MIC:
134		wiinst_tmp = &card->wavein.mic;
135		break;
136	case WAVERECORD_FX:
137		wiinst_tmp = &card->wavein.fx;
138		break;
139	default:
140		BUG();
141		break;
142	}
143
144	spin_lock_irqsave(&card->lock, flags);
145	if (*wiinst_tmp != NULL) {
146		spin_unlock_irqrestore(&card->lock, flags);
147		return -1;
148	}
149
150	*wiinst_tmp = wiinst;
151	spin_unlock_irqrestore(&card->lock, flags);
152
153	/* handle 8 bit recording */
154	if (wiinst->format.bytesperchannel == 1) {
155		if (wiinst->buffer.size > 0x8000) {
156			wiinst->buffer.size = 0x8000;
157			wiinst->buffer.sizeregval = 0x1f;
158		} else
159			wiinst->buffer.sizeregval += 4;
160
161		wiinst->buffer.cov = 2;
162	} else
163		wiinst->buffer.cov = 1;
164
165	if (alloc_buffer(card, &wiinst->buffer) < 0) {
166		ERROR();
167		return -1;
168	}
169
170	emu10k1_set_record_src(card, wiinst);
171
172	emu10k1_reset_record(card, &wiinst->buffer);
173
174	wiinst->buffer.hw_pos = 0;
175	wiinst->buffer.pos = 0;
176	wiinst->buffer.bytestocopy = 0;
177
178	delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;
179
180	emu10k1_timer_install(card, &wiinst->timer, delay / 2);
181
182	wiinst->state = WAVE_STATE_OPEN;
183
184	return 0;
185}
186
187void emu10k1_wavein_close(struct emu10k1_wavedevice *wave_dev)
188{
189	struct emu10k1_card *card = wave_dev->card;
190	struct wiinst *wiinst = wave_dev->wiinst;
191	unsigned long flags;
192
193	DPF(2, "emu10k1_wavein_close()\n");
194
195	emu10k1_wavein_stop(wave_dev);
196
197	emu10k1_timer_uninstall(card, &wiinst->timer);
198
199	free_buffer(card, &wiinst->buffer);
200
201	spin_lock_irqsave(&card->lock, flags);
202	switch (wave_dev->wiinst->recsrc) {
203	case WAVERECORD_AC97:
204		card->wavein.ac97 = NULL;
205		break;
206	case WAVERECORD_MIC:
207		card->wavein.mic = NULL;
208		break;
209	case WAVERECORD_FX:
210		card->wavein.fx = NULL;
211		break;
212	default:
213		BUG();
214		break;
215	}
216	spin_unlock_irqrestore(&card->lock, flags);
217
218	wiinst->state = WAVE_STATE_CLOSED;
219}
220
221void emu10k1_wavein_start(struct emu10k1_wavedevice *wave_dev)
222{
223	struct emu10k1_card *card = wave_dev->card;
224	struct wiinst *wiinst = wave_dev->wiinst;
225
226	DPF(2, "emu10k1_wavein_start()\n");
227
228	emu10k1_start_record(card, &wiinst->buffer);
229	emu10k1_timer_enable(wave_dev->card, &wiinst->timer);
230
231	wiinst->state |= WAVE_STATE_STARTED;
232}
233
234void emu10k1_wavein_stop(struct emu10k1_wavedevice *wave_dev)
235{
236	struct emu10k1_card *card = wave_dev->card;
237	struct wiinst *wiinst = wave_dev->wiinst;
238
239	DPF(2, "emu10k1_wavein_stop()\n");
240
241	if (!(wiinst->state & WAVE_STATE_STARTED))
242		return;
243
244	emu10k1_timer_disable(card, &wiinst->timer);
245	emu10k1_stop_record(card, &wiinst->buffer);
246
247	wiinst->state &= ~WAVE_STATE_STARTED;
248}
249
250int emu10k1_wavein_setformat(struct emu10k1_wavedevice *wave_dev, struct wave_format *format)
251{
252	struct emu10k1_card *card = wave_dev->card;
253	struct wiinst *wiinst = wave_dev->wiinst;
254	u16 delay;
255
256	DPF(2, "emu10k1_wavein_setformat()\n");
257
258	if (wiinst->state & WAVE_STATE_STARTED)
259		return -1;
260
261	query_format(wiinst->recsrc, format);
262
263	if ((wiinst->format.samplingrate != format->samplingrate)
264	    || (wiinst->format.bitsperchannel != format->bitsperchannel)
265	    || (wiinst->format.channels != format->channels)) {
266
267		wiinst->format = *format;
268
269		if (wiinst->state == WAVE_STATE_CLOSED)
270			return 0;
271
272		wiinst->buffer.size *= wiinst->buffer.cov;
273
274		if (wiinst->format.bytesperchannel == 1) {
275			wiinst->buffer.cov = 2;
276			wiinst->buffer.size /= wiinst->buffer.cov;
277		} else
278			wiinst->buffer.cov = 1;
279
280		emu10k1_timer_uninstall(card, &wiinst->timer);
281
282		delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;
283
284		emu10k1_timer_install(card, &wiinst->timer, delay / 2);
285	}
286
287	return 0;
288}
289
290void emu10k1_wavein_getxfersize(struct wiinst *wiinst, u32 * size)
291{
292	struct wavein_buffer *buffer = &wiinst->buffer;
293
294	*size = buffer->bytestocopy;
295
296	if (wiinst->mmapped)
297		return;
298
299	if (*size > buffer->size) {
300		*size = buffer->size;
301		buffer->pos = buffer->hw_pos;
302		buffer->bytestocopy = buffer->size;
303		DPF(1, "buffer overrun\n");
304	}
305}
306
307static int copy_block(u8 __user *dst, u8 * src, u32 str, u32 len, u8 cov)
308{
309	if (cov == 1) {
310		if (__copy_to_user(dst, src + str, len))
311			return -EFAULT;
312	} else {
313		u8 byte;
314		u32 i;
315
316		src += 1 + 2 * str;
317
318		for (i = 0; i < len; i++) {
319			byte = src[2 * i] ^ 0x80;
320			if (__copy_to_user(dst + i, &byte, 1))
321				return -EFAULT;
322		}
323	}
324
325	return 0;
326}
327
328int emu10k1_wavein_xferdata(struct wiinst *wiinst, u8 __user *data, u32 * size)
329{
330	struct wavein_buffer *buffer = &wiinst->buffer;
331	u32 sizetocopy, sizetocopy_now, start;
332	unsigned long flags;
333	int ret;
334
335	sizetocopy = min_t(u32, buffer->size, *size);
336	*size = sizetocopy;
337
338	if (!sizetocopy)
339		return 0;
340
341	spin_lock_irqsave(&wiinst->lock, flags);
342	start = buffer->pos;
343	buffer->pos += sizetocopy;
344	buffer->pos %= buffer->size;
345	buffer->bytestocopy -= sizetocopy;
346	sizetocopy_now = buffer->size - start;
347
348	spin_unlock_irqrestore(&wiinst->lock, flags);
349
350	if (sizetocopy > sizetocopy_now) {
351		sizetocopy -= sizetocopy_now;
352
353		ret = copy_block(data, buffer->addr, start, sizetocopy_now,
354				 buffer->cov);
355		if (ret == 0)
356			ret = copy_block(data + sizetocopy_now, buffer->addr, 0,
357					 sizetocopy, buffer->cov);
358	} else {
359		ret = copy_block(data, buffer->addr, start, sizetocopy,
360				 buffer->cov);
361	}
362
363	return ret;
364}
365
366void emu10k1_wavein_update(struct emu10k1_card *card, struct wiinst *wiinst)
367{
368	u32 hw_pos;
369	u32 diff;
370
371	/* There is no actual start yet */
372	if (!(wiinst->state & WAVE_STATE_STARTED)) {
373		hw_pos = wiinst->buffer.hw_pos;
374	} else {
375		/* hw_pos in byte units */
376		hw_pos = sblive_readptr(card, wiinst->buffer.idxreg, 0) / wiinst->buffer.cov;
377	}
378
379	diff = (wiinst->buffer.size + hw_pos - wiinst->buffer.hw_pos) % wiinst->buffer.size;
380	wiinst->total_recorded += diff;
381	wiinst->buffer.bytestocopy += diff;
382
383	wiinst->buffer.hw_pos = hw_pos;
384}
385