1 /* 2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> 3 * 4 * Original author: 5 * Ben Collins <bcollins@ubuntu.com> 6 * 7 * Additional work by: 8 * John Brooks <john.brooks@bluecherry.net> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 */ 20 21 #include <linux/kernel.h> 22 #include <linux/mempool.h> 23 #include <linux/poll.h> 24 #include <linux/kthread.h> 25 #include <linux/freezer.h> 26 #include <linux/module.h> 27 #include <linux/slab.h> 28 29 #include <sound/core.h> 30 #include <sound/initval.h> 31 #include <sound/pcm.h> 32 #include <sound/control.h> 33 34 #include "solo6x10.h" 35 #include "solo6x10-tw28.h" 36 37 #define G723_FDMA_PAGES 32 38 #define G723_PERIOD_BYTES 48 39 #define G723_PERIOD_BLOCK 1024 40 #define G723_FRAMES_PER_PAGE 48 41 42 /* Sets up channels 16-19 for decoding and 0-15 for encoding */ 43 #define OUTMODE_MASK 0x300 44 45 #define SAMPLERATE 8000 46 #define BITRATE 25 47 48 /* The solo writes to 1k byte pages, 32 pages, in the dma. Each 1k page 49 * is broken down to 20 * 48 byte regions (one for each channel possible) 50 * with the rest of the page being dummy data. */ 51 #define PERIODS G723_FDMA_PAGES 52 #define G723_INTR_ORDER 4 /* 0 - 4 */ 53 54 struct solo_snd_pcm { 55 int on; 56 spinlock_t lock; 57 struct solo_dev *solo_dev; 58 u8 *g723_buf; 59 dma_addr_t g723_dma; 60 }; 61 62 static void solo_g723_config(struct solo_dev *solo_dev) 63 { 64 int clk_div; 65 66 clk_div = (solo_dev->clock_mhz * 1000000) 67 / (SAMPLERATE * (BITRATE * 2) * 2); 68 69 solo_reg_write(solo_dev, SOLO_AUDIO_SAMPLE, 70 SOLO_AUDIO_BITRATE(BITRATE) 71 | SOLO_AUDIO_CLK_DIV(clk_div)); 72 73 solo_reg_write(solo_dev, SOLO_AUDIO_FDMA_INTR, 74 SOLO_AUDIO_FDMA_INTERVAL(1) 75 | SOLO_AUDIO_INTR_ORDER(G723_INTR_ORDER) 76 | SOLO_AUDIO_FDMA_BASE(SOLO_G723_EXT_ADDR(solo_dev) >> 16)); 77 78 solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL, 79 SOLO_AUDIO_ENABLE 80 | SOLO_AUDIO_I2S_MODE 81 | SOLO_AUDIO_I2S_MULTI(3) 82 | SOLO_AUDIO_MODE(OUTMODE_MASK)); 83 } 84 85 void solo_g723_isr(struct solo_dev *solo_dev) 86 { 87 struct snd_pcm_str *pstr = 88 &solo_dev->snd_pcm->streams[SNDRV_PCM_STREAM_CAPTURE]; 89 struct snd_pcm_substream *ss; 90 struct solo_snd_pcm *solo_pcm; 91 92 for (ss = pstr->substream; ss != NULL; ss = ss->next) { 93 if (snd_pcm_substream_chip(ss) == NULL) 94 continue; 95 96 /* This means open() hasn't been called on this one */ 97 if (snd_pcm_substream_chip(ss) == solo_dev) 98 continue; 99 100 /* Haven't triggered a start yet */ 101 solo_pcm = snd_pcm_substream_chip(ss); 102 if (!solo_pcm->on) 103 continue; 104 105 snd_pcm_period_elapsed(ss); 106 } 107 } 108 109 static int snd_solo_hw_params(struct snd_pcm_substream *ss, 110 struct snd_pcm_hw_params *hw_params) 111 { 112 return snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(hw_params)); 113 } 114 115 static int snd_solo_hw_free(struct snd_pcm_substream *ss) 116 { 117 return snd_pcm_lib_free_pages(ss); 118 } 119 120 static const struct snd_pcm_hardware snd_solo_pcm_hw = { 121 .info = (SNDRV_PCM_INFO_MMAP | 122 SNDRV_PCM_INFO_INTERLEAVED | 123 SNDRV_PCM_INFO_BLOCK_TRANSFER | 124 SNDRV_PCM_INFO_MMAP_VALID), 125 .formats = SNDRV_PCM_FMTBIT_U8, 126 .rates = SNDRV_PCM_RATE_8000, 127 .rate_min = SAMPLERATE, 128 .rate_max = SAMPLERATE, 129 .channels_min = 1, 130 .channels_max = 1, 131 .buffer_bytes_max = G723_PERIOD_BYTES * PERIODS, 132 .period_bytes_min = G723_PERIOD_BYTES, 133 .period_bytes_max = G723_PERIOD_BYTES, 134 .periods_min = PERIODS, 135 .periods_max = PERIODS, 136 }; 137 138 static int snd_solo_pcm_open(struct snd_pcm_substream *ss) 139 { 140 struct solo_dev *solo_dev = snd_pcm_substream_chip(ss); 141 struct solo_snd_pcm *solo_pcm; 142 143 solo_pcm = kzalloc(sizeof(*solo_pcm), GFP_KERNEL); 144 if (solo_pcm == NULL) 145 goto oom; 146 147 solo_pcm->g723_buf = pci_alloc_consistent(solo_dev->pdev, 148 G723_PERIOD_BYTES, 149 &solo_pcm->g723_dma); 150 if (solo_pcm->g723_buf == NULL) 151 goto oom; 152 153 spin_lock_init(&solo_pcm->lock); 154 solo_pcm->solo_dev = solo_dev; 155 ss->runtime->hw = snd_solo_pcm_hw; 156 157 snd_pcm_substream_chip(ss) = solo_pcm; 158 159 return 0; 160 161 oom: 162 kfree(solo_pcm); 163 return -ENOMEM; 164 } 165 166 static int snd_solo_pcm_close(struct snd_pcm_substream *ss) 167 { 168 struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss); 169 170 snd_pcm_substream_chip(ss) = solo_pcm->solo_dev; 171 pci_free_consistent(solo_pcm->solo_dev->pdev, G723_PERIOD_BYTES, 172 solo_pcm->g723_buf, solo_pcm->g723_dma); 173 kfree(solo_pcm); 174 175 return 0; 176 } 177 178 static int snd_solo_pcm_trigger(struct snd_pcm_substream *ss, int cmd) 179 { 180 struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss); 181 struct solo_dev *solo_dev = solo_pcm->solo_dev; 182 int ret = 0; 183 184 spin_lock(&solo_pcm->lock); 185 186 switch (cmd) { 187 case SNDRV_PCM_TRIGGER_START: 188 if (solo_pcm->on == 0) { 189 /* If this is the first user, switch on interrupts */ 190 if (atomic_inc_return(&solo_dev->snd_users) == 1) 191 solo_irq_on(solo_dev, SOLO_IRQ_G723); 192 solo_pcm->on = 1; 193 } 194 break; 195 case SNDRV_PCM_TRIGGER_STOP: 196 if (solo_pcm->on) { 197 /* If this was our last user, switch them off */ 198 if (atomic_dec_return(&solo_dev->snd_users) == 0) 199 solo_irq_off(solo_dev, SOLO_IRQ_G723); 200 solo_pcm->on = 0; 201 } 202 break; 203 default: 204 ret = -EINVAL; 205 } 206 207 spin_unlock(&solo_pcm->lock); 208 209 return ret; 210 } 211 212 static int snd_solo_pcm_prepare(struct snd_pcm_substream *ss) 213 { 214 return 0; 215 } 216 217 static snd_pcm_uframes_t snd_solo_pcm_pointer(struct snd_pcm_substream *ss) 218 { 219 struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss); 220 struct solo_dev *solo_dev = solo_pcm->solo_dev; 221 snd_pcm_uframes_t idx = solo_reg_read(solo_dev, SOLO_AUDIO_STA) & 0x1f; 222 223 return idx * G723_FRAMES_PER_PAGE; 224 } 225 226 static int snd_solo_pcm_copy_user(struct snd_pcm_substream *ss, int channel, 227 unsigned long pos, void __user *dst, 228 unsigned long count) 229 { 230 struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss); 231 struct solo_dev *solo_dev = solo_pcm->solo_dev; 232 int err, i; 233 234 for (i = 0; i < (count / G723_FRAMES_PER_PAGE); i++) { 235 int page = (pos / G723_FRAMES_PER_PAGE) + i; 236 237 err = solo_p2m_dma_t(solo_dev, 0, solo_pcm->g723_dma, 238 SOLO_G723_EXT_ADDR(solo_dev) + 239 (page * G723_PERIOD_BLOCK) + 240 (ss->number * G723_PERIOD_BYTES), 241 G723_PERIOD_BYTES, 0, 0); 242 if (err) 243 return err; 244 245 if (copy_to_user(dst, solo_pcm->g723_buf, G723_PERIOD_BYTES)) 246 return -EFAULT; 247 dst += G723_PERIOD_BYTES; 248 } 249 250 return 0; 251 } 252 253 static int snd_solo_pcm_copy_kernel(struct snd_pcm_substream *ss, int channel, 254 unsigned long pos, void *dst, 255 unsigned long count) 256 { 257 struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss); 258 struct solo_dev *solo_dev = solo_pcm->solo_dev; 259 int err, i; 260 261 for (i = 0; i < (count / G723_FRAMES_PER_PAGE); i++) { 262 int page = (pos / G723_FRAMES_PER_PAGE) + i; 263 264 err = solo_p2m_dma_t(solo_dev, 0, solo_pcm->g723_dma, 265 SOLO_G723_EXT_ADDR(solo_dev) + 266 (page * G723_PERIOD_BLOCK) + 267 (ss->number * G723_PERIOD_BYTES), 268 G723_PERIOD_BYTES, 0, 0); 269 if (err) 270 return err; 271 272 memcpy(dst, solo_pcm->g723_buf, G723_PERIOD_BYTES); 273 dst += G723_PERIOD_BYTES; 274 } 275 276 return 0; 277 } 278 279 static const struct snd_pcm_ops snd_solo_pcm_ops = { 280 .open = snd_solo_pcm_open, 281 .close = snd_solo_pcm_close, 282 .ioctl = snd_pcm_lib_ioctl, 283 .hw_params = snd_solo_hw_params, 284 .hw_free = snd_solo_hw_free, 285 .prepare = snd_solo_pcm_prepare, 286 .trigger = snd_solo_pcm_trigger, 287 .pointer = snd_solo_pcm_pointer, 288 .copy_user = snd_solo_pcm_copy_user, 289 .copy_kernel = snd_solo_pcm_copy_kernel, 290 }; 291 292 static int snd_solo_capture_volume_info(struct snd_kcontrol *kcontrol, 293 struct snd_ctl_elem_info *info) 294 { 295 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 296 info->count = 1; 297 info->value.integer.min = 0; 298 info->value.integer.max = 15; 299 info->value.integer.step = 1; 300 301 return 0; 302 } 303 304 static int snd_solo_capture_volume_get(struct snd_kcontrol *kcontrol, 305 struct snd_ctl_elem_value *value) 306 { 307 struct solo_dev *solo_dev = snd_kcontrol_chip(kcontrol); 308 u8 ch = value->id.numid - 1; 309 310 value->value.integer.value[0] = tw28_get_audio_gain(solo_dev, ch); 311 312 return 0; 313 } 314 315 static int snd_solo_capture_volume_put(struct snd_kcontrol *kcontrol, 316 struct snd_ctl_elem_value *value) 317 { 318 struct solo_dev *solo_dev = snd_kcontrol_chip(kcontrol); 319 u8 ch = value->id.numid - 1; 320 u8 old_val; 321 322 old_val = tw28_get_audio_gain(solo_dev, ch); 323 if (old_val == value->value.integer.value[0]) 324 return 0; 325 326 tw28_set_audio_gain(solo_dev, ch, value->value.integer.value[0]); 327 328 return 1; 329 } 330 331 static const struct snd_kcontrol_new snd_solo_capture_volume = { 332 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 333 .name = "Capture Volume", 334 .info = snd_solo_capture_volume_info, 335 .get = snd_solo_capture_volume_get, 336 .put = snd_solo_capture_volume_put, 337 }; 338 339 static int solo_snd_pcm_init(struct solo_dev *solo_dev) 340 { 341 struct snd_card *card = solo_dev->snd_card; 342 struct snd_pcm *pcm; 343 struct snd_pcm_substream *ss; 344 int ret; 345 int i; 346 347 ret = snd_pcm_new(card, card->driver, 0, 0, solo_dev->nr_chans, 348 &pcm); 349 if (ret < 0) 350 return ret; 351 352 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, 353 &snd_solo_pcm_ops); 354 355 snd_pcm_chip(pcm) = solo_dev; 356 pcm->info_flags = 0; 357 strscpy(pcm->name, card->shortname, sizeof(pcm->name)); 358 359 for (i = 0, ss = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; 360 ss; ss = ss->next, i++) 361 sprintf(ss->name, "Camera #%d Audio", i); 362 363 snd_pcm_lib_preallocate_pages_for_all(pcm, 364 SNDRV_DMA_TYPE_CONTINUOUS, 365 snd_dma_continuous_data(GFP_KERNEL), 366 G723_PERIOD_BYTES * PERIODS, 367 G723_PERIOD_BYTES * PERIODS); 368 369 solo_dev->snd_pcm = pcm; 370 371 return 0; 372 } 373 374 int solo_g723_init(struct solo_dev *solo_dev) 375 { 376 static struct snd_device_ops ops = { }; 377 struct snd_card *card; 378 struct snd_kcontrol_new kctl; 379 char name[32]; 380 int ret; 381 382 atomic_set(&solo_dev->snd_users, 0); 383 384 /* Allows for easier mapping between video and audio */ 385 sprintf(name, "Softlogic%d", solo_dev->vfd->num); 386 387 ret = snd_card_new(&solo_dev->pdev->dev, 388 SNDRV_DEFAULT_IDX1, name, THIS_MODULE, 0, 389 &solo_dev->snd_card); 390 if (ret < 0) 391 return ret; 392 393 card = solo_dev->snd_card; 394 395 strscpy(card->driver, SOLO6X10_NAME, sizeof(card->driver)); 396 strscpy(card->shortname, "SOLO-6x10 Audio", sizeof(card->shortname)); 397 sprintf(card->longname, "%s on %s IRQ %d", card->shortname, 398 pci_name(solo_dev->pdev), solo_dev->pdev->irq); 399 400 ret = snd_device_new(card, SNDRV_DEV_LOWLEVEL, solo_dev, &ops); 401 if (ret < 0) 402 goto snd_error; 403 404 /* Mixer controls */ 405 strscpy(card->mixername, "SOLO-6x10", sizeof(card->mixername)); 406 kctl = snd_solo_capture_volume; 407 kctl.count = solo_dev->nr_chans; 408 409 ret = snd_ctl_add(card, snd_ctl_new1(&kctl, solo_dev)); 410 if (ret < 0) 411 return ret; 412 413 ret = solo_snd_pcm_init(solo_dev); 414 if (ret < 0) 415 goto snd_error; 416 417 ret = snd_card_register(card); 418 if (ret < 0) 419 goto snd_error; 420 421 solo_g723_config(solo_dev); 422 423 dev_info(&solo_dev->pdev->dev, "Alsa sound card as %s\n", name); 424 425 return 0; 426 427 snd_error: 428 snd_card_free(card); 429 return ret; 430 } 431 432 void solo_g723_exit(struct solo_dev *solo_dev) 433 { 434 if (!solo_dev->snd_card) 435 return; 436 437 solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL, 0); 438 solo_irq_off(solo_dev, SOLO_IRQ_G723); 439 440 snd_card_free(solo_dev->snd_card); 441 solo_dev->snd_card = NULL; 442 } 443