Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Beep using pcm
0004  *
0005  * Copyright (c) by Takashi Iwai <tiwai@suse.de>
0006  */
0007 
0008 #include <linux/io.h>
0009 #include <asm/irq.h>
0010 #include <linux/init.h>
0011 #include <linux/slab.h>
0012 #include <linux/input.h>
0013 #include <linux/pci.h>
0014 #include <linux/dma-mapping.h>
0015 #include <sound/core.h>
0016 #include <sound/control.h>
0017 #include "pmac.h"
0018 
0019 struct pmac_beep {
0020     int running;        /* boolean */
0021     int volume;     /* mixer volume: 0-100 */
0022     int volume_play;    /* currently playing volume */
0023     int hz;
0024     int nsamples;
0025     short *buf;     /* allocated wave buffer */
0026     dma_addr_t addr;    /* physical address of buffer */
0027     struct input_dev *dev;
0028 };
0029 
0030 /*
0031  * stop beep if running
0032  */
0033 void snd_pmac_beep_stop(struct snd_pmac *chip)
0034 {
0035     struct pmac_beep *beep = chip->beep;
0036     if (beep && beep->running) {
0037         beep->running = 0;
0038         snd_pmac_beep_dma_stop(chip);
0039     }
0040 }
0041 
0042 /*
0043  * Stuff for outputting a beep.  The values range from -327 to +327
0044  * so we can multiply by an amplitude in the range 0..100 to get a
0045  * signed short value to put in the output buffer.
0046  */
0047 static const short beep_wform[256] = {
0048     0,  40, 79, 117,    153,    187,    218,    245,
0049     269,    288,    304,    316,    323,    327,    327,    324,
0050     318,    310,    299,    288,    275,    262,    249,    236,
0051     224,    213,    204,    196,    190,    186,    183,    182,
0052     182,    183,    186,    189,    192,    196,    200,    203,
0053     206,    208,    209,    209,    209,    207,    204,    201,
0054     197,    193,    188,    183,    179,    174,    170,    166,
0055     163,    161,    160,    159,    159,    160,    161,    162,
0056     164,    166,    168,    169,    171,    171,    171,    170,
0057     169,    167,    163,    159,    155,    150,    144,    139,
0058     133,    128,    122,    117,    113,    110,    107,    105,
0059     103,    103,    103,    103,    104,    104,    105,    105,
0060     105,    103,    101,    97, 92, 86, 78, 68,
0061     58, 45, 32, 18, 3,  -11,    -26,    -41,
0062     -55,    -68,    -79,    -88,    -95,    -100,   -102,   -102,
0063     -99,    -93,    -85,    -75,    -62,    -48,    -33,    -16,
0064     0,  16, 33, 48, 62, 75, 85, 93,
0065     99, 102,    102,    100,    95, 88, 79, 68,
0066     55, 41, 26, 11, -3, -18,    -32,    -45,
0067     -58,    -68,    -78,    -86,    -92,    -97,    -101,   -103,
0068     -105,   -105,   -105,   -104,   -104,   -103,   -103,   -103,
0069     -103,   -105,   -107,   -110,   -113,   -117,   -122,   -128,
0070     -133,   -139,   -144,   -150,   -155,   -159,   -163,   -167,
0071     -169,   -170,   -171,   -171,   -171,   -169,   -168,   -166,
0072     -164,   -162,   -161,   -160,   -159,   -159,   -160,   -161,
0073     -163,   -166,   -170,   -174,   -179,   -183,   -188,   -193,
0074     -197,   -201,   -204,   -207,   -209,   -209,   -209,   -208,
0075     -206,   -203,   -200,   -196,   -192,   -189,   -186,   -183,
0076     -182,   -182,   -183,   -186,   -190,   -196,   -204,   -213,
0077     -224,   -236,   -249,   -262,   -275,   -288,   -299,   -310,
0078     -318,   -324,   -327,   -327,   -323,   -316,   -304,   -288,
0079     -269,   -245,   -218,   -187,   -153,   -117,   -79,    -40,
0080 };
0081 
0082 #define BEEP_SRATE  22050   /* 22050 Hz sample rate */
0083 #define BEEP_BUFLEN 512
0084 #define BEEP_VOLUME 15  /* 0 - 100 */
0085 
0086 static int snd_pmac_beep_event(struct input_dev *dev, unsigned int type,
0087                    unsigned int code, int hz)
0088 {
0089     struct snd_pmac *chip;
0090     struct pmac_beep *beep;
0091     unsigned long flags;
0092     int beep_speed = 0;
0093     int srate;
0094     int period, ncycles, nsamples;
0095     int i, j, f;
0096     short *p;
0097 
0098     if (type != EV_SND)
0099         return -1;
0100 
0101     switch (code) {
0102     case SND_BELL: if (hz) hz = 1000; break;
0103     case SND_TONE: break;
0104     default: return -1;
0105     }
0106 
0107     chip = input_get_drvdata(dev);
0108     if (!chip)
0109         return -1;
0110     beep = chip->beep;
0111     if (!beep)
0112         return -1;
0113 
0114     if (! hz) {
0115         spin_lock_irqsave(&chip->reg_lock, flags);
0116         if (beep->running)
0117             snd_pmac_beep_stop(chip);
0118         spin_unlock_irqrestore(&chip->reg_lock, flags);
0119         return 0;
0120     }
0121 
0122     beep_speed = snd_pmac_rate_index(chip, &chip->playback, BEEP_SRATE);
0123     srate = chip->freq_table[beep_speed];
0124 
0125     if (hz <= srate / BEEP_BUFLEN || hz > srate / 2)
0126         hz = 1000;
0127 
0128     spin_lock_irqsave(&chip->reg_lock, flags);
0129     if (chip->playback.running || chip->capture.running || beep->running) {
0130         spin_unlock_irqrestore(&chip->reg_lock, flags);
0131         return 0;
0132     }
0133     beep->running = 1;
0134     spin_unlock_irqrestore(&chip->reg_lock, flags);
0135 
0136     if (hz == beep->hz && beep->volume == beep->volume_play) {
0137         nsamples = beep->nsamples;
0138     } else {
0139         period = srate * 256 / hz;  /* fixed point */
0140         ncycles = BEEP_BUFLEN * 256 / period;
0141         nsamples = (period * ncycles) >> 8;
0142         f = ncycles * 65536 / nsamples;
0143         j = 0;
0144         p = beep->buf;
0145         for (i = 0; i < nsamples; ++i, p += 2) {
0146             p[0] = p[1] = beep_wform[j >> 8] * beep->volume;
0147             j = (j + f) & 0xffff;
0148         }
0149         beep->hz = hz;
0150         beep->volume_play = beep->volume;
0151         beep->nsamples = nsamples;
0152     }
0153 
0154     spin_lock_irqsave(&chip->reg_lock, flags);
0155     snd_pmac_beep_dma_start(chip, beep->nsamples * 4, beep->addr, beep_speed);
0156     spin_unlock_irqrestore(&chip->reg_lock, flags);
0157     return 0;
0158 }
0159 
0160 /*
0161  * beep volume mixer
0162  */
0163 
0164 static int snd_pmac_info_beep(struct snd_kcontrol *kcontrol,
0165                   struct snd_ctl_elem_info *uinfo)
0166 {
0167     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0168     uinfo->count = 1;
0169     uinfo->value.integer.min = 0;
0170     uinfo->value.integer.max = 100;
0171     return 0;
0172 }
0173 
0174 static int snd_pmac_get_beep(struct snd_kcontrol *kcontrol,
0175                  struct snd_ctl_elem_value *ucontrol)
0176 {
0177     struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
0178     if (snd_BUG_ON(!chip->beep))
0179         return -ENXIO;
0180     ucontrol->value.integer.value[0] = chip->beep->volume;
0181     return 0;
0182 }
0183 
0184 static int snd_pmac_put_beep(struct snd_kcontrol *kcontrol,
0185                  struct snd_ctl_elem_value *ucontrol)
0186 {
0187     struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
0188     unsigned int oval, nval;
0189     if (snd_BUG_ON(!chip->beep))
0190         return -ENXIO;
0191     oval = chip->beep->volume;
0192     nval = ucontrol->value.integer.value[0];
0193     if (nval > 100)
0194         return -EINVAL;
0195     chip->beep->volume = nval;
0196     return oval != chip->beep->volume;
0197 }
0198 
0199 static const struct snd_kcontrol_new snd_pmac_beep_mixer = {
0200     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0201     .name = "Beep Playback Volume",
0202     .info = snd_pmac_info_beep,
0203     .get = snd_pmac_get_beep,
0204     .put = snd_pmac_put_beep,
0205 };
0206 
0207 /* Initialize beep stuff */
0208 int snd_pmac_attach_beep(struct snd_pmac *chip)
0209 {
0210     struct pmac_beep *beep;
0211     struct input_dev *input_dev;
0212     struct snd_kcontrol *beep_ctl;
0213     void *dmabuf;
0214     int err = -ENOMEM;
0215 
0216     beep = kzalloc(sizeof(*beep), GFP_KERNEL);
0217     if (! beep)
0218         return -ENOMEM;
0219     dmabuf = dma_alloc_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4,
0220                     &beep->addr, GFP_KERNEL);
0221     input_dev = input_allocate_device();
0222     if (! dmabuf || ! input_dev)
0223         goto fail1;
0224 
0225     /* FIXME: set more better values */
0226     input_dev->name = "PowerMac Beep";
0227     input_dev->phys = "powermac/beep";
0228     input_dev->id.bustype = BUS_ADB;
0229     input_dev->id.vendor = 0x001f;
0230     input_dev->id.product = 0x0001;
0231     input_dev->id.version = 0x0100;
0232 
0233     input_dev->evbit[0] = BIT_MASK(EV_SND);
0234     input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
0235     input_dev->event = snd_pmac_beep_event;
0236     input_dev->dev.parent = &chip->pdev->dev;
0237     input_set_drvdata(input_dev, chip);
0238 
0239     beep->dev = input_dev;
0240     beep->buf = dmabuf;
0241     beep->volume = BEEP_VOLUME;
0242     beep->running = 0;
0243 
0244     beep_ctl = snd_ctl_new1(&snd_pmac_beep_mixer, chip);
0245     err = snd_ctl_add(chip->card, beep_ctl);
0246     if (err < 0)
0247         goto fail1;
0248 
0249     chip->beep = beep;
0250 
0251     err = input_register_device(beep->dev);
0252     if (err)
0253         goto fail2;
0254  
0255     return 0;
0256  
0257  fail2: snd_ctl_remove(chip->card, beep_ctl);
0258  fail1: input_free_device(input_dev);
0259     if (dmabuf)
0260         dma_free_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4,
0261                   dmabuf, beep->addr);
0262     kfree(beep);
0263     return err;
0264 }
0265 
0266 void snd_pmac_detach_beep(struct snd_pmac *chip)
0267 {
0268     if (chip->beep) {
0269         input_unregister_device(chip->beep->dev);
0270         dma_free_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4,
0271                   chip->beep->buf, chip->beep->addr);
0272         kfree(chip->beep);
0273         chip->beep = NULL;
0274     }
0275 }