1719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* 2719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * Asihpi soundcard 3719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * Copyright (c) by AudioScience Inc <alsa@audioscience.com> 4719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * 5719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * This program is free software; you can redistribute it and/or modify 6719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * it under the terms of version 2 of the GNU General Public License as 7719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * published by the Free Software Foundation; 8719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * 9719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * This program is distributed in the hope that it will be useful, 10719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * but WITHOUT ANY WARRANTY; without even the implied warranty of 11719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * GNU General Public License for more details. 13719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * 14719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * You should have received a copy of the GNU General Public License 15719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * along with this program; if not, write to the Free Software 16719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * 18719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * 19719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * The following is not a condition of use, merely a request: 20719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * If you modify this program, particularly if you fix errors, AudioScience Inc 21719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * would appreciate it if you grant us the right to use those modifications 22719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * for any purpose including commercial applications. 23719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 24e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 25719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include "hpi_internal.h" 26719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include "hpimsginit.h" 27719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include "hpioctl.h" 28719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 29719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <linux/pci.h> 30719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <linux/init.h> 31719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <linux/jiffies.h> 32719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <linux/slab.h> 33719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <linux/time.h> 34719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <linux/wait.h> 35719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <sound/core.h> 36719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <sound/control.h> 37719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <sound/pcm.h> 38719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <sound/pcm_params.h> 39719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <sound/info.h> 40719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <sound/initval.h> 41719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <sound/tlv.h> 42719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <sound/hwdep.h> 43719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 44f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett 45719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_LICENSE("GPL"); 46719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_AUTHOR("AudioScience inc. <support@audioscience.com>"); 47719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx"); 48719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 49b0096a65677fa8d7e50975dc7282ce313610d9e8Eliot Blennerhassett#if defined CONFIG_SND_DEBUG 50a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett/* copied from pcm_lib.c, hope later patch will make that version public 51a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassettand this copy can be removed */ 52a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassettstatic void pcm_debug_name(struct snd_pcm_substream *substream, 53a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett char *name, size_t len) 54a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett{ 55a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snprintf(name, len, "pcmC%dD%d%c:%d", 56a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett substream->pcm->card->number, 57a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett substream->pcm->device, 58a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett substream->stream ? 'c' : 'p', 59a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett substream->number); 60a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett} 61a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett#define DEBUG_NAME(substream, name) char name[16]; pcm_debug_name(substream, name, sizeof(name)) 62b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett#else 63a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett#define pcm_debug_name(s, n, l) do { } while (0) 64a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett#define DEBUG_NAME(name, substream) do { } while (0) 65b0096a65677fa8d7e50975dc7282ce313610d9e8Eliot Blennerhassett#endif 66a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett 67b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett#if defined CONFIG_SND_DEBUG_VERBOSE 68b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett/** 69b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett * snd_printddd - very verbose debug printk 70b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett * @format: format string 71b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett * 72b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett * Works like snd_printk() for debugging purposes. 73b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett * Ignored when CONFIG_SND_DEBUG_VERBOSE is not set. 74b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett * Must set snd module debug parameter to 3 to enable at runtime. 75b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett */ 76b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett#define snd_printddd(format, args...) \ 77b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett __snd_printk(3, __FILE__, __LINE__, format, ##args) 78b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett#else 79b0096a65677fa8d7e50975dc7282ce313610d9e8Eliot Blennerhassett#define snd_printddd(format, args...) do { } while (0) 80b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett#endif 81b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett 82719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* index 0-MAX */ 83719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 84719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; 85719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int enable_hpi_hwdep = 1; 86719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 87719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettmodule_param_array(index, int, NULL, S_IRUGO); 88719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_PARM_DESC(index, "ALSA index value for AudioScience soundcard."); 89719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 90719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettmodule_param_array(id, charp, NULL, S_IRUGO); 91719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_PARM_DESC(id, "ALSA ID string for AudioScience soundcard."); 92719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 93719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettmodule_param_array(enable, bool, NULL, S_IRUGO); 94719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_PARM_DESC(enable, "ALSA enable AudioScience soundcard."); 95719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 96719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettmodule_param(enable_hpi_hwdep, bool, S_IRUGO|S_IWUSR); 97719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_PARM_DESC(enable_hpi_hwdep, 98719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "ALSA enable HPI hwdep for AudioScience soundcard "); 99719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 100719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* identify driver */ 101719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#ifdef KERNEL_ALSA_BUILD 102e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassettstatic char *build_info = "Built using headers from kernel source"; 103719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettmodule_param(build_info, charp, S_IRUGO); 104719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_PARM_DESC(build_info, "built using headers from kernel source"); 105719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#else 106e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassettstatic char *build_info = "Built within ALSA source"; 107719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettmodule_param(build_info, charp, S_IRUGO); 108719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_PARM_DESC(build_info, "built within ALSA source"); 109719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#endif 110719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 111719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* set to 1 to dump every control from adapter to log */ 112719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic const int mixer_dump; 113719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 114719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define DEFAULT_SAMPLERATE 44100 115719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int adapter_fs = DEFAULT_SAMPLERATE; 116719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 117719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* defaults */ 118719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define PERIODS_MIN 2 119e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett#define PERIOD_BYTES_MIN 2048 120719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define BUFFER_BYTES_MAX (512 * 1024) 121719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 122719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define MAX_CLOCKSOURCES (HPI_SAMPLECLOCK_SOURCE_LAST + 1 + 7) 123719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 124719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstruct clk_source { 125719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int source; 126719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int index; 127719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett char *name; 128719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 129719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 130719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstruct clk_cache { 131719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int count; 132719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int has_local; 133719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct clk_source s[MAX_CLOCKSOURCES]; 134719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 135719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 136719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* Per card data */ 137719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstruct snd_card_asihpi { 138719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card; 139719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct pci_dev *pci; 140719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 adapter_index; 141719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 serial_number; 142719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 type; 143719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 version; 144719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 num_outstreams; 145719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 num_instreams; 146719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 147719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_mixer; 148719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct clk_cache cc; 149719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 150f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett u16 can_dma; 151719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 support_grouping; 152719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 support_mrx; 153719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 update_interval_frames; 154719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 in_max_chans; 155719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 out_max_chans; 156719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 157719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 158719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* Per stream data */ 159719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstruct snd_card_asihpi_pcm { 160719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct timer_list timer; 161719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int respawn_timer; 162719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int hpi_buffer_attached; 163ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett unsigned int buffer_bytes; 164ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett unsigned int period_bytes; 165719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int bytes_per_sec; 166e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett unsigned int pcm_buf_host_rw_ofs; /* Host R/W pos */ 167e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett unsigned int pcm_buf_dma_ofs; /* DMA R/W offset in buffer */ 168e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett unsigned int pcm_buf_elapsed_dma_ofs; /* DMA R/W offset in buffer */ 1690b7ce9e2bd2d9dbc8f4797b0cd5e0d138cb529e1Eliot Blennerhassett unsigned int drained_count; 170719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_substream *substream; 171719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_stream; 172719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_format format; 173719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 174719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 175719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* universal stream verbs work with out or in stream handles */ 176719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 177719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* Functions to allow driver to give a buffer to HPI for busmastering */ 178719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 179719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic u16 hpi_stream_host_buffer_attach( 180719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_stream, /* handle to outstream. */ 181719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 size_in_bytes, /* size in bytes of bus mastering buffer */ 182719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 pci_address 183719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett) 184719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 185719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_message hm; 186719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_response hr; 187719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int obj = hpi_handle_object(h_stream); 188719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 189719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!h_stream) 190719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return HPI_ERROR_INVALID_OBJ; 191719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_init_message_response(&hm, &hr, obj, 192719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett obj == HPI_OBJ_OSTREAM ? 193719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_OSTREAM_HOSTBUFFER_ALLOC : 194719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_ISTREAM_HOSTBUFFER_ALLOC); 195719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 196719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_to_indexes(h_stream, &hm.adapter_index, 197719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hm.obj_index); 198719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 199719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hm.u.d.u.buffer.buffer_size = size_in_bytes; 200719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hm.u.d.u.buffer.pci_address = pci_address; 201719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hm.u.d.u.buffer.command = HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER; 202719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_send_recv(&hm, &hr); 203719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return hr.error; 204719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 205719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 206ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic u16 hpi_stream_host_buffer_detach(u32 h_stream) 207719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 208719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_message hm; 209719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_response hr; 210719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int obj = hpi_handle_object(h_stream); 211719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 212719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!h_stream) 213719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return HPI_ERROR_INVALID_OBJ; 214719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 215719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_init_message_response(&hm, &hr, obj, 216719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett obj == HPI_OBJ_OSTREAM ? 217719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_OSTREAM_HOSTBUFFER_FREE : 218719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_ISTREAM_HOSTBUFFER_FREE); 219719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 220719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_to_indexes(h_stream, &hm.adapter_index, 221719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hm.obj_index); 222719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hm.u.d.u.buffer.command = HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER; 223719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_send_recv(&hm, &hr); 224719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return hr.error; 225719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 226719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 227ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic inline u16 hpi_stream_start(u32 h_stream) 228719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 229719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) 230ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_outstream_start(h_stream); 231719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 232ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_instream_start(h_stream); 233719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 234719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 235ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic inline u16 hpi_stream_stop(u32 h_stream) 236719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 237719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) 238ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_outstream_stop(h_stream); 239719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 240ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_instream_stop(h_stream); 241719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 242719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 243719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic inline u16 hpi_stream_get_info_ex( 244719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_stream, 245719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 *pw_state, 246719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 *pbuffer_size, 247719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 *pdata_in_buffer, 248719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 *psample_count, 249719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 *pauxiliary_data 250719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett) 251719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 252e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett u16 e; 253719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) 254ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett e = hpi_outstream_get_info_ex(h_stream, pw_state, 255719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pbuffer_size, pdata_in_buffer, 256719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett psample_count, pauxiliary_data); 257719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 258ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett e = hpi_instream_get_info_ex(h_stream, pw_state, 259719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pbuffer_size, pdata_in_buffer, 260719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett psample_count, pauxiliary_data); 261e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett return e; 262719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 263719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 264ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic inline u16 hpi_stream_group_add( 265719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_master, 266719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_stream) 267719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 268719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (hpi_handle_object(h_master) == HPI_OBJ_OSTREAM) 269ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_outstream_group_add(h_master, h_stream); 270719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 271ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_instream_group_add(h_master, h_stream); 272719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 273719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 274ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic inline u16 hpi_stream_group_reset(u32 h_stream) 275719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 276719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) 277ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_outstream_group_reset(h_stream); 278719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 279ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_instream_group_reset(h_stream); 280719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 281719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 282ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic inline u16 hpi_stream_group_get_map( 283719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_stream, u32 *mo, u32 *mi) 284719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 285719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) 286ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_outstream_group_get_map(h_stream, mo, mi); 287719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 288ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_instream_group_get_map(h_stream, mo, mi); 289719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 290719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 291719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic u16 handle_error(u16 err, int line, char *filename) 292719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 293719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 294719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett printk(KERN_WARNING 295719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "in file %s, line %d: HPI error %d\n", 296719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett filename, line, err); 297719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 298719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 299719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 300719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define hpi_handle_error(x) handle_error(x, __LINE__, __FILE__) 301719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 302719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/***************************** GENERAL PCM ****************/ 303a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett 304a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassettstatic void print_hwparams(struct snd_pcm_substream *substream, 305a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett struct snd_pcm_hw_params *p) 306719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 307a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett DEBUG_NAME(substream, name); 308a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printd("%s HWPARAMS\n", name); 309a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printd(" samplerate %d Hz\n", params_rate(p)); 310a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printd(" channels %d\n", params_channels(p)); 311a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printd(" format %d\n", params_format(p)); 312a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printd(" subformat %d\n", params_subformat(p)); 313a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printd(" buffer %d B\n", params_buffer_bytes(p)); 314a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printd(" period %d B\n", params_period_bytes(p)); 315a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printd(" access %d\n", params_access(p)); 316a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printd(" period_size %d\n", params_period_size(p)); 317a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printd(" periods %d\n", params_periods(p)); 318a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printd(" buffer_size %d\n", params_buffer_size(p)); 319a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printd(" %d B/s\n", params_rate(p) * 320a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett params_channels(p) * 321a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_pcm_format_width(params_format(p)) / 8); 322a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett 323719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 324719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 325719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic snd_pcm_format_t hpi_to_alsa_formats[] = { 326719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett -1, /* INVALID */ 327719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_FORMAT_U8, /* HPI_FORMAT_PCM8_UNSIGNED 1 */ 328719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_FORMAT_S16, /* HPI_FORMAT_PCM16_SIGNED 2 */ 329719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett -1, /* HPI_FORMAT_MPEG_L1 3 */ 330719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_FORMAT_MPEG, /* HPI_FORMAT_MPEG_L2 4 */ 331719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_FORMAT_MPEG, /* HPI_FORMAT_MPEG_L3 5 */ 332719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett -1, /* HPI_FORMAT_DOLBY_AC2 6 */ 333719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett -1, /* HPI_FORMAT_DOLBY_AC3 7 */ 334719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_FORMAT_S16_BE,/* HPI_FORMAT_PCM16_BIGENDIAN 8 */ 335719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett -1, /* HPI_FORMAT_AA_TAGIT1_HITS 9 */ 336719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett -1, /* HPI_FORMAT_AA_TAGIT1_INSERTS 10 */ 337719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_FORMAT_S32, /* HPI_FORMAT_PCM32_SIGNED 11 */ 338719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett -1, /* HPI_FORMAT_RAW_BITSTREAM 12 */ 339719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett -1, /* HPI_FORMAT_AA_TAGIT1_HITS_EX1 13 */ 340719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_FORMAT_FLOAT, /* HPI_FORMAT_PCM32_FLOAT 14 */ 341719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#if 1 342719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* ALSA can't handle 3 byte sample size together with power-of-2 343719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * constraint on buffer_bytes, so disable this format 344719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 345719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett -1 346719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#else 347ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett /* SNDRV_PCM_FORMAT_S24_3LE */ /* HPI_FORMAT_PCM24_SIGNED 15 */ 348719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#endif 349719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 350719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 351719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 352719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_format_alsa2hpi(snd_pcm_format_t alsa_format, 353719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 *hpi_format) 354719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 355719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 format; 356719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 357719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (format = HPI_FORMAT_PCM8_UNSIGNED; 358719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett format <= HPI_FORMAT_PCM24_SIGNED; format++) { 359719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (hpi_to_alsa_formats[format] == alsa_format) { 360719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett *hpi_format = format; 361719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 362719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 363719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 364719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 365719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printd(KERN_WARNING "failed match for alsa format %d\n", 366719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett alsa_format); 367719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett *hpi_format = 0; 368719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 369719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 370719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 371719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void snd_card_asihpi_pcm_samplerates(struct snd_card_asihpi *asihpi, 372719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_hardware *pcmhw) 373719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 374719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 err; 375719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control; 376719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 sample_rate; 377719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int idx; 378719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int rate_min = 200000; 379719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int rate_max = 0; 380719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int rates = 0; 381719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 382719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (asihpi->support_mrx) { 383719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_CONTINUOUS; 384719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_8000_96000; 385719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rate_min = 8000; 386719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rate_max = 100000; 387719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else { 388719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* on cards without SRC, 389719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett valid rates are determined by sampleclock */ 390ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_mixer_get_control(asihpi->h_mixer, 391719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, 392719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_CONTROL_SAMPLECLOCK, &h_control); 393719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) { 394719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_ERR 395e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "No local sampleclock, err %d\n", err); 396719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 397719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 3987bf76c33e9a1ecb2a15f1a066d4e032b5d0922a7Eliot Blennerhassett for (idx = -1; idx < 100; idx++) { 3997bf76c33e9a1ecb2a15f1a066d4e032b5d0922a7Eliot Blennerhassett if (idx == -1) { 4007bf76c33e9a1ecb2a15f1a066d4e032b5d0922a7Eliot Blennerhassett if (hpi_sample_clock_get_sample_rate(h_control, 4017bf76c33e9a1ecb2a15f1a066d4e032b5d0922a7Eliot Blennerhassett &sample_rate)) 4027bf76c33e9a1ecb2a15f1a066d4e032b5d0922a7Eliot Blennerhassett continue; 4037bf76c33e9a1ecb2a15f1a066d4e032b5d0922a7Eliot Blennerhassett } else if (hpi_sample_clock_query_local_rate(h_control, 4047bf76c33e9a1ecb2a15f1a066d4e032b5d0922a7Eliot Blennerhassett idx, &sample_rate)) { 405719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 406719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 407719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 408719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rate_min = min(rate_min, sample_rate); 409719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rate_max = max(rate_max, sample_rate); 410719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 411719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett switch (sample_rate) { 412719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 5512: 413719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_5512; 414719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 415719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 8000: 416719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_8000; 417719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 418719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 11025: 419719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_11025; 420719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 421719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 16000: 422719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_16000; 423719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 424719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 22050: 425719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_22050; 426719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 427719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 32000: 428719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_32000; 429719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 430719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 44100: 431719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_44100; 432719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 433719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 48000: 434719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_48000; 435719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 436719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 64000: 437719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_64000; 438719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 439719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 88200: 440719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_88200; 441719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 442719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 96000: 443719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_96000; 444719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 445719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 176400: 446719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_176400; 447719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 448719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 192000: 449719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_192000; 450719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 451719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett default: /* some other rate */ 452719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_KNOT; 453719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 454719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 455719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 456719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 457719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pcmhw->rates = rates; 458719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pcmhw->rate_min = rate_min; 459719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pcmhw->rate_max = rate_max; 460719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 461719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 462719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream, 463719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_hw_params *params) 464719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 465719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 466719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 467719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); 468719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 469719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 format; 470315e8f7501ad929acacfa94c251283e837f281edKulikov Vasiliy int width; 471719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int bytes_per_sec; 472719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 473a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett print_hwparams(substream, params); 474719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); 475719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) 476719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 477719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_card_asihpi_format_alsa2hpi(params_format(params), &format); 478719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 479719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 480719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 481719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error(hpi_format_create(&dpcm->format, 482719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett params_channels(params), 483719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett format, params_rate(params), 0, 0)); 484719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 485719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 486ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (hpi_instream_reset(dpcm->h_stream) != 0) 487719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 488719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 489ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (hpi_instream_set_format( 490719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->h_stream, &dpcm->format) != 0) 491719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 492719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 493719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 494719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->hpi_buffer_attached = 0; 495f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett if (card->can_dma) { 496ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_stream_host_buffer_attach(dpcm->h_stream, 497719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett params_buffer_bytes(params), runtime->dma_addr); 498719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err == 0) { 499b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett snd_printdd( 500719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "stream_host_buffer_attach succeeded %u %lu\n", 501719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett params_buffer_bytes(params), 502719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (unsigned long)runtime->dma_addr); 503719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else { 504b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett snd_printd("stream_host_buffer_attach error %d\n", 505719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err); 506719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -ENOMEM; 507719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 508719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 509ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_stream_get_info_ex(dpcm->h_stream, NULL, 510719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &dpcm->hpi_buffer_attached, 511719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett NULL, NULL, NULL); 512719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 513b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett snd_printdd("stream_host_buffer_attach status 0x%x\n", 514719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->hpi_buffer_attached); 515719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 516719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett bytes_per_sec = params_rate(params) * params_channels(params); 517315e8f7501ad929acacfa94c251283e837f281edKulikov Vasiliy width = snd_pcm_format_width(params_format(params)); 518315e8f7501ad929acacfa94c251283e837f281edKulikov Vasiliy bytes_per_sec *= width; 519719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett bytes_per_sec /= 8; 520315e8f7501ad929acacfa94c251283e837f281edKulikov Vasiliy if (width < 0 || bytes_per_sec == 0) 521719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 522719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 523719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->bytes_per_sec = bytes_per_sec; 524ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett dpcm->buffer_bytes = params_buffer_bytes(params); 525ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett dpcm->period_bytes = params_period_bytes(params); 526719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 527719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 528719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 529719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 530e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassettstatic int 531e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassettsnd_card_asihpi_hw_free(struct snd_pcm_substream *substream) 532e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett{ 533e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 534e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 535e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett if (dpcm->hpi_buffer_attached) 536ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_stream_host_buffer_detach(dpcm->h_stream); 537e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 538e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett snd_pcm_lib_free_pages(substream); 539e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett return 0; 540e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett} 541e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 542e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassettstatic void snd_card_asihpi_runtime_free(struct snd_pcm_runtime *runtime) 543e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett{ 544e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 545e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett kfree(dpcm); 546e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett} 547e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 548719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void snd_card_asihpi_pcm_timer_start(struct snd_pcm_substream * 549719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett substream) 550719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 551719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 552719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 553719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int expiry; 554719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 555ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett expiry = HZ / 200; 556ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett /*? (dpcm->period_bytes * HZ / dpcm->bytes_per_sec); */ 557e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett expiry = max(expiry, 1); /* don't let it be zero! */ 558719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->timer.expires = jiffies + expiry; 559719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->respawn_timer = 1; 560719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett add_timer(&dpcm->timer); 561719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 562719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 563719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void snd_card_asihpi_pcm_timer_stop(struct snd_pcm_substream *substream) 564719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 565719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 566719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 567719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 568719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->respawn_timer = 0; 569719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett del_timer(&dpcm->timer); 570719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 571719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 572719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, 573719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int cmd) 574719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 575719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = substream->runtime->private_data; 576719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); 577719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_substream *s; 578719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 e; 579a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett DEBUG_NAME(substream, name); 580a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett 581a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printdd("%s trigger\n", name); 582719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 583719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett switch (cmd) { 584719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case SNDRV_PCM_TRIGGER_START: 585719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_group_for_each_entry(s, substream) { 586e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett struct snd_pcm_runtime *runtime = s->runtime; 587e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett struct snd_card_asihpi_pcm *ds = runtime->private_data; 588719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 589719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (snd_pcm_substream_chip(s) != card) 590719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett continue; 591719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 592ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett /* don't link Cap and Play */ 593ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (substream->stream != s->stream) 594ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett continue; 595ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett 5960b7ce9e2bd2d9dbc8f4797b0cd5e0d138cb529e1Eliot Blennerhassett ds->drained_count = 0; 597f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { 598719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* How do I know how much valid data is present 599e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett * in buffer? Must be at least one period! 600e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett * Guessing 2 periods, but if 601719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * buffer is bigger it may contain even more 602719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * data?? 603719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 604ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett unsigned int preload = ds->period_bytes * 1; 605b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett snd_printddd("%d preload x%x\n", s->number, preload); 606719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error(hpi_outstream_write_buf( 607ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett ds->h_stream, 608e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett &runtime->dma_area[0], 609719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett preload, 610719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &ds->format)); 611e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett ds->pcm_buf_host_rw_ofs = preload; 612719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 613719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 614719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (card->support_grouping) { 615a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printdd("%d group\n", s->number); 616ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett e = hpi_stream_group_add( 617719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->h_stream, 618719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ds->h_stream); 619719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!e) { 620719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_trigger_done(s, substream); 621719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else { 622719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error(e); 623719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 624719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 625719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else 626719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 627719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 628b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett snd_printdd("start\n"); 629719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* start the master stream */ 630719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_pcm_timer_start(substream); 631c4ed97d9e7ec9b8c8453af4ce55497d85970426cEliot Blennerhassett if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) || 632f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett !card->can_dma) 633ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_stream_start(dpcm->h_stream)); 634719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 635719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 636719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case SNDRV_PCM_TRIGGER_STOP: 637719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_pcm_timer_stop(substream); 638719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_group_for_each_entry(s, substream) { 639719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (snd_pcm_substream_chip(s) != card) 640719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett continue; 641ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett /* don't link Cap and Play */ 642ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (substream->stream != s->stream) 643ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett continue; 644719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 645719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /*? workaround linked streams don't 646719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett transition to SETUP 20070706*/ 647719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett s->runtime->status->state = SNDRV_PCM_STATE_SETUP; 648719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 649719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (card->support_grouping) { 650a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printdd("%d group\n", s->number); 651719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_trigger_done(s, substream); 652719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else 653719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 654719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 655b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett snd_printdd("stop\n"); 656719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 657719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* _prepare and _hwparams reset the stream */ 658ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_stream_stop(dpcm->h_stream)); 659719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 660719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error( 661ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_outstream_reset(dpcm->h_stream)); 662719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 663719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (card->support_grouping) 664ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_stream_group_reset(dpcm->h_stream)); 665719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 666719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 667719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 668b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett snd_printdd("pause release\n"); 669ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_stream_start(dpcm->h_stream)); 670719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_pcm_timer_start(substream); 671719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 672719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 673b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett snd_printdd("pause\n"); 674719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_pcm_timer_stop(substream); 675ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_stream_stop(dpcm->h_stream)); 676719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 677719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett default: 678ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett snd_printd(KERN_ERR "\tINVALID\n"); 679719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 680719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 681719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 682719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 683719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 684719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 685719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*algorithm outline 686719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Without linking degenerates to getting single stream pos etc 687719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Without mmap 2nd loop degenerates to snd_pcm_period_elapsed 688719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett*/ 689719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* 690e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassettpcm_buf_dma_ofs=get_buf_pos(s); 691719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettfor_each_linked_stream(s) { 692e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett pcm_buf_dma_ofs=get_buf_pos(s); 693ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett min_buf_pos = modulo_min(min_buf_pos, pcm_buf_dma_ofs, buffer_bytes) 694e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett new_data = min(new_data, calc_new_data(pcm_buf_dma_ofs,irq_pos) 695719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 696719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassetttimer.expires = jiffies + predict_next_period_ready(min_buf_pos); 697719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettfor_each_linked_stream(s) { 698e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett s->pcm_buf_dma_ofs = min_buf_pos; 699ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (new_data > period_bytes) { 700719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (mmap) { 701ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett irq_pos = (irq_pos + period_bytes) % buffer_bytes; 702719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (playback) { 703ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett write(period_bytes); 704719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else { 705ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett read(period_bytes); 706719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 707719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 708719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_period_elapsed(s); 709719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 710719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 711719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett*/ 712719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 713719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/** Minimum of 2 modulo values. Works correctly when the difference between 714719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett* the values is less than half the modulus 715719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett*/ 716719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic inline unsigned int modulo_min(unsigned int a, unsigned int b, 717719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned long int modulus) 718719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 719719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int result; 720719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (((a-b) % modulus) < (modulus/2)) 721719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett result = b; 722719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 723719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett result = a; 724719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 725719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return result; 726719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 727719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 728719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/** Timer function, equivalent to interrupt service routine for cards 729719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett*/ 730719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void snd_card_asihpi_timer_function(unsigned long data) 731719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 732719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = (struct snd_card_asihpi_pcm *)data; 733ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett struct snd_pcm_substream *substream = dpcm->substream; 734ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); 735719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime; 736719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_substream *s; 737719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int newdata = 0; 738e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett unsigned int pcm_buf_dma_ofs, min_buf_pos = 0; 739719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int remdata, xfercount, next_jiffies; 740719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int first = 1; 741ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett int loops = 0; 742719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 state; 743e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett u32 buffer_size, bytes_avail, samples_played, on_card_bytes; 744a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett DEBUG_NAME(substream, name); 745719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 746a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printdd("%s snd_card_asihpi_timer_function\n", name); 747ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett 748719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* find minimum newdata and buffer pos in group */ 749ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett snd_pcm_group_for_each_entry(s, substream) { 750719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *ds = s->runtime->private_data; 751719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime = s->runtime; 752719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 753719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (snd_pcm_substream_chip(s) != card) 754719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett continue; 755719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 756ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett /* don't link Cap and Play */ 757ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (substream->stream != s->stream) 758ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett continue; 759ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett 760ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_stream_get_info_ex( 761719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ds->h_stream, &state, 762e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett &buffer_size, &bytes_avail, 763e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett &samples_played, &on_card_bytes)); 764719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 765719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* number of bytes in on-card buffer */ 766e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett runtime->delay = on_card_bytes; 767719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 768f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett if (!card->can_dma) 769f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett on_card_bytes = bytes_avail; 770f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett 771ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { 772e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett pcm_buf_dma_ofs = ds->pcm_buf_host_rw_ofs - bytes_avail; 773ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (state == HPI_STATE_STOPPED) { 774ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if ((bytes_avail == 0) && 775ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett (on_card_bytes < ds->pcm_buf_host_rw_ofs)) { 776ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_stream_start(ds->h_stream)); 777b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett snd_printdd("P%d start\n", s->number); 7780b7ce9e2bd2d9dbc8f4797b0cd5e0d138cb529e1Eliot Blennerhassett ds->drained_count = 0; 779ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett } 780ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett } else if (state == HPI_STATE_DRAINED) { 781b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett snd_printd(KERN_WARNING "P%d drained\n", 782ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett s->number); 7830b7ce9e2bd2d9dbc8f4797b0cd5e0d138cb529e1Eliot Blennerhassett ds->drained_count++; 7840b7ce9e2bd2d9dbc8f4797b0cd5e0d138cb529e1Eliot Blennerhassett if (ds->drained_count > 2) { 7850b7ce9e2bd2d9dbc8f4797b0cd5e0d138cb529e1Eliot Blennerhassett snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN); 7860b7ce9e2bd2d9dbc8f4797b0cd5e0d138cb529e1Eliot Blennerhassett continue; 7870b7ce9e2bd2d9dbc8f4797b0cd5e0d138cb529e1Eliot Blennerhassett } 7880b7ce9e2bd2d9dbc8f4797b0cd5e0d138cb529e1Eliot Blennerhassett } else { 7890b7ce9e2bd2d9dbc8f4797b0cd5e0d138cb529e1Eliot Blennerhassett ds->drained_count = 0; 790ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett } 791ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett } else 792e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett pcm_buf_dma_ofs = bytes_avail + ds->pcm_buf_host_rw_ofs; 793719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 794719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (first) { 795719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* can't statically init min when wrap is involved */ 796e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett min_buf_pos = pcm_buf_dma_ofs; 797ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett newdata = (pcm_buf_dma_ofs - ds->pcm_buf_elapsed_dma_ofs) % ds->buffer_bytes; 798719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett first = 0; 799719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else { 800719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett min_buf_pos = 801e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett modulo_min(min_buf_pos, pcm_buf_dma_ofs, UINT_MAX+1L); 802719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett newdata = min( 803ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett (pcm_buf_dma_ofs - ds->pcm_buf_elapsed_dma_ofs) % ds->buffer_bytes, 804719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett newdata); 805719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 806719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 807a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printdd("hw_ptr 0x%04lX, appl_ptr 0x%04lX\n", 808719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (unsigned long)frames_to_bytes(runtime, 809719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime->status->hw_ptr), 810719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (unsigned long)frames_to_bytes(runtime, 811719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime->control->appl_ptr)); 812e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 813a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printdd("%d S=%d, " 814a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett "rw=0x%04X, dma=0x%04X, left=0x%04X, " 815a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett "aux=0x%04X space=0x%04X\n", 816a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett s->number, state, 817a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett ds->pcm_buf_host_rw_ofs, pcm_buf_dma_ofs, 818a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett (int)bytes_avail, 819e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett (int)on_card_bytes, buffer_size-bytes_avail); 820ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett loops++; 821719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 822e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett pcm_buf_dma_ofs = min_buf_pos; 823719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 824ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett remdata = newdata % dpcm->period_bytes; 825ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett xfercount = newdata - remdata; /* a multiple of period_bytes */ 826e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett /* come back when on_card_bytes has decreased enough to allow 827e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett write to happen, or when data has been consumed to make another 828e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett period 829e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett */ 830ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (xfercount && (on_card_bytes > dpcm->period_bytes)) 831ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett next_jiffies = ((on_card_bytes - dpcm->period_bytes) * HZ / dpcm->bytes_per_sec); 832e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett else 833ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett next_jiffies = ((dpcm->period_bytes - remdata) * HZ / dpcm->bytes_per_sec); 834e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 835e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett next_jiffies = max(next_jiffies, 1U); 836719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->timer.expires = jiffies + next_jiffies; 837a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printdd("jif %d buf pos 0x%04X newdata 0x%04X xfer 0x%04X\n", 838e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett next_jiffies, pcm_buf_dma_ofs, newdata, xfercount); 839e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 840ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett snd_pcm_group_for_each_entry(s, substream) { 841719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *ds = s->runtime->private_data; 842719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 843ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett /* don't link Cap and Play */ 844ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (substream->stream != s->stream) 845ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett continue; 846ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett 847e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett ds->pcm_buf_dma_ofs = pcm_buf_dma_ofs; 848e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 849f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett if (xfercount && 850f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett /* Limit use of on card fifo for playback */ 851f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett ((on_card_bytes <= ds->period_bytes) || 852f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett (s->stream == SNDRV_PCM_STREAM_CAPTURE))) 853f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett 854f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett { 855f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett 856f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett unsigned int buf_ofs = ds->pcm_buf_host_rw_ofs % ds->buffer_bytes; 857f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett unsigned int xfer1, xfer2; 858f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett char *pd = &s->runtime->dma_area[buf_ofs]; 859f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett 860b0096a65677fa8d7e50975dc7282ce313610d9e8Eliot Blennerhassett if (card->can_dma) { /* buffer wrap is handled at lower level */ 861f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett xfer1 = xfercount; 862f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett xfer2 = 0; 863f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett } else { 864f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett xfer1 = min(xfercount, ds->buffer_bytes - buf_ofs); 865f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett xfer2 = xfercount - xfer1; 866f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett } 867f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett 868f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { 869f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett snd_printddd("P%d write1 0x%04X 0x%04X\n", 870f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett s->number, xfer1, buf_ofs); 871f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett hpi_handle_error( 872f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett hpi_outstream_write_buf( 873f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett ds->h_stream, pd, xfer1, 874f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett &ds->format)); 875f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett 876f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett if (xfer2) { 877f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett pd = s->runtime->dma_area; 878f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett 879f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett snd_printddd("P%d write2 0x%04X 0x%04X\n", 880719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett s->number, 881f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett xfercount - xfer1, buf_ofs); 882719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error( 883719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_outstream_write_buf( 884f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett ds->h_stream, pd, 885f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett xfercount - xfer1, 886719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &ds->format)); 887f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett } 888f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett } else { 889f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett snd_printddd("C%d read1 0x%04x\n", 890f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett s->number, xfer1); 891f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett hpi_handle_error( 892f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett hpi_instream_read_buf( 893f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett ds->h_stream, 894f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett pd, xfer1)); 895f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett if (xfer2) { 896f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett pd = s->runtime->dma_area; 897f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett snd_printddd("C%d read2 0x%04x\n", 898f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett s->number, xfer2); 899719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error( 900719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_instream_read_buf( 901ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett ds->h_stream, 902f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett pd, xfer2)); 903719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 904f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett } 905f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett ds->pcm_buf_host_rw_ofs = ds->pcm_buf_host_rw_ofs + xfercount; 906e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett ds->pcm_buf_elapsed_dma_ofs = pcm_buf_dma_ofs; 907719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_period_elapsed(s); 908719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 909719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 910719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 911719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (dpcm->respawn_timer) 912719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett add_timer(&dpcm->timer); 913719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 914719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 915719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/***************************** PLAYBACK OPS ****************/ 916719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_playback_ioctl(struct snd_pcm_substream *substream, 917719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int cmd, void *arg) 918719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 919a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printddd(KERN_INFO "P%d ioctl %d\n", substream->number, cmd); 920719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return snd_pcm_lib_ioctl(substream, cmd, arg); 921719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 922719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 923719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_playback_prepare(struct snd_pcm_substream * 924719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett substream) 925719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 926719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 927719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 928719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 929a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printdd("P%d prepare\n", substream->number); 930719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 931ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_outstream_reset(dpcm->h_stream)); 932e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dpcm->pcm_buf_host_rw_ofs = 0; 933e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dpcm->pcm_buf_dma_ofs = 0; 934e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dpcm->pcm_buf_elapsed_dma_ofs = 0; 935719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 936719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 937719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 938719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic snd_pcm_uframes_t 939719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettsnd_card_asihpi_playback_pointer(struct snd_pcm_substream *substream) 940719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 941719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 942719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 943719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_uframes_t ptr; 944719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 945ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett ptr = bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes); 946a6477134db119a22aa30911ff18e440b8db9df65Eliot Blennerhassett snd_printddd("P%d pointer = 0x%04lx\n", substream->number, (unsigned long)ptr); 947719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ptr; 948719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 949719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 950719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void snd_card_asihpi_playback_format(struct snd_card_asihpi *asihpi, 951719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_stream, 952719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_hardware *pcmhw) 953719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 954719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_format hpi_format; 955719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 format; 956719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 err; 957719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control; 958719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 sample_rate = 48000; 959719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 960719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* on cards without SRC, must query at valid rate, 961719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * maybe set by external sync 962719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 963ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_mixer_get_control(asihpi->h_mixer, 964719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, 965719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_CONTROL_SAMPLECLOCK, &h_control); 966719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 967719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err) 968ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_sample_clock_get_sample_rate(h_control, 969719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &sample_rate); 970719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 971719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (format = HPI_FORMAT_PCM8_UNSIGNED; 972719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett format <= HPI_FORMAT_PCM24_SIGNED; format++) { 973719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = hpi_format_create(&hpi_format, 974719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2, format, sample_rate, 128000, 0); 975719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err) 976ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_outstream_query_format(h_stream, 977719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_format); 978719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err && (hpi_to_alsa_formats[format] != -1)) 979719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pcmhw->formats |= 980719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (1ULL << hpi_to_alsa_formats[format]); 981719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 982719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 983719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 984719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic struct snd_pcm_hardware snd_card_asihpi_playback = { 985719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .channels_min = 1, 986719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .channels_max = 2, 987719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .buffer_bytes_max = BUFFER_BYTES_MAX, 988719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .period_bytes_min = PERIOD_BYTES_MIN, 989719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN, 990719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .periods_min = PERIODS_MIN, 991719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, 992719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .fifo_size = 0, 993719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 994719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 995719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream) 996719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 997719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 998719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm; 999719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); 1000719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 1001719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1002719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); 1003719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (dpcm == NULL) 1004719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -ENOMEM; 1005719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1006719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = 1007ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_outstream_open(card->adapter_index, 1008719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett substream->number, &dpcm->h_stream); 1009719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error(err); 1010719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 1011719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett kfree(dpcm); 1012719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err == HPI_ERROR_OBJ_ALREADY_OPEN) 1013719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EBUSY; 1014719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 1015719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EIO; 1016719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1017719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /*? also check ASI5000 samplerate source 1018719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett If external, only support external rate. 101925985edcedea6396277003854657b5f3cb31a628Lucas De Marchi If internal and other stream playing, can't switch 1020719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 1021719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1022719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett init_timer(&dpcm->timer); 1023719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->timer.data = (unsigned long) dpcm; 1024719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->timer.function = snd_card_asihpi_timer_function; 1025719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->substream = substream; 1026719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime->private_data = dpcm; 1027719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime->private_free = snd_card_asihpi_runtime_free; 1028719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1029719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_playback.channels_max = card->out_max_chans; 1030719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /*?snd_card_asihpi_playback.period_bytes_min = 1031719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett card->out_max_chans * 4096; */ 1032719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1033719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_playback_format(card, dpcm->h_stream, 1034719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &snd_card_asihpi_playback); 1035719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1036719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_pcm_samplerates(card, &snd_card_asihpi_playback); 1037719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1038719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_playback.info = SNDRV_PCM_INFO_INTERLEAVED | 1039719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_INFO_DOUBLE | 1040719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_INFO_BATCH | 1041719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_INFO_BLOCK_TRANSFER | 1042f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett SNDRV_PCM_INFO_PAUSE | 1043f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett SNDRV_PCM_INFO_MMAP | 1044f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett SNDRV_PCM_INFO_MMAP_VALID; 1045719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1046719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (card->support_grouping) 1047719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_playback.info |= SNDRV_PCM_INFO_SYNC_START; 1048719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1049719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* struct is copied, so can create initializer dynamically */ 1050719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime->hw = snd_card_asihpi_playback; 1051719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1052f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett if (card->can_dma) 1053719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_pcm_hw_constraint_pow2(runtime, 0, 1054719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_HW_PARAM_BUFFER_BYTES); 1055719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) 1056719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 1057719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1058719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 1059719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett card->update_interval_frames); 106026aebef420f8036213419b8a46e3a07db51439cdEliot Blennerhassett 1061719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 1062e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett card->update_interval_frames * 2, UINT_MAX); 1063719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1064719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_set_sync(substream); 1065719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1066b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett snd_printdd("playback open\n"); 1067719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1068719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1069719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1070719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1071719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_playback_close(struct snd_pcm_substream *substream) 1072719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1073719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 1074719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 1075719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1076ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_outstream_close(dpcm->h_stream)); 1077b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett snd_printdd("playback close\n"); 1078719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1079719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1080719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1081719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1082719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic struct snd_pcm_ops snd_card_asihpi_playback_mmap_ops = { 1083719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .open = snd_card_asihpi_playback_open, 1084719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .close = snd_card_asihpi_playback_close, 1085719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .ioctl = snd_card_asihpi_playback_ioctl, 1086719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .hw_params = snd_card_asihpi_pcm_hw_params, 1087719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .hw_free = snd_card_asihpi_hw_free, 1088719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .prepare = snd_card_asihpi_playback_prepare, 1089719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .trigger = snd_card_asihpi_trigger, 1090719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .pointer = snd_card_asihpi_playback_pointer, 1091719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 1092719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1093719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/***************************** CAPTURE OPS ****************/ 1094719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic snd_pcm_uframes_t 1095719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettsnd_card_asihpi_capture_pointer(struct snd_pcm_substream *substream) 1096719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1097719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 1098719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 1099719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1100b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett snd_printddd("capture pointer %d=%d\n", 1101e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett substream->number, dpcm->pcm_buf_dma_ofs); 1102e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett /* NOTE Unlike playback can't use actual samples_played 1103719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for the capture position, because those samples aren't yet in 1104719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett the local buffer available for reading. 1105719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 1106ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes); 1107719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1108719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1109719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_capture_ioctl(struct snd_pcm_substream *substream, 1110719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int cmd, void *arg) 1111719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1112719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return snd_pcm_lib_ioctl(substream, cmd, arg); 1113719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1114719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1115719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_capture_prepare(struct snd_pcm_substream *substream) 1116719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1117719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 1118719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 1119719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1120ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_instream_reset(dpcm->h_stream)); 1121e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dpcm->pcm_buf_host_rw_ofs = 0; 1122e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dpcm->pcm_buf_dma_ofs = 0; 1123e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dpcm->pcm_buf_elapsed_dma_ofs = 0; 1124719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1125b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett snd_printdd("Capture Prepare %d\n", substream->number); 1126719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1127719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1128719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1129719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1130719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1131719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void snd_card_asihpi_capture_format(struct snd_card_asihpi *asihpi, 1132719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_stream, 1133719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_hardware *pcmhw) 1134719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1135719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_format hpi_format; 1136719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 format; 1137719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 err; 1138719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control; 1139719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 sample_rate = 48000; 1140719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1141719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* on cards without SRC, must query at valid rate, 1142719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett maybe set by external sync */ 1143ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_mixer_get_control(asihpi->h_mixer, 1144719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, 1145719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_CONTROL_SAMPLECLOCK, &h_control); 1146719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1147719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err) 1148ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_sample_clock_get_sample_rate(h_control, 1149719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &sample_rate); 1150719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1151719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (format = HPI_FORMAT_PCM8_UNSIGNED; 1152719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett format <= HPI_FORMAT_PCM24_SIGNED; format++) { 1153719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1154719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = hpi_format_create(&hpi_format, 2, format, 1155719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett sample_rate, 128000, 0); 1156719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err) 1157ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_instream_query_format(h_stream, 1158719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_format); 1159719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err) 1160719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pcmhw->formats |= 1161719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (1ULL << hpi_to_alsa_formats[format]); 1162719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1163719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1164719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1165719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1166719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic struct snd_pcm_hardware snd_card_asihpi_capture = { 1167719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .channels_min = 1, 1168719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .channels_max = 2, 1169719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .buffer_bytes_max = BUFFER_BYTES_MAX, 1170719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .period_bytes_min = PERIOD_BYTES_MIN, 1171719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN, 1172719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .periods_min = PERIODS_MIN, 1173719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, 1174719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .fifo_size = 0, 1175719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 1176719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1177719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream) 1178719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1179719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 1180719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); 1181719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm; 1182719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 1183719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1184719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); 1185719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (dpcm == NULL) 1186719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -ENOMEM; 1187719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1188b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett snd_printdd("capture open adapter %d stream %d\n", 1189719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett card->adapter_index, substream->number); 1190719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1191719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = hpi_handle_error( 1192ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_instream_open(card->adapter_index, 1193719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett substream->number, &dpcm->h_stream)); 1194719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 1195719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett kfree(dpcm); 1196719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err == HPI_ERROR_OBJ_ALREADY_OPEN) 1197719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EBUSY; 1198719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 1199719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EIO; 1200719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1201719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1202719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett init_timer(&dpcm->timer); 1203719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->timer.data = (unsigned long) dpcm; 1204719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->timer.function = snd_card_asihpi_timer_function; 1205719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->substream = substream; 1206719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime->private_data = dpcm; 1207719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime->private_free = snd_card_asihpi_runtime_free; 1208719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1209719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_capture.channels_max = card->in_max_chans; 1210719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_capture_format(card, dpcm->h_stream, 1211719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &snd_card_asihpi_capture); 1212719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_pcm_samplerates(card, &snd_card_asihpi_capture); 1213f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett snd_card_asihpi_capture.info = SNDRV_PCM_INFO_INTERLEAVED | 1214f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett SNDRV_PCM_INFO_MMAP | 1215f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett SNDRV_PCM_INFO_MMAP_VALID; 1216719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1217e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett if (card->support_grouping) 1218e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_SYNC_START; 1219e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 1220719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime->hw = snd_card_asihpi_capture; 1221719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1222f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett if (card->can_dma) 1223719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_pcm_hw_constraint_pow2(runtime, 0, 1224719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_HW_PARAM_BUFFER_BYTES); 1225719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) 1226719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 1227719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1228719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 1229719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett card->update_interval_frames); 1230719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 1231719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett card->update_interval_frames * 2, UINT_MAX); 1232719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1233719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_set_sync(substream); 1234719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1235719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1236719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1237719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1238719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_capture_close(struct snd_pcm_substream *substream) 1239719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1240719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = substream->runtime->private_data; 1241719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1242ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_instream_close(dpcm->h_stream)); 1243719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1244719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1245719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1246719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = { 1247719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .open = snd_card_asihpi_capture_open, 1248719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .close = snd_card_asihpi_capture_close, 1249719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .ioctl = snd_card_asihpi_capture_ioctl, 1250719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .hw_params = snd_card_asihpi_pcm_hw_params, 1251719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .hw_free = snd_card_asihpi_hw_free, 1252719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .prepare = snd_card_asihpi_capture_prepare, 1253719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .trigger = snd_card_asihpi_trigger, 1254719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .pointer = snd_card_asihpi_capture_pointer, 1255719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 1256719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1257719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi, 1258719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int device, int substreams) 1259719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1260719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm *pcm; 1261719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 1262719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1263e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett err = snd_pcm_new(asihpi->card, "Asihpi PCM", device, 1264719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->num_outstreams, asihpi->num_instreams, 1265719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &pcm); 1266719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) 1267719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 1268719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* pointer to ops struct is stored, dont change ops afterwards! */ 1269719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, 1270719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &snd_card_asihpi_playback_mmap_ops); 1271719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, 1272719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &snd_card_asihpi_capture_mmap_ops); 1273719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1274719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pcm->private_data = asihpi; 1275719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pcm->info_flags = 0; 1276e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett strcpy(pcm->name, "Asihpi PCM"); 1277719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1278719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /*? do we want to emulate MMAP for non-BBM cards? 1279719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Jack doesn't work with ALSAs MMAP emulation - WHY NOT? */ 1280719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 1281719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_dma_pci_data(asihpi->pci), 1282719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 64*1024, BUFFER_BYTES_MAX); 1283719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1284719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1285719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1286719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1287719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/***************************** MIXER CONTROLS ****************/ 1288719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstruct hpi_control { 1289719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control; 1290719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 control_type; 1291719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 src_node_type; 1292719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 src_node_index; 1293719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 dst_node_type; 1294719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 dst_node_index; 1295719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 band; 1296719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett char name[44]; /* copied to snd_ctl_elem_id.name[44]; */ 1297719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 1298719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1299ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic const char * const asihpi_tuner_band_names[] = { 1300719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "invalid", 1301719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "AM", 1302719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "FM mono", 1303719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "TV NTSC-M", 1304719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "FM stereo", 1305719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "AUX", 1306719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "TV PAL BG", 1307719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "TV PAL I", 1308719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "TV PAL DK", 1309719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "TV SECAM", 1310719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 1311719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1312719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettcompile_time_assert( 1313719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (ARRAY_SIZE(asihpi_tuner_band_names) == 1314719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (HPI_TUNER_BAND_LAST+1)), 1315719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett assert_tuner_band_names_size); 1316719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1317ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic const char * const asihpi_src_names[] = { 1318719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "no source", 1319e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "PCM", 1320e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Line", 1321e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Digital", 1322e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Tuner", 1323719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "RF", 1324e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Clock", 1325e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Bitstream", 1326e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Microphone", 1327e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Cobranet", 1328e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Analog", 1329e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Adapter", 1330719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 1331719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1332719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettcompile_time_assert( 1333719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (ARRAY_SIZE(asihpi_src_names) == 1334168f1b07ccc0e8edecb67fab2d0670861853e2fdEliot Blennerhassett (HPI_SOURCENODE_LAST_INDEX-HPI_SOURCENODE_NONE+1)), 1335719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett assert_src_names_size); 1336719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1337ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic const char * const asihpi_dst_names[] = { 1338719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "no destination", 1339e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "PCM", 1340e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Line", 1341e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Digital", 1342719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "RF", 1343e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Speaker", 1344e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Cobranet Out", 1345e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Analog" 1346719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 1347719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1348719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettcompile_time_assert( 1349719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (ARRAY_SIZE(asihpi_dst_names) == 1350168f1b07ccc0e8edecb67fab2d0670861853e2fdEliot Blennerhassett (HPI_DESTNODE_LAST_INDEX-HPI_DESTNODE_NONE+1)), 1351719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett assert_dst_names_size); 1352719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1353719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic inline int ctl_add(struct snd_card *card, struct snd_kcontrol_new *ctl, 1354719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi) 1355719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1356719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 1357719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1358719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_ctl_add(card, snd_ctl_new1(ctl, asihpi)); 1359719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) 1360719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 1361719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else if (mixer_dump) 1362719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_INFO "added %s(%d)\n", ctl->name, ctl->index); 1363719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1364719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1365719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1366719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1367719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* Convert HPI control name and location into ALSA control name */ 1368719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void asihpi_ctl_init(struct snd_kcontrol_new *snd_control, 1369719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl, 1370719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett char *name) 1371719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1372550ac6ba4ef0e57f6edbadf2b018d5125d2f7e98Eliot Blennerhassett char *dir; 1373719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett memset(snd_control, 0, sizeof(*snd_control)); 1374719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control->name = hpi_ctl->name; 1375719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control->private_value = hpi_ctl->h_control; 1376719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control->iface = SNDRV_CTL_ELEM_IFACE_MIXER; 1377719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control->index = 0; 1378719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1379550ac6ba4ef0e57f6edbadf2b018d5125d2f7e98Eliot Blennerhassett if (hpi_ctl->src_node_type + HPI_SOURCENODE_NONE == HPI_SOURCENODE_CLOCK_SOURCE) 1380550ac6ba4ef0e57f6edbadf2b018d5125d2f7e98Eliot Blennerhassett dir = ""; /* clock is neither capture nor playback */ 1381550ac6ba4ef0e57f6edbadf2b018d5125d2f7e98Eliot Blennerhassett else if (hpi_ctl->dst_node_type + HPI_DESTNODE_NONE == HPI_DESTNODE_ISTREAM) 1382e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dir = "Capture "; /* On or towards a PCM capture destination*/ 1383e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett else if ((hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) && 1384e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett (!hpi_ctl->dst_node_type)) 1385e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dir = "Capture "; /* On a source node that is not PCM playback */ 1386ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett else if (hpi_ctl->src_node_type && 1387ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett (hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) && 1388e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett (hpi_ctl->dst_node_type)) 1389e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dir = "Monitor Playback "; /* Between an input and an output */ 1390e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett else 1391e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dir = "Playback "; /* PCM Playback source, or output node */ 1392e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 1393719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (hpi_ctl->src_node_type && hpi_ctl->dst_node_type) 1394550ac6ba4ef0e57f6edbadf2b018d5125d2f7e98Eliot Blennerhassett sprintf(hpi_ctl->name, "%s %d %s %d %s%s", 1395719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi_src_names[hpi_ctl->src_node_type], 1396719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_ctl->src_node_index, 1397719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi_dst_names[hpi_ctl->dst_node_type], 1398719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_ctl->dst_node_index, 1399e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dir, name); 1400719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else if (hpi_ctl->dst_node_type) { 1401e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett sprintf(hpi_ctl->name, "%s %d %s%s", 1402719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi_dst_names[hpi_ctl->dst_node_type], 1403719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_ctl->dst_node_index, 1404e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dir, name); 1405719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else { 1406e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett sprintf(hpi_ctl->name, "%s %d %s%s", 1407719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi_src_names[hpi_ctl->src_node_type], 1408719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_ctl->src_node_index, 1409e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dir, name); 1410719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1411ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett /* printk(KERN_INFO "Adding %s %d to %d ", hpi_ctl->name, 1412ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_ctl->wSrcNodeType, hpi_ctl->wDstNodeType); */ 1413719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1414719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1415719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 1416719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Volume controls 1417719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 1418719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define VOL_STEP_mB 1 1419719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_volume_info(struct snd_kcontrol *kcontrol, 1420719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 1421719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1422719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1423719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 err; 1424719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* native gains are in millibels */ 1425719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short min_gain_mB; 1426719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short max_gain_mB; 1427719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short step_gain_mB; 1428719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1429ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_volume_query_range(h_control, 1430719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &min_gain_mB, &max_gain_mB, &step_gain_mB); 1431719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) { 1432719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett max_gain_mB = 0; 1433719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett min_gain_mB = -10000; 1434719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett step_gain_mB = VOL_STEP_mB; 1435719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1436719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1437719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1438719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 2; 1439719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.min = min_gain_mB / VOL_STEP_mB; 1440719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.max = max_gain_mB / VOL_STEP_mB; 1441719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.step = step_gain_mB / VOL_STEP_mB; 1442719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1443719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1444719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1445719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_volume_get(struct snd_kcontrol *kcontrol, 1446719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1447719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1448719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1449719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short an_gain_mB[HPI_MAX_CHANNELS]; 1450719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1451ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_volume_get_gain(h_control, an_gain_mB)); 1452719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0] = an_gain_mB[0] / VOL_STEP_mB; 1453719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[1] = an_gain_mB[1] / VOL_STEP_mB; 1454719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1455719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1456719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1457719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1458719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_volume_put(struct snd_kcontrol *kcontrol, 1459719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1460719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1461719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int change; 1462719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1463719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short an_gain_mB[HPI_MAX_CHANNELS]; 1464719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1465719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett an_gain_mB[0] = 1466719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (ucontrol->value.integer.value[0]) * VOL_STEP_mB; 1467719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett an_gain_mB[1] = 1468719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (ucontrol->value.integer.value[1]) * VOL_STEP_mB; 1469719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* change = asihpi->mixer_volume[addr][0] != left || 1470719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->mixer_volume[addr][1] != right; 1471719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 1472719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett change = 1; 1473ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_volume_set_gain(h_control, an_gain_mB)); 1474719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return change; 1475719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1476719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1477719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic const DECLARE_TLV_DB_SCALE(db_scale_100, -10000, VOL_STEP_mB, 0); 1478719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1479719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_volume_add(struct snd_card_asihpi *asihpi, 1480719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl) 1481719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1482719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 1483719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_kcontrol_new snd_control; 1484719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1485e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Volume"); 1486719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | 1487719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_CTL_ELEM_ACCESS_TLV_READ; 1488719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_volume_info; 1489719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_volume_get; 1490719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_volume_put; 1491719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.tlv.p = db_scale_100; 1492719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1493719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ctl_add(card, &snd_control, asihpi); 1494719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1495719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1496719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 1497719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Level controls 1498719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 1499719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_level_info(struct snd_kcontrol *kcontrol, 1500719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 1501719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1502719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1503719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 err; 1504719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short min_gain_mB; 1505719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short max_gain_mB; 1506719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short step_gain_mB; 1507719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1508719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = 1509ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_level_query_range(h_control, &min_gain_mB, 1510719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &max_gain_mB, &step_gain_mB); 1511719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) { 1512719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett max_gain_mB = 2400; 1513719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett min_gain_mB = -1000; 1514719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett step_gain_mB = 100; 1515719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1516719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1517719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1518719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 2; 1519719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.min = min_gain_mB / HPI_UNITS_PER_dB; 1520719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.max = max_gain_mB / HPI_UNITS_PER_dB; 1521719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.step = step_gain_mB / HPI_UNITS_PER_dB; 1522719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1523719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1524719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1525719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_level_get(struct snd_kcontrol *kcontrol, 1526719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1527719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1528719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1529719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short an_gain_mB[HPI_MAX_CHANNELS]; 1530719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1531ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_level_get_gain(h_control, an_gain_mB)); 1532719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0] = 1533719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett an_gain_mB[0] / HPI_UNITS_PER_dB; 1534719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[1] = 1535719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett an_gain_mB[1] / HPI_UNITS_PER_dB; 1536719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1537719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1538719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1539719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1540719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_level_put(struct snd_kcontrol *kcontrol, 1541719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1542719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1543719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int change; 1544719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1545719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short an_gain_mB[HPI_MAX_CHANNELS]; 1546719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1547719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett an_gain_mB[0] = 1548719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (ucontrol->value.integer.value[0]) * HPI_UNITS_PER_dB; 1549719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett an_gain_mB[1] = 1550719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (ucontrol->value.integer.value[1]) * HPI_UNITS_PER_dB; 1551719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* change = asihpi->mixer_level[addr][0] != left || 1552719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->mixer_level[addr][1] != right; 1553719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 1554719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett change = 1; 1555ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_level_set_gain(h_control, an_gain_mB)); 1556719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return change; 1557719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1558719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1559719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic const DECLARE_TLV_DB_SCALE(db_scale_level, -1000, 100, 0); 1560719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1561719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_level_add(struct snd_card_asihpi *asihpi, 1562719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl) 1563719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1564719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 1565719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_kcontrol_new snd_control; 1566719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1567719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* can't use 'volume' cos some nodes have volume as well */ 1568e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Level"); 1569719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | 1570719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_CTL_ELEM_ACCESS_TLV_READ; 1571719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_level_info; 1572719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_level_get; 1573719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_level_put; 1574719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.tlv.p = db_scale_level; 1575719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1576719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ctl_add(card, &snd_control, asihpi); 1577719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1578719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1579719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 1580719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett AESEBU controls 1581719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 1582719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1583719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* AESEBU format */ 1584ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic const char * const asihpi_aesebu_format_names[] = { 1585ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett "N/A", "S/PDIF", "AES/EBU" }; 1586719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1587719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_aesebu_format_info(struct snd_kcontrol *kcontrol, 1588719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 1589719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1590719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1591719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 1592719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.items = 3; 1593719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1594719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 1595719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.item = 1596719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.items - 1; 1597719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1598719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett strcpy(uinfo->value.enumerated.name, 1599719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi_aesebu_format_names[uinfo->value.enumerated.item]); 1600719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1601719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1602719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1603719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1604719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_aesebu_format_get(struct snd_kcontrol *kcontrol, 1605719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol, 1606ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett u16 (*func)(u32, u16 *)) 1607719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1608719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1609719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 source, err; 1610719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1611ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = func(h_control, &source); 1612719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1613719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* default to N/A */ 1614719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = 0; 1615719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* return success but set the control to N/A */ 1616719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 1617719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1618719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (source == HPI_AESEBU_FORMAT_SPDIF) 1619719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = 1; 1620719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (source == HPI_AESEBU_FORMAT_AESEBU) 1621719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = 2; 1622719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1623719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1624719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1625719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1626719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_aesebu_format_put(struct snd_kcontrol *kcontrol, 1627719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol, 1628ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett u16 (*func)(u32, u16)) 1629719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1630719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1631719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1632719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* default to S/PDIF */ 1633719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 source = HPI_AESEBU_FORMAT_SPDIF; 1634719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1635719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (ucontrol->value.enumerated.item[0] == 1) 1636719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett source = HPI_AESEBU_FORMAT_SPDIF; 1637719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (ucontrol->value.enumerated.item[0] == 2) 1638719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett source = HPI_AESEBU_FORMAT_AESEBU; 1639719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1640ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (func(h_control, source) != 0) 1641719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 1642719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1643719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 1; 1644719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1645719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1646719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_aesebu_rx_format_get(struct snd_kcontrol *kcontrol, 1647719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) { 1648719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return snd_asihpi_aesebu_format_get(kcontrol, ucontrol, 1649ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_aesebu_receiver_get_format); 1650719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1651719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1652719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_aesebu_rx_format_put(struct snd_kcontrol *kcontrol, 1653719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) { 1654719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return snd_asihpi_aesebu_format_put(kcontrol, ucontrol, 1655ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_aesebu_receiver_set_format); 1656719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1657719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1658719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_aesebu_rxstatus_info(struct snd_kcontrol *kcontrol, 1659719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 1660719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1661719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1662719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 1663719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1664719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.min = 0; 1665719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.max = 0X1F; 1666719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.step = 1; 1667719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1668719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1669719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1670719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1671719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_aesebu_rxstatus_get(struct snd_kcontrol *kcontrol, 1672719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) { 1673719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1674719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1675719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 status; 1676719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1677ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_aesebu_receiver_get_error_status( 1678ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett h_control, &status)); 1679719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0] = status; 1680719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1681719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1682719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1683719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi, 1684719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl) 1685719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1686719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 1687719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_kcontrol_new snd_control; 1688719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1689e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Format"); 1690719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; 1691719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_aesebu_format_info; 1692719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_aesebu_rx_format_get; 1693719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_aesebu_rx_format_put; 1694719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1695719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1696719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (ctl_add(card, &snd_control, asihpi) < 0) 1697719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 1698719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1699e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Status"); 1700719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = 1701719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; 1702719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_aesebu_rxstatus_info; 1703719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_aesebu_rxstatus_get; 1704719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1705719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ctl_add(card, &snd_control, asihpi); 1706719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1707719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1708719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_aesebu_tx_format_get(struct snd_kcontrol *kcontrol, 1709719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) { 1710719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return snd_asihpi_aesebu_format_get(kcontrol, ucontrol, 1711ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_aesebu_transmitter_get_format); 1712719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1713719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1714719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_aesebu_tx_format_put(struct snd_kcontrol *kcontrol, 1715719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) { 1716719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return snd_asihpi_aesebu_format_put(kcontrol, ucontrol, 1717ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_aesebu_transmitter_set_format); 1718719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1719719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1720719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1721719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_aesebu_tx_add(struct snd_card_asihpi *asihpi, 1722719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl) 1723719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1724719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 1725719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_kcontrol_new snd_control; 1726719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1727e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Format"); 1728719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; 1729719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_aesebu_format_info; 1730719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_aesebu_tx_format_get; 1731719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_aesebu_tx_format_put; 1732719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1733719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ctl_add(card, &snd_control, asihpi); 1734719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1735719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1736719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 1737719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Tuner controls 1738719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 1739719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1740719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* Gain */ 1741719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1742719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_tuner_gain_info(struct snd_kcontrol *kcontrol, 1743719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 1744719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1745719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1746719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 err; 1747719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short idx; 1748719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 gain_range[3]; 1749719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1750719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (idx = 0; idx < 3; idx++) { 1751ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_tuner_query_gain(h_control, 1752719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett idx, &gain_range[idx]); 1753719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err != 0) 1754719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 1755719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1756719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1757719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1758719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 1759719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.min = ((int)gain_range[0]) / HPI_UNITS_PER_dB; 1760719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.max = ((int)gain_range[1]) / HPI_UNITS_PER_dB; 1761719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.step = ((int) gain_range[2]) / HPI_UNITS_PER_dB; 1762719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1763719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1764719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1765719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_tuner_gain_get(struct snd_kcontrol *kcontrol, 1766719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1767719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1768719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* 1769719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol); 1770719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 1771719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1772719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short gain; 1773719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1774ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_tuner_get_gain(h_control, &gain)); 1775719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0] = gain / HPI_UNITS_PER_dB; 1776719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1777719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1778719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1779719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1780719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_tuner_gain_put(struct snd_kcontrol *kcontrol, 1781719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1782719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1783719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* 1784719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol); 1785719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 1786719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1787719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short gain; 1788719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1789719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett gain = (ucontrol->value.integer.value[0]) * HPI_UNITS_PER_dB; 1790ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_tuner_set_gain(h_control, gain)); 1791719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1792719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 1; 1793719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1794719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1795719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* Band */ 1796719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1797719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int asihpi_tuner_band_query(struct snd_kcontrol *kcontrol, 1798719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 *band_list, u32 len) { 1799719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1800719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 err = 0; 1801719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 i; 1802719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1803719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (i = 0; i < len; i++) { 1804ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_tuner_query_band( 1805719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett h_control, i, &band_list[i]); 1806719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err != 0) 1807719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 1808719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1809719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1810719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err && (err != HPI_ERROR_INVALID_OBJ_INDEX)) 1811719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EIO; 1812719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1813719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return i; 1814719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1815719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1816719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_tuner_band_info(struct snd_kcontrol *kcontrol, 1817719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 1818719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1819719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 tuner_bands[HPI_TUNER_BAND_LAST]; 1820719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int num_bands = 0; 1821719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1822719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands, 1823719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_TUNER_BAND_LAST); 1824719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1825719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (num_bands < 0) 1826719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return num_bands; 1827719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1828719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1829719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 1830719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.items = num_bands; 1831719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1832719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (num_bands > 0) { 1833719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (uinfo->value.enumerated.item >= 1834719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.items) 1835719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.item = 1836719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.items - 1; 1837719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1838719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett strcpy(uinfo->value.enumerated.name, 1839719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi_tuner_band_names[ 1840719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett tuner_bands[uinfo->value.enumerated.item]]); 1841719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1842719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1843719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1844719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1845719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1846719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_tuner_band_get(struct snd_kcontrol *kcontrol, 1847719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1848719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1849719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1850719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* 1851719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol); 1852719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 1853719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 band, idx; 1854719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 tuner_bands[HPI_TUNER_BAND_LAST]; 1855719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 num_bands = 0; 1856719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1857719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands, 1858719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_TUNER_BAND_LAST); 1859719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1860ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_tuner_get_band(h_control, &band)); 1861719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1862719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = -1; 1863719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (idx = 0; idx < HPI_TUNER_BAND_LAST; idx++) 1864719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (tuner_bands[idx] == band) { 1865719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = idx; 1866719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 1867719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1868719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1869719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1870719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1871719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1872719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_tuner_band_put(struct snd_kcontrol *kcontrol, 1873719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1874719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1875719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* 1876719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol); 1877719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 1878719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1879719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 band; 1880719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 tuner_bands[HPI_TUNER_BAND_LAST]; 1881719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 num_bands = 0; 1882719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1883719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands, 1884719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_TUNER_BAND_LAST); 1885719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1886719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett band = tuner_bands[ucontrol->value.enumerated.item[0]]; 1887ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_tuner_set_band(h_control, band)); 1888719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1889719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 1; 1890719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1891719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1892719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* Freq */ 1893719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1894719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_tuner_freq_info(struct snd_kcontrol *kcontrol, 1895719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 1896719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1897719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1898719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 err; 1899719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 tuner_bands[HPI_TUNER_BAND_LAST]; 1900719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 num_bands = 0, band_iter, idx; 1901719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 freq_range[3], temp_freq_range[3]; 1902719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1903719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands, 1904719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_TUNER_BAND_LAST); 1905719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1906719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett freq_range[0] = INT_MAX; 1907719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett freq_range[1] = 0; 1908719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett freq_range[2] = INT_MAX; 1909719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1910719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (band_iter = 0; band_iter < num_bands; band_iter++) { 1911719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (idx = 0; idx < 3; idx++) { 1912ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_tuner_query_frequency(h_control, 1913719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett idx, tuner_bands[band_iter], 1914719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &temp_freq_range[idx]); 1915719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err != 0) 1916719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 1917719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1918719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1919719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* skip band with bogus stepping */ 1920719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (temp_freq_range[2] <= 0) 1921719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett continue; 1922719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1923719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (temp_freq_range[0] < freq_range[0]) 1924719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett freq_range[0] = temp_freq_range[0]; 1925719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (temp_freq_range[1] > freq_range[1]) 1926719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett freq_range[1] = temp_freq_range[1]; 1927719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (temp_freq_range[2] < freq_range[2]) 1928719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett freq_range[2] = temp_freq_range[2]; 1929719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1930719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1931719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1932719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 1933719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.min = ((int)freq_range[0]); 1934719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.max = ((int)freq_range[1]); 1935719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.step = ((int)freq_range[2]); 1936719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1937719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1938719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1939719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_tuner_freq_get(struct snd_kcontrol *kcontrol, 1940719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1941719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1942719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1943719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 freq; 1944719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1945ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_tuner_get_frequency(h_control, &freq)); 1946719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0] = freq; 1947719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1948719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1949719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1950719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1951719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_tuner_freq_put(struct snd_kcontrol *kcontrol, 1952719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1953719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1954719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1955719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 freq; 1956719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1957719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett freq = ucontrol->value.integer.value[0]; 1958ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_tuner_set_frequency(h_control, freq)); 1959719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1960719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 1; 1961719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1962719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1963719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* Tuner control group initializer */ 1964719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi, 1965719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl) 1966719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1967719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 1968719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_kcontrol_new snd_control; 1969719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1970719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.private_value = hpi_ctl->h_control; 1971719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; 1972719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1973ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (!hpi_tuner_get_gain(hpi_ctl->h_control, NULL)) { 1974e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Gain"); 1975719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_tuner_gain_info; 1976719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_tuner_gain_get; 1977719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_tuner_gain_put; 1978719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1979719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (ctl_add(card, &snd_control, asihpi) < 0) 1980719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 1981719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1982719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1983e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Band"); 1984719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_tuner_band_info; 1985719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_tuner_band_get; 1986719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_tuner_band_put; 1987719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1988719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (ctl_add(card, &snd_control, asihpi) < 0) 1989719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 1990719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1991e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Freq"); 1992719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_tuner_freq_info; 1993719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_tuner_freq_get; 1994719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_tuner_freq_put; 1995719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1996719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ctl_add(card, &snd_control, asihpi); 1997719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1998719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1999719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 2000719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Meter controls 2001719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 2002719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_meter_info(struct snd_kcontrol *kcontrol, 2003719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 2004719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2005719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 2006719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = HPI_MAX_CHANNELS; 2007719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.min = 0; 2008719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.max = 0x7FFFFFFF; 2009719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2010719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2011719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2012719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* linear values for 10dB steps */ 2013719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int log2lin[] = { 2014719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 0x7FFFFFFF, /* 0dB */ 2015719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 679093956, 2016719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 214748365, 2017719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 67909396, 2018719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 21474837, 2019719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 6790940, 2020719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2147484, /* -60dB */ 2021719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 679094, 2022719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 214748, /* -80 */ 2023719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 67909, 2024719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 21475, /* -100 */ 2025719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 6791, 2026719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2147, 2027719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 679, 2028719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 214, 2029719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 68, 2030719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 21, 2031719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 7, 2032719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2 2033719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 2034719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2035719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_meter_get(struct snd_kcontrol *kcontrol, 2036719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2037719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2038719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2039719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short an_gain_mB[HPI_MAX_CHANNELS], i; 2040719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 err; 2041719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2042ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_meter_get_peak(h_control, an_gain_mB); 2043719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2044719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (i = 0; i < HPI_MAX_CHANNELS; i++) { 2045719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) { 2046719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[i] = 0; 2047719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else if (an_gain_mB[i] >= 0) { 2048719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[i] = 2049719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett an_gain_mB[i] << 16; 2050719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else { 2051719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* -ve is log value in millibels < -60dB, 2052719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * convert to (roughly!) linear, 2053719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 2054719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[i] = 2055719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett log2lin[an_gain_mB[i] / -1000]; 2056719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2057719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2058719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2059719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2060719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2061719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_meter_add(struct snd_card_asihpi *asihpi, 2062719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl, int subidx) 2063719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2064719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 2065719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_kcontrol_new snd_control; 2066719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2067e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Meter"); 2068719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = 2069719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; 2070719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_meter_info; 2071719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_meter_get; 2072719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2073719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.index = subidx; 2074719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2075719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ctl_add(card, &snd_control, asihpi); 2076719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2077719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2078719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 2079719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Multiplexer controls 2080719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 2081719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_mux_count_sources(struct snd_kcontrol *snd_control) 2082719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2083719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = snd_control->private_value; 2084719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control hpi_ctl; 2085719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int s, err; 2086719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (s = 0; s < 32; s++) { 2087ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_multiplexer_query_source(h_control, s, 2088719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_ctl. 2089719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett src_node_type, 2090719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_ctl. 2091719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett src_node_index); 2092719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 2093719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2094719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2095719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return s; 2096719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2097719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2098719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_mux_info(struct snd_kcontrol *kcontrol, 2099719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 2100719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2101719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 2102719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 src_node_type, src_node_index; 2103719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2104719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2105719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2106719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 2107719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.items = 2108719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_mux_count_sources(kcontrol); 2109719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2110719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 2111719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.item = 2112719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.items - 1; 2113719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2114719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = 2115ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_multiplexer_query_source(h_control, 2116719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.item, 2117719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &src_node_type, &src_node_index); 2118719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2119719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett sprintf(uinfo->value.enumerated.name, "%s %d", 2120168f1b07ccc0e8edecb67fab2d0670861853e2fdEliot Blennerhassett asihpi_src_names[src_node_type - HPI_SOURCENODE_NONE], 2121719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett src_node_index); 2122719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2123719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2124719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2125719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_mux_get(struct snd_kcontrol *kcontrol, 2126719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2127719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2128719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2129719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 source_type, source_index; 2130719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 src_node_type, src_node_index; 2131719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int s; 2132719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2133ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_multiplexer_get_source(h_control, 2134719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &source_type, &source_index)); 2135719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* Should cache this search result! */ 2136719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (s = 0; s < 256; s++) { 2137ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (hpi_multiplexer_query_source(h_control, s, 2138719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &src_node_type, &src_node_index)) 2139719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2140719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2141719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if ((source_type == src_node_type) 2142719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett && (source_index == src_node_index)) { 2143719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = s; 2144719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2145719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2146719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2147719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printd(KERN_WARNING 2148e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Control %x failed to match mux source %hu %hu\n", 2149719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett h_control, source_type, source_index); 2150719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = 0; 2151719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2152719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2153719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2154719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_mux_put(struct snd_kcontrol *kcontrol, 2155719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2156719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2157719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int change; 2158719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2159719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 source_type, source_index; 2160719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 e; 2161719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2162719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett change = 1; 2163719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2164ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett e = hpi_multiplexer_query_source(h_control, 2165719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0], 2166719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &source_type, &source_index); 2167719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!e) 2168719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error( 2169ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_multiplexer_set_source(h_control, 2170719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett source_type, source_index)); 2171719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return change; 2172719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2173719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2174719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2175719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_mux_add(struct snd_card_asihpi *asihpi, 2176719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl) 2177719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2178719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 2179719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_kcontrol_new snd_control; 2180719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2181e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Route"); 2182719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; 2183719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_mux_info; 2184719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_mux_get; 2185719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_mux_put; 2186719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2187719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ctl_add(card, &snd_control, asihpi); 2188719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2189719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2190719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2191719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 2192719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Channel mode controls 2193719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 2194719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_cmode_info(struct snd_kcontrol *kcontrol, 2195719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 2196719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2197e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett static const char * const mode_names[HPI_CHANNEL_MODE_LAST + 1] = { 2198e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "invalid", 2199e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Normal", "Swap", 2200e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "From Left", "From Right", 2201e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "To Left", "To Right" 2202719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett }; 2203719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2204719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2205719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 mode; 2206719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int i; 2207e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett u16 mode_map[6]; 2208e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett int valid_modes = 0; 2209719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2210719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* HPI channel mode values can be from 1 to 6 2211719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Some adapters only support a contiguous subset 2212719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 2213719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (i = 0; i < HPI_CHANNEL_MODE_LAST; i++) 2214e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett if (!hpi_channel_mode_query_mode( 2215ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett h_control, i, &mode)) { 2216e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett mode_map[valid_modes] = mode; 2217e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett valid_modes++; 2218e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett } 2219719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2220719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2221719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 2222e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett uinfo->value.enumerated.items = valid_modes; 2223719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2224e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett if (uinfo->value.enumerated.item >= valid_modes) 2225e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett uinfo->value.enumerated.item = valid_modes - 1; 2226719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2227719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett strcpy(uinfo->value.enumerated.name, 2228e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett mode_names[mode_map[uinfo->value.enumerated.item]]); 2229719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2230719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2231719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2232719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2233719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_cmode_get(struct snd_kcontrol *kcontrol, 2234719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2235719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2236719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2237719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 mode; 2238719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2239ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (hpi_channel_mode_get(h_control, &mode)) 2240719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett mode = 1; 2241719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2242719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = mode - 1; 2243719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2244719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2245719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2246719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2247719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_cmode_put(struct snd_kcontrol *kcontrol, 2248719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2249719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2250719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int change; 2251719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2252719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2253719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett change = 1; 2254719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2255ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_channel_mode_set(h_control, 2256719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] + 1)); 2257719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return change; 2258719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2259719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2260719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2261719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_cmode_add(struct snd_card_asihpi *asihpi, 2262719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl) 2263719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2264719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 2265719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_kcontrol_new snd_control; 2266719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2267e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Mode"); 2268719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; 2269719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_cmode_info; 2270719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_cmode_get; 2271719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_cmode_put; 2272719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2273719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ctl_add(card, &snd_control, asihpi); 2274719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2275719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2276719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 2277719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Sampleclock source controls 2278719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 2279ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic char *sampleclock_sources[MAX_CLOCKSOURCES] = { 2280ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett "N/A", "Local PLL", "Digital Sync", "Word External", "Word Header", 2281ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett "SMPTE", "Digital1", "Auto", "Network", "Invalid", 2282ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett "Prev Module", 2283ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett "Digital2", "Digital3", "Digital4", "Digital5", 2284ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett "Digital6", "Digital7", "Digital8"}; 2285719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2286719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_clksrc_info(struct snd_kcontrol *kcontrol, 2287719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 2288719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2289719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi = 2290719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (struct snd_card_asihpi *)(kcontrol->private_data); 2291719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct clk_cache *clkcache = &asihpi->cc; 2292719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2293719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 2294719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.items = clkcache->count; 2295719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2296719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 2297719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.item = 2298719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.items - 1; 2299719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2300719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett strcpy(uinfo->value.enumerated.name, 2301719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->s[uinfo->value.enumerated.item].name); 2302719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2303719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2304719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2305719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_clksrc_get(struct snd_kcontrol *kcontrol, 2306719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2307719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2308719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi = 2309719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (struct snd_card_asihpi *)(kcontrol->private_data); 2310719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct clk_cache *clkcache = &asihpi->cc; 2311719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2312719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 source, srcindex = 0; 2313719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int i; 2314719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2315719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = 0; 2316ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (hpi_sample_clock_get_source(h_control, &source)) 2317719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett source = 0; 2318719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2319719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT) 2320ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (hpi_sample_clock_get_source_index(h_control, &srcindex)) 2321719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett srcindex = 0; 2322719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2323719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (i = 0; i < clkcache->count; i++) 2324719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if ((clkcache->s[i].source == source) && 2325719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (clkcache->s[i].index == srcindex)) 2326719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2327719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2328719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = i; 2329719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2330719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2331719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2332719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2333719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_clksrc_put(struct snd_kcontrol *kcontrol, 2334719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2335719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2336719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi = 2337719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (struct snd_card_asihpi *)(kcontrol->private_data); 2338719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct clk_cache *clkcache = &asihpi->cc; 2339719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int change, item; 2340719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2341719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2342719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett change = 1; 2343719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett item = ucontrol->value.enumerated.item[0]; 2344719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (item >= clkcache->count) 2345719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett item = clkcache->count-1; 2346719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2347ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_sample_clock_set_source( 2348719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett h_control, clkcache->s[item].source)); 2349719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2350719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (clkcache->s[item].source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT) 2351ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_sample_clock_set_source_index( 2352719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett h_control, clkcache->s[item].index)); 2353719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return change; 2354719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2355719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2356719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 2357719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Clkrate controls 2358719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 2359719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* Need to change this to enumerated control with list of rates */ 2360719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_clklocal_info(struct snd_kcontrol *kcontrol, 2361719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 2362719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2363719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 2364719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 2365719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.min = 8000; 2366719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.max = 192000; 2367719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.step = 100; 2368719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2369719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2370719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2371719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2372719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_clklocal_get(struct snd_kcontrol *kcontrol, 2373719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2374719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2375719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2376719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 rate; 2377719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 e; 2378719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2379ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett e = hpi_sample_clock_get_local_rate(h_control, &rate); 2380719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!e) 2381719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0] = rate; 2382719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 2383719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0] = 0; 2384719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2385719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2386719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2387719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_clklocal_put(struct snd_kcontrol *kcontrol, 2388719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2389719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2390719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int change; 2391719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2392719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2393719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* change = asihpi->mixer_clkrate[addr][0] != left || 2394719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->mixer_clkrate[addr][1] != right; 2395719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 2396719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett change = 1; 2397ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_sample_clock_set_local_rate(h_control, 2398719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0])); 2399719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return change; 2400719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2401719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2402719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_clkrate_info(struct snd_kcontrol *kcontrol, 2403719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 2404719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2405719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 2406719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 2407719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.min = 8000; 2408719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.max = 192000; 2409719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.step = 100; 2410719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2411719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2412719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2413719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2414719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_clkrate_get(struct snd_kcontrol *kcontrol, 2415719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2416719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2417719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2418719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 rate; 2419719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 e; 2420719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2421ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett e = hpi_sample_clock_get_sample_rate(h_control, &rate); 2422719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!e) 2423719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0] = rate; 2424719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 2425719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0] = 0; 2426719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2427719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2428719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2429719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi, 2430719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl) 2431719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2432719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 2433719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_kcontrol_new snd_control; 2434719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2435719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct clk_cache *clkcache = &asihpi->cc; 2436719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 hSC = hpi_ctl->h_control; 2437719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int has_aes_in = 0; 2438719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int i, j; 2439719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 source; 2440719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2441719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.private_value = hpi_ctl->h_control; 2442719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2443719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->has_local = 0; 2444719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2445719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (i = 0; i <= HPI_SAMPLECLOCK_SOURCE_LAST; i++) { 2446ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (hpi_sample_clock_query_source(hSC, 2447719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett i, &source)) 2448719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2449719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->s[i].source = source; 2450719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->s[i].index = 0; 2451719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->s[i].name = sampleclock_sources[source]; 2452719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT) 2453719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett has_aes_in = 1; 2454719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (source == HPI_SAMPLECLOCK_SOURCE_LOCAL) 2455719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->has_local = 1; 2456719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2457719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (has_aes_in) 2458719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* already will have picked up index 0 above */ 2459719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (j = 1; j < 8; j++) { 2460ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (hpi_sample_clock_query_source_index(hSC, 2461719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett j, HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT, 2462719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &source)) 2463719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2464719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->s[i].source = 2465719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT; 2466719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->s[i].index = j; 2467719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->s[i].name = sampleclock_sources[ 2468719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett j+HPI_SAMPLECLOCK_SOURCE_LAST]; 2469719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett i++; 2470719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2471719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->count = i; 2472719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2473e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Source"); 2474719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ; 2475719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_clksrc_info; 2476719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_clksrc_get; 2477719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_clksrc_put; 2478719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (ctl_add(card, &snd_control, asihpi) < 0) 2479719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 2480719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2481719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2482719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (clkcache->has_local) { 2483e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Localrate"); 2484719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ; 2485719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_clklocal_info; 2486719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_clklocal_get; 2487719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_clklocal_put; 2488719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2489719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2490719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (ctl_add(card, &snd_control, asihpi) < 0) 2491719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 2492719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2493719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2494e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Rate"); 2495719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = 2496719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; 2497719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_clkrate_info; 2498719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_clkrate_get; 2499719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2500719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ctl_add(card, &snd_control, asihpi); 2501719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2502719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 2503719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Mixer 2504719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 2505719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2506719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi) 2507719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2508719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 2509719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int idx = 0; 2510719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int subindex = 0; 2511719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 2512719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control hpi_ctl, prev_ctl; 2513719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2514719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (snd_BUG_ON(!asihpi)) 2515719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 2516e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett strcpy(card->mixername, "Asihpi Mixer"); 2517719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2518719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = 2519ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_mixer_open(asihpi->adapter_index, 2520719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &asihpi->h_mixer); 2521719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error(err); 2522719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 2523719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -err; 2524719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 252521896bc010c17e5ac58951e771496ec2fb1051edTakashi Iwai memset(&prev_ctl, 0, sizeof(prev_ctl)); 252621896bc010c17e5ac58951e771496ec2fb1051edTakashi Iwai prev_ctl.control_type = -1; 252721896bc010c17e5ac58951e771496ec2fb1051edTakashi Iwai 2528719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (idx = 0; idx < 2000; idx++) { 2529719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = hpi_mixer_get_control_by_index( 2530ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett asihpi->h_mixer, 2531719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett idx, 2532719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_ctl.src_node_type, 2533719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_ctl.src_node_index, 2534719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_ctl.dst_node_type, 2535719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_ctl.dst_node_index, 2536719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_ctl.control_type, 2537719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_ctl.h_control); 2538719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) { 2539719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err == HPI_ERROR_CONTROL_DISABLED) { 2540719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (mixer_dump) 2541719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_INFO 2542e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Disabled HPI Control(%d)\n", 2543719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett idx); 2544719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett continue; 2545719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else 2546719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2547719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2548719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2549719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2550168f1b07ccc0e8edecb67fab2d0670861853e2fdEliot Blennerhassett hpi_ctl.src_node_type -= HPI_SOURCENODE_NONE; 2551168f1b07ccc0e8edecb67fab2d0670861853e2fdEliot Blennerhassett hpi_ctl.dst_node_type -= HPI_DESTNODE_NONE; 2552719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2553719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* ASI50xx in SSX mode has multiple meters on the same node. 2554719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Use subindex to create distinct ALSA controls 2555719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for any duplicated controls. 2556719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 2557719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if ((hpi_ctl.control_type == prev_ctl.control_type) && 2558719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (hpi_ctl.src_node_type == prev_ctl.src_node_type) && 2559719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (hpi_ctl.src_node_index == prev_ctl.src_node_index) && 2560719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (hpi_ctl.dst_node_type == prev_ctl.dst_node_type) && 2561719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (hpi_ctl.dst_node_index == prev_ctl.dst_node_index)) 2562719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett subindex++; 2563719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 2564719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett subindex = 0; 2565719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2566719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett prev_ctl = hpi_ctl; 2567719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2568719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett switch (hpi_ctl.control_type) { 2569719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_VOLUME: 2570719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_asihpi_volume_add(asihpi, &hpi_ctl); 2571719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2572719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_LEVEL: 2573719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_asihpi_level_add(asihpi, &hpi_ctl); 2574719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2575719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_MULTIPLEXER: 2576719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_asihpi_mux_add(asihpi, &hpi_ctl); 2577719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2578719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_CHANNEL_MODE: 2579719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_asihpi_cmode_add(asihpi, &hpi_ctl); 2580719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2581719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_METER: 2582719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_asihpi_meter_add(asihpi, &hpi_ctl, subindex); 2583719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2584719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_SAMPLECLOCK: 2585719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_asihpi_sampleclock_add( 2586719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi, &hpi_ctl); 2587719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2588719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_CONNECTION: /* ignore these */ 2589719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett continue; 2590719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_TUNER: 2591719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_asihpi_tuner_add(asihpi, &hpi_ctl); 2592719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2593719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_AESEBU_TRANSMITTER: 2594719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_asihpi_aesebu_tx_add(asihpi, &hpi_ctl); 2595719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2596719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_AESEBU_RECEIVER: 2597719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_asihpi_aesebu_rx_add(asihpi, &hpi_ctl); 2598719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2599719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_VOX: 2600719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_BITSTREAM: 2601719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_MICROPHONE: 2602719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_PARAMETRIC_EQ: 2603719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_COMPANDER: 2604719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett default: 2605719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (mixer_dump) 2606719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_INFO 2607e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Untranslated HPI Control" 2608719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "(%d) %d %d %d %d %d\n", 2609719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett idx, 2610719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_ctl.control_type, 2611719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_ctl.src_node_type, 2612719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_ctl.src_node_index, 2613719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_ctl.dst_node_type, 2614719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_ctl.dst_node_index); 2615719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett continue; 2616719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett }; 2617719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) 2618719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 2619719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2620719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (HPI_ERROR_INVALID_OBJ_INDEX != err) 2621719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error(err); 2622719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2623719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_INFO "%d mixer controls found\n", idx); 2624719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2625719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2626719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2627719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2628719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 2629719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /proc interface 2630719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 2631719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2632719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void 2633719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettsnd_asihpi_proc_read(struct snd_info_entry *entry, 2634719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_info_buffer *buffer) 2635719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2636719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi = entry->private_data; 2637719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 version; 2638719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control; 2639719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 rate = 0; 2640719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 source = 0; 2641719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 2642719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2643719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_iprintf(buffer, "ASIHPI driver proc file\n"); 2644719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_iprintf(buffer, 2645719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "adapter ID=%4X\n_index=%d\n" 2646719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "num_outstreams=%d\n_num_instreams=%d\n", 2647719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->type, asihpi->adapter_index, 2648719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->num_outstreams, asihpi->num_instreams); 2649719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2650719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett version = asihpi->version; 2651719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_iprintf(buffer, 2652719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "serial#=%d\n_hw version %c%d\nDSP code version %03d\n", 2653719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->serial_number, ((version >> 3) & 0xf) + 'A', 2654719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett version & 0x7, 2655719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ((version >> 13) * 100) + ((version >> 7) & 0x3f)); 2656719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2657ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_mixer_get_control(asihpi->h_mixer, 2658719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, 2659719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_CONTROL_SAMPLECLOCK, &h_control); 2660719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2661719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err) { 2662ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_sample_clock_get_sample_rate( 2663719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett h_control, &rate); 2664ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err += hpi_sample_clock_get_source(h_control, &source); 2665719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2666719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err) 2667719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_iprintf(buffer, "sample_clock=%d_hz, source %s\n", 2668719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rate, sampleclock_sources[source]); 2669719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2670719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2671719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2672719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2673719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2674719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void __devinit snd_asihpi_proc_init(struct snd_card_asihpi *asihpi) 2675719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2676719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_info_entry *entry; 2677719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2678719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!snd_card_proc_new(asihpi->card, "info", &entry)) 2679719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_info_set_text_ops(entry, asihpi, snd_asihpi_proc_read); 2680719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2681719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2682719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 2683719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HWDEP 2684719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 2685719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2686719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_hpi_open(struct snd_hwdep *hw, struct file *file) 2687719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2688719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (enable_hpi_hwdep) 2689719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2690719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 2691719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -ENODEV; 2692719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2693719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2694719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2695719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_hpi_release(struct snd_hwdep *hw, struct file *file) 2696719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2697719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (enable_hpi_hwdep) 2698719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return asihpi_hpi_release(file); 2699719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 2700719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -ENODEV; 2701719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2702719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2703719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_hpi_ioctl(struct snd_hwdep *hw, struct file *file, 2704719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int cmd, unsigned long arg) 2705719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2706719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (enable_hpi_hwdep) 2707719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return asihpi_hpi_ioctl(file, cmd, arg); 2708719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 2709719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -ENODEV; 2710719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2711719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2712719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2713719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* results in /dev/snd/hwC#D0 file for each card with index # 2714719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett also /proc/asound/hwdep will contain '#-00: asihpi (HPI) for each card' 2715719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett*/ 2716719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi, 2717719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int device, struct snd_hwdep **rhwdep) 2718719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2719719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_hwdep *hw; 2720719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 2721719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2722719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (rhwdep) 2723719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett *rhwdep = NULL; 2724719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_hwdep_new(asihpi->card, "HPI", device, &hw); 2725719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) 2726719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 2727719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett strcpy(hw->name, "asihpi (HPI)"); 2728719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hw->iface = SNDRV_HWDEP_IFACE_LAST; 2729719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hw->ops.open = snd_asihpi_hpi_open; 2730719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hw->ops.ioctl = snd_asihpi_hpi_ioctl; 2731719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hw->ops.release = snd_asihpi_hpi_release; 2732719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hw->private_data = asihpi; 2733719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (rhwdep) 2734719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett *rhwdep = hw; 2735719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2736719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2737719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2738719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 2739719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett CARD 2740719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 2741719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_probe(struct pci_dev *pci_dev, 2742719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett const struct pci_device_id *pci_id) 2743719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2744719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 2745719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2746719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 version; 2747719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int pcm_substreams; 2748719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2749719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_adapter *hpi_card; 2750719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card; 2751719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi; 2752719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2753719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control; 2754719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_stream; 2755719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2756719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett static int dev; 2757719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (dev >= SNDRV_CARDS) 2758719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -ENODEV; 2759719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2760719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* Should this be enable[hpi_card->index] ? */ 2761719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!enable[dev]) { 2762719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dev++; 2763719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -ENOENT; 2764719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2765719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2766719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = asihpi_adapter_probe(pci_dev, pci_id); 2767719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) 2768719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 2769719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2770719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_card = pci_get_drvdata(pci_dev); 2771719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* first try to give the card the same index as its hardware index */ 2772719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_card_create(hpi_card->index, 2773719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett id[hpi_card->index], THIS_MODULE, 2774719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett sizeof(struct snd_card_asihpi), 2775719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &card); 2776719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) { 2777719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* if that fails, try the default index==next available */ 2778719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = 2779719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_create(index[dev], id[dev], 2780719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett THIS_MODULE, 2781719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett sizeof(struct snd_card_asihpi), 2782719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &card); 2783719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) 2784719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 2785719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_WARNING 2786e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "**** WARNING **** Adapter index %d->ALSA index %d\n", 2787719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_card->index, card->number); 2788719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2789719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 27901225367a481ae751738630158c7ca96aa1c7bac8Eliot Blennerhassett snd_card_set_dev(card, &pci_dev->dev); 27911225367a481ae751738630158c7ca96aa1c7bac8Eliot Blennerhassett 2792719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi = (struct snd_card_asihpi *) card->private_data; 2793719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->card = card; 27941225367a481ae751738630158c7ca96aa1c7bac8Eliot Blennerhassett asihpi->pci = pci_dev; 2795719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->adapter_index = hpi_card->index; 2796ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_adapter_get_info( 2797719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->adapter_index, 2798719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &asihpi->num_outstreams, 2799719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &asihpi->num_instreams, 2800719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &asihpi->version, 2801719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &asihpi->serial_number, &asihpi->type)); 2802719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2803719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett version = asihpi->version; 2804719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_INFO "adapter ID=%4X index=%d num_outstreams=%d " 2805719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "num_instreams=%d S/N=%d\n" 2806e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Hw Version %c%d DSP code version %03d\n", 2807719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->type, asihpi->adapter_index, 2808719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->num_outstreams, 2809719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->num_instreams, asihpi->serial_number, 2810719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ((version >> 3) & 0xf) + 'A', 2811719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett version & 0x7, 2812719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ((version >> 13) * 100) + ((version >> 7) & 0x3f)); 2813719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2814719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pcm_substreams = asihpi->num_outstreams; 2815719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (pcm_substreams < asihpi->num_instreams) 2816719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pcm_substreams = asihpi->num_instreams; 2817719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2818ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_adapter_get_property(asihpi->adapter_index, 2819719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_ADAPTER_PROPERTY_CAPS1, 2820719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett NULL, &asihpi->support_grouping); 2821719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 2822719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->support_grouping = 0; 2823719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2824ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_adapter_get_property(asihpi->adapter_index, 2825719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_ADAPTER_PROPERTY_CAPS2, 2826719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &asihpi->support_mrx, NULL); 2827719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 2828719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->support_mrx = 0; 2829719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2830ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_adapter_get_property(asihpi->adapter_index, 2831719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_ADAPTER_PROPERTY_INTERVAL, 2832719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett NULL, &asihpi->update_interval_frames); 2833719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 2834719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->update_interval_frames = 512; 2835719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2836f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett if (!asihpi->can_dma) 283726aebef420f8036213419b8a46e3a07db51439cdEliot Blennerhassett asihpi->update_interval_frames *= 2; 283826aebef420f8036213419b8a46e3a07db51439cdEliot Blennerhassett 2839ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_instream_open(asihpi->adapter_index, 2840719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 0, &h_stream)); 2841719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2842ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_instream_host_buffer_free(h_stream); 2843f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett asihpi->can_dma = (!err); 2844719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2845ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_instream_close(h_stream)); 2846719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2847ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_adapter_get_property(asihpi->adapter_index, 2848719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_ADAPTER_PROPERTY_CURCHANNELS, 2849719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &asihpi->in_max_chans, &asihpi->out_max_chans); 2850719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) { 2851719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->in_max_chans = 2; 2852719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->out_max_chans = 2; 2853719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2854719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2855f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett snd_printk(KERN_INFO "has dma:%d, grouping:%d, mrx:%d\n", 2856f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett asihpi->can_dma, 2857719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->support_grouping, 2858719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->support_mrx 2859719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ); 2860719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2861719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_card_asihpi_pcm_new(asihpi, 0, pcm_substreams); 2862719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) { 2863719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_ERR "pcm_new failed\n"); 2864719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett goto __nodev; 2865719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2866719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_card_asihpi_mixer_new(asihpi); 2867719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) { 2868719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_ERR "mixer_new failed\n"); 2869719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett goto __nodev; 2870719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2871719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2872ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_mixer_get_control(asihpi->h_mixer, 2873719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, 2874719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_CONTROL_SAMPLECLOCK, &h_control); 2875719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2876719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err) 2877719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = hpi_sample_clock_set_local_rate( 2878ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett h_control, adapter_fs); 2879719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2880719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_asihpi_proc_init(asihpi); 2881719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2882719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* always create, can be enabled or disabled dynamically 2883719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett by enable_hwdep module param*/ 2884719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_asihpi_hpi_new(asihpi, 0, NULL); 2885719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2886f3d145aac913b318e96e5c2763d8908805a5e30aEliot Blennerhassett strcpy(card->driver, "ASIHPI"); 2887719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2888719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett sprintf(card->shortname, "AudioScience ASI%4X", asihpi->type); 2889719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett sprintf(card->longname, "%s %i", 2890719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett card->shortname, asihpi->adapter_index); 2891719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_card_register(card); 2892b2e65c8e9133218eb28c30e79ddd3d66d4666ba0Eliot Blennerhassett 2893719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err) { 2894719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_card->snd_card_asihpi = card; 2895719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dev++; 2896719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2897719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2898719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett__nodev: 2899719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_free(card); 2900719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_ERR "snd_asihpi_probe error %d\n", err); 2901719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 2902719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2903719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2904719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2905719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void __devexit snd_asihpi_remove(struct pci_dev *pci_dev) 2906719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2907719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_adapter *hpi_card = pci_get_drvdata(pci_dev); 2908719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2909719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_free(hpi_card->snd_card_asihpi); 2910719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_card->snd_card_asihpi = NULL; 2911719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi_adapter_remove(pci_dev); 2912719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2913719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2914719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic DEFINE_PCI_DEVICE_TABLE(asihpi_pci_tbl) = { 2915719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett {HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_DSP6205, 2916719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0, 2917719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (kernel_ulong_t)HPI_6205}, 2918719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett {HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_PCI2040, 2919719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0, 2920719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (kernel_ulong_t)HPI_6000}, 2921719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett {0,} 2922719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 2923719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_DEVICE_TABLE(pci, asihpi_pci_tbl); 2924719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2925719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic struct pci_driver driver = { 2926719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .name = "asihpi", 2927719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .id_table = asihpi_pci_tbl, 2928719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .probe = snd_asihpi_probe, 2929719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .remove = __devexit_p(snd_asihpi_remove), 2930719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#ifdef CONFIG_PM 2931719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* .suspend = snd_asihpi_suspend, 2932719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .resume = snd_asihpi_resume, */ 2933719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#endif 2934719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 2935719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2936719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __init snd_asihpi_init(void) 2937719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2938719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi_init(); 2939719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return pci_register_driver(&driver); 2940719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2941719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2942719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void __exit snd_asihpi_exit(void) 2943719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2944719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2945719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pci_unregister_driver(&driver); 2946719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi_exit(); 2947719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2948719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2949719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettmodule_init(snd_asihpi_init) 2950719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettmodule_exit(snd_asihpi_exit) 2951719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2952