File Index
Files and directories
Sign in
FILE

es1688_lib.c

File preview with syntax highlighting.

linux-6.19.14/sound/isa/es1688/es1688_lib.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
  4 *  Routines for control of ESS ES1688/688/488 chip
  5 */
  6
  7#include <linux/init.h>
  8#include <linux/interrupt.h>
  9#include <linux/delay.h>
 10#include <linux/slab.h>
 11#include <linux/ioport.h>
 12#include <linux/module.h>
 13#include <linux/io.h>
 14#include <sound/core.h>
 15#include <sound/es1688.h>
 16#include <sound/initval.h>
 17
 18#include <asm/dma.h>
 19
 20MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
 21MODULE_DESCRIPTION("ESS ESx688 lowlevel module");
 22MODULE_LICENSE("GPL");
 23
 24static int snd_es1688_dsp_command(struct snd_es1688 *chip, unsigned char val)
 25{
 26	int i;
 27
 28	for (i = 10000; i; i--)
 29		if ((inb(ES1688P(chip, STATUS)) & 0x80) == 0) {
 30			outb(val, ES1688P(chip, COMMAND));
 31			return 1;
 32		}
 33	dev_dbg(chip->card->dev, "%s: timeout (0x%x)\n", __func__, val);
 34	return 0;
 35}
 36
 37static int snd_es1688_dsp_get_byte(struct snd_es1688 *chip)
 38{
 39	int i;
 40
 41	for (i = 1000; i; i--)
 42		if (inb(ES1688P(chip, DATA_AVAIL)) & 0x80)
 43			return inb(ES1688P(chip, READ));
 44	dev_dbg(chip->card->dev, "es1688 get byte failed: 0x%lx = 0x%x!!!\n",
 45		ES1688P(chip, DATA_AVAIL), inb(ES1688P(chip, DATA_AVAIL)));
 46	return -ENODEV;
 47}
 48
 49static int snd_es1688_write(struct snd_es1688 *chip,
 50			    unsigned char reg, unsigned char data)
 51{
 52	if (!snd_es1688_dsp_command(chip, reg))
 53		return 0;
 54	return snd_es1688_dsp_command(chip, data);
 55}
 56
 57static int snd_es1688_read(struct snd_es1688 *chip, unsigned char reg)
 58{
 59	/* Read a byte from an extended mode register of ES1688 */
 60	if (!snd_es1688_dsp_command(chip, 0xc0))
 61		return -1;
 62	if (!snd_es1688_dsp_command(chip, reg))
 63		return -1;
 64	return snd_es1688_dsp_get_byte(chip);
 65}
 66
 67void snd_es1688_mixer_write(struct snd_es1688 *chip,
 68			    unsigned char reg, unsigned char data)
 69{
 70	outb(reg, ES1688P(chip, MIXER_ADDR));
 71	udelay(10);
 72	outb(data, ES1688P(chip, MIXER_DATA));
 73	udelay(10);
 74}
 75
 76static unsigned char snd_es1688_mixer_read(struct snd_es1688 *chip, unsigned char reg)
 77{
 78	unsigned char result;
 79
 80	outb(reg, ES1688P(chip, MIXER_ADDR));
 81	udelay(10);
 82	result = inb(ES1688P(chip, MIXER_DATA));
 83	udelay(10);
 84	return result;
 85}
 86
 87int snd_es1688_reset(struct snd_es1688 *chip)
 88{
 89	int i;
 90
 91	outb(3, ES1688P(chip, RESET));		/* valid only for ESS chips, SB -> 1 */
 92	udelay(10);
 93	outb(0, ES1688P(chip, RESET));
 94	udelay(30);
 95	for (i = 0; i < 1000 && !(inb(ES1688P(chip, DATA_AVAIL)) & 0x80); i++);
 96	if (inb(ES1688P(chip, READ)) != 0xaa) {
 97		dev_dbg(chip->card->dev, "ess_reset at 0x%lx: failed!!!\n",
 98			chip->port);
 99		return -ENODEV;
100	}
101	snd_es1688_dsp_command(chip, 0xc6);	/* enable extended mode */
102	return 0;
103}
104EXPORT_SYMBOL(snd_es1688_reset);
105
106static int snd_es1688_probe(struct snd_es1688 *chip)
107{
108	unsigned short major, minor;
109	int i;
110
111	/*
112	 *  initialization sequence
113	 */
114
115	scoped_guard(spinlock_irqsave, &chip->reg_lock) {	/* Some ESS1688 cards need this */
116		inb(ES1688P(chip, ENABLE1));	/* ENABLE1 */
117		inb(ES1688P(chip, ENABLE1));	/* ENABLE1 */
118		inb(ES1688P(chip, ENABLE1));	/* ENABLE1 */
119		inb(ES1688P(chip, ENABLE2));	/* ENABLE2 */
120		inb(ES1688P(chip, ENABLE1));	/* ENABLE1 */
121		inb(ES1688P(chip, ENABLE2));	/* ENABLE2 */
122		inb(ES1688P(chip, ENABLE1));	/* ENABLE1 */
123		inb(ES1688P(chip, ENABLE1));	/* ENABLE1 */
124		inb(ES1688P(chip, ENABLE2));	/* ENABLE2 */
125		inb(ES1688P(chip, ENABLE1));	/* ENABLE1 */
126		inb(ES1688P(chip, ENABLE0));	/* ENABLE0 */
127
128		if (snd_es1688_reset(chip) < 0) {
129			dev_dbg(chip->card->dev, "ESS: [0x%lx] reset failed... 0x%x\n",
130				chip->port, inb(ES1688P(chip, READ)));
131			return -ENODEV;
132		}
133		snd_es1688_dsp_command(chip, 0xe7);	/* return identification */
134
135		for (i = 1000, major = minor = 0; i; i--) {
136			if (inb(ES1688P(chip, DATA_AVAIL)) & 0x80) {
137				if (major == 0)
138					major = inb(ES1688P(chip, READ));
139				else
140					minor = inb(ES1688P(chip, READ));
141			}
142		}
143	}
144
145	dev_dbg(chip->card->dev,
146		"ESS: [0x%lx] found.. major = 0x%x, minor = 0x%x\n",
147		chip->port, major, minor);
148
149	chip->version = (major << 8) | minor;
150	if (!chip->version)
151		return -ENODEV;	/* probably SB */
152
153	switch (chip->version & 0xfff0) {
154	case 0x4880:
155		dev_err(chip->card->dev,
156			"[0x%lx] ESS: AudioDrive ES488 detected, but driver is in another place\n",
157			chip->port);
158		return -ENODEV;
159	case 0x6880:
160		break;
161	default:
162		dev_err(chip->card->dev,
163			"[0x%lx] ESS: unknown AudioDrive chip with version 0x%x (Jazz16 soundcard?)\n",
164			chip->port, chip->version);
165		return -ENODEV;
166	}
167
168	scoped_guard(spinlock_irqsave, &chip->reg_lock) {
169		snd_es1688_write(chip, 0xb1, 0x10);	/* disable IRQ */
170		snd_es1688_write(chip, 0xb2, 0x00);	/* disable DMA */
171	}
172
173	/* enable joystick, but disable OPL3 */
174	scoped_guard(spinlock_irqsave, &chip->mixer_lock) {
175		snd_es1688_mixer_write(chip, 0x40, 0x01);
176	}
177
178	return 0;
179}
180
181static int snd_es1688_init(struct snd_es1688 * chip, int enable)
182{
183	static const int irqs[16] = {-1, -1, 0, -1, -1, 1, -1, 2, -1, 0, 3, -1, -1, -1, -1, -1};
184	int cfg, irq_bits, dma, dma_bits, tmp, tmp1;
185
186	/* ok.. setup MPU-401 port and joystick and OPL3 */
187	cfg = 0x01;		/* enable joystick, but disable OPL3 */
188	if (enable && chip->mpu_port >= 0x300 && chip->mpu_irq > 0 && chip->hardware != ES1688_HW_688) {
189		tmp = (chip->mpu_port & 0x0f0) >> 4;
190		if (tmp <= 3) {
191			switch (chip->mpu_irq) {
192			case 9:
193				tmp1 = 4;
194				break;
195			case 5:
196				tmp1 = 5;
197				break;
198			case 7:
199				tmp1 = 6;
200				break;
201			case 10:
202				tmp1 = 7;
203				break;
204			default:
205				tmp1 = 0;
206			}
207			if (tmp1) {
208				cfg |= (tmp << 3) | (tmp1 << 5);
209			}
210		}
211	}
212	scoped_guard(spinlock_irqsave, &chip->reg_lock) {
213		snd_es1688_mixer_write(chip, 0x40, cfg);
214	}
215	/* --- */
216	scoped_guard(spinlock_irqsave, &chip->reg_lock) {
217		snd_es1688_read(chip, 0xb1);
218		snd_es1688_read(chip, 0xb2);
219	}
220	if (enable) {
221		cfg = 0xf0;	/* enable only DMA counter interrupt */
222		irq_bits = irqs[chip->irq & 0x0f];
223		if (irq_bits < 0) {
224			dev_err(chip->card->dev,
225				"[0x%lx] ESS: bad IRQ %d for ES1688 chip!!\n",
226				chip->port, chip->irq);
227#if 0
228			irq_bits = 0;
229			cfg = 0x10;
230#endif
231			return -EINVAL;
232		}
233		scoped_guard(spinlock_irqsave, &chip->reg_lock) {
234			snd_es1688_write(chip, 0xb1, cfg | (irq_bits << 2));
235		}
236		cfg = 0xf0;	/* extended mode DMA enable */
237		dma = chip->dma8;
238		if (dma > 3 || dma == 2) {
239			dev_err(chip->card->dev,
240				"[0x%lx] ESS: bad DMA channel %d for ES1688 chip!!\n",
241				chip->port, dma);
242#if 0
243			dma_bits = 0;
244			cfg = 0x00;	/* disable all DMA */
245#endif
246			return -EINVAL;
247		} else {
248			dma_bits = dma;
249			if (dma != 3)
250				dma_bits++;
251		}
252		scoped_guard(spinlock_irqsave, &chip->reg_lock) {
253			snd_es1688_write(chip, 0xb2, cfg | (dma_bits << 2));
254		}
255	} else {
256		scoped_guard(spinlock_irqsave, &chip->reg_lock) {
257			snd_es1688_write(chip, 0xb1, 0x10);	/* disable IRQ */
258			snd_es1688_write(chip, 0xb2, 0x00);	/* disable DMA */
259		}
260	}
261	scoped_guard(spinlock_irqsave, &chip->reg_lock) {
262		snd_es1688_read(chip, 0xb1);
263		snd_es1688_read(chip, 0xb2);
264		snd_es1688_reset(chip);
265	}
266	return 0;
267}
268
269/*
270
271 */
272
273static const struct snd_ratnum clocks[2] = {
274	{
275		.num = 795444,
276		.den_min = 1,
277		.den_max = 128,
278		.den_step = 1,
279	},
280	{
281		.num = 397722,
282		.den_min = 1,
283		.den_max = 128,
284		.den_step = 1,
285	}
286};
287
288static const struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks  = {
289	.nrats = 2,
290	.rats = clocks,
291};
292
293static void snd_es1688_set_rate(struct snd_es1688 *chip, struct snd_pcm_substream *substream)
294{
295	struct snd_pcm_runtime *runtime = substream->runtime;
296	unsigned int bits, divider;
297
298	if (runtime->rate_num == clocks[0].num)
299		bits = 256 - runtime->rate_den;
300	else
301		bits = 128 - runtime->rate_den;
302	/* set filter register */
303	divider = 256 - 7160000*20/(8*82*runtime->rate);
304	/* write result to hardware */
305	snd_es1688_write(chip, 0xa1, bits);
306	snd_es1688_write(chip, 0xa2, divider);
307}
308
309static int snd_es1688_trigger(struct snd_es1688 *chip, int cmd, unsigned char value)
310{
311	int val;
312
313	if (cmd == SNDRV_PCM_TRIGGER_STOP) {
314		value = 0x00;
315	} else if (cmd != SNDRV_PCM_TRIGGER_START) {
316		return -EINVAL;
317	}
318	guard(spinlock)(&chip->reg_lock);
319	chip->trigger_value = value;
320	val = snd_es1688_read(chip, 0xb8);
321	if ((val < 0) || (val & 0x0f) == value)
322		return -EINVAL;	/* something is wrong */
323#if 0
324	dev_dbg(chip->card->dev, "trigger: val = 0x%x, value = 0x%x\n", val, value);
325	dev_dbg(chip->card->dev, "trigger: pointer = 0x%x\n",
326		snd_dma_pointer(chip->dma8, chip->dma_size));
327#endif
328	snd_es1688_write(chip, 0xb8, (val & 0xf0) | value);
329	return 0;
330}
331
332static int snd_es1688_playback_prepare(struct snd_pcm_substream *substream)
333{
334	struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
335	struct snd_pcm_runtime *runtime = substream->runtime;
336	unsigned int size = snd_pcm_lib_buffer_bytes(substream);
337	unsigned int count = snd_pcm_lib_period_bytes(substream);
338
339	chip->dma_size = size;
340	scoped_guard(spinlock_irqsave, &chip->reg_lock) {
341		snd_es1688_reset(chip);
342		snd_es1688_set_rate(chip, substream);
343		snd_es1688_write(chip, 0xb8, 4);	/* auto init DMA mode */
344		snd_es1688_write(chip, 0xa8, (snd_es1688_read(chip, 0xa8) & ~0x03) | (3 - runtime->channels));
345		snd_es1688_write(chip, 0xb9, 2);	/* demand mode (4 bytes/request) */
346		if (runtime->channels == 1) {
347			if (snd_pcm_format_width(runtime->format) == 8) {
348				/* 8. bit mono */
349				snd_es1688_write(chip, 0xb6, 0x80);
350				snd_es1688_write(chip, 0xb7, 0x51);
351				snd_es1688_write(chip, 0xb7, 0xd0);
352			} else {
353				/* 16. bit mono */
354				snd_es1688_write(chip, 0xb6, 0x00);
355				snd_es1688_write(chip, 0xb7, 0x71);
356				snd_es1688_write(chip, 0xb7, 0xf4);
357			}
358		} else {
359			if (snd_pcm_format_width(runtime->format) == 8) {
360				/* 8. bit stereo */
361				snd_es1688_write(chip, 0xb6, 0x80);
362				snd_es1688_write(chip, 0xb7, 0x51);
363				snd_es1688_write(chip, 0xb7, 0x98);
364			} else {
365				/* 16. bit stereo */
366				snd_es1688_write(chip, 0xb6, 0x00);
367				snd_es1688_write(chip, 0xb7, 0x71);
368				snd_es1688_write(chip, 0xb7, 0xbc);
369			}
370		}
371		snd_es1688_write(chip, 0xb1, (snd_es1688_read(chip, 0xb1) & 0x0f) | 0x50);
372		snd_es1688_write(chip, 0xb2, (snd_es1688_read(chip, 0xb2) & 0x0f) | 0x50);
373		snd_es1688_dsp_command(chip, ES1688_DSP_CMD_SPKON);
374	}
375	/* --- */
376	count = -count;
377	snd_dma_program(chip->dma8, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
378	scoped_guard(spinlock_irqsave, &chip->reg_lock) {
379		snd_es1688_write(chip, 0xa4, (unsigned char) count);
380		snd_es1688_write(chip, 0xa5, (unsigned char) (count >> 8));
381	}
382	return 0;
383}
384
385static int snd_es1688_playback_trigger(struct snd_pcm_substream *substream,
386				       int cmd)
387{
388	struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
389	return snd_es1688_trigger(chip, cmd, 0x05);
390}
391
392static int snd_es1688_capture_prepare(struct snd_pcm_substream *substream)
393{
394	struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
395	struct snd_pcm_runtime *runtime = substream->runtime;
396	unsigned int size = snd_pcm_lib_buffer_bytes(substream);
397	unsigned int count = snd_pcm_lib_period_bytes(substream);
398
399	chip->dma_size = size;
400	scoped_guard(spinlock_irqsave, &chip->reg_lock) {
401		snd_es1688_reset(chip);
402		snd_es1688_set_rate(chip, substream);
403		snd_es1688_dsp_command(chip, ES1688_DSP_CMD_SPKOFF);
404		snd_es1688_write(chip, 0xb8, 0x0e);	/* auto init DMA mode */
405		snd_es1688_write(chip, 0xa8, (snd_es1688_read(chip, 0xa8) & ~0x03) | (3 - runtime->channels));
406		snd_es1688_write(chip, 0xb9, 2);	/* demand mode (4 bytes/request) */
407		if (runtime->channels == 1) {
408			if (snd_pcm_format_width(runtime->format) == 8) {
409				/* 8. bit mono */
410				snd_es1688_write(chip, 0xb7, 0x51);
411				snd_es1688_write(chip, 0xb7, 0xd0);
412			} else {
413				/* 16. bit mono */
414				snd_es1688_write(chip, 0xb7, 0x71);
415				snd_es1688_write(chip, 0xb7, 0xf4);
416			}
417		} else {
418			if (snd_pcm_format_width(runtime->format) == 8) {
419				/* 8. bit stereo */
420				snd_es1688_write(chip, 0xb7, 0x51);
421				snd_es1688_write(chip, 0xb7, 0x98);
422			} else {
423				/* 16. bit stereo */
424				snd_es1688_write(chip, 0xb7, 0x71);
425				snd_es1688_write(chip, 0xb7, 0xbc);
426			}
427		}
428		snd_es1688_write(chip, 0xb1, (snd_es1688_read(chip, 0xb1) & 0x0f) | 0x50);
429		snd_es1688_write(chip, 0xb2, (snd_es1688_read(chip, 0xb2) & 0x0f) | 0x50);
430	}
431	/* --- */
432	count = -count;
433	snd_dma_program(chip->dma8, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
434	scoped_guard(spinlock_irqsave, &chip->reg_lock) {
435		snd_es1688_write(chip, 0xa4, (unsigned char) count);
436		snd_es1688_write(chip, 0xa5, (unsigned char) (count >> 8));
437	}
438	return 0;
439}
440
441static int snd_es1688_capture_trigger(struct snd_pcm_substream *substream,
442				      int cmd)
443{
444	struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
445	return snd_es1688_trigger(chip, cmd, 0x0f);
446}
447
448static irqreturn_t snd_es1688_interrupt(int irq, void *dev_id)
449{
450	struct snd_es1688 *chip = dev_id;
451
452	if (chip->trigger_value == 0x05)	/* ok.. playback is active */
453		snd_pcm_period_elapsed(chip->playback_substream);
454	if (chip->trigger_value == 0x0f)	/* ok.. capture is active */
455		snd_pcm_period_elapsed(chip->capture_substream);
456
457	inb(ES1688P(chip, DATA_AVAIL));	/* ack interrupt */
458	return IRQ_HANDLED;
459}
460
461static snd_pcm_uframes_t snd_es1688_playback_pointer(struct snd_pcm_substream *substream)
462{
463	struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
464	size_t ptr;
465	
466	if (chip->trigger_value != 0x05)
467		return 0;
468	ptr = snd_dma_pointer(chip->dma8, chip->dma_size);
469	return bytes_to_frames(substream->runtime, ptr);
470}
471
472static snd_pcm_uframes_t snd_es1688_capture_pointer(struct snd_pcm_substream *substream)
473{
474	struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
475	size_t ptr;
476	
477	if (chip->trigger_value != 0x0f)
478		return 0;
479	ptr = snd_dma_pointer(chip->dma8, chip->dma_size);
480	return bytes_to_frames(substream->runtime, ptr);
481}
482
483/*
484
485 */
486
487static const struct snd_pcm_hardware snd_es1688_playback =
488{
489	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
490				 SNDRV_PCM_INFO_MMAP_VALID),
491	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
492	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
493	.rate_min =		4000,
494	.rate_max =		48000,
495	.channels_min =		1,
496	.channels_max =		2,
497	.buffer_bytes_max =	65536,
498	.period_bytes_min =	64,
499	.period_bytes_max =	65536,
500	.periods_min =		1,
501	.periods_max =		1024,
502	.fifo_size =		0,
503};
504
505static const struct snd_pcm_hardware snd_es1688_capture =
506{
507	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
508				 SNDRV_PCM_INFO_MMAP_VALID),
509	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
510	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
511	.rate_min =		4000,
512	.rate_max =		48000,
513	.channels_min =		1,
514	.channels_max =		2,
515	.buffer_bytes_max =	65536,
516	.period_bytes_min =	64,
517	.period_bytes_max =	65536,
518	.periods_min =		1,
519	.periods_max =		1024,
520	.fifo_size =		0,
521};
522
523/*
524
525 */
526
527static int snd_es1688_playback_open(struct snd_pcm_substream *substream)
528{
529	struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
530	struct snd_pcm_runtime *runtime = substream->runtime;
531
532	if (chip->capture_substream != NULL)
533		return -EAGAIN;
534	chip->playback_substream = substream;
535	runtime->hw = snd_es1688_playback;
536	snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
537				      &hw_constraints_clocks);
538	return 0;
539}
540
541static int snd_es1688_capture_open(struct snd_pcm_substream *substream)
542{
543	struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
544	struct snd_pcm_runtime *runtime = substream->runtime;
545
546	if (chip->playback_substream != NULL)
547		return -EAGAIN;
548	chip->capture_substream = substream;
549	runtime->hw = snd_es1688_capture;
550	snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
551				      &hw_constraints_clocks);
552	return 0;
553}
554
555static int snd_es1688_playback_close(struct snd_pcm_substream *substream)
556{
557	struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
558
559	chip->playback_substream = NULL;
560	return 0;
561}
562
563static int snd_es1688_capture_close(struct snd_pcm_substream *substream)
564{
565	struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
566
567	chip->capture_substream = NULL;
568	return 0;
569}
570
571static int snd_es1688_free(struct snd_es1688 *chip)
572{
573	if (chip->hardware != ES1688_HW_UNDEF)
574		snd_es1688_init(chip, 0);
575	release_and_free_resource(chip->res_port);
576	if (chip->irq >= 0)
577		free_irq(chip->irq, (void *) chip);
578	if (chip->dma8 >= 0) {
579		disable_dma(chip->dma8);
580		free_dma(chip->dma8);
581	}
582	return 0;
583}
584
585static int snd_es1688_dev_free(struct snd_device *device)
586{
587	struct snd_es1688 *chip = device->device_data;
588	return snd_es1688_free(chip);
589}
590
591static const char *snd_es1688_chip_id(struct snd_es1688 *chip)
592{
593	static char tmp[16];
594	sprintf(tmp, "ES%s688 rev %i", chip->hardware == ES1688_HW_688 ? "" : "1", chip->version & 0x0f);
595	return tmp;
596}
597
598int snd_es1688_create(struct snd_card *card,
599		      struct snd_es1688 *chip,
600		      unsigned long port,
601		      unsigned long mpu_port,
602		      int irq,
603		      int mpu_irq,
604		      int dma8,
605		      unsigned short hardware)
606{
607	static const struct snd_device_ops ops = {
608		.dev_free =	snd_es1688_dev_free,
609	};
610                                
611	int err;
612
613	if (chip == NULL)
614		return -ENOMEM;
615	chip->card = card;
616	chip->irq = -1;
617	chip->dma8 = -1;
618	chip->hardware = ES1688_HW_UNDEF;
619	
620	chip->res_port = request_region(port + 4, 12, "ES1688");
621	if (chip->res_port == NULL) {
622		dev_err(card->dev, "es1688: can't grab port 0x%lx\n", port + 4);
623		err = -EBUSY;
624		goto exit;
625	}
626
627	err = request_irq(irq, snd_es1688_interrupt, 0, "ES1688", (void *) chip);
628	if (err < 0) {
629		dev_err(card->dev, "es1688: can't grab IRQ %d\n", irq);
630		goto exit;
631	}
632
633	chip->irq = irq;
634	card->sync_irq = chip->irq;
635	err = request_dma(dma8, "ES1688");
636
637	if (err < 0) {
638		dev_err(card->dev, "es1688: can't grab DMA8 %d\n", dma8);
639		goto exit;
640	}
641	chip->dma8 = dma8;
642
643	spin_lock_init(&chip->reg_lock);
644	spin_lock_init(&chip->mixer_lock);
645	chip->port = port;
646	mpu_port &= ~0x000f;
647	if (mpu_port < 0x300 || mpu_port > 0x330)
648		mpu_port = 0;
649	chip->mpu_port = mpu_port;
650	chip->mpu_irq = mpu_irq;
651	chip->hardware = hardware;
652
653	err = snd_es1688_probe(chip);
654	if (err < 0)
655		goto exit;
656
657	err = snd_es1688_init(chip, 1);
658	if (err < 0)
659		goto exit;
660
661	/* Register device */
662	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
663exit:
664	if (err)
665		snd_es1688_free(chip);
666	return err;
667}
668
669static const struct snd_pcm_ops snd_es1688_playback_ops = {
670	.open =			snd_es1688_playback_open,
671	.close =		snd_es1688_playback_close,
672	.prepare =		snd_es1688_playback_prepare,
673	.trigger =		snd_es1688_playback_trigger,
674	.pointer =		snd_es1688_playback_pointer,
675};
676
677static const struct snd_pcm_ops snd_es1688_capture_ops = {
678	.open =			snd_es1688_capture_open,
679	.close =		snd_es1688_capture_close,
680	.prepare =		snd_es1688_capture_prepare,
681	.trigger =		snd_es1688_capture_trigger,
682	.pointer =		snd_es1688_capture_pointer,
683};
684
685int snd_es1688_pcm(struct snd_card *card, struct snd_es1688 *chip, int device)
686{
687	struct snd_pcm *pcm;
688	int err;
689
690	err = snd_pcm_new(card, "ESx688", device, 1, 1, &pcm);
691	if (err < 0)
692		return err;
693
694	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_es1688_playback_ops);
695	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_es1688_capture_ops);
696
697	pcm->private_data = chip;
698	pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
699	strscpy(pcm->name, snd_es1688_chip_id(chip));
700	chip->pcm = pcm;
701
702	snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, card->dev,
703				       64*1024, 64*1024);
704	return 0;
705}
706
707/*
708 *  MIXER part
709 */
710
711static int snd_es1688_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
712{
713	static const char * const texts[8] = {
714		"Mic", "Mic Master", "CD", "AOUT",
715		"Mic1", "Mix", "Line", "Master"
716	};
717
718	return snd_ctl_enum_info(uinfo, 1, 8, texts);
719}
720
721static int snd_es1688_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
722{
723	struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
724	ucontrol->value.enumerated.item[0] = snd_es1688_mixer_read(chip, ES1688_REC_DEV) & 7;
725	return 0;
726}
727
728static int snd_es1688_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
729{
730	struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
731	unsigned char oval, nval;
732	int change;
733	
734	if (ucontrol->value.enumerated.item[0] > 8)
735		return -EINVAL;
736	guard(spinlock_irqsave)(&chip->reg_lock);
737	oval = snd_es1688_mixer_read(chip, ES1688_REC_DEV);
738	nval = (ucontrol->value.enumerated.item[0] & 7) | (oval & ~15);
739	change = nval != oval;
740	if (change)
741		snd_es1688_mixer_write(chip, ES1688_REC_DEV, nval);
742	return change;
743}
744
745#define ES1688_SINGLE(xname, xindex, reg, shift, mask, invert) \
746{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
747  .info = snd_es1688_info_single, \
748  .get = snd_es1688_get_single, .put = snd_es1688_put_single, \
749  .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
750
751static int snd_es1688_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
752{
753	int mask = (kcontrol->private_value >> 16) & 0xff;
754
755	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
756	uinfo->count = 1;
757	uinfo->value.integer.min = 0;
758	uinfo->value.integer.max = mask;
759	return 0;
760}
761
762static int snd_es1688_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
763{
764	struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
765	int reg = kcontrol->private_value & 0xff;
766	int shift = (kcontrol->private_value >> 8) & 0xff;
767	int mask = (kcontrol->private_value >> 16) & 0xff;
768	int invert = (kcontrol->private_value >> 24) & 0xff;
769	
770	guard(spinlock_irqsave)(&chip->reg_lock);
771	ucontrol->value.integer.value[0] = (snd_es1688_mixer_read(chip, reg) >> shift) & mask;
772	if (invert)
773		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
774	return 0;
775}
776
777static int snd_es1688_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
778{
779	struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
780	int reg = kcontrol->private_value & 0xff;
781	int shift = (kcontrol->private_value >> 8) & 0xff;
782	int mask = (kcontrol->private_value >> 16) & 0xff;
783	int invert = (kcontrol->private_value >> 24) & 0xff;
784	int change;
785	unsigned char oval, nval;
786	
787	nval = (ucontrol->value.integer.value[0] & mask);
788	if (invert)
789		nval = mask - nval;
790	nval <<= shift;
791	guard(spinlock_irqsave)(&chip->reg_lock);
792	oval = snd_es1688_mixer_read(chip, reg);
793	nval = (oval & ~(mask << shift)) | nval;
794	change = nval != oval;
795	if (change)
796		snd_es1688_mixer_write(chip, reg, nval);
797	return change;
798}
799
800#define ES1688_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
801{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
802  .info = snd_es1688_info_double, \
803  .get = snd_es1688_get_double, .put = snd_es1688_put_double, \
804  .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
805
806static int snd_es1688_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
807{
808	int mask = (kcontrol->private_value >> 24) & 0xff;
809
810	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
811	uinfo->count = 2;
812	uinfo->value.integer.min = 0;
813	uinfo->value.integer.max = mask;
814	return 0;
815}
816
817static int snd_es1688_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
818{
819	struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
820	int left_reg = kcontrol->private_value & 0xff;
821	int right_reg = (kcontrol->private_value >> 8) & 0xff;
822	int shift_left = (kcontrol->private_value >> 16) & 0x07;
823	int shift_right = (kcontrol->private_value >> 19) & 0x07;
824	int mask = (kcontrol->private_value >> 24) & 0xff;
825	int invert = (kcontrol->private_value >> 22) & 1;
826	unsigned char left, right;
827	
828	guard(spinlock_irqsave)(&chip->reg_lock);
829	if (left_reg < 0xa0)
830		left = snd_es1688_mixer_read(chip, left_reg);
831	else
832		left = snd_es1688_read(chip, left_reg);
833	if (left_reg != right_reg) {
834		if (right_reg < 0xa0) 
835			right = snd_es1688_mixer_read(chip, right_reg);
836		else
837			right = snd_es1688_read(chip, right_reg);
838	} else
839		right = left;
840	ucontrol->value.integer.value[0] = (left >> shift_left) & mask;
841	ucontrol->value.integer.value[1] = (right >> shift_right) & mask;
842	if (invert) {
843		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
844		ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
845	}
846	return 0;
847}
848
849static int snd_es1688_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
850{
851	struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
852	int left_reg = kcontrol->private_value & 0xff;
853	int right_reg = (kcontrol->private_value >> 8) & 0xff;
854	int shift_left = (kcontrol->private_value >> 16) & 0x07;
855	int shift_right = (kcontrol->private_value >> 19) & 0x07;
856	int mask = (kcontrol->private_value >> 24) & 0xff;
857	int invert = (kcontrol->private_value >> 22) & 1;
858	int change;
859	unsigned char val1, val2, oval1, oval2;
860	
861	val1 = ucontrol->value.integer.value[0] & mask;
862	val2 = ucontrol->value.integer.value[1] & mask;
863	if (invert) {
864		val1 = mask - val1;
865		val2 = mask - val2;
866	}
867	val1 <<= shift_left;
868	val2 <<= shift_right;
869	guard(spinlock_irqsave)(&chip->reg_lock);
870	if (left_reg != right_reg) {
871		if (left_reg < 0xa0)
872			oval1 = snd_es1688_mixer_read(chip, left_reg);
873		else
874			oval1 = snd_es1688_read(chip, left_reg);
875		if (right_reg < 0xa0)
876			oval2 = snd_es1688_mixer_read(chip, right_reg);
877		else
878			oval2 = snd_es1688_read(chip, right_reg);
879		val1 = (oval1 & ~(mask << shift_left)) | val1;
880		val2 = (oval2 & ~(mask << shift_right)) | val2;
881		change = val1 != oval1 || val2 != oval2;
882		if (change) {
883			if (left_reg < 0xa0)
884				snd_es1688_mixer_write(chip, left_reg, val1);
885			else
886				snd_es1688_write(chip, left_reg, val1);
887			if (right_reg < 0xa0)
888				snd_es1688_mixer_write(chip, right_reg, val1);
889			else
890				snd_es1688_write(chip, right_reg, val1);
891		}
892	} else {
893		if (left_reg < 0xa0)
894			oval1 = snd_es1688_mixer_read(chip, left_reg);
895		else
896			oval1 = snd_es1688_read(chip, left_reg);
897		val1 = (oval1 & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2;
898		change = val1 != oval1;
899		if (change) {
900			if (left_reg < 0xa0)
901				snd_es1688_mixer_write(chip, left_reg, val1);
902			else
903				snd_es1688_write(chip, left_reg, val1);
904		}
905			
906	}
907	return change;
908}
909
910static const struct snd_kcontrol_new snd_es1688_controls[] = {
911ES1688_DOUBLE("Master Playback Volume", 0, ES1688_MASTER_DEV, ES1688_MASTER_DEV, 4, 0, 15, 0),
912ES1688_DOUBLE("PCM Playback Volume", 0, ES1688_PCM_DEV, ES1688_PCM_DEV, 4, 0, 15, 0),
913ES1688_DOUBLE("Line Playback Volume", 0, ES1688_LINE_DEV, ES1688_LINE_DEV, 4, 0, 15, 0),
914ES1688_DOUBLE("CD Playback Volume", 0, ES1688_CD_DEV, ES1688_CD_DEV, 4, 0, 15, 0),
915ES1688_DOUBLE("FM Playback Volume", 0, ES1688_FM_DEV, ES1688_FM_DEV, 4, 0, 15, 0),
916ES1688_DOUBLE("Mic Playback Volume", 0, ES1688_MIC_DEV, ES1688_MIC_DEV, 4, 0, 15, 0),
917ES1688_DOUBLE("Aux Playback Volume", 0, ES1688_AUX_DEV, ES1688_AUX_DEV, 4, 0, 15, 0),
918ES1688_SINGLE("Beep Playback Volume", 0, ES1688_SPEAKER_DEV, 0, 7, 0),
919ES1688_DOUBLE("Capture Volume", 0, ES1688_RECLEV_DEV, ES1688_RECLEV_DEV, 4, 0, 15, 0),
920ES1688_SINGLE("Capture Switch", 0, ES1688_REC_DEV, 4, 1, 1),
921{
922	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
923	.name = "Capture Source",
924	.info = snd_es1688_info_mux,
925	.get = snd_es1688_get_mux,
926	.put = snd_es1688_put_mux,
927},
928};
929
930#define ES1688_INIT_TABLE_SIZE (sizeof(snd_es1688_init_table)/2)
931
932static const unsigned char snd_es1688_init_table[][2] = {
933	{ ES1688_MASTER_DEV, 0 },
934	{ ES1688_PCM_DEV, 0 },
935	{ ES1688_LINE_DEV, 0 },
936	{ ES1688_CD_DEV, 0 },
937	{ ES1688_FM_DEV, 0 },
938	{ ES1688_MIC_DEV, 0 },
939	{ ES1688_AUX_DEV, 0 },
940	{ ES1688_SPEAKER_DEV, 0 },
941	{ ES1688_RECLEV_DEV, 0 },
942	{ ES1688_REC_DEV, 0x17 }
943};
944                                        
945int snd_es1688_mixer(struct snd_card *card, struct snd_es1688 *chip)
946{
947	unsigned int idx;
948	int err;
949	unsigned char reg, val;
950
951	if (snd_BUG_ON(!chip || !card))
952		return -EINVAL;
953
954	strscpy(card->mixername, snd_es1688_chip_id(chip));
955
956	for (idx = 0; idx < ARRAY_SIZE(snd_es1688_controls); idx++) {
957		err = snd_ctl_add(card, snd_ctl_new1(&snd_es1688_controls[idx], chip));
958		if (err < 0)
959			return err;
960	}
961	for (idx = 0; idx < ES1688_INIT_TABLE_SIZE; idx++) {
962		reg = snd_es1688_init_table[idx][0];
963		val = snd_es1688_init_table[idx][1];
964		if (reg < 0xa0)
965			snd_es1688_mixer_write(chip, reg, val);
966		else
967			snd_es1688_write(chip, reg, val);
968	}
969	return 0;
970}
971
972EXPORT_SYMBOL(snd_es1688_mixer_write);
973EXPORT_SYMBOL(snd_es1688_create);
974EXPORT_SYMBOL(snd_es1688_pcm);
975EXPORT_SYMBOL(snd_es1688_mixer);
~/ Read-only file preview.