Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2010-2013 Bluecherry, LLC <https://www.bluecherrydvr.com>
0004  *
0005  * Original author:
0006  * Ben Collins <bcollins@ubuntu.com>
0007  *
0008  * Additional work by:
0009  * John Brooks <john.brooks@bluecherry.net>
0010  */
0011 
0012 #include <linux/kernel.h>
0013 #include <linux/mempool.h>
0014 #include <linux/poll.h>
0015 #include <linux/kthread.h>
0016 #include <linux/freezer.h>
0017 #include <linux/module.h>
0018 #include <linux/slab.h>
0019 
0020 #include <sound/core.h>
0021 #include <sound/initval.h>
0022 #include <sound/pcm.h>
0023 #include <sound/control.h>
0024 
0025 #include "solo6x10.h"
0026 #include "solo6x10-tw28.h"
0027 
0028 #define G723_FDMA_PAGES     32
0029 #define G723_PERIOD_BYTES   48
0030 #define G723_PERIOD_BLOCK   1024
0031 #define G723_FRAMES_PER_PAGE    48
0032 
0033 /* Sets up channels 16-19 for decoding and 0-15 for encoding */
0034 #define OUTMODE_MASK        0x300
0035 
0036 #define SAMPLERATE      8000
0037 #define BITRATE         25
0038 
0039 /* The solo writes to 1k byte pages, 32 pages, in the dma. Each 1k page
0040  * is broken down to 20 * 48 byte regions (one for each channel possible)
0041  * with the rest of the page being dummy data. */
0042 #define PERIODS         G723_FDMA_PAGES
0043 #define G723_INTR_ORDER     4 /* 0 - 4 */
0044 
0045 struct solo_snd_pcm {
0046     int             on;
0047     spinlock_t          lock;
0048     struct solo_dev         *solo_dev;
0049     u8              *g723_buf;
0050     dma_addr_t          g723_dma;
0051 };
0052 
0053 static void solo_g723_config(struct solo_dev *solo_dev)
0054 {
0055     int clk_div;
0056 
0057     clk_div = (solo_dev->clock_mhz * 1000000)
0058         / (SAMPLERATE * (BITRATE * 2) * 2);
0059 
0060     solo_reg_write(solo_dev, SOLO_AUDIO_SAMPLE,
0061                SOLO_AUDIO_BITRATE(BITRATE)
0062                | SOLO_AUDIO_CLK_DIV(clk_div));
0063 
0064     solo_reg_write(solo_dev, SOLO_AUDIO_FDMA_INTR,
0065                SOLO_AUDIO_FDMA_INTERVAL(1)
0066                | SOLO_AUDIO_INTR_ORDER(G723_INTR_ORDER)
0067                | SOLO_AUDIO_FDMA_BASE(SOLO_G723_EXT_ADDR(solo_dev) >> 16));
0068 
0069     solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL,
0070                SOLO_AUDIO_ENABLE
0071                | SOLO_AUDIO_I2S_MODE
0072                | SOLO_AUDIO_I2S_MULTI(3)
0073                | SOLO_AUDIO_MODE(OUTMODE_MASK));
0074 }
0075 
0076 void solo_g723_isr(struct solo_dev *solo_dev)
0077 {
0078     struct snd_pcm_str *pstr =
0079         &solo_dev->snd_pcm->streams[SNDRV_PCM_STREAM_CAPTURE];
0080     struct snd_pcm_substream *ss;
0081     struct solo_snd_pcm *solo_pcm;
0082 
0083     for (ss = pstr->substream; ss != NULL; ss = ss->next) {
0084         if (snd_pcm_substream_chip(ss) == NULL)
0085             continue;
0086 
0087         /* This means open() hasn't been called on this one */
0088         if (snd_pcm_substream_chip(ss) == solo_dev)
0089             continue;
0090 
0091         /* Haven't triggered a start yet */
0092         solo_pcm = snd_pcm_substream_chip(ss);
0093         if (!solo_pcm->on)
0094             continue;
0095 
0096         snd_pcm_period_elapsed(ss);
0097     }
0098 }
0099 
0100 static const struct snd_pcm_hardware snd_solo_pcm_hw = {
0101     .info           = (SNDRV_PCM_INFO_MMAP |
0102                    SNDRV_PCM_INFO_INTERLEAVED |
0103                    SNDRV_PCM_INFO_BLOCK_TRANSFER |
0104                    SNDRV_PCM_INFO_MMAP_VALID),
0105     .formats        = SNDRV_PCM_FMTBIT_U8,
0106     .rates          = SNDRV_PCM_RATE_8000,
0107     .rate_min       = SAMPLERATE,
0108     .rate_max       = SAMPLERATE,
0109     .channels_min       = 1,
0110     .channels_max       = 1,
0111     .buffer_bytes_max   = G723_PERIOD_BYTES * PERIODS,
0112     .period_bytes_min   = G723_PERIOD_BYTES,
0113     .period_bytes_max   = G723_PERIOD_BYTES,
0114     .periods_min        = PERIODS,
0115     .periods_max        = PERIODS,
0116 };
0117 
0118 static int snd_solo_pcm_open(struct snd_pcm_substream *ss)
0119 {
0120     struct solo_dev *solo_dev = snd_pcm_substream_chip(ss);
0121     struct solo_snd_pcm *solo_pcm;
0122 
0123     solo_pcm = kzalloc(sizeof(*solo_pcm), GFP_KERNEL);
0124     if (solo_pcm == NULL)
0125         goto oom;
0126 
0127     solo_pcm->g723_buf = dma_alloc_coherent(&solo_dev->pdev->dev,
0128                         G723_PERIOD_BYTES,
0129                         &solo_pcm->g723_dma,
0130                         GFP_KERNEL);
0131     if (solo_pcm->g723_buf == NULL)
0132         goto oom;
0133 
0134     spin_lock_init(&solo_pcm->lock);
0135     solo_pcm->solo_dev = solo_dev;
0136     ss->runtime->hw = snd_solo_pcm_hw;
0137 
0138     snd_pcm_substream_chip(ss) = solo_pcm;
0139 
0140     return 0;
0141 
0142 oom:
0143     kfree(solo_pcm);
0144     return -ENOMEM;
0145 }
0146 
0147 static int snd_solo_pcm_close(struct snd_pcm_substream *ss)
0148 {
0149     struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
0150 
0151     snd_pcm_substream_chip(ss) = solo_pcm->solo_dev;
0152     dma_free_coherent(&solo_pcm->solo_dev->pdev->dev, G723_PERIOD_BYTES,
0153               solo_pcm->g723_buf, solo_pcm->g723_dma);
0154     kfree(solo_pcm);
0155 
0156     return 0;
0157 }
0158 
0159 static int snd_solo_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
0160 {
0161     struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
0162     struct solo_dev *solo_dev = solo_pcm->solo_dev;
0163     int ret = 0;
0164 
0165     spin_lock(&solo_pcm->lock);
0166 
0167     switch (cmd) {
0168     case SNDRV_PCM_TRIGGER_START:
0169         if (solo_pcm->on == 0) {
0170             /* If this is the first user, switch on interrupts */
0171             if (atomic_inc_return(&solo_dev->snd_users) == 1)
0172                 solo_irq_on(solo_dev, SOLO_IRQ_G723);
0173             solo_pcm->on = 1;
0174         }
0175         break;
0176     case SNDRV_PCM_TRIGGER_STOP:
0177         if (solo_pcm->on) {
0178             /* If this was our last user, switch them off */
0179             if (atomic_dec_return(&solo_dev->snd_users) == 0)
0180                 solo_irq_off(solo_dev, SOLO_IRQ_G723);
0181             solo_pcm->on = 0;
0182         }
0183         break;
0184     default:
0185         ret = -EINVAL;
0186     }
0187 
0188     spin_unlock(&solo_pcm->lock);
0189 
0190     return ret;
0191 }
0192 
0193 static int snd_solo_pcm_prepare(struct snd_pcm_substream *ss)
0194 {
0195     return 0;
0196 }
0197 
0198 static snd_pcm_uframes_t snd_solo_pcm_pointer(struct snd_pcm_substream *ss)
0199 {
0200     struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
0201     struct solo_dev *solo_dev = solo_pcm->solo_dev;
0202     snd_pcm_uframes_t idx = solo_reg_read(solo_dev, SOLO_AUDIO_STA) & 0x1f;
0203 
0204     return idx * G723_FRAMES_PER_PAGE;
0205 }
0206 
0207 static int snd_solo_pcm_copy_user(struct snd_pcm_substream *ss, int channel,
0208                   unsigned long pos, void __user *dst,
0209                   unsigned long count)
0210 {
0211     struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
0212     struct solo_dev *solo_dev = solo_pcm->solo_dev;
0213     int err, i;
0214 
0215     for (i = 0; i < (count / G723_FRAMES_PER_PAGE); i++) {
0216         int page = (pos / G723_FRAMES_PER_PAGE) + i;
0217 
0218         err = solo_p2m_dma_t(solo_dev, 0, solo_pcm->g723_dma,
0219                      SOLO_G723_EXT_ADDR(solo_dev) +
0220                      (page * G723_PERIOD_BLOCK) +
0221                      (ss->number * G723_PERIOD_BYTES),
0222                      G723_PERIOD_BYTES, 0, 0);
0223         if (err)
0224             return err;
0225 
0226         if (copy_to_user(dst, solo_pcm->g723_buf, G723_PERIOD_BYTES))
0227             return -EFAULT;
0228         dst += G723_PERIOD_BYTES;
0229     }
0230 
0231     return 0;
0232 }
0233 
0234 static int snd_solo_pcm_copy_kernel(struct snd_pcm_substream *ss, int channel,
0235                     unsigned long pos, void *dst,
0236                     unsigned long count)
0237 {
0238     struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
0239     struct solo_dev *solo_dev = solo_pcm->solo_dev;
0240     int err, i;
0241 
0242     for (i = 0; i < (count / G723_FRAMES_PER_PAGE); i++) {
0243         int page = (pos / G723_FRAMES_PER_PAGE) + i;
0244 
0245         err = solo_p2m_dma_t(solo_dev, 0, solo_pcm->g723_dma,
0246                      SOLO_G723_EXT_ADDR(solo_dev) +
0247                      (page * G723_PERIOD_BLOCK) +
0248                      (ss->number * G723_PERIOD_BYTES),
0249                      G723_PERIOD_BYTES, 0, 0);
0250         if (err)
0251             return err;
0252 
0253         memcpy(dst, solo_pcm->g723_buf, G723_PERIOD_BYTES);
0254         dst += G723_PERIOD_BYTES;
0255     }
0256 
0257     return 0;
0258 }
0259 
0260 static const struct snd_pcm_ops snd_solo_pcm_ops = {
0261     .open = snd_solo_pcm_open,
0262     .close = snd_solo_pcm_close,
0263     .prepare = snd_solo_pcm_prepare,
0264     .trigger = snd_solo_pcm_trigger,
0265     .pointer = snd_solo_pcm_pointer,
0266     .copy_user = snd_solo_pcm_copy_user,
0267     .copy_kernel = snd_solo_pcm_copy_kernel,
0268 };
0269 
0270 static int snd_solo_capture_volume_info(struct snd_kcontrol *kcontrol,
0271                     struct snd_ctl_elem_info *info)
0272 {
0273     info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0274     info->count = 1;
0275     info->value.integer.min = 0;
0276     info->value.integer.max = 15;
0277     info->value.integer.step = 1;
0278 
0279     return 0;
0280 }
0281 
0282 static int snd_solo_capture_volume_get(struct snd_kcontrol *kcontrol,
0283                        struct snd_ctl_elem_value *value)
0284 {
0285     struct solo_dev *solo_dev = snd_kcontrol_chip(kcontrol);
0286     u8 ch = value->id.numid - 1;
0287 
0288     value->value.integer.value[0] = tw28_get_audio_gain(solo_dev, ch);
0289 
0290     return 0;
0291 }
0292 
0293 static int snd_solo_capture_volume_put(struct snd_kcontrol *kcontrol,
0294                        struct snd_ctl_elem_value *value)
0295 {
0296     struct solo_dev *solo_dev = snd_kcontrol_chip(kcontrol);
0297     u8 ch = value->id.numid - 1;
0298     u8 old_val;
0299 
0300     old_val = tw28_get_audio_gain(solo_dev, ch);
0301     if (old_val == value->value.integer.value[0])
0302         return 0;
0303 
0304     tw28_set_audio_gain(solo_dev, ch, value->value.integer.value[0]);
0305 
0306     return 1;
0307 }
0308 
0309 static const struct snd_kcontrol_new snd_solo_capture_volume = {
0310     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0311     .name = "Capture Volume",
0312     .info = snd_solo_capture_volume_info,
0313     .get = snd_solo_capture_volume_get,
0314     .put = snd_solo_capture_volume_put,
0315 };
0316 
0317 static int solo_snd_pcm_init(struct solo_dev *solo_dev)
0318 {
0319     struct snd_card *card = solo_dev->snd_card;
0320     struct snd_pcm *pcm;
0321     struct snd_pcm_substream *ss;
0322     int ret;
0323     int i;
0324 
0325     ret = snd_pcm_new(card, card->driver, 0, 0, solo_dev->nr_chans,
0326               &pcm);
0327     if (ret < 0)
0328         return ret;
0329 
0330     snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
0331             &snd_solo_pcm_ops);
0332 
0333     snd_pcm_chip(pcm) = solo_dev;
0334     pcm->info_flags = 0;
0335     strscpy(pcm->name, card->shortname, sizeof(pcm->name));
0336 
0337     for (i = 0, ss = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
0338          ss; ss = ss->next, i++)
0339         sprintf(ss->name, "Camera #%d Audio", i);
0340 
0341     snd_pcm_set_managed_buffer_all(pcm,
0342                        SNDRV_DMA_TYPE_CONTINUOUS,
0343                        NULL,
0344                        G723_PERIOD_BYTES * PERIODS,
0345                        G723_PERIOD_BYTES * PERIODS);
0346 
0347     solo_dev->snd_pcm = pcm;
0348 
0349     return 0;
0350 }
0351 
0352 int solo_g723_init(struct solo_dev *solo_dev)
0353 {
0354     static struct snd_device_ops ops = { };
0355     struct snd_card *card;
0356     struct snd_kcontrol_new kctl;
0357     char name[32];
0358     int ret;
0359 
0360     atomic_set(&solo_dev->snd_users, 0);
0361 
0362     /* Allows for easier mapping between video and audio */
0363     sprintf(name, "Softlogic%d", solo_dev->vfd->num);
0364 
0365     ret = snd_card_new(&solo_dev->pdev->dev,
0366                SNDRV_DEFAULT_IDX1, name, THIS_MODULE, 0,
0367                &solo_dev->snd_card);
0368     if (ret < 0)
0369         return ret;
0370 
0371     card = solo_dev->snd_card;
0372 
0373     strscpy(card->driver, SOLO6X10_NAME, sizeof(card->driver));
0374     strscpy(card->shortname, "SOLO-6x10 Audio", sizeof(card->shortname));
0375     sprintf(card->longname, "%s on %s IRQ %d", card->shortname,
0376         pci_name(solo_dev->pdev), solo_dev->pdev->irq);
0377 
0378     ret = snd_device_new(card, SNDRV_DEV_LOWLEVEL, solo_dev, &ops);
0379     if (ret < 0)
0380         goto snd_error;
0381 
0382     /* Mixer controls */
0383     strscpy(card->mixername, "SOLO-6x10", sizeof(card->mixername));
0384     kctl = snd_solo_capture_volume;
0385     kctl.count = solo_dev->nr_chans;
0386 
0387     ret = snd_ctl_add(card, snd_ctl_new1(&kctl, solo_dev));
0388     if (ret < 0)
0389         goto snd_error;
0390 
0391     ret = solo_snd_pcm_init(solo_dev);
0392     if (ret < 0)
0393         goto snd_error;
0394 
0395     ret = snd_card_register(card);
0396     if (ret < 0)
0397         goto snd_error;
0398 
0399     solo_g723_config(solo_dev);
0400 
0401     dev_info(&solo_dev->pdev->dev, "Alsa sound card as %s\n", name);
0402 
0403     return 0;
0404 
0405 snd_error:
0406     snd_card_free(card);
0407     return ret;
0408 }
0409 
0410 void solo_g723_exit(struct solo_dev *solo_dev)
0411 {
0412     if (!solo_dev->snd_card)
0413         return;
0414 
0415     solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL, 0);
0416     solo_irq_off(solo_dev, SOLO_IRQ_G723);
0417 
0418     snd_card_free(solo_dev->snd_card);
0419     solo_dev->snd_card = NULL;
0420 }