aboutsummaryrefslogtreecommitdiffstats
path: root/sound/isa
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2009-12-20 13:01:50 -0500
committerTakashi Iwai <tiwai@suse.de>2009-12-21 06:09:22 -0500
commitad8decb7f5dfd556e4a8400e37b127cd20d8e4c5 (patch)
tree66db96ffc99390123215e50aed95cba42165994f /sound/isa
parent5b4b2a41a1a80f5560364b7ef001486cd8fb5230 (diff)
ALSA: jazz16: Add support for Media Vision Jazz16 chipset
This is one of Sound Blaster Pro compatible chipsets which is supported by Linux OSS driver and was missing native supoort for ALSA. The Jazz16 audio codec is Crystal CS4216 which is capable of playback and recording up to 48 kHz stereo. Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/isa')
-rw-r--r--sound/isa/Kconfig16
-rw-r--r--sound/isa/sb/Makefile2
-rw-r--r--sound/isa/sb/jazz16.c385
-rw-r--r--sound/isa/sb/sb8_main.c117
-rw-r--r--sound/isa/sb/sb_common.c3
-rw-r--r--sound/isa/sb/sb_mixer.c3
6 files changed, 510 insertions, 16 deletions
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 194af3b01e13..755a0a5f0e3f 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -239,6 +239,22 @@ config SND_INTERWAVE_STB
239 To compile this driver as a module, choose M here: the module 239 To compile this driver as a module, choose M here: the module
240 will be called snd-interwave-stb. 240 will be called snd-interwave-stb.
241 241
242config SND_JAZZ16
243 tristate "Media Vision Jazz16 card and compatibles"
244 select SND_OPL3_LIB
245 select SND_MPU401_UART
246 select SND_SB8_DSP
247 help
248 Say Y here to include support for soundcards based on the
249 Media Vision Jazz16 chipset: digital chip MVD1216 (Jazz16),
250 codec MVA416 (CS4216) and mixer MVA514 (ICS2514).
251 Media Vision's Jazz16 cards were sold under names Pro Sonic 16,
252 Premium 3-D and Pro 3-D. There were also OEMs cards with the
253 Jazz16 chipset.
254
255 To compile this driver as a module, choose M here: the module
256 will be called snd-jazz16.
257
242config SND_OPL3SA2 258config SND_OPL3SA2
243 tristate "Yamaha OPL3-SA2/SA3" 259 tristate "Yamaha OPL3-SA2/SA3"
244 select SND_OPL3_LIB 260 select SND_OPL3_LIB
diff --git a/sound/isa/sb/Makefile b/sound/isa/sb/Makefile
index faeffceb01b7..af3669681788 100644
--- a/sound/isa/sb/Makefile
+++ b/sound/isa/sb/Makefile
@@ -12,6 +12,7 @@ snd-sb16-objs := sb16.o
12snd-sbawe-objs := sbawe.o emu8000.o 12snd-sbawe-objs := sbawe.o emu8000.o
13snd-emu8000-synth-objs := emu8000_synth.o emu8000_callback.o emu8000_patch.o emu8000_pcm.o 13snd-emu8000-synth-objs := emu8000_synth.o emu8000_callback.o emu8000_patch.o emu8000_pcm.o
14snd-es968-objs := es968.o 14snd-es968-objs := es968.o
15snd-jazz16-objs := jazz16.o
15 16
16# Toplevel Module Dependency 17# Toplevel Module Dependency
17obj-$(CONFIG_SND_SB_COMMON) += snd-sb-common.o 18obj-$(CONFIG_SND_SB_COMMON) += snd-sb-common.o
@@ -21,6 +22,7 @@ obj-$(CONFIG_SND_SB8) += snd-sb8.o
21obj-$(CONFIG_SND_SB16) += snd-sb16.o 22obj-$(CONFIG_SND_SB16) += snd-sb16.o
22obj-$(CONFIG_SND_SBAWE) += snd-sbawe.o 23obj-$(CONFIG_SND_SBAWE) += snd-sbawe.o
23obj-$(CONFIG_SND_ES968) += snd-es968.o 24obj-$(CONFIG_SND_ES968) += snd-es968.o
25obj-$(CONFIG_SND_JAZZ16) += snd-jazz16.o
24ifeq ($(CONFIG_SND_SB16_CSP),y) 26ifeq ($(CONFIG_SND_SB16_CSP),y)
25 obj-$(CONFIG_SND_SB16) += snd-sb16-csp.o 27 obj-$(CONFIG_SND_SB16) += snd-sb16-csp.o
26 obj-$(CONFIG_SND_SBAWE) += snd-sb16-csp.o 28 obj-$(CONFIG_SND_SBAWE) += snd-sb16-csp.o
diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c
new file mode 100644
index 000000000000..d52966b75846
--- /dev/null
+++ b/sound/isa/sb/jazz16.c
@@ -0,0 +1,385 @@
1
2/*
3 * jazz16.c - driver for Media Vision Jazz16 based soundcards.
4 * Copyright (C) 2009 Krzysztof Helt <krzysztof.h1@wp.pl>
5 * Based on patches posted by Rask Ingemann Lambertsen and Rene Herman.
6 * Based on OSS Sound Blaster driver.
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file COPYING in the main directory of this archive for
10 * more details.
11 *
12 */
13
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/io.h>
17#include <asm/dma.h>
18#include <linux/isa.h>
19#include <sound/core.h>
20#include <sound/mpu401.h>
21#include <sound/opl3.h>
22#include <sound/sb.h>
23#define SNDRV_LEGACY_FIND_FREE_IRQ
24#define SNDRV_LEGACY_FIND_FREE_DMA
25#include <sound/initval.h>
26
27#define PFX "jazz16: "
28
29MODULE_DESCRIPTION("Media Vision Jazz16");
30MODULE_SUPPORTED_DEVICE("{{Media Vision ??? },"
31 "{RTL,RTL3000}}");
32
33MODULE_AUTHOR("Krzysztof Helt <krzysztof.h1@wp.pl>");
34MODULE_LICENSE("GPL");
35
36static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
37static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
38static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
39static unsigned long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
40static unsigned long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
41static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
42static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
43static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
44static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
45
46module_param_array(index, int, NULL, 0444);
47MODULE_PARM_DESC(index, "Index value for Media Vision Jazz16 based soundcard.");
48module_param_array(id, charp, NULL, 0444);
49MODULE_PARM_DESC(id, "ID string for Media Vision Jazz16 based soundcard.");
50module_param_array(enable, bool, NULL, 0444);
51MODULE_PARM_DESC(enable, "Enable Media Vision Jazz16 based soundcard.");
52module_param_array(port, long, NULL, 0444);
53MODULE_PARM_DESC(port, "Port # for jazz16 driver.");
54module_param_array(mpu_port, long, NULL, 0444);
55MODULE_PARM_DESC(mpu_port, "MPU-401 port # for jazz16 driver.");
56module_param_array(irq, int, NULL, 0444);
57MODULE_PARM_DESC(irq, "IRQ # for jazz16 driver.");
58module_param_array(mpu_irq, int, NULL, 0444);
59MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for jazz16 driver.");
60module_param_array(dma8, int, NULL, 0444);
61MODULE_PARM_DESC(dma8, "DMA8 # for jazz16 driver.");
62module_param_array(dma16, int, NULL, 0444);
63MODULE_PARM_DESC(dma16, "DMA16 # for jazz16 driver.");
64
65#define SB_JAZZ16_WAKEUP 0xaf
66#define SB_JAZZ16_SET_PORTS 0x50
67#define SB_DSP_GET_JAZZ_BRD_REV 0xfa
68#define SB_JAZZ16_SET_DMAINTR 0xfb
69#define SB_DSP_GET_JAZZ_MODEL 0xfe
70
71struct snd_card_jazz16 {
72 struct snd_sb *chip;
73};
74
75static irqreturn_t jazz16_interrupt(int irq, void *chip)
76{
77 return snd_sb8dsp_interrupt(chip);
78}
79
80static int __devinit jazz16_configure_ports(unsigned long port,
81 unsigned long mpu_port, int idx)
82{
83 unsigned char val;
84
85 if (!request_region(0x201, 1, "jazz16 config")) {
86 snd_printk(KERN_ERR "config port region is already in use.\n");
87 return -EBUSY;
88 }
89 outb(SB_JAZZ16_WAKEUP - idx, 0x201);
90 udelay(100);
91 outb(SB_JAZZ16_SET_PORTS + idx, 0x201);
92 udelay(100);
93 val = port & 0x70;
94 val |= (mpu_port & 0x30) >> 4;
95 outb(val, 0x201);
96
97 release_region(0x201, 1);
98 return 0;
99}
100
101static int __devinit jazz16_detect_board(unsigned long port,
102 unsigned long mpu_port)
103{
104 int err;
105 int val;
106 struct snd_sb chip;
107
108 if (!request_region(port, 0x10, "jazz16")) {
109 snd_printk(KERN_ERR "I/O port region is already in use.\n");
110 return -EBUSY;
111 }
112 /* just to call snd_sbdsp_command/reset/get_byte() */
113 chip.port = port;
114
115 err = snd_sbdsp_reset(&chip);
116 if (err < 0)
117 for (val = 0; val < 4; val++) {
118 err = jazz16_configure_ports(port, mpu_port, val);
119 if (err < 0)
120 break;
121
122 err = snd_sbdsp_reset(&chip);
123 if (!err)
124 break;
125 }
126 if (err < 0) {
127 err = -ENODEV;
128 goto err_unmap;
129 }
130 if (!snd_sbdsp_command(&chip, SB_DSP_GET_JAZZ_BRD_REV)) {
131 err = -EBUSY;
132 goto err_unmap;
133 }
134 val = snd_sbdsp_get_byte(&chip);
135 if (val >= 0x30)
136 snd_sbdsp_get_byte(&chip);
137
138 if ((val & 0xf0) != 0x10) {
139 err = -ENODEV;
140 goto err_unmap;
141 }
142 if (!snd_sbdsp_command(&chip, SB_DSP_GET_JAZZ_MODEL)) {
143 err = -EBUSY;
144 goto err_unmap;
145 }
146 snd_sbdsp_get_byte(&chip);
147 err = snd_sbdsp_get_byte(&chip);
148 snd_printd("Media Vision Jazz16 board detected: rev 0x%x, model 0x%x\n",
149 val, err);
150
151 err = 0;
152
153err_unmap:
154 release_region(port, 0x10);
155 return err;
156}
157
158static int __devinit jazz16_configure_board(struct snd_sb *chip, int mpu_irq)
159{
160 static unsigned char jazz_irq_bits[] = { 0, 0, 2, 3, 0, 1, 0, 4,
161 0, 2, 5, 0, 0, 0, 0, 6 };
162 static unsigned char jazz_dma_bits[] = { 0, 1, 0, 2, 0, 3, 0, 4 };
163
164 if (jazz_dma_bits[chip->dma8] == 0 ||
165 jazz_dma_bits[chip->dma16] == 0 ||
166 jazz_irq_bits[chip->irq] == 0)
167 return -EINVAL;
168
169 if (!snd_sbdsp_command(chip, SB_JAZZ16_SET_DMAINTR))
170 return -EBUSY;
171
172 if (!snd_sbdsp_command(chip,
173 jazz_dma_bits[chip->dma8] |
174 (jazz_dma_bits[chip->dma16] << 4)))
175 return -EBUSY;
176
177 if (!snd_sbdsp_command(chip,
178 jazz_irq_bits[chip->irq] |
179 (jazz_irq_bits[mpu_irq] << 4)))
180 return -EBUSY;
181
182 return 0;
183}
184
185static int __devinit snd_jazz16_match(struct device *devptr, unsigned int dev)
186{
187 if (!enable[dev])
188 return 0;
189 if (port[dev] == SNDRV_AUTO_PORT) {
190 snd_printk(KERN_ERR "please specify port\n");
191 return 0;
192 }
193 if (dma16[dev] != SNDRV_AUTO_DMA &&
194 dma16[dev] != 5 && dma16[dev] != 7) {
195 snd_printk(KERN_ERR "dma16 must be 5 or 7");
196 return 0;
197 }
198 return 1;
199}
200
201static int __devinit snd_jazz16_probe(struct device *devptr, unsigned int dev)
202{
203 struct snd_card *card;
204 struct snd_card_jazz16 *jazz16;
205 struct snd_sb *chip;
206 struct snd_opl3 *opl3;
207 static int possible_irqs[] = {2, 3, 5, 7, 9, 10, 15, -1};
208 static int possible_dmas8[] = {1, 3, -1};
209 static int possible_dmas16[] = {5, 7, -1};
210 int err, xirq, xdma8, xdma16, xmpu_port, xmpu_irq;
211
212 err = snd_card_create(index[dev], id[dev], THIS_MODULE,
213 sizeof(struct snd_card_jazz16), &card);
214 if (err < 0)
215 return err;
216
217 jazz16 = card->private_data;
218
219 xirq = irq[dev];
220 if (xirq == SNDRV_AUTO_IRQ) {
221 xirq = snd_legacy_find_free_irq(possible_irqs);
222 if (xirq < 0) {
223 snd_printk(KERN_ERR "unable to find a free IRQ\n");
224 err = -EBUSY;
225 goto err_free;
226 }
227 }
228 xdma8 = dma8[dev];
229 if (xdma8 == SNDRV_AUTO_DMA) {
230 xdma8 = snd_legacy_find_free_dma(possible_dmas8);
231 if (xdma8 < 0) {
232 snd_printk(KERN_ERR "unable to find a free DMA8\n");
233 err = -EBUSY;
234 goto err_free;
235 }
236 }
237 xdma16 = dma16[dev];
238 if (xdma16 == SNDRV_AUTO_DMA) {
239 xdma16 = snd_legacy_find_free_dma(possible_dmas16);
240 if (xdma16 < 0) {
241 snd_printk(KERN_ERR "unable to find a free DMA16\n");
242 err = -EBUSY;
243 goto err_free;
244 }
245 }
246
247 xmpu_port = mpu_port[dev];
248 if (xmpu_port == SNDRV_AUTO_PORT)
249 xmpu_port = 0;
250 err = jazz16_detect_board(port[dev], xmpu_port);
251 if (err < 0) {
252 printk(KERN_ERR "Media Vision Jazz16 board not detected\n");
253 goto err_free;
254 }
255 err = snd_sbdsp_create(card, port[dev], irq[dev],
256 jazz16_interrupt,
257 dma8[dev], dma16[dev],
258 SB_HW_JAZZ16,
259 &chip);
260 if (err < 0)
261 goto err_free;
262
263 xmpu_irq = mpu_irq[dev];
264 if (xmpu_irq == SNDRV_AUTO_IRQ || mpu_port[dev] == SNDRV_AUTO_PORT)
265 xmpu_irq = 0;
266 err = jazz16_configure_board(chip, xmpu_irq);
267 if (err < 0) {
268 printk(KERN_ERR "Media Vision Jazz16 configuration failed\n");
269 goto err_free;
270 }
271
272 jazz16->chip = chip;
273
274 strcpy(card->driver, "jazz16");
275 strcpy(card->shortname, "Media Vision Jazz16");
276 sprintf(card->longname,
277 "Media Vision Jazz16 at 0x%lx, irq %d, dma8 %d, dma16 %d",
278 port[dev], xirq, xdma8, xdma16);
279
280 err = snd_sb8dsp_pcm(chip, 0, NULL);
281 if (err < 0)
282 goto err_free;
283 err = snd_sbmixer_new(chip);
284 if (err < 0)
285 goto err_free;
286
287 err = snd_opl3_create(card, chip->port, chip->port + 2,
288 OPL3_HW_AUTO, 1, &opl3);
289 if (err < 0)
290 snd_printk(KERN_WARNING "no OPL device at 0x%lx-0x%lx\n",
291 chip->port, chip->port + 2);
292 else {
293 err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
294 if (err < 0)
295 goto err_free;
296 }
297 if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
298 if (mpu_irq[dev] == SNDRV_AUTO_IRQ)
299 mpu_irq[dev] = -1;
300
301 if (snd_mpu401_uart_new(card, 0,
302 MPU401_HW_MPU401,
303 mpu_port[dev], 0,
304 mpu_irq[dev],
305 mpu_irq[dev] >= 0 ? IRQF_DISABLED : 0,
306 NULL) < 0)
307 snd_printk(KERN_ERR "no MPU-401 device at 0x%lx\n",
308 mpu_port[dev]);
309 }
310
311 snd_card_set_dev(card, devptr);
312
313 err = snd_card_register(card);
314 if (err < 0)
315 goto err_free;
316
317 dev_set_drvdata(devptr, card);
318 return 0;
319
320err_free:
321 snd_card_free(card);
322 return err;
323}
324
325static int __devexit snd_jazz16_remove(struct device *devptr, unsigned int dev)
326{
327 struct snd_card *card = dev_get_drvdata(devptr);
328
329 dev_set_drvdata(devptr, NULL);
330 snd_card_free(card);
331 return 0;
332}
333
334#ifdef CONFIG_PM
335static int snd_jazz16_suspend(struct device *pdev, unsigned int n,
336 pm_message_t state)
337{
338 struct snd_card *card = dev_get_drvdata(pdev);
339 struct snd_card_jazz16 *acard = card->private_data;
340 struct snd_sb *chip = acard->chip;
341
342 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
343 snd_pcm_suspend_all(chip->pcm);
344 snd_sbmixer_suspend(chip);
345 return 0;
346}
347
348static int snd_jazz16_resume(struct device *pdev, unsigned int n)
349{
350 struct snd_card *card = dev_get_drvdata(pdev);
351 struct snd_card_jazz16 *acard = card->private_data;
352 struct snd_sb *chip = acard->chip;
353
354 snd_sbdsp_reset(chip);
355 snd_sbmixer_resume(chip);
356 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
357 return 0;
358}
359#endif
360
361static struct isa_driver snd_jazz16_driver = {
362 .match = snd_jazz16_match,
363 .probe = snd_jazz16_probe,
364 .remove = __devexit_p(snd_jazz16_remove),
365#ifdef CONFIG_PM
366 .suspend = snd_jazz16_suspend,
367 .resume = snd_jazz16_resume,
368#endif
369 .driver = {
370 .name = "jazz16"
371 },
372};
373
374static int __init alsa_card_jazz16_init(void)
375{
376 return isa_register_driver(&snd_jazz16_driver, SNDRV_CARDS);
377}
378
379static void __exit alsa_card_jazz16_exit(void)
380{
381 isa_unregister_driver(&snd_jazz16_driver);
382}
383
384module_init(alsa_card_jazz16_init)
385module_exit(alsa_card_jazz16_exit)
diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c
index 658d55769c9c..3222aed5fac6 100644
--- a/sound/isa/sb/sb8_main.c
+++ b/sound/isa/sb/sb8_main.c
@@ -106,9 +106,21 @@ static int snd_sb8_playback_prepare(struct snd_pcm_substream *substream)
106 struct snd_sb *chip = snd_pcm_substream_chip(substream); 106 struct snd_sb *chip = snd_pcm_substream_chip(substream);
107 struct snd_pcm_runtime *runtime = substream->runtime; 107 struct snd_pcm_runtime *runtime = substream->runtime;
108 unsigned int mixreg, rate, size, count; 108 unsigned int mixreg, rate, size, count;
109 unsigned char format;
110 unsigned char stereo = runtime->channels > 1;
111 int dma;
109 112
110 rate = runtime->rate; 113 rate = runtime->rate;
111 switch (chip->hardware) { 114 switch (chip->hardware) {
115 case SB_HW_JAZZ16:
116 if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) {
117 if (chip->mode & SB_MODE_CAPTURE_16)
118 return -EBUSY;
119 else
120 chip->mode |= SB_MODE_PLAYBACK_16;
121 }
122 chip->playback_format = SB_DSP_LO_OUTPUT_AUTO;
123 break;
112 case SB_HW_PRO: 124 case SB_HW_PRO:
113 if (runtime->channels > 1) { 125 if (runtime->channels > 1) {
114 if (snd_BUG_ON(rate != SB8_RATE(11025) && 126 if (snd_BUG_ON(rate != SB8_RATE(11025) &&
@@ -133,11 +145,21 @@ static int snd_sb8_playback_prepare(struct snd_pcm_substream *substream)
133 default: 145 default:
134 return -EINVAL; 146 return -EINVAL;
135 } 147 }
148 if (chip->mode & SB_MODE_PLAYBACK_16) {
149 format = stereo ? SB_DSP_STEREO_16BIT : SB_DSP_MONO_16BIT;
150 dma = chip->dma16;
151 } else {
152 format = stereo ? SB_DSP_STEREO_8BIT : SB_DSP_MONO_8BIT;
153 chip->mode |= SB_MODE_PLAYBACK_8;
154 dma = chip->dma8;
155 }
136 size = chip->p_dma_size = snd_pcm_lib_buffer_bytes(substream); 156 size = chip->p_dma_size = snd_pcm_lib_buffer_bytes(substream);
137 count = chip->p_period_size = snd_pcm_lib_period_bytes(substream); 157 count = chip->p_period_size = snd_pcm_lib_period_bytes(substream);
138 spin_lock_irqsave(&chip->reg_lock, flags); 158 spin_lock_irqsave(&chip->reg_lock, flags);
139 snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON); 159 snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON);
140 if (runtime->channels > 1) { 160 if (chip->hardware == SB_HW_JAZZ16)
161 snd_sbdsp_command(chip, format);
162 else if (stereo) {
141 /* set playback stereo mode */ 163 /* set playback stereo mode */
142 spin_lock(&chip->mixer_lock); 164 spin_lock(&chip->mixer_lock);
143 mixreg = snd_sbmixer_read(chip, SB_DSP_STEREO_SW); 165 mixreg = snd_sbmixer_read(chip, SB_DSP_STEREO_SW);
@@ -147,15 +169,14 @@ static int snd_sb8_playback_prepare(struct snd_pcm_substream *substream)
147 /* Soundblaster hardware programming reference guide, 3-23 */ 169 /* Soundblaster hardware programming reference guide, 3-23 */
148 snd_sbdsp_command(chip, SB_DSP_DMA8_EXIT); 170 snd_sbdsp_command(chip, SB_DSP_DMA8_EXIT);
149 runtime->dma_area[0] = 0x80; 171 runtime->dma_area[0] = 0x80;
150 snd_dma_program(chip->dma8, runtime->dma_addr, 1, DMA_MODE_WRITE); 172 snd_dma_program(dma, runtime->dma_addr, 1, DMA_MODE_WRITE);
151 /* force interrupt */ 173 /* force interrupt */
152 chip->mode = SB_MODE_HALT;
153 snd_sbdsp_command(chip, SB_DSP_OUTPUT); 174 snd_sbdsp_command(chip, SB_DSP_OUTPUT);
154 snd_sbdsp_command(chip, 0); 175 snd_sbdsp_command(chip, 0);
155 snd_sbdsp_command(chip, 0); 176 snd_sbdsp_command(chip, 0);
156 } 177 }
157 snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE); 178 snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE);
158 if (runtime->channels > 1) { 179 if (stereo) {
159 snd_sbdsp_command(chip, 256 - runtime->rate_den / 2); 180 snd_sbdsp_command(chip, 256 - runtime->rate_den / 2);
160 spin_lock(&chip->mixer_lock); 181 spin_lock(&chip->mixer_lock);
161 /* save output filter status and turn it off */ 182 /* save output filter status and turn it off */
@@ -168,13 +189,15 @@ static int snd_sb8_playback_prepare(struct snd_pcm_substream *substream)
168 snd_sbdsp_command(chip, 256 - runtime->rate_den); 189 snd_sbdsp_command(chip, 256 - runtime->rate_den);
169 } 190 }
170 if (chip->playback_format != SB_DSP_OUTPUT) { 191 if (chip->playback_format != SB_DSP_OUTPUT) {
192 if (chip->mode & SB_MODE_PLAYBACK_16)
193 count /= 2;
171 count--; 194 count--;
172 snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE); 195 snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE);
173 snd_sbdsp_command(chip, count & 0xff); 196 snd_sbdsp_command(chip, count & 0xff);
174 snd_sbdsp_command(chip, count >> 8); 197 snd_sbdsp_command(chip, count >> 8);
175 } 198 }
176 spin_unlock_irqrestore(&chip->reg_lock, flags); 199 spin_unlock_irqrestore(&chip->reg_lock, flags);
177 snd_dma_program(chip->dma8, runtime->dma_addr, 200 snd_dma_program(dma, runtime->dma_addr,
178 size, DMA_MODE_WRITE | DMA_AUTOINIT); 201 size, DMA_MODE_WRITE | DMA_AUTOINIT);
179 return 0; 202 return 0;
180} 203}
@@ -212,7 +235,6 @@ static int snd_sb8_playback_trigger(struct snd_pcm_substream *substream,
212 snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF); 235 snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
213 } 236 }
214 spin_unlock_irqrestore(&chip->reg_lock, flags); 237 spin_unlock_irqrestore(&chip->reg_lock, flags);
215 chip->mode = (cmd == SNDRV_PCM_TRIGGER_START) ? SB_MODE_PLAYBACK_8 : SB_MODE_HALT;
216 return 0; 238 return 0;
217} 239}
218 240
@@ -234,9 +256,21 @@ static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream)
234 struct snd_sb *chip = snd_pcm_substream_chip(substream); 256 struct snd_sb *chip = snd_pcm_substream_chip(substream);
235 struct snd_pcm_runtime *runtime = substream->runtime; 257 struct snd_pcm_runtime *runtime = substream->runtime;
236 unsigned int mixreg, rate, size, count; 258 unsigned int mixreg, rate, size, count;
259 unsigned char format;
260 unsigned char stereo = runtime->channels > 1;
261 int dma;
237 262
238 rate = runtime->rate; 263 rate = runtime->rate;
239 switch (chip->hardware) { 264 switch (chip->hardware) {
265 case SB_HW_JAZZ16:
266 if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) {
267 if (chip->mode & SB_MODE_PLAYBACK_16)
268 return -EBUSY;
269 else
270 chip->mode |= SB_MODE_CAPTURE_16;
271 }
272 chip->capture_format = SB_DSP_LO_INPUT_AUTO;
273 break;
240 case SB_HW_PRO: 274 case SB_HW_PRO:
241 if (runtime->channels > 1) { 275 if (runtime->channels > 1) {
242 if (snd_BUG_ON(rate != SB8_RATE(11025) && 276 if (snd_BUG_ON(rate != SB8_RATE(11025) &&
@@ -262,14 +296,24 @@ static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream)
262 default: 296 default:
263 return -EINVAL; 297 return -EINVAL;
264 } 298 }
299 if (chip->mode & SB_MODE_CAPTURE_16) {
300 format = stereo ? SB_DSP_STEREO_16BIT : SB_DSP_MONO_16BIT;
301 dma = chip->dma16;
302 } else {
303 format = stereo ? SB_DSP_STEREO_8BIT : SB_DSP_MONO_8BIT;
304 chip->mode |= SB_MODE_CAPTURE_8;
305 dma = chip->dma8;
306 }
265 size = chip->c_dma_size = snd_pcm_lib_buffer_bytes(substream); 307 size = chip->c_dma_size = snd_pcm_lib_buffer_bytes(substream);
266 count = chip->c_period_size = snd_pcm_lib_period_bytes(substream); 308 count = chip->c_period_size = snd_pcm_lib_period_bytes(substream);
267 spin_lock_irqsave(&chip->reg_lock, flags); 309 spin_lock_irqsave(&chip->reg_lock, flags);
268 snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF); 310 snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
269 if (runtime->channels > 1) 311 if (chip->hardware == SB_HW_JAZZ16)
312 snd_sbdsp_command(chip, format);
313 else if (stereo)
270 snd_sbdsp_command(chip, SB_DSP_STEREO_8BIT); 314 snd_sbdsp_command(chip, SB_DSP_STEREO_8BIT);
271 snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE); 315 snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE);
272 if (runtime->channels > 1) { 316 if (stereo) {
273 snd_sbdsp_command(chip, 256 - runtime->rate_den / 2); 317 snd_sbdsp_command(chip, 256 - runtime->rate_den / 2);
274 spin_lock(&chip->mixer_lock); 318 spin_lock(&chip->mixer_lock);
275 /* save input filter status and turn it off */ 319 /* save input filter status and turn it off */
@@ -282,13 +326,15 @@ static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream)
282 snd_sbdsp_command(chip, 256 - runtime->rate_den); 326 snd_sbdsp_command(chip, 256 - runtime->rate_den);
283 } 327 }
284 if (chip->capture_format != SB_DSP_INPUT) { 328 if (chip->capture_format != SB_DSP_INPUT) {
329 if (chip->mode & SB_MODE_PLAYBACK_16)
330 count /= 2;
285 count--; 331 count--;
286 snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE); 332 snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE);
287 snd_sbdsp_command(chip, count & 0xff); 333 snd_sbdsp_command(chip, count & 0xff);
288 snd_sbdsp_command(chip, count >> 8); 334 snd_sbdsp_command(chip, count >> 8);
289 } 335 }
290 spin_unlock_irqrestore(&chip->reg_lock, flags); 336 spin_unlock_irqrestore(&chip->reg_lock, flags);
291 snd_dma_program(chip->dma8, runtime->dma_addr, 337 snd_dma_program(dma, runtime->dma_addr,
292 size, DMA_MODE_READ | DMA_AUTOINIT); 338 size, DMA_MODE_READ | DMA_AUTOINIT);
293 return 0; 339 return 0;
294} 340}
@@ -328,7 +374,6 @@ static int snd_sb8_capture_trigger(struct snd_pcm_substream *substream,
328 snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF); 374 snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
329 } 375 }
330 spin_unlock_irqrestore(&chip->reg_lock, flags); 376 spin_unlock_irqrestore(&chip->reg_lock, flags);
331 chip->mode = (cmd == SNDRV_PCM_TRIGGER_START) ? SB_MODE_CAPTURE_8 : SB_MODE_HALT;
332 return 0; 377 return 0;
333} 378}
334 379
@@ -339,13 +384,21 @@ irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip)
339 384
340 snd_sb_ack_8bit(chip); 385 snd_sb_ack_8bit(chip);
341 switch (chip->mode) { 386 switch (chip->mode) {
342 case SB_MODE_PLAYBACK_8: /* ok.. playback is active */ 387 case SB_MODE_PLAYBACK_16: /* ok.. playback is active */
388 if (chip->hardware != SB_HW_JAZZ16)
389 break;
390 /* fallthru */
391 case SB_MODE_PLAYBACK_8:
343 substream = chip->playback_substream; 392 substream = chip->playback_substream;
344 runtime = substream->runtime; 393 runtime = substream->runtime;
345 if (chip->playback_format == SB_DSP_OUTPUT) 394 if (chip->playback_format == SB_DSP_OUTPUT)
346 snd_sb8_playback_trigger(substream, SNDRV_PCM_TRIGGER_START); 395 snd_sb8_playback_trigger(substream, SNDRV_PCM_TRIGGER_START);
347 snd_pcm_period_elapsed(substream); 396 snd_pcm_period_elapsed(substream);
348 break; 397 break;
398 case SB_MODE_CAPTURE_16:
399 if (chip->hardware != SB_HW_JAZZ16)
400 break;
401 /* fallthru */
349 case SB_MODE_CAPTURE_8: 402 case SB_MODE_CAPTURE_8:
350 substream = chip->capture_substream; 403 substream = chip->capture_substream;
351 runtime = substream->runtime; 404 runtime = substream->runtime;
@@ -361,10 +414,15 @@ static snd_pcm_uframes_t snd_sb8_playback_pointer(struct snd_pcm_substream *subs
361{ 414{
362 struct snd_sb *chip = snd_pcm_substream_chip(substream); 415 struct snd_sb *chip = snd_pcm_substream_chip(substream);
363 size_t ptr; 416 size_t ptr;
417 int dma;
364 418
365 if (chip->mode != SB_MODE_PLAYBACK_8) 419 if (chip->mode & SB_MODE_PLAYBACK_8)
420 dma = chip->dma8;
421 else if (chip->mode & SB_MODE_PLAYBACK_16)
422 dma = chip->dma16;
423 else
366 return 0; 424 return 0;
367 ptr = snd_dma_pointer(chip->dma8, chip->p_dma_size); 425 ptr = snd_dma_pointer(dma, chip->p_dma_size);
368 return bytes_to_frames(substream->runtime, ptr); 426 return bytes_to_frames(substream->runtime, ptr);
369} 427}
370 428
@@ -372,10 +430,15 @@ static snd_pcm_uframes_t snd_sb8_capture_pointer(struct snd_pcm_substream *subst
372{ 430{
373 struct snd_sb *chip = snd_pcm_substream_chip(substream); 431 struct snd_sb *chip = snd_pcm_substream_chip(substream);
374 size_t ptr; 432 size_t ptr;
433 int dma;
375 434
376 if (chip->mode != SB_MODE_CAPTURE_8) 435 if (chip->mode & SB_MODE_CAPTURE_8)
436 dma = chip->dma8;
437 else if (chip->mode & SB_MODE_CAPTURE_16)
438 dma = chip->dma16;
439 else
377 return 0; 440 return 0;
378 ptr = snd_dma_pointer(chip->dma8, chip->c_dma_size); 441 ptr = snd_dma_pointer(dma, chip->c_dma_size);
379 return bytes_to_frames(substream->runtime, ptr); 442 return bytes_to_frames(substream->runtime, ptr);
380} 443}
381 444
@@ -446,6 +509,13 @@ static int snd_sb8_open(struct snd_pcm_substream *substream)
446 runtime->hw = snd_sb8_capture; 509 runtime->hw = snd_sb8_capture;
447 } 510 }
448 switch (chip->hardware) { 511 switch (chip->hardware) {
512 case SB_HW_JAZZ16:
513 runtime->hw.formats |= SNDRV_PCM_FMTBIT_S16_LE;
514 runtime->hw.rates |= SNDRV_PCM_RATE_8000_48000;
515 runtime->hw.rate_min = 4000;
516 runtime->hw.rate_max = 50000;
517 runtime->hw.channels_max = 2;
518 break;
449 case SB_HW_PRO: 519 case SB_HW_PRO:
450 runtime->hw.rate_max = 44100; 520 runtime->hw.rate_max = 44100;
451 runtime->hw.channels_max = 2; 521 runtime->hw.channels_max = 2;
@@ -468,6 +538,14 @@ static int snd_sb8_open(struct snd_pcm_substream *substream)
468 } 538 }
469 snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 539 snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
470 &hw_constraints_clock); 540 &hw_constraints_clock);
541 if (chip->dma8 > 3 || chip->dma16 >= 0) {
542 snd_pcm_hw_constraint_step(runtime, 0,
543 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 2);
544 snd_pcm_hw_constraint_step(runtime, 0,
545 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 2);
546 runtime->hw.buffer_bytes_max = 128 * 1024 * 1024;
547 runtime->hw.period_bytes_max = 128 * 1024 * 1024;
548 }
471 return 0; 549 return 0;
472} 550}
473 551
@@ -480,6 +558,10 @@ static int snd_sb8_close(struct snd_pcm_substream *substream)
480 chip->capture_substream = NULL; 558 chip->capture_substream = NULL;
481 spin_lock_irqsave(&chip->open_lock, flags); 559 spin_lock_irqsave(&chip->open_lock, flags);
482 chip->open &= ~SB_OPEN_PCM; 560 chip->open &= ~SB_OPEN_PCM;
561 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
562 chip->mode &= ~SB_MODE_PLAYBACK;
563 else
564 chip->mode &= ~SB_MODE_CAPTURE;
483 spin_unlock_irqrestore(&chip->open_lock, flags); 565 spin_unlock_irqrestore(&chip->open_lock, flags);
484 return 0; 566 return 0;
485} 567}
@@ -515,6 +597,7 @@ int snd_sb8dsp_pcm(struct snd_sb *chip, int device, struct snd_pcm ** rpcm)
515 struct snd_card *card = chip->card; 597 struct snd_card *card = chip->card;
516 struct snd_pcm *pcm; 598 struct snd_pcm *pcm;
517 int err; 599 int err;
600 size_t max_prealloc = 64 * 1024;
518 601
519 if (rpcm) 602 if (rpcm)
520 *rpcm = NULL; 603 *rpcm = NULL;
@@ -527,9 +610,11 @@ int snd_sb8dsp_pcm(struct snd_sb *chip, int device, struct snd_pcm ** rpcm)
527 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb8_playback_ops); 610 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb8_playback_ops);
528 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb8_capture_ops); 611 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb8_capture_ops);
529 612
613 if (chip->dma8 > 3 || chip->dma16 >= 0)
614 max_prealloc = 128 * 1024;
530 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 615 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
531 snd_dma_isa_data(), 616 snd_dma_isa_data(),
532 64*1024, 64*1024); 617 64*1024, max_prealloc);
533 618
534 if (rpcm) 619 if (rpcm)
535 *rpcm = pcm; 620 *rpcm = pcm;
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
index 27a651502251..eae6c1c0eff9 100644
--- a/sound/isa/sb/sb_common.c
+++ b/sound/isa/sb/sb_common.c
@@ -170,6 +170,9 @@ static int snd_sbdsp_probe(struct snd_sb * chip)
170 case SB_HW_CS5530: 170 case SB_HW_CS5530:
171 str = "16 (CS5530)"; 171 str = "16 (CS5530)";
172 break; 172 break;
173 case SB_HW_JAZZ16:
174 str = "Pro (Jazz16)";
175 break;
173 default: 176 default:
174 return -ENODEV; 177 return -ENODEV;
175 } 178 }
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c
index 8cfc41fbe368..6496822c1808 100644
--- a/sound/isa/sb/sb_mixer.c
+++ b/sound/isa/sb/sb_mixer.c
@@ -779,6 +779,7 @@ int snd_sbmixer_new(struct snd_sb *chip)
779 return err; 779 return err;
780 break; 780 break;
781 case SB_HW_PRO: 781 case SB_HW_PRO:
782 case SB_HW_JAZZ16:
782 if ((err = snd_sbmixer_init(chip, 783 if ((err = snd_sbmixer_init(chip,
783 snd_sbpro_controls, 784 snd_sbpro_controls,
784 ARRAY_SIZE(snd_sbpro_controls), 785 ARRAY_SIZE(snd_sbpro_controls),
@@ -929,6 +930,7 @@ void snd_sbmixer_suspend(struct snd_sb *chip)
929 save_mixer(chip, sb20_saved_regs, ARRAY_SIZE(sb20_saved_regs)); 930 save_mixer(chip, sb20_saved_regs, ARRAY_SIZE(sb20_saved_regs));
930 break; 931 break;
931 case SB_HW_PRO: 932 case SB_HW_PRO:
933 case SB_HW_JAZZ16:
932 save_mixer(chip, sbpro_saved_regs, ARRAY_SIZE(sbpro_saved_regs)); 934 save_mixer(chip, sbpro_saved_regs, ARRAY_SIZE(sbpro_saved_regs));
933 break; 935 break;
934 case SB_HW_16: 936 case SB_HW_16:
@@ -955,6 +957,7 @@ void snd_sbmixer_resume(struct snd_sb *chip)
955 restore_mixer(chip, sb20_saved_regs, ARRAY_SIZE(sb20_saved_regs)); 957 restore_mixer(chip, sb20_saved_regs, ARRAY_SIZE(sb20_saved_regs));
956 break; 958 break;
957 case SB_HW_PRO: 959 case SB_HW_PRO:
960 case SB_HW_JAZZ16:
958 restore_mixer(chip, sbpro_saved_regs, ARRAY_SIZE(sbpro_saved_regs)); 961 restore_mixer(chip, sbpro_saved_regs, ARRAY_SIZE(sbpro_saved_regs));
959 break; 962 break;
960 case SB_HW_16: 963 case SB_HW_16: