1/* 2 * Line6 Pod HD 3 * 4 * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation, version 2. 9 * 10 */ 11 12#include <sound/core.h> 13#include <sound/pcm.h> 14 15#include "audio.h" 16#include "driver.h" 17#include "pcm.h" 18#include "podhd.h" 19 20#define PODHD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */ 21 22static struct snd_ratden podhd_ratden = { 23 .num_min = 48000, 24 .num_max = 48000, 25 .num_step = 1, 26 .den = 1, 27}; 28 29static struct line6_pcm_properties podhd_pcm_properties = { 30 .snd_line6_playback_hw = { 31 .info = (SNDRV_PCM_INFO_MMAP | 32 SNDRV_PCM_INFO_INTERLEAVED | 33 SNDRV_PCM_INFO_BLOCK_TRANSFER | 34 SNDRV_PCM_INFO_MMAP_VALID | 35 SNDRV_PCM_INFO_PAUSE | 36#ifdef CONFIG_PM 37 SNDRV_PCM_INFO_RESUME | 38#endif 39 SNDRV_PCM_INFO_SYNC_START), 40 .formats = SNDRV_PCM_FMTBIT_S24_3LE, 41 .rates = SNDRV_PCM_RATE_48000, 42 .rate_min = 48000, 43 .rate_max = 48000, 44 .channels_min = 2, 45 .channels_max = 2, 46 .buffer_bytes_max = 60000, 47 .period_bytes_min = 64, 48 .period_bytes_max = 8192, 49 .periods_min = 1, 50 .periods_max = 1024}, 51 .snd_line6_capture_hw = { 52 .info = (SNDRV_PCM_INFO_MMAP | 53 SNDRV_PCM_INFO_INTERLEAVED | 54 SNDRV_PCM_INFO_BLOCK_TRANSFER | 55 SNDRV_PCM_INFO_MMAP_VALID | 56#ifdef CONFIG_PM 57 SNDRV_PCM_INFO_RESUME | 58#endif 59 SNDRV_PCM_INFO_SYNC_START), 60 .formats = SNDRV_PCM_FMTBIT_S24_3LE, 61 .rates = SNDRV_PCM_RATE_48000, 62 .rate_min = 48000, 63 .rate_max = 48000, 64 .channels_min = 2, 65 .channels_max = 2, 66 .buffer_bytes_max = 60000, 67 .period_bytes_min = 64, 68 .period_bytes_max = 8192, 69 .periods_min = 1, 70 .periods_max = 1024}, 71 .snd_line6_rates = { 72 .nrats = 1, 73 .rats = &podhd_ratden}, 74 .bytes_per_frame = PODHD_BYTES_PER_FRAME 75}; 76 77/* 78 POD HD destructor. 79*/ 80static void podhd_destruct(struct usb_interface *interface) 81{ 82 struct usb_line6_podhd *podhd = usb_get_intfdata(interface); 83 84 if (podhd == NULL) 85 return; 86 line6_cleanup_audio(&podhd->line6); 87} 88 89/* 90 Try to init POD HD device. 91*/ 92static int podhd_try_init(struct usb_interface *interface, 93 struct usb_line6_podhd *podhd) 94{ 95 int err; 96 struct usb_line6 *line6 = &podhd->line6; 97 98 if ((interface == NULL) || (podhd == NULL)) 99 return -ENODEV; 100 101 /* initialize audio system: */ 102 err = line6_init_audio(line6); 103 if (err < 0) 104 return err; 105 106 /* initialize MIDI subsystem: */ 107 err = line6_init_midi(line6); 108 if (err < 0) 109 return err; 110 111 /* initialize PCM subsystem: */ 112 err = line6_init_pcm(line6, &podhd_pcm_properties); 113 if (err < 0) 114 return err; 115 116 /* register USB audio system: */ 117 err = line6_register_audio(line6); 118 return err; 119} 120 121/* 122 Init POD HD device (and clean up in case of failure). 123*/ 124int line6_podhd_init(struct usb_interface *interface, 125 struct usb_line6_podhd *podhd) 126{ 127 int err = podhd_try_init(interface, podhd); 128 129 if (err < 0) 130 podhd_destruct(interface); 131 132 return err; 133} 134 135/* 136 POD HD device disconnected. 137*/ 138void line6_podhd_disconnect(struct usb_interface *interface) 139{ 140 struct usb_line6_podhd *podhd; 141 142 if (interface == NULL) 143 return; 144 podhd = usb_get_intfdata(interface); 145 146 if (podhd != NULL) { 147 struct snd_line6_pcm *line6pcm = podhd->line6.line6pcm; 148 149 if (line6pcm != NULL) 150 line6_pcm_disconnect(line6pcm); 151 } 152 153 podhd_destruct(interface); 154} 155