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