~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/pcmcia/vx/vxp_ops.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /sound/pcmcia/vx/vxp_ops.c (Architecture mips) and /sound/pcmcia/vx/vxp_ops.c (Architecture i386)


  1 // SPDX-License-Identifier: GPL-2.0-or-later        1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*                                                  2 /*
  3  * Driver for Digigram VXpocket soundcards          3  * Driver for Digigram VXpocket soundcards
  4  *                                                  4  *
  5  * lowlevel routines for VXpocket soundcards        5  * lowlevel routines for VXpocket soundcards
  6  *                                                  6  *
  7  * Copyright (c) 2002 by Takashi Iwai <tiwai@s      7  * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
  8  */                                                 8  */
  9                                                     9 
 10 #include <linux/delay.h>                           10 #include <linux/delay.h>
 11 #include <linux/device.h>                          11 #include <linux/device.h>
 12 #include <linux/firmware.h>                        12 #include <linux/firmware.h>
 13 #include <linux/io.h>                              13 #include <linux/io.h>
 14 #include <sound/core.h>                            14 #include <sound/core.h>
 15 #include "vxpocket.h"                              15 #include "vxpocket.h"
 16                                                    16 
 17                                                    17 
 18 static const int vxp_reg_offset[VX_REG_MAX] =      18 static const int vxp_reg_offset[VX_REG_MAX] = {
 19         [VX_ICR]        = 0x00,         // ICR     19         [VX_ICR]        = 0x00,         // ICR
 20         [VX_CVR]        = 0x01,         // CVR     20         [VX_CVR]        = 0x01,         // CVR
 21         [VX_ISR]        = 0x02,         // ISR     21         [VX_ISR]        = 0x02,         // ISR
 22         [VX_IVR]        = 0x03,         // IVR     22         [VX_IVR]        = 0x03,         // IVR
 23         [VX_RXH]        = 0x05,         // RXH     23         [VX_RXH]        = 0x05,         // RXH
 24         [VX_RXM]        = 0x06,         // RXM     24         [VX_RXM]        = 0x06,         // RXM
 25         [VX_RXL]        = 0x07,         // RXL     25         [VX_RXL]        = 0x07,         // RXL
 26         [VX_DMA]        = 0x04,         // DMA     26         [VX_DMA]        = 0x04,         // DMA
 27         [VX_CDSP]       = 0x08,         // CDS     27         [VX_CDSP]       = 0x08,         // CDSP
 28         [VX_LOFREQ]     = 0x09,         // LFR     28         [VX_LOFREQ]     = 0x09,         // LFREQ
 29         [VX_HIFREQ]     = 0x0a,         // HFR     29         [VX_HIFREQ]     = 0x0a,         // HFREQ
 30         [VX_DATA]       = 0x0b,         // DAT     30         [VX_DATA]       = 0x0b,         // DATA
 31         [VX_MICRO]      = 0x0c,         // MIC     31         [VX_MICRO]      = 0x0c,         // MICRO
 32         [VX_DIALOG]     = 0x0d,         // DIA     32         [VX_DIALOG]     = 0x0d,         // DIALOG
 33         [VX_CSUER]      = 0x0e,         // CSU     33         [VX_CSUER]      = 0x0e,         // CSUER
 34         [VX_RUER]       = 0x0f,         // RUE     34         [VX_RUER]       = 0x0f,         // RUER
 35 };                                                 35 };
 36                                                    36 
 37                                                    37 
 38 static inline unsigned long vxp_reg_addr(struc     38 static inline unsigned long vxp_reg_addr(struct vx_core *_chip, int reg)
 39 {                                                  39 {
 40         struct snd_vxpocket *chip = to_vxpocke     40         struct snd_vxpocket *chip = to_vxpocket(_chip);
 41         return chip->port + vxp_reg_offset[reg     41         return chip->port + vxp_reg_offset[reg];
 42 }                                                  42 }
 43                                                    43 
 44 /*                                                 44 /*
 45  * snd_vx_inb - read a byte from the register      45  * snd_vx_inb - read a byte from the register
 46  * @offset: register offset                        46  * @offset: register offset
 47  */                                                47  */
 48 static unsigned char vxp_inb(struct vx_core *c     48 static unsigned char vxp_inb(struct vx_core *chip, int offset)
 49 {                                                  49 {
 50         return inb(vxp_reg_addr(chip, offset))     50         return inb(vxp_reg_addr(chip, offset));
 51 }                                                  51 }
 52                                                    52 
 53 /*                                                 53 /*
 54  * snd_vx_outb - write a byte on the register      54  * snd_vx_outb - write a byte on the register
 55  * @offset: the register offset                    55  * @offset: the register offset
 56  * @val: the value to write                        56  * @val: the value to write
 57  */                                                57  */
 58 static void vxp_outb(struct vx_core *chip, int     58 static void vxp_outb(struct vx_core *chip, int offset, unsigned char val)
 59 {                                                  59 {
 60         outb(val, vxp_reg_addr(chip, offset));     60         outb(val, vxp_reg_addr(chip, offset));
 61 }                                                  61 }
 62                                                    62 
 63 /*                                                 63 /*
 64  * redefine macros to call directly                64  * redefine macros to call directly
 65  */                                                65  */
 66 #undef vx_inb                                      66 #undef vx_inb
 67 #define vx_inb(chip,reg)        vxp_inb((struc     67 #define vx_inb(chip,reg)        vxp_inb((struct vx_core *)(chip), VX_##reg)
 68 #undef vx_outb                                     68 #undef vx_outb
 69 #define vx_outb(chip,reg,val)   vxp_outb((stru     69 #define vx_outb(chip,reg,val)   vxp_outb((struct vx_core *)(chip), VX_##reg,val)
 70                                                    70 
 71                                                    71 
 72 /*                                                 72 /*
 73  * vx_check_magic - check the magic word on xi     73  * vx_check_magic - check the magic word on xilinx
 74  *                                                 74  *
 75  * returns zero if a magic word is detected, o     75  * returns zero if a magic word is detected, or a negative error code.
 76  */                                                76  */
 77 static int vx_check_magic(struct vx_core *chip     77 static int vx_check_magic(struct vx_core *chip)
 78 {                                                  78 {
 79         unsigned long end_time = jiffies + HZ      79         unsigned long end_time = jiffies + HZ / 5;
 80         int c;                                     80         int c;
 81         do {                                       81         do {
 82                 c = vx_inb(chip, CDSP);            82                 c = vx_inb(chip, CDSP);
 83                 if (c == CDSP_MAGIC)               83                 if (c == CDSP_MAGIC)
 84                         return 0;                  84                         return 0;
 85                 msleep(10);                        85                 msleep(10);
 86         } while (time_after_eq(end_time, jiffi     86         } while (time_after_eq(end_time, jiffies));
 87         dev_err(chip->card->dev, "cannot find      87         dev_err(chip->card->dev, "cannot find xilinx magic word (%x)\n", c);
 88         return -EIO;                               88         return -EIO;
 89 }                                                  89 }
 90                                                    90 
 91                                                    91 
 92 /*                                                 92 /*
 93  * vx_reset_dsp - reset the DSP                    93  * vx_reset_dsp - reset the DSP
 94  */                                                94  */
 95                                                    95 
 96 #define XX_DSP_RESET_WAIT_TIME          2          96 #define XX_DSP_RESET_WAIT_TIME          2       /* ms */
 97                                                    97 
 98 static void vxp_reset_dsp(struct vx_core *_chi     98 static void vxp_reset_dsp(struct vx_core *_chip)
 99 {                                                  99 {
100         struct snd_vxpocket *chip = to_vxpocke    100         struct snd_vxpocket *chip = to_vxpocket(_chip);
101                                                   101 
102         /* set the reset dsp bit to 1 */          102         /* set the reset dsp bit to 1 */
103         vx_outb(chip, CDSP, chip->regCDSP | VX    103         vx_outb(chip, CDSP, chip->regCDSP | VXP_CDSP_DSP_RESET_MASK);
104         vx_inb(chip, CDSP);                       104         vx_inb(chip, CDSP);
105         mdelay(XX_DSP_RESET_WAIT_TIME);           105         mdelay(XX_DSP_RESET_WAIT_TIME);
106         /* reset the bit */                       106         /* reset the bit */
107         chip->regCDSP &= ~VXP_CDSP_DSP_RESET_M    107         chip->regCDSP &= ~VXP_CDSP_DSP_RESET_MASK;
108         vx_outb(chip, CDSP, chip->regCDSP);       108         vx_outb(chip, CDSP, chip->regCDSP);
109         vx_inb(chip, CDSP);                       109         vx_inb(chip, CDSP);
110         mdelay(XX_DSP_RESET_WAIT_TIME);           110         mdelay(XX_DSP_RESET_WAIT_TIME);
111 }                                                 111 }
112                                                   112 
113 /*                                                113 /*
114  * reset codec bit                                114  * reset codec bit
115  */                                               115  */
116 static void vxp_reset_codec(struct vx_core *_c    116 static void vxp_reset_codec(struct vx_core *_chip)
117 {                                                 117 {
118         struct snd_vxpocket *chip = to_vxpocke    118         struct snd_vxpocket *chip = to_vxpocket(_chip);
119                                                   119 
120         /* Set the reset CODEC bit to 1. */       120         /* Set the reset CODEC bit to 1. */
121         vx_outb(chip, CDSP, chip->regCDSP | VX    121         vx_outb(chip, CDSP, chip->regCDSP | VXP_CDSP_CODEC_RESET_MASK);
122         vx_inb(chip, CDSP);                       122         vx_inb(chip, CDSP);
123         msleep(10);                               123         msleep(10);
124         /* Set the reset CODEC bit to 0. */       124         /* Set the reset CODEC bit to 0. */
125         chip->regCDSP &= ~VXP_CDSP_CODEC_RESET    125         chip->regCDSP &= ~VXP_CDSP_CODEC_RESET_MASK;
126         vx_outb(chip, CDSP, chip->regCDSP);       126         vx_outb(chip, CDSP, chip->regCDSP);
127         vx_inb(chip, CDSP);                       127         vx_inb(chip, CDSP);
128         msleep(1);                                128         msleep(1);
129 }                                                 129 }
130                                                   130 
131 /*                                                131 /*
132  * vx_load_xilinx_binary - load the xilinx bin    132  * vx_load_xilinx_binary - load the xilinx binary image
133  * the binary image is the binary array conver    133  * the binary image is the binary array converted from the bitstream file.
134  */                                               134  */
135 static int vxp_load_xilinx_binary(struct vx_co    135 static int vxp_load_xilinx_binary(struct vx_core *_chip, const struct firmware *fw)
136 {                                                 136 {
137         struct snd_vxpocket *chip = to_vxpocke    137         struct snd_vxpocket *chip = to_vxpocket(_chip);
138         unsigned int i;                           138         unsigned int i;
139         int c;                                    139         int c;
140         int regCSUER, regRUER;                    140         int regCSUER, regRUER;
141         const unsigned char *image;               141         const unsigned char *image;
142         unsigned char data;                       142         unsigned char data;
143                                                   143 
144         /* Switch to programmation mode */        144         /* Switch to programmation mode */
145         chip->regDIALOG |= VXP_DLG_XILINX_REPR    145         chip->regDIALOG |= VXP_DLG_XILINX_REPROG_MASK;
146         vx_outb(chip, DIALOG, chip->regDIALOG)    146         vx_outb(chip, DIALOG, chip->regDIALOG);
147                                                   147 
148         /* Save register CSUER and RUER */        148         /* Save register CSUER and RUER */
149         regCSUER = vx_inb(chip, CSUER);           149         regCSUER = vx_inb(chip, CSUER);
150         regRUER = vx_inb(chip, RUER);             150         regRUER = vx_inb(chip, RUER);
151                                                   151 
152         /* reset HF0 and HF1 */                   152         /* reset HF0 and HF1 */
153         vx_outb(chip, ICR, 0);                    153         vx_outb(chip, ICR, 0);
154                                                   154 
155         /* Wait for answer HF2 equal to 1 */      155         /* Wait for answer HF2 equal to 1 */
156         if (vx_check_isr(_chip, ISR_HF2, ISR_H    156         if (vx_check_isr(_chip, ISR_HF2, ISR_HF2, 20) < 0)
157                 goto _error;                      157                 goto _error;
158                                                   158 
159         /* set HF1 for loading xilinx binary *    159         /* set HF1 for loading xilinx binary */
160         vx_outb(chip, ICR, ICR_HF1);              160         vx_outb(chip, ICR, ICR_HF1);
161         image = fw->data;                         161         image = fw->data;
162         for (i = 0; i < fw->size; i++, image++    162         for (i = 0; i < fw->size; i++, image++) {
163                 data = *image;                    163                 data = *image;
164                 if (vx_wait_isr_bit(_chip, ISR    164                 if (vx_wait_isr_bit(_chip, ISR_TX_EMPTY) < 0)
165                         goto _error;              165                         goto _error;
166                 vx_outb(chip, TXL, data);         166                 vx_outb(chip, TXL, data);
167                 /* wait for reading */            167                 /* wait for reading */
168                 if (vx_wait_for_rx_full(_chip)    168                 if (vx_wait_for_rx_full(_chip) < 0)
169                         goto _error;              169                         goto _error;
170                 c = vx_inb(chip, RXL);            170                 c = vx_inb(chip, RXL);
171                 if (c != (int)data)               171                 if (c != (int)data)
172                         dev_err(_chip->card->d    172                         dev_err(_chip->card->dev,
173                                 "vxpocket: loa    173                                 "vxpocket: load xilinx mismatch at %d: 0x%x != 0x%x\n",
174                                 i, c, (int)dat    174                                 i, c, (int)data);
175         }                                         175         }
176                                                   176 
177         /* reset HF1 */                           177         /* reset HF1 */
178         vx_outb(chip, ICR, 0);                    178         vx_outb(chip, ICR, 0);
179                                                   179 
180         /* wait for HF3 */                        180         /* wait for HF3 */
181         if (vx_check_isr(_chip, ISR_HF3, ISR_H    181         if (vx_check_isr(_chip, ISR_HF3, ISR_HF3, 20) < 0)
182                 goto _error;                      182                 goto _error;
183                                                   183 
184         /* read the number of bytes received *    184         /* read the number of bytes received */
185         if (vx_wait_for_rx_full(_chip) < 0)       185         if (vx_wait_for_rx_full(_chip) < 0)
186                 goto _error;                      186                 goto _error;
187                                                   187 
188         c = (int)vx_inb(chip, RXH) << 16;         188         c = (int)vx_inb(chip, RXH) << 16;
189         c |= (int)vx_inb(chip, RXM) << 8;         189         c |= (int)vx_inb(chip, RXM) << 8;
190         c |= vx_inb(chip, RXL);                   190         c |= vx_inb(chip, RXL);
191                                                   191 
192         dev_dbg(_chip->card->dev,                 192         dev_dbg(_chip->card->dev,
193                 "xilinx: dsp size received 0x%    193                 "xilinx: dsp size received 0x%x, orig 0x%zx\n", c, fw->size);
194                                                   194 
195         vx_outb(chip, ICR, ICR_HF0);              195         vx_outb(chip, ICR, ICR_HF0);
196                                                   196 
197         /* TEMPO 250ms : wait until Xilinx is     197         /* TEMPO 250ms : wait until Xilinx is downloaded */
198         msleep(300);                              198         msleep(300);
199                                                   199 
200         /* test magical word */                   200         /* test magical word */
201         if (vx_check_magic(_chip) < 0)            201         if (vx_check_magic(_chip) < 0)
202                 goto _error;                      202                 goto _error;
203                                                   203 
204         /* Restore register 0x0E and 0x0F (thu    204         /* Restore register 0x0E and 0x0F (thus replacing COR and FCSR) */
205         vx_outb(chip, CSUER, regCSUER);           205         vx_outb(chip, CSUER, regCSUER);
206         vx_outb(chip, RUER, regRUER);             206         vx_outb(chip, RUER, regRUER);
207                                                   207 
208         /* Reset the Xilinx's signal enabling     208         /* Reset the Xilinx's signal enabling IO access */
209         chip->regDIALOG |= VXP_DLG_XILINX_REPR    209         chip->regDIALOG |= VXP_DLG_XILINX_REPROG_MASK;
210         vx_outb(chip, DIALOG, chip->regDIALOG)    210         vx_outb(chip, DIALOG, chip->regDIALOG);
211         vx_inb(chip, DIALOG);                     211         vx_inb(chip, DIALOG);
212         msleep(10);                               212         msleep(10);
213         chip->regDIALOG &= ~VXP_DLG_XILINX_REP    213         chip->regDIALOG &= ~VXP_DLG_XILINX_REPROG_MASK;
214         vx_outb(chip, DIALOG, chip->regDIALOG)    214         vx_outb(chip, DIALOG, chip->regDIALOG);
215         vx_inb(chip, DIALOG);                     215         vx_inb(chip, DIALOG);
216                                                   216 
217         /* Reset of the Codec */                  217         /* Reset of the Codec */
218         vxp_reset_codec(_chip);                   218         vxp_reset_codec(_chip);
219         vx_reset_dsp(_chip);                      219         vx_reset_dsp(_chip);
220                                                   220 
221         return 0;                                 221         return 0;
222                                                   222 
223  _error:                                          223  _error:
224         vx_outb(chip, CSUER, regCSUER);           224         vx_outb(chip, CSUER, regCSUER);
225         vx_outb(chip, RUER, regRUER);             225         vx_outb(chip, RUER, regRUER);
226         chip->regDIALOG &= ~VXP_DLG_XILINX_REP    226         chip->regDIALOG &= ~VXP_DLG_XILINX_REPROG_MASK;
227         vx_outb(chip, DIALOG, chip->regDIALOG)    227         vx_outb(chip, DIALOG, chip->regDIALOG);
228         return -EIO;                              228         return -EIO;
229 }                                                 229 }
230                                                   230 
231                                                   231 
232 /*                                                232 /*
233  * vxp_load_dsp - load_dsp callback               233  * vxp_load_dsp - load_dsp callback
234  */                                               234  */
235 static int vxp_load_dsp(struct vx_core *vx, in    235 static int vxp_load_dsp(struct vx_core *vx, int index, const struct firmware *fw)
236 {                                                 236 {
237         int err;                                  237         int err;
238                                                   238 
239         switch (index) {                          239         switch (index) {
240         case 0:                                   240         case 0:
241                 /* xilinx boot */                 241                 /* xilinx boot */
242                 err = vx_check_magic(vx);         242                 err = vx_check_magic(vx);
243                 if (err < 0)                      243                 if (err < 0)
244                         return err;               244                         return err;
245                 err = snd_vx_load_boot_image(v    245                 err = snd_vx_load_boot_image(vx, fw);
246                 if (err < 0)                      246                 if (err < 0)
247                         return err;               247                         return err;
248                 return 0;                         248                 return 0;
249         case 1:                                   249         case 1:
250                 /* xilinx image */                250                 /* xilinx image */
251                 return vxp_load_xilinx_binary(    251                 return vxp_load_xilinx_binary(vx, fw);
252         case 2:                                   252         case 2:
253                 /* DSP boot */                    253                 /* DSP boot */
254                 return snd_vx_dsp_boot(vx, fw)    254                 return snd_vx_dsp_boot(vx, fw);
255         case 3:                                   255         case 3:
256                 /* DSP image */                   256                 /* DSP image */
257                 return snd_vx_dsp_load(vx, fw)    257                 return snd_vx_dsp_load(vx, fw);
258         default:                                  258         default:
259                 snd_BUG();                        259                 snd_BUG();
260                 return -EINVAL;                   260                 return -EINVAL;
261         }                                         261         }
262 }                                                 262 }
263                                                   263                 
264                                                   264 
265 /*                                                265 /*
266  * vx_test_and_ack - test and acknowledge inte    266  * vx_test_and_ack - test and acknowledge interrupt
267  *                                                267  *
268  * called from irq hander, too                    268  * called from irq hander, too
269  *                                                269  *
270  * spinlock held!                                 270  * spinlock held!
271  */                                               271  */
272 static int vxp_test_and_ack(struct vx_core *_c    272 static int vxp_test_and_ack(struct vx_core *_chip)
273 {                                                 273 {
274         struct snd_vxpocket *chip = to_vxpocke    274         struct snd_vxpocket *chip = to_vxpocket(_chip);
275                                                   275 
276         /* not booted yet? */                     276         /* not booted yet? */
277         if (! (_chip->chip_status & VX_STAT_XI    277         if (! (_chip->chip_status & VX_STAT_XILINX_LOADED))
278                 return -ENXIO;                    278                 return -ENXIO;
279                                                   279 
280         if (! (vx_inb(chip, DIALOG) & VXP_DLG_    280         if (! (vx_inb(chip, DIALOG) & VXP_DLG_MEMIRQ_MASK))
281                 return -EIO;                      281                 return -EIO;
282                                                   282         
283         /* ok, interrupts generated, now ack i    283         /* ok, interrupts generated, now ack it */
284         /* set ACQUIT bit up and down */          284         /* set ACQUIT bit up and down */
285         vx_outb(chip, DIALOG, chip->regDIALOG     285         vx_outb(chip, DIALOG, chip->regDIALOG | VXP_DLG_ACK_MEMIRQ_MASK);
286         /* useless read just to spend some tim    286         /* useless read just to spend some time and maintain
287          * the ACQUIT signal up for a while (     287          * the ACQUIT signal up for a while ( a bus cycle )
288          */                                       288          */
289         vx_inb(chip, DIALOG);                     289         vx_inb(chip, DIALOG);
290         vx_outb(chip, DIALOG, chip->regDIALOG     290         vx_outb(chip, DIALOG, chip->regDIALOG & ~VXP_DLG_ACK_MEMIRQ_MASK);
291                                                   291 
292         return 0;                                 292         return 0;
293 }                                                 293 }
294                                                   294 
295                                                   295 
296 /*                                                296 /*
297  * vx_validate_irq - enable/disable IRQ           297  * vx_validate_irq - enable/disable IRQ
298  */                                               298  */
299 static void vxp_validate_irq(struct vx_core *_    299 static void vxp_validate_irq(struct vx_core *_chip, int enable)
300 {                                                 300 {
301         struct snd_vxpocket *chip = to_vxpocke    301         struct snd_vxpocket *chip = to_vxpocket(_chip);
302                                                   302 
303         /* Set the interrupt enable bit to 1 i    303         /* Set the interrupt enable bit to 1 in CDSP register */
304         if (enable)                               304         if (enable)
305                 chip->regCDSP |= VXP_CDSP_VALI    305                 chip->regCDSP |= VXP_CDSP_VALID_IRQ_MASK;
306         else                                      306         else
307                 chip->regCDSP &= ~VXP_CDSP_VAL    307                 chip->regCDSP &= ~VXP_CDSP_VALID_IRQ_MASK;
308         vx_outb(chip, CDSP, chip->regCDSP);       308         vx_outb(chip, CDSP, chip->regCDSP);
309 }                                                 309 }
310                                                   310 
311 /*                                                311 /*
312  * vx_setup_pseudo_dma - set up the pseudo dma    312  * vx_setup_pseudo_dma - set up the pseudo dma read/write mode.
313  * @do_write: 0 = read, 1 = set up for DMA wri    313  * @do_write: 0 = read, 1 = set up for DMA write
314  */                                               314  */
315 static void vx_setup_pseudo_dma(struct vx_core    315 static void vx_setup_pseudo_dma(struct vx_core *_chip, int do_write)
316 {                                                 316 {
317         struct snd_vxpocket *chip = to_vxpocke    317         struct snd_vxpocket *chip = to_vxpocket(_chip);
318                                                   318 
319         /* Interrupt mode and HREQ pin enabled    319         /* Interrupt mode and HREQ pin enabled for host transmit / receive data transfers */
320         vx_outb(chip, ICR, do_write ? ICR_TREQ    320         vx_outb(chip, ICR, do_write ? ICR_TREQ : ICR_RREQ);
321         /* Reset the pseudo-dma register */       321         /* Reset the pseudo-dma register */
322         vx_inb(chip, ISR);                        322         vx_inb(chip, ISR);
323         vx_outb(chip, ISR, 0);                    323         vx_outb(chip, ISR, 0);
324                                                   324 
325         /* Select DMA in read/write transfer m    325         /* Select DMA in read/write transfer mode and in 16-bit accesses */
326         chip->regDIALOG |= VXP_DLG_DMA16_SEL_M    326         chip->regDIALOG |= VXP_DLG_DMA16_SEL_MASK;
327         chip->regDIALOG |= do_write ? VXP_DLG_    327         chip->regDIALOG |= do_write ? VXP_DLG_DMAWRITE_SEL_MASK : VXP_DLG_DMAREAD_SEL_MASK;
328         vx_outb(chip, DIALOG, chip->regDIALOG)    328         vx_outb(chip, DIALOG, chip->regDIALOG);
329                                                   329 
330 }                                                 330 }
331                                                   331 
332 /*                                                332 /*
333  * vx_release_pseudo_dma - disable the pseudo-    333  * vx_release_pseudo_dma - disable the pseudo-DMA mode
334  */                                               334  */
335 static void vx_release_pseudo_dma(struct vx_co    335 static void vx_release_pseudo_dma(struct vx_core *_chip)
336 {                                                 336 {
337         struct snd_vxpocket *chip = to_vxpocke    337         struct snd_vxpocket *chip = to_vxpocket(_chip);
338                                                   338 
339         /* Disable DMA and 16-bit accesses */     339         /* Disable DMA and 16-bit accesses */
340         chip->regDIALOG &= ~(VXP_DLG_DMAWRITE_    340         chip->regDIALOG &= ~(VXP_DLG_DMAWRITE_SEL_MASK|
341                              VXP_DLG_DMAREAD_S    341                              VXP_DLG_DMAREAD_SEL_MASK|
342                              VXP_DLG_DMA16_SEL    342                              VXP_DLG_DMA16_SEL_MASK);
343         vx_outb(chip, DIALOG, chip->regDIALOG)    343         vx_outb(chip, DIALOG, chip->regDIALOG);
344         /* HREQ pin disabled. */                  344         /* HREQ pin disabled. */
345         vx_outb(chip, ICR, 0);                    345         vx_outb(chip, ICR, 0);
346 }                                                 346 }
347                                                   347 
348 /*                                                348 /*
349  * vx_pseudo_dma_write - write bulk data on ps    349  * vx_pseudo_dma_write - write bulk data on pseudo-DMA mode
350  * @count: data length to transfer in bytes       350  * @count: data length to transfer in bytes
351  *                                                351  *
352  * data size must be aligned to 6 bytes to ens    352  * data size must be aligned to 6 bytes to ensure the 24bit alignment on DSP.
353  * NB: call with a certain lock!                  353  * NB: call with a certain lock!
354  */                                               354  */
355 static void vxp_dma_write(struct vx_core *chip    355 static void vxp_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime,
356                           struct vx_pipe *pipe    356                           struct vx_pipe *pipe, int count)
357 {                                                 357 {
358         long port = vxp_reg_addr(chip, VX_DMA)    358         long port = vxp_reg_addr(chip, VX_DMA);
359         int offset = pipe->hw_ptr;                359         int offset = pipe->hw_ptr;
360         unsigned short *addr = (unsigned short    360         unsigned short *addr = (unsigned short *)(runtime->dma_area + offset);
361                                                   361 
362         vx_setup_pseudo_dma(chip, 1);             362         vx_setup_pseudo_dma(chip, 1);
363         if (offset + count >= pipe->buffer_byt    363         if (offset + count >= pipe->buffer_bytes) {
364                 int length = pipe->buffer_byte    364                 int length = pipe->buffer_bytes - offset;
365                 count -= length;                  365                 count -= length;
366                 length >>= 1; /* in 16bit word    366                 length >>= 1; /* in 16bit words */
367                 /* Transfer using pseudo-dma.     367                 /* Transfer using pseudo-dma. */
368                 for (; length > 0; length--) {    368                 for (; length > 0; length--) {
369                         outw(*addr, port);        369                         outw(*addr, port);
370                         addr++;                   370                         addr++;
371                 }                                 371                 }
372                 addr = (unsigned short *)runti    372                 addr = (unsigned short *)runtime->dma_area;
373                 pipe->hw_ptr = 0;                 373                 pipe->hw_ptr = 0;
374         }                                         374         }
375         pipe->hw_ptr += count;                    375         pipe->hw_ptr += count;
376         count >>= 1; /* in 16bit words */         376         count >>= 1; /* in 16bit words */
377         /* Transfer using pseudo-dma. */          377         /* Transfer using pseudo-dma. */
378         for (; count > 0; count--) {              378         for (; count > 0; count--) {
379                 outw(*addr, port);                379                 outw(*addr, port);
380                 addr++;                           380                 addr++;
381         }                                         381         }
382         vx_release_pseudo_dma(chip);              382         vx_release_pseudo_dma(chip);
383 }                                                 383 }
384                                                   384 
385                                                   385 
386 /*                                                386 /*
387  * vx_pseudo_dma_read - read bulk data on pseu    387  * vx_pseudo_dma_read - read bulk data on pseudo DMA mode
388  * @offset: buffer offset in bytes                388  * @offset: buffer offset in bytes
389  * @count: data length to transfer in bytes       389  * @count: data length to transfer in bytes
390  *                                                390  *
391  * the read length must be aligned to 6 bytes,    391  * the read length must be aligned to 6 bytes, as well as write.
392  * NB: call with a certain lock!                  392  * NB: call with a certain lock!
393  */                                               393  */
394 static void vxp_dma_read(struct vx_core *chip,    394 static void vxp_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime,
395                          struct vx_pipe *pipe,    395                          struct vx_pipe *pipe, int count)
396 {                                                 396 {
397         struct snd_vxpocket *pchip = to_vxpock    397         struct snd_vxpocket *pchip = to_vxpocket(chip);
398         long port = vxp_reg_addr(chip, VX_DMA)    398         long port = vxp_reg_addr(chip, VX_DMA);
399         int offset = pipe->hw_ptr;                399         int offset = pipe->hw_ptr;
400         unsigned short *addr = (unsigned short    400         unsigned short *addr = (unsigned short *)(runtime->dma_area + offset);
401                                                   401 
402         if (snd_BUG_ON(count % 2))                402         if (snd_BUG_ON(count % 2))
403                 return;                           403                 return;
404         vx_setup_pseudo_dma(chip, 0);             404         vx_setup_pseudo_dma(chip, 0);
405         if (offset + count >= pipe->buffer_byt    405         if (offset + count >= pipe->buffer_bytes) {
406                 int length = pipe->buffer_byte    406                 int length = pipe->buffer_bytes - offset;
407                 count -= length;                  407                 count -= length;
408                 length >>= 1; /* in 16bit word    408                 length >>= 1; /* in 16bit words */
409                 /* Transfer using pseudo-dma.     409                 /* Transfer using pseudo-dma. */
410                 for (; length > 0; length--)      410                 for (; length > 0; length--)
411                         *addr++ = inw(port);      411                         *addr++ = inw(port);
412                 addr = (unsigned short *)runti    412                 addr = (unsigned short *)runtime->dma_area;
413                 pipe->hw_ptr = 0;                 413                 pipe->hw_ptr = 0;
414         }                                         414         }
415         pipe->hw_ptr += count;                    415         pipe->hw_ptr += count;
416         count >>= 1; /* in 16bit words */         416         count >>= 1; /* in 16bit words */
417         /* Transfer using pseudo-dma. */          417         /* Transfer using pseudo-dma. */
418         for (; count > 1; count--)                418         for (; count > 1; count--)
419                 *addr++ = inw(port);              419                 *addr++ = inw(port);
420         /* Disable DMA */                         420         /* Disable DMA */
421         pchip->regDIALOG &= ~VXP_DLG_DMAREAD_S    421         pchip->regDIALOG &= ~VXP_DLG_DMAREAD_SEL_MASK;
422         vx_outb(chip, DIALOG, pchip->regDIALOG    422         vx_outb(chip, DIALOG, pchip->regDIALOG);
423         /* Read the last word (16 bits) */        423         /* Read the last word (16 bits) */
424         *addr = inw(port);                        424         *addr = inw(port);
425         /* Disable 16-bit accesses */             425         /* Disable 16-bit accesses */
426         pchip->regDIALOG &= ~VXP_DLG_DMA16_SEL    426         pchip->regDIALOG &= ~VXP_DLG_DMA16_SEL_MASK;
427         vx_outb(chip, DIALOG, pchip->regDIALOG    427         vx_outb(chip, DIALOG, pchip->regDIALOG);
428         /* HREQ pin disabled. */                  428         /* HREQ pin disabled. */
429         vx_outb(chip, ICR, 0);                    429         vx_outb(chip, ICR, 0);
430 }                                                 430 }
431                                                   431 
432                                                   432 
433 /*                                                433 /*
434  * write a codec data (24bit)                     434  * write a codec data (24bit)
435  */                                               435  */
436 static void vxp_write_codec_reg(struct vx_core    436 static void vxp_write_codec_reg(struct vx_core *chip, int codec, unsigned int data)
437 {                                                 437 {
438         int i;                                    438         int i;
439                                                   439 
440         /* Activate access to the correspondin    440         /* Activate access to the corresponding codec register */
441         if (! codec)                              441         if (! codec)
442                 vx_inb(chip, LOFREQ);             442                 vx_inb(chip, LOFREQ);
443         else                                      443         else
444                 vx_inb(chip, CODEC2);             444                 vx_inb(chip, CODEC2);
445                                                   445                 
446         /* We have to send 24 bits (3 x 8 bits    446         /* We have to send 24 bits (3 x 8 bits). Start with most signif. Bit */
447         for (i = 0; i < 24; i++, data <<= 1)      447         for (i = 0; i < 24; i++, data <<= 1)
448                 vx_outb(chip, DATA, ((data & 0    448                 vx_outb(chip, DATA, ((data & 0x800000) ? VX_DATA_CODEC_MASK : 0));
449                                                   449         
450         /* Terminate access to codec registers    450         /* Terminate access to codec registers */
451         vx_inb(chip, HIFREQ);                     451         vx_inb(chip, HIFREQ);
452 }                                                 452 }
453                                                   453 
454                                                   454 
455 /*                                                455 /*
456  * vx_set_mic_boost - set mic boost level (on     456  * vx_set_mic_boost - set mic boost level (on vxp440 only)
457  * @boost: 0 = 20dB, 1 = +38dB                    457  * @boost: 0 = 20dB, 1 = +38dB
458  */                                               458  */
459 void vx_set_mic_boost(struct vx_core *chip, in    459 void vx_set_mic_boost(struct vx_core *chip, int boost)
460 {                                                 460 {
461         struct snd_vxpocket *pchip = to_vxpock    461         struct snd_vxpocket *pchip = to_vxpocket(chip);
462                                                   462 
463         if (chip->chip_status & VX_STAT_IS_STA    463         if (chip->chip_status & VX_STAT_IS_STALE)
464                 return;                           464                 return;
465                                                   465 
466         mutex_lock(&chip->lock);                  466         mutex_lock(&chip->lock);
467         if (pchip->regCDSP & P24_CDSP_MICS_SEL    467         if (pchip->regCDSP & P24_CDSP_MICS_SEL_MASK) {
468                 if (boost) {                      468                 if (boost) {
469                         /* boost: 38 dB */        469                         /* boost: 38 dB */
470                         pchip->regCDSP &= ~P24    470                         pchip->regCDSP &= ~P24_CDSP_MIC20_SEL_MASK;
471                         pchip->regCDSP |=  P24    471                         pchip->regCDSP |=  P24_CDSP_MIC38_SEL_MASK;
472                 } else {                          472                 } else {
473                         /* minimum value: 20 d    473                         /* minimum value: 20 dB */
474                         pchip->regCDSP |=  P24    474                         pchip->regCDSP |=  P24_CDSP_MIC20_SEL_MASK;
475                         pchip->regCDSP &= ~P24    475                         pchip->regCDSP &= ~P24_CDSP_MIC38_SEL_MASK;
476                 }                                 476                 }
477                 vx_outb(chip, CDSP, pchip->reg    477                 vx_outb(chip, CDSP, pchip->regCDSP);
478         }                                         478         }
479         mutex_unlock(&chip->lock);                479         mutex_unlock(&chip->lock);
480 }                                                 480 }
481                                                   481 
482 /*                                                482 /*
483  * remap the linear value (0-8) to the actual     483  * remap the linear value (0-8) to the actual value (0-15)
484  */                                               484  */
485 static int vx_compute_mic_level(int level)        485 static int vx_compute_mic_level(int level)
486 {                                                 486 {
487         switch (level) {                          487         switch (level) {
488         case 5: level = 6 ; break;                488         case 5: level = 6 ; break;
489         case 6: level = 8 ; break;                489         case 6: level = 8 ; break;
490         case 7: level = 11; break;                490         case 7: level = 11; break;
491         case 8: level = 15; break;                491         case 8: level = 15; break;
492         default: break ;                          492         default: break ;
493         }                                         493         }
494         return level;                             494         return level;
495 }                                                 495 }
496                                                   496 
497 /*                                                497 /*
498  * vx_set_mic_level - set mic level (on vxpock    498  * vx_set_mic_level - set mic level (on vxpocket only)
499  * @level: the mic level = 0 - 8 (max)            499  * @level: the mic level = 0 - 8 (max)
500  */                                               500  */
501 void vx_set_mic_level(struct vx_core *chip, in    501 void vx_set_mic_level(struct vx_core *chip, int level)
502 {                                                 502 {
503         struct snd_vxpocket *pchip = to_vxpock    503         struct snd_vxpocket *pchip = to_vxpocket(chip);
504                                                   504 
505         if (chip->chip_status & VX_STAT_IS_STA    505         if (chip->chip_status & VX_STAT_IS_STALE)
506                 return;                           506                 return;
507                                                   507 
508         mutex_lock(&chip->lock);                  508         mutex_lock(&chip->lock);
509         if (pchip->regCDSP & VXP_CDSP_MIC_SEL_    509         if (pchip->regCDSP & VXP_CDSP_MIC_SEL_MASK) {
510                 level = vx_compute_mic_level(l    510                 level = vx_compute_mic_level(level);
511                 vx_outb(chip, MICRO, level);      511                 vx_outb(chip, MICRO, level);
512         }                                         512         }
513         mutex_unlock(&chip->lock);                513         mutex_unlock(&chip->lock);
514 }                                                 514 }
515                                                   515 
516                                                   516 
517 /*                                                517 /*
518  * change the input audio source                  518  * change the input audio source
519  */                                               519  */
520 static void vxp_change_audio_source(struct vx_    520 static void vxp_change_audio_source(struct vx_core *_chip, int src)
521 {                                                 521 {
522         struct snd_vxpocket *chip = to_vxpocke    522         struct snd_vxpocket *chip = to_vxpocket(_chip);
523                                                   523 
524         switch (src) {                            524         switch (src) {
525         case VX_AUDIO_SRC_DIGITAL:                525         case VX_AUDIO_SRC_DIGITAL:
526                 chip->regCDSP |= VXP_CDSP_DATA    526                 chip->regCDSP |= VXP_CDSP_DATAIN_SEL_MASK;
527                 vx_outb(chip, CDSP, chip->regC    527                 vx_outb(chip, CDSP, chip->regCDSP);
528                 break;                            528                 break;
529         case VX_AUDIO_SRC_LINE:                   529         case VX_AUDIO_SRC_LINE:
530                 chip->regCDSP &= ~VXP_CDSP_DAT    530                 chip->regCDSP &= ~VXP_CDSP_DATAIN_SEL_MASK;
531                 if (_chip->type == VX_TYPE_VXP    531                 if (_chip->type == VX_TYPE_VXP440)
532                         chip->regCDSP &= ~P24_    532                         chip->regCDSP &= ~P24_CDSP_MICS_SEL_MASK;
533                 else                              533                 else
534                         chip->regCDSP &= ~VXP_    534                         chip->regCDSP &= ~VXP_CDSP_MIC_SEL_MASK;
535                 vx_outb(chip, CDSP, chip->regC    535                 vx_outb(chip, CDSP, chip->regCDSP);
536                 break;                            536                 break;
537         case VX_AUDIO_SRC_MIC:                    537         case VX_AUDIO_SRC_MIC:
538                 chip->regCDSP &= ~VXP_CDSP_DAT    538                 chip->regCDSP &= ~VXP_CDSP_DATAIN_SEL_MASK;
539                 /* reset mic levels */            539                 /* reset mic levels */
540                 if (_chip->type == VX_TYPE_VXP    540                 if (_chip->type == VX_TYPE_VXP440) {
541                         chip->regCDSP &= ~P24_    541                         chip->regCDSP &= ~P24_CDSP_MICS_SEL_MASK;
542                         if (chip->mic_level)      542                         if (chip->mic_level)
543                                 chip->regCDSP     543                                 chip->regCDSP |=  P24_CDSP_MIC38_SEL_MASK;
544                         else                      544                         else
545                                 chip->regCDSP     545                                 chip->regCDSP |= P24_CDSP_MIC20_SEL_MASK;
546                         vx_outb(chip, CDSP, ch    546                         vx_outb(chip, CDSP, chip->regCDSP);
547                 } else {                          547                 } else {
548                         chip->regCDSP |= VXP_C    548                         chip->regCDSP |= VXP_CDSP_MIC_SEL_MASK;
549                         vx_outb(chip, CDSP, ch    549                         vx_outb(chip, CDSP, chip->regCDSP);
550                         vx_outb(chip, MICRO, v    550                         vx_outb(chip, MICRO, vx_compute_mic_level(chip->mic_level));
551                 }                                 551                 }
552                 break;                            552                 break;
553         }                                         553         }
554 }                                                 554 }
555                                                   555 
556 /*                                                556 /*
557  * change the clock source                        557  * change the clock source
558  * source = INTERNAL_QUARTZ or UER_SYNC           558  * source = INTERNAL_QUARTZ or UER_SYNC
559  */                                               559  */
560 static void vxp_set_clock_source(struct vx_cor    560 static void vxp_set_clock_source(struct vx_core *_chip, int source)
561 {                                                 561 {
562         struct snd_vxpocket *chip = to_vxpocke    562         struct snd_vxpocket *chip = to_vxpocket(_chip);
563                                                   563 
564         if (source == INTERNAL_QUARTZ)            564         if (source == INTERNAL_QUARTZ)
565                 chip->regCDSP &= ~VXP_CDSP_CLO    565                 chip->regCDSP &= ~VXP_CDSP_CLOCKIN_SEL_MASK;
566         else                                      566         else
567                 chip->regCDSP |= VXP_CDSP_CLOC    567                 chip->regCDSP |= VXP_CDSP_CLOCKIN_SEL_MASK;
568         vx_outb(chip, CDSP, chip->regCDSP);       568         vx_outb(chip, CDSP, chip->regCDSP);
569 }                                                 569 }
570                                                   570 
571                                                   571 
572 /*                                                572 /*
573  * reset the board                                573  * reset the board
574  */                                               574  */
575 static void vxp_reset_board(struct vx_core *_c    575 static void vxp_reset_board(struct vx_core *_chip, int cold_reset)
576 {                                                 576 {
577         struct snd_vxpocket *chip = to_vxpocke    577         struct snd_vxpocket *chip = to_vxpocket(_chip);
578                                                   578 
579         chip->regCDSP = 0;                        579         chip->regCDSP = 0;
580         chip->regDIALOG = 0;                      580         chip->regDIALOG = 0;
581 }                                                 581 }
582                                                   582 
583                                                   583 
584 /*                                                584 /*
585  * callbacks                                      585  * callbacks
586  */                                               586  */
587 /* exported */                                    587 /* exported */
588 const struct snd_vx_ops snd_vxpocket_ops = {      588 const struct snd_vx_ops snd_vxpocket_ops = {
589         .in8 = vxp_inb,                           589         .in8 = vxp_inb,
590         .out8 = vxp_outb,                         590         .out8 = vxp_outb,
591         .test_and_ack = vxp_test_and_ack,         591         .test_and_ack = vxp_test_and_ack,
592         .validate_irq = vxp_validate_irq,         592         .validate_irq = vxp_validate_irq,
593         .write_codec = vxp_write_codec_reg,       593         .write_codec = vxp_write_codec_reg,
594         .reset_codec = vxp_reset_codec,           594         .reset_codec = vxp_reset_codec,
595         .change_audio_source = vxp_change_audi    595         .change_audio_source = vxp_change_audio_source,
596         .set_clock_source = vxp_set_clock_sour    596         .set_clock_source = vxp_set_clock_source,
597         .load_dsp = vxp_load_dsp,                 597         .load_dsp = vxp_load_dsp,
598         .add_controls = vxp_add_mic_controls,     598         .add_controls = vxp_add_mic_controls,
599         .reset_dsp = vxp_reset_dsp,               599         .reset_dsp = vxp_reset_dsp,
600         .reset_board = vxp_reset_board,           600         .reset_board = vxp_reset_board,
601         .dma_write = vxp_dma_write,               601         .dma_write = vxp_dma_write,
602         .dma_read = vxp_dma_read,                 602         .dma_read = vxp_dma_read,
603 };                                                603 };
604                                                   604 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php