asihpi.c revision c4ed97d9e7ec9b8c8453af4ce55497d85970426c
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/* >0: print Hw params, timer vars. >1: print stream write/copy sizes */ 26719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define REALLY_VERBOSE_LOGGING 0 27719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 28719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#if REALLY_VERBOSE_LOGGING 29719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define VPRINTK1 snd_printd 30719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#else 31719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define VPRINTK1(...) 32719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#endif 33719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 34719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#if REALLY_VERBOSE_LOGGING > 1 35719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define VPRINTK2 snd_printd 36719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#else 37719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define VPRINTK2(...) 38719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#endif 39719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 40719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include "hpi_internal.h" 41719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include "hpimsginit.h" 42719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include "hpioctl.h" 43719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 44719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <linux/pci.h> 45e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett#include <linux/version.h> 46719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <linux/init.h> 47719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <linux/jiffies.h> 48719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <linux/slab.h> 49719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <linux/time.h> 50719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <linux/wait.h> 51719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <sound/core.h> 52719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <sound/control.h> 53719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <sound/pcm.h> 54719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <sound/pcm_params.h> 55719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <sound/info.h> 56719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <sound/initval.h> 57719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <sound/tlv.h> 58719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#include <sound/hwdep.h> 59719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 60719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 61719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_LICENSE("GPL"); 62719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_AUTHOR("AudioScience inc. <support@audioscience.com>"); 63719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx"); 64719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 65719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* index 0-MAX */ 66719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 67719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; 68719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int enable_hpi_hwdep = 1; 69719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 70719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettmodule_param_array(index, int, NULL, S_IRUGO); 71719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_PARM_DESC(index, "ALSA index value for AudioScience soundcard."); 72719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 73719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettmodule_param_array(id, charp, NULL, S_IRUGO); 74719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_PARM_DESC(id, "ALSA ID string for AudioScience soundcard."); 75719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 76719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettmodule_param_array(enable, bool, NULL, S_IRUGO); 77719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_PARM_DESC(enable, "ALSA enable AudioScience soundcard."); 78719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 79719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettmodule_param(enable_hpi_hwdep, bool, S_IRUGO|S_IWUSR); 80719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_PARM_DESC(enable_hpi_hwdep, 81719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "ALSA enable HPI hwdep for AudioScience soundcard "); 82719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 83719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* identify driver */ 84719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#ifdef KERNEL_ALSA_BUILD 85e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassettstatic char *build_info = "Built using headers from kernel source"; 86719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettmodule_param(build_info, charp, S_IRUGO); 87719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_PARM_DESC(build_info, "built using headers from kernel source"); 88719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#else 89e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassettstatic char *build_info = "Built within ALSA source"; 90719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettmodule_param(build_info, charp, S_IRUGO); 91719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_PARM_DESC(build_info, "built within ALSA source"); 92719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#endif 93719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 94719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* set to 1 to dump every control from adapter to log */ 95719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic const int mixer_dump; 96719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 97719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define DEFAULT_SAMPLERATE 44100 98719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int adapter_fs = DEFAULT_SAMPLERATE; 99719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 100719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* defaults */ 101719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define PERIODS_MIN 2 102e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett#define PERIOD_BYTES_MIN 2048 103719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define BUFFER_BYTES_MAX (512 * 1024) 104719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 105ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett/* convert stream to character */ 106ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett#define SCHR(s) ((s == SNDRV_PCM_STREAM_PLAYBACK) ? 'P' : 'C') 107ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett 108719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*#define TIMER_MILLISECONDS 20 109719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define FORCE_TIMER_JIFFIES ((TIMER_MILLISECONDS * HZ + 999)/1000) 110719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett*/ 111719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 112719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define MAX_CLOCKSOURCES (HPI_SAMPLECLOCK_SOURCE_LAST + 1 + 7) 113719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 114719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstruct clk_source { 115719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int source; 116719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int index; 117719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett char *name; 118719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 119719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 120719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstruct clk_cache { 121719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int count; 122719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int has_local; 123719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct clk_source s[MAX_CLOCKSOURCES]; 124719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 125719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 126719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* Per card data */ 127719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstruct snd_card_asihpi { 128719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card; 129719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct pci_dev *pci; 130719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 adapter_index; 131719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 serial_number; 132719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 type; 133719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 version; 134719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 num_outstreams; 135719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 num_instreams; 136719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 137719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_mixer; 138719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct clk_cache cc; 139719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 140719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 support_mmap; 141719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 support_grouping; 142719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 support_mrx; 143719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 update_interval_frames; 144719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 in_max_chans; 145719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 out_max_chans; 146719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 147719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 148719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* Per stream data */ 149719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstruct snd_card_asihpi_pcm { 150719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct timer_list timer; 151719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int respawn_timer; 152719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int hpi_buffer_attached; 153ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett unsigned int buffer_bytes; 154ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett unsigned int period_bytes; 155719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int bytes_per_sec; 156e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett unsigned int pcm_buf_host_rw_ofs; /* Host R/W pos */ 157e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett unsigned int pcm_buf_dma_ofs; /* DMA R/W offset in buffer */ 158e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett unsigned int pcm_buf_elapsed_dma_ofs; /* DMA R/W offset in buffer */ 159719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_substream *substream; 160719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_stream; 161719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_format format; 162719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 163719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 164719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* universal stream verbs work with out or in stream handles */ 165719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 166719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* Functions to allow driver to give a buffer to HPI for busmastering */ 167719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 168719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic u16 hpi_stream_host_buffer_attach( 169719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_stream, /* handle to outstream. */ 170719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 size_in_bytes, /* size in bytes of bus mastering buffer */ 171719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 pci_address 172719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett) 173719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 174719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_message hm; 175719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_response hr; 176719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int obj = hpi_handle_object(h_stream); 177719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 178719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!h_stream) 179719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return HPI_ERROR_INVALID_OBJ; 180719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_init_message_response(&hm, &hr, obj, 181719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett obj == HPI_OBJ_OSTREAM ? 182719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_OSTREAM_HOSTBUFFER_ALLOC : 183719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_ISTREAM_HOSTBUFFER_ALLOC); 184719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 185719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_to_indexes(h_stream, &hm.adapter_index, 186719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hm.obj_index); 187719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 188719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hm.u.d.u.buffer.buffer_size = size_in_bytes; 189719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hm.u.d.u.buffer.pci_address = pci_address; 190719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hm.u.d.u.buffer.command = HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER; 191719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_send_recv(&hm, &hr); 192719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return hr.error; 193719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 194719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 195ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic u16 hpi_stream_host_buffer_detach(u32 h_stream) 196719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 197719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_message hm; 198719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_response hr; 199719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int obj = hpi_handle_object(h_stream); 200719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 201719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!h_stream) 202719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return HPI_ERROR_INVALID_OBJ; 203719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 204719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_init_message_response(&hm, &hr, obj, 205719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett obj == HPI_OBJ_OSTREAM ? 206719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_OSTREAM_HOSTBUFFER_FREE : 207719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_ISTREAM_HOSTBUFFER_FREE); 208719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 209719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_to_indexes(h_stream, &hm.adapter_index, 210719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hm.obj_index); 211719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hm.u.d.u.buffer.command = HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER; 212719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_send_recv(&hm, &hr); 213719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return hr.error; 214719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 215719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 216ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic inline u16 hpi_stream_start(u32 h_stream) 217719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 218719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) 219ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_outstream_start(h_stream); 220719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 221ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_instream_start(h_stream); 222719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 223719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 224ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic inline u16 hpi_stream_stop(u32 h_stream) 225719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 226719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) 227ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_outstream_stop(h_stream); 228719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 229ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_instream_stop(h_stream); 230719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 231719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 232719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic inline u16 hpi_stream_get_info_ex( 233719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_stream, 234719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 *pw_state, 235719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 *pbuffer_size, 236719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 *pdata_in_buffer, 237719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 *psample_count, 238719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 *pauxiliary_data 239719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett) 240719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 241e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett u16 e; 242719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) 243ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett e = hpi_outstream_get_info_ex(h_stream, pw_state, 244719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pbuffer_size, pdata_in_buffer, 245719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett psample_count, pauxiliary_data); 246719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 247ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett e = hpi_instream_get_info_ex(h_stream, pw_state, 248719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pbuffer_size, pdata_in_buffer, 249719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett psample_count, pauxiliary_data); 250e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett return e; 251719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 252719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 253ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic inline u16 hpi_stream_group_add( 254719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_master, 255719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_stream) 256719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 257719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (hpi_handle_object(h_master) == HPI_OBJ_OSTREAM) 258ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_outstream_group_add(h_master, h_stream); 259719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 260ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_instream_group_add(h_master, h_stream); 261719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 262719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 263ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic inline u16 hpi_stream_group_reset(u32 h_stream) 264719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 265719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) 266ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_outstream_group_reset(h_stream); 267719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 268ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_instream_group_reset(h_stream); 269719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 270719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 271ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic inline u16 hpi_stream_group_get_map( 272719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_stream, u32 *mo, u32 *mi) 273719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 274719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) 275ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_outstream_group_get_map(h_stream, mo, mi); 276719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 277ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return hpi_instream_group_get_map(h_stream, mo, mi); 278719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 279719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 280719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic u16 handle_error(u16 err, int line, char *filename) 281719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 282719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 283719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett printk(KERN_WARNING 284719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "in file %s, line %d: HPI error %d\n", 285719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett filename, line, err); 286719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 287719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 288719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 289719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define hpi_handle_error(x) handle_error(x, __LINE__, __FILE__) 290719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 291719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/***************************** GENERAL PCM ****************/ 292719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#if REALLY_VERBOSE_LOGGING 293719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void print_hwparams(struct snd_pcm_hw_params *p) 294719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 295719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printd("HWPARAMS \n"); 296719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printd("samplerate %d \n", params_rate(p)); 297e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett snd_printd("Channels %d \n", params_channels(p)); 298e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett snd_printd("Format %d \n", params_format(p)); 299719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printd("subformat %d \n", params_subformat(p)); 300e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett snd_printd("Buffer bytes %d \n", params_buffer_bytes(p)); 301e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett snd_printd("Period bytes %d \n", params_period_bytes(p)); 302719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printd("access %d \n", params_access(p)); 303719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printd("period_size %d \n", params_period_size(p)); 304719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printd("periods %d \n", params_periods(p)); 305719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printd("buffer_size %d \n", params_buffer_size(p)); 306719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 307719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#else 308719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define print_hwparams(x) 309719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#endif 310719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 311719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic snd_pcm_format_t hpi_to_alsa_formats[] = { 312719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett -1, /* INVALID */ 313719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_FORMAT_U8, /* HPI_FORMAT_PCM8_UNSIGNED 1 */ 314719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_FORMAT_S16, /* HPI_FORMAT_PCM16_SIGNED 2 */ 315719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett -1, /* HPI_FORMAT_MPEG_L1 3 */ 316719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_FORMAT_MPEG, /* HPI_FORMAT_MPEG_L2 4 */ 317719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_FORMAT_MPEG, /* HPI_FORMAT_MPEG_L3 5 */ 318719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett -1, /* HPI_FORMAT_DOLBY_AC2 6 */ 319719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett -1, /* HPI_FORMAT_DOLBY_AC3 7 */ 320719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_FORMAT_S16_BE,/* HPI_FORMAT_PCM16_BIGENDIAN 8 */ 321719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett -1, /* HPI_FORMAT_AA_TAGIT1_HITS 9 */ 322719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett -1, /* HPI_FORMAT_AA_TAGIT1_INSERTS 10 */ 323719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_FORMAT_S32, /* HPI_FORMAT_PCM32_SIGNED 11 */ 324719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett -1, /* HPI_FORMAT_RAW_BITSTREAM 12 */ 325719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett -1, /* HPI_FORMAT_AA_TAGIT1_HITS_EX1 13 */ 326719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_FORMAT_FLOAT, /* HPI_FORMAT_PCM32_FLOAT 14 */ 327719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#if 1 328719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* ALSA can't handle 3 byte sample size together with power-of-2 329719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * constraint on buffer_bytes, so disable this format 330719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 331719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett -1 332719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#else 333ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett /* SNDRV_PCM_FORMAT_S24_3LE */ /* HPI_FORMAT_PCM24_SIGNED 15 */ 334719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#endif 335719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 336719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 337719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 338719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_format_alsa2hpi(snd_pcm_format_t alsa_format, 339719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 *hpi_format) 340719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 341719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 format; 342719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 343719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (format = HPI_FORMAT_PCM8_UNSIGNED; 344719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett format <= HPI_FORMAT_PCM24_SIGNED; format++) { 345719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (hpi_to_alsa_formats[format] == alsa_format) { 346719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett *hpi_format = format; 347719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 348719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 349719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 350719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 351719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printd(KERN_WARNING "failed match for alsa format %d\n", 352719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett alsa_format); 353719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett *hpi_format = 0; 354719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 355719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 356719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 357719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void snd_card_asihpi_pcm_samplerates(struct snd_card_asihpi *asihpi, 358719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_hardware *pcmhw) 359719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 360719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 err; 361719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control; 362719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 sample_rate; 363719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int idx; 364719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int rate_min = 200000; 365719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int rate_max = 0; 366719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int rates = 0; 367719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 368719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (asihpi->support_mrx) { 369719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_CONTINUOUS; 370719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_8000_96000; 371719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rate_min = 8000; 372719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rate_max = 100000; 373719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else { 374719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* on cards without SRC, 375719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett valid rates are determined by sampleclock */ 376ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_mixer_get_control(asihpi->h_mixer, 377719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, 378719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_CONTROL_SAMPLECLOCK, &h_control); 379719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) { 380719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_ERR 381e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "No local sampleclock, err %d\n", err); 382719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 383719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 384719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (idx = 0; idx < 100; idx++) { 385ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (hpi_sample_clock_query_local_rate( 386719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett h_control, idx, &sample_rate)) { 387719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!idx) 388719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_ERR 389e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Local rate query failed\n"); 390719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 391719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 392719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 393719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 394719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rate_min = min(rate_min, sample_rate); 395719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rate_max = max(rate_max, sample_rate); 396719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 397719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett switch (sample_rate) { 398719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 5512: 399719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_5512; 400719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 401719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 8000: 402719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_8000; 403719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 404719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 11025: 405719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_11025; 406719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 407719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 16000: 408719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_16000; 409719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 410719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 22050: 411719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_22050; 412719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 413719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 32000: 414719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_32000; 415719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 416719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 44100: 417719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_44100; 418719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 419719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 48000: 420719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_48000; 421719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 422719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 64000: 423719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_64000; 424719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 425719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 88200: 426719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_88200; 427719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 428719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 96000: 429719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_96000; 430719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 431719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 176400: 432719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_176400; 433719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 434719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case 192000: 435719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_192000; 436719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 437719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett default: /* some other rate */ 438719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates |= SNDRV_PCM_RATE_KNOT; 439719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 440719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 441719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 442719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 443719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* printk(KERN_INFO "Supported rates %X %d %d\n", 444719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rates, rate_min, rate_max); */ 445719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pcmhw->rates = rates; 446719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pcmhw->rate_min = rate_min; 447719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pcmhw->rate_max = rate_max; 448719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 449719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 450719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream, 451719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_hw_params *params) 452719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 453719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 454719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 455719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); 456719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 457719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 format; 458315e8f7501ad929acacfa94c251283e837f281edKulikov Vasiliy int width; 459719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int bytes_per_sec; 460719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 461719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett print_hwparams(params); 462719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); 463719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) 464719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 465719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_card_asihpi_format_alsa2hpi(params_format(params), &format); 466719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 467719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 468719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 469719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett VPRINTK1(KERN_INFO "format %d, %d chans, %d_hz\n", 470719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett format, params_channels(params), 471719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett params_rate(params)); 472719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 473719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error(hpi_format_create(&dpcm->format, 474719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett params_channels(params), 475719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett format, params_rate(params), 0, 0)); 476719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 477719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 478ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (hpi_instream_reset(dpcm->h_stream) != 0) 479719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 480719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 481ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (hpi_instream_set_format( 482719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->h_stream, &dpcm->format) != 0) 483719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 484719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 485719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 486719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->hpi_buffer_attached = 0; 487719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (card->support_mmap) { 488719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 489ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_stream_host_buffer_attach(dpcm->h_stream, 490719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett params_buffer_bytes(params), runtime->dma_addr); 491719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err == 0) { 492ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO 493719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "stream_host_buffer_attach succeeded %u %lu\n", 494719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett params_buffer_bytes(params), 495719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (unsigned long)runtime->dma_addr); 496719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else { 497719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printd(KERN_INFO 498719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "stream_host_buffer_attach error %d\n", 499719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err); 500719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -ENOMEM; 501719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 502719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 503ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_stream_get_info_ex(dpcm->h_stream, NULL, 504719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &dpcm->hpi_buffer_attached, 505719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett NULL, NULL, NULL); 506719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 507ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO "stream_host_buffer_attach status 0x%x\n", 508719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->hpi_buffer_attached); 509719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 510719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett bytes_per_sec = params_rate(params) * params_channels(params); 511315e8f7501ad929acacfa94c251283e837f281edKulikov Vasiliy width = snd_pcm_format_width(params_format(params)); 512315e8f7501ad929acacfa94c251283e837f281edKulikov Vasiliy bytes_per_sec *= width; 513719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett bytes_per_sec /= 8; 514315e8f7501ad929acacfa94c251283e837f281edKulikov Vasiliy if (width < 0 || bytes_per_sec == 0) 515719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 516719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 517719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->bytes_per_sec = bytes_per_sec; 518ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett dpcm->buffer_bytes = params_buffer_bytes(params); 519ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett dpcm->period_bytes = params_period_bytes(params); 520ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO "buffer_bytes=%d, period_bytes=%d, bps=%d\n", 521ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett dpcm->buffer_bytes, dpcm->period_bytes, bytes_per_sec); 522719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 523719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 524719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 525719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 526e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassettstatic int 527e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassettsnd_card_asihpi_hw_free(struct snd_pcm_substream *substream) 528e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett{ 529e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 530e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 531e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett if (dpcm->hpi_buffer_attached) 532ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_stream_host_buffer_detach(dpcm->h_stream); 533e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 534e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett snd_pcm_lib_free_pages(substream); 535e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett return 0; 536e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett} 537e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 538e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassettstatic void snd_card_asihpi_runtime_free(struct snd_pcm_runtime *runtime) 539e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett{ 540e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 541e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett kfree(dpcm); 542e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett} 543e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 544719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void snd_card_asihpi_pcm_timer_start(struct snd_pcm_substream * 545719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett substream) 546719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 547719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 548719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 549719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int expiry; 550719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 551ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett expiry = HZ / 200; 552ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett /*? (dpcm->period_bytes * HZ / dpcm->bytes_per_sec); */ 553e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett expiry = max(expiry, 1); /* don't let it be zero! */ 554719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->timer.expires = jiffies + expiry; 555719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->respawn_timer = 1; 556719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett add_timer(&dpcm->timer); 557719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 558719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 559719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void snd_card_asihpi_pcm_timer_stop(struct snd_pcm_substream *substream) 560719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 561719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 562719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 563719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 564719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->respawn_timer = 0; 565719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett del_timer(&dpcm->timer); 566719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 567719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 568719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, 569719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int cmd) 570719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 571719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = substream->runtime->private_data; 572719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); 573719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_substream *s; 574719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 e; 575719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 576ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO "%c%d trigger\n", 577ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett SCHR(substream->stream), substream->number); 578719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett switch (cmd) { 579719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case SNDRV_PCM_TRIGGER_START: 580719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_group_for_each_entry(s, substream) { 581e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett struct snd_pcm_runtime *runtime = s->runtime; 582e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett struct snd_card_asihpi_pcm *ds = runtime->private_data; 583719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 584719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (snd_pcm_substream_chip(s) != card) 585719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett continue; 586719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 587ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett /* don't link Cap and Play */ 588ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (substream->stream != s->stream) 589ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett continue; 590ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett 591719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if ((s->stream == SNDRV_PCM_STREAM_PLAYBACK) && 592719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (card->support_mmap)) { 593719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* How do I know how much valid data is present 594e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett * in buffer? Must be at least one period! 595e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett * Guessing 2 periods, but if 596719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * buffer is bigger it may contain even more 597719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * data?? 598719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 599ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett unsigned int preload = ds->period_bytes * 1; 600ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK2(KERN_INFO "%d preload x%x\n", s->number, preload); 601719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error(hpi_outstream_write_buf( 602ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett ds->h_stream, 603e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett &runtime->dma_area[0], 604719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett preload, 605719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &ds->format)); 606e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett ds->pcm_buf_host_rw_ofs = preload; 607719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 608719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 609719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (card->support_grouping) { 610ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO "\t%c%d group\n", 611ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett SCHR(s->stream), 612719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett s->number); 613ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett e = hpi_stream_group_add( 614719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->h_stream, 615719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ds->h_stream); 616719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!e) { 617719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_trigger_done(s, substream); 618719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else { 619719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error(e); 620719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 621719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 622719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else 623719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 624719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 625ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO "start\n"); 626719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* start the master stream */ 627719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_pcm_timer_start(substream); 628c4ed97d9e7ec9b8c8453af4ce55497d85970426cEliot Blennerhassett if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) || 629c4ed97d9e7ec9b8c8453af4ce55497d85970426cEliot Blennerhassett !card->support_mmap) 630ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_stream_start(dpcm->h_stream)); 631719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 632719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 633719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case SNDRV_PCM_TRIGGER_STOP: 634719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_pcm_timer_stop(substream); 635719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_group_for_each_entry(s, substream) { 636719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (snd_pcm_substream_chip(s) != card) 637719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett continue; 638ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett /* don't link Cap and Play */ 639ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (substream->stream != s->stream) 640ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett continue; 641719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 642719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /*? workaround linked streams don't 643719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett transition to SETUP 20070706*/ 644719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett s->runtime->status->state = SNDRV_PCM_STATE_SETUP; 645719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 646719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (card->support_grouping) { 647ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO "\t%c%d group\n", 648ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett SCHR(s->stream), 649719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett s->number); 650719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_trigger_done(s, substream); 651719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else 652719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 653719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 654ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO "stop\n"); 655719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 656719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* _prepare and _hwparams reset the stream */ 657ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_stream_stop(dpcm->h_stream)); 658719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 659719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error( 660ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_outstream_reset(dpcm->h_stream)); 661719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 662719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (card->support_grouping) 663ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_stream_group_reset(dpcm->h_stream)); 664719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 665719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 666719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 667ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO "pause release\n"); 668ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_stream_start(dpcm->h_stream)); 669719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_pcm_timer_start(substream); 670719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 671719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 672ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO "pause\n"); 673719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_pcm_timer_stop(substream); 674ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_stream_stop(dpcm->h_stream)); 675719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 676719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett default: 677ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett snd_printd(KERN_ERR "\tINVALID\n"); 678719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 679719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 680719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 681719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 682719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 683719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 684719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*algorithm outline 685719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Without linking degenerates to getting single stream pos etc 686719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Without mmap 2nd loop degenerates to snd_pcm_period_elapsed 687719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett*/ 688719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* 689e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassettpcm_buf_dma_ofs=get_buf_pos(s); 690719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettfor_each_linked_stream(s) { 691e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett pcm_buf_dma_ofs=get_buf_pos(s); 692ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett min_buf_pos = modulo_min(min_buf_pos, pcm_buf_dma_ofs, buffer_bytes) 693e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett new_data = min(new_data, calc_new_data(pcm_buf_dma_ofs,irq_pos) 694719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 695719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassetttimer.expires = jiffies + predict_next_period_ready(min_buf_pos); 696719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettfor_each_linked_stream(s) { 697e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett s->pcm_buf_dma_ofs = min_buf_pos; 698ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (new_data > period_bytes) { 699719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (mmap) { 700ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett irq_pos = (irq_pos + period_bytes) % buffer_bytes; 701719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (playback) { 702ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett write(period_bytes); 703719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else { 704ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett read(period_bytes); 705719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 706719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 707719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_period_elapsed(s); 708719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 709719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 710719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett*/ 711719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 712719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/** Minimum of 2 modulo values. Works correctly when the difference between 713719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett* the values is less than half the modulus 714719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett*/ 715719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic inline unsigned int modulo_min(unsigned int a, unsigned int b, 716719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned long int modulus) 717719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 718719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int result; 719719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (((a-b) % modulus) < (modulus/2)) 720719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett result = b; 721719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 722719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett result = a; 723719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 724719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return result; 725719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 726719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 727719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/** Timer function, equivalent to interrupt service routine for cards 728719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett*/ 729719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void snd_card_asihpi_timer_function(unsigned long data) 730719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 731719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = (struct snd_card_asihpi_pcm *)data; 732ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett struct snd_pcm_substream *substream = dpcm->substream; 733ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); 734719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime; 735719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_substream *s; 736719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int newdata = 0; 737e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett unsigned int pcm_buf_dma_ofs, min_buf_pos = 0; 738719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int remdata, xfercount, next_jiffies; 739719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int first = 1; 740ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett int loops = 0; 741719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 state; 742e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett u32 buffer_size, bytes_avail, samples_played, on_card_bytes; 743719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 744ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO "%c%d snd_card_asihpi_timer_function\n", 745ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett SCHR(substream->stream), substream->number); 746ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett 747719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* find minimum newdata and buffer pos in group */ 748ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett snd_pcm_group_for_each_entry(s, substream) { 749719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *ds = s->runtime->private_data; 750719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime = s->runtime; 751719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 752719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (snd_pcm_substream_chip(s) != card) 753719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett continue; 754719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 755ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett /* don't link Cap and Play */ 756ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (substream->stream != s->stream) 757ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett continue; 758ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett 759ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_stream_get_info_ex( 760719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ds->h_stream, &state, 761e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett &buffer_size, &bytes_avail, 762e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett &samples_played, &on_card_bytes)); 763719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 764719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* number of bytes in on-card buffer */ 765e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett runtime->delay = on_card_bytes; 766719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 767ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { 768e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett pcm_buf_dma_ofs = ds->pcm_buf_host_rw_ofs - bytes_avail; 769ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (state == HPI_STATE_STOPPED) { 770ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if ((bytes_avail == 0) && 771ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett (on_card_bytes < ds->pcm_buf_host_rw_ofs)) { 772ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_stream_start(ds->h_stream)); 773ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO "P%d start\n", s->number); 774ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett } 775ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett } else if (state == HPI_STATE_DRAINED) { 776ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_WARNING "P%d drained\n", 777ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett s->number); 778ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett /*snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN); 779ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett continue; */ 780ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett } 781ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett } else 782e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett pcm_buf_dma_ofs = bytes_avail + ds->pcm_buf_host_rw_ofs; 783719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 784719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (first) { 785719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* can't statically init min when wrap is involved */ 786e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett min_buf_pos = pcm_buf_dma_ofs; 787ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett newdata = (pcm_buf_dma_ofs - ds->pcm_buf_elapsed_dma_ofs) % ds->buffer_bytes; 788719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett first = 0; 789719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else { 790719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett min_buf_pos = 791e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett modulo_min(min_buf_pos, pcm_buf_dma_ofs, UINT_MAX+1L); 792719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett newdata = min( 793ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett (pcm_buf_dma_ofs - ds->pcm_buf_elapsed_dma_ofs) % ds->buffer_bytes, 794719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett newdata); 795719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 796719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 797ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO "PB timer hw_ptr x%04lX, appl_ptr x%04lX\n", 798719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (unsigned long)frames_to_bytes(runtime, 799719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime->status->hw_ptr), 800719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (unsigned long)frames_to_bytes(runtime, 801719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime->control->appl_ptr)); 802e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 803ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO "%d %c%d S=%d, rw=%04X, dma=x%04X, left=x%04X," 804ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett " aux=x%04X space=x%04X\n", 805ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett loops, SCHR(s->stream), s->number, 806e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett state, ds->pcm_buf_host_rw_ofs, pcm_buf_dma_ofs, (int)bytes_avail, 807e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett (int)on_card_bytes, buffer_size-bytes_avail); 808ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett loops++; 809719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 810e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett pcm_buf_dma_ofs = min_buf_pos; 811719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 812ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett remdata = newdata % dpcm->period_bytes; 813ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett xfercount = newdata - remdata; /* a multiple of period_bytes */ 814e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett /* come back when on_card_bytes has decreased enough to allow 815e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett write to happen, or when data has been consumed to make another 816e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett period 817e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett */ 818ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (xfercount && (on_card_bytes > dpcm->period_bytes)) 819ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett next_jiffies = ((on_card_bytes - dpcm->period_bytes) * HZ / dpcm->bytes_per_sec); 820e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett else 821ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett next_jiffies = ((dpcm->period_bytes - remdata) * HZ / dpcm->bytes_per_sec); 822e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 823e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett next_jiffies = max(next_jiffies, 1U); 824719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->timer.expires = jiffies + next_jiffies; 825ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO "jif %d buf pos x%04X newdata x%04X xfer x%04X\n", 826e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett next_jiffies, pcm_buf_dma_ofs, newdata, xfercount); 827e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 828ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett snd_pcm_group_for_each_entry(s, substream) { 829719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *ds = s->runtime->private_data; 830719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 831ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett /* don't link Cap and Play */ 832ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (substream->stream != s->stream) 833ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett continue; 834ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett 835e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett ds->pcm_buf_dma_ofs = pcm_buf_dma_ofs; 836e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 837ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (xfercount && (on_card_bytes <= ds->period_bytes)) { 838719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (card->support_mmap) { 839719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { 840ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK2(KERN_INFO "P%d write x%04x\n", 841719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett s->number, 842ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett ds->period_bytes); 843719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error( 844719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_outstream_write_buf( 845ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett ds->h_stream, 846719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &s->runtime-> 847719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dma_area[0], 848719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett xfercount, 849719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &ds->format)); 850719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else { 851ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK2(KERN_INFO "C%d read x%04x\n", 852719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett s->number, 853e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett xfercount); 854719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error( 855719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_instream_read_buf( 856ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett ds->h_stream, 857719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett NULL, xfercount)); 858719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 859e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett ds->pcm_buf_host_rw_ofs = ds->pcm_buf_host_rw_ofs + xfercount; 860719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } /* else R/W will be handled by read/write callbacks */ 861e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett ds->pcm_buf_elapsed_dma_ofs = pcm_buf_dma_ofs; 862719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_period_elapsed(s); 863719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 864719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 865719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 866719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (dpcm->respawn_timer) 867719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett add_timer(&dpcm->timer); 868719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 869719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 870719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/***************************** PLAYBACK OPS ****************/ 871719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_playback_ioctl(struct snd_pcm_substream *substream, 872719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int cmd, void *arg) 873719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 874719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* snd_printd(KERN_INFO "Playback ioctl %d\n", cmd); */ 875719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return snd_pcm_lib_ioctl(substream, cmd, arg); 876719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 877719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 878719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_playback_prepare(struct snd_pcm_substream * 879719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett substream) 880719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 881719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 882719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 883719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 884ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO "playback prepare %d\n", substream->number); 885719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 886ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_outstream_reset(dpcm->h_stream)); 887e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dpcm->pcm_buf_host_rw_ofs = 0; 888e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dpcm->pcm_buf_dma_ofs = 0; 889e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dpcm->pcm_buf_elapsed_dma_ofs = 0; 890719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 891719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 892719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 893719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic snd_pcm_uframes_t 894719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettsnd_card_asihpi_playback_pointer(struct snd_pcm_substream *substream) 895719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 896719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 897719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 898719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_uframes_t ptr; 899719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 900ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett ptr = bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes); 901ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett /* VPRINTK2(KERN_INFO "playback_pointer=x%04lx\n", (unsigned long)ptr); */ 902719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ptr; 903719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 904719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 905719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void snd_card_asihpi_playback_format(struct snd_card_asihpi *asihpi, 906719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_stream, 907719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_hardware *pcmhw) 908719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 909719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_format hpi_format; 910719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 format; 911719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 err; 912719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control; 913719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 sample_rate = 48000; 914719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 915719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* on cards without SRC, must query at valid rate, 916719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * maybe set by external sync 917719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 918ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_mixer_get_control(asihpi->h_mixer, 919719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, 920719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_CONTROL_SAMPLECLOCK, &h_control); 921719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 922719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err) 923ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_sample_clock_get_sample_rate(h_control, 924719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &sample_rate); 925719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 926719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (format = HPI_FORMAT_PCM8_UNSIGNED; 927719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett format <= HPI_FORMAT_PCM24_SIGNED; format++) { 928719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = hpi_format_create(&hpi_format, 929719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2, format, sample_rate, 128000, 0); 930719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err) 931ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_outstream_query_format(h_stream, 932719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_format); 933719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err && (hpi_to_alsa_formats[format] != -1)) 934719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pcmhw->formats |= 935719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (1ULL << hpi_to_alsa_formats[format]); 936719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 937719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 938719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 939719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic struct snd_pcm_hardware snd_card_asihpi_playback = { 940719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .channels_min = 1, 941719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .channels_max = 2, 942719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .buffer_bytes_max = BUFFER_BYTES_MAX, 943719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .period_bytes_min = PERIOD_BYTES_MIN, 944719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN, 945719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .periods_min = PERIODS_MIN, 946719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, 947719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .fifo_size = 0, 948719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 949719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 950719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream) 951719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 952719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 953719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm; 954719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); 955719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 956719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 957719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); 958719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (dpcm == NULL) 959719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -ENOMEM; 960719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 961719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = 962ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_outstream_open(card->adapter_index, 963719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett substream->number, &dpcm->h_stream); 964719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error(err); 965719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 966719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett kfree(dpcm); 967719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err == HPI_ERROR_OBJ_ALREADY_OPEN) 968719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EBUSY; 969719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 970719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EIO; 971719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 972719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /*? also check ASI5000 samplerate source 973719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett If external, only support external rate. 974719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett If internal and other stream playing, cant switch 975719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 976719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 977719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett init_timer(&dpcm->timer); 978719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->timer.data = (unsigned long) dpcm; 979719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->timer.function = snd_card_asihpi_timer_function; 980719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->substream = substream; 981719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime->private_data = dpcm; 982719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime->private_free = snd_card_asihpi_runtime_free; 983719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 984719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_playback.channels_max = card->out_max_chans; 985719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /*?snd_card_asihpi_playback.period_bytes_min = 986719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett card->out_max_chans * 4096; */ 987719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 988719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_playback_format(card, dpcm->h_stream, 989719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &snd_card_asihpi_playback); 990719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 991719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_pcm_samplerates(card, &snd_card_asihpi_playback); 992719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 993719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_playback.info = SNDRV_PCM_INFO_INTERLEAVED | 994719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_INFO_DOUBLE | 995719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_INFO_BATCH | 996719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_INFO_BLOCK_TRANSFER | 997719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_INFO_PAUSE; 998719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 999719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (card->support_mmap) 1000719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_playback.info |= SNDRV_PCM_INFO_MMAP | 1001719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_INFO_MMAP_VALID; 1002719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1003719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (card->support_grouping) 1004719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_playback.info |= SNDRV_PCM_INFO_SYNC_START; 1005719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1006719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* struct is copied, so can create initializer dynamically */ 1007719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime->hw = snd_card_asihpi_playback; 1008719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1009719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (card->support_mmap) 1010719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_pcm_hw_constraint_pow2(runtime, 0, 1011719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_HW_PARAM_BUFFER_BYTES); 1012719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) 1013719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 1014719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1015719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 1016719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett card->update_interval_frames); 1017719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 1018e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett card->update_interval_frames * 2, UINT_MAX); 1019719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1020719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_set_sync(substream); 1021719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1022ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO "playback open\n"); 1023719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1024719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1025719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1026719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1027719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_playback_close(struct snd_pcm_substream *substream) 1028719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1029719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 1030719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 1031719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1032ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_outstream_close(dpcm->h_stream)); 1033ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO "playback close\n"); 1034719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1035719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1036719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1037719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1038719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_playback_copy(struct snd_pcm_substream *substream, 1039719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int channel, 1040719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_uframes_t pos, 1041719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett void __user *src, 1042719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_uframes_t count) 1043719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1044719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 1045719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 1046719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int len; 1047719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1048719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett len = frames_to_bytes(runtime, count); 1049719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1050719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (copy_from_user(runtime->dma_area, src, len)) 1051719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EFAULT; 1052719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1053719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett VPRINTK2(KERN_DEBUG "playback copy%d %u bytes\n", 1054719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett substream->number, len); 1055719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1056ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_outstream_write_buf(dpcm->h_stream, 1057719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime->dma_area, len, &dpcm->format)); 1058719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1059e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dpcm->pcm_buf_host_rw_ofs = dpcm->pcm_buf_host_rw_ofs + len; 1060e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 1061719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1062719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1063719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1064719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_playback_silence(struct snd_pcm_substream * 1065719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett substream, int channel, 1066719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_uframes_t pos, 1067719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_uframes_t count) 1068719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1069719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int len; 1070719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 1071719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 1072719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1073719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett len = frames_to_bytes(runtime, count); 1074ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1(KERN_INFO "playback silence %u bytes\n", len); 1075719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1076719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett memset(runtime->dma_area, 0, len); 1077ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_outstream_write_buf(dpcm->h_stream, 1078719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime->dma_area, len, &dpcm->format)); 1079719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1080719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1081719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1082719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic struct snd_pcm_ops snd_card_asihpi_playback_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 .copy = snd_card_asihpi_playback_copy, 1092719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .silence = snd_card_asihpi_playback_silence, 1093719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 1094719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1095719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic struct snd_pcm_ops snd_card_asihpi_playback_mmap_ops = { 1096719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .open = snd_card_asihpi_playback_open, 1097719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .close = snd_card_asihpi_playback_close, 1098719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .ioctl = snd_card_asihpi_playback_ioctl, 1099719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .hw_params = snd_card_asihpi_pcm_hw_params, 1100719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .hw_free = snd_card_asihpi_hw_free, 1101719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .prepare = snd_card_asihpi_playback_prepare, 1102719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .trigger = snd_card_asihpi_trigger, 1103719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .pointer = snd_card_asihpi_playback_pointer, 1104719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 1105719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1106719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/***************************** CAPTURE OPS ****************/ 1107719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic snd_pcm_uframes_t 1108719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettsnd_card_asihpi_capture_pointer(struct snd_pcm_substream *substream) 1109719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1110719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 1111719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 1112719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1113ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK2(KERN_INFO "capture pointer %d=%d\n", 1114e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett substream->number, dpcm->pcm_buf_dma_ofs); 1115e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett /* NOTE Unlike playback can't use actual samples_played 1116719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for the capture position, because those samples aren't yet in 1117719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett the local buffer available for reading. 1118719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 1119ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett return bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes); 1120719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1121719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1122719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_capture_ioctl(struct snd_pcm_substream *substream, 1123719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int cmd, void *arg) 1124719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1125719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return snd_pcm_lib_ioctl(substream, cmd, arg); 1126719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1127719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1128719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_capture_prepare(struct snd_pcm_substream *substream) 1129719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1130719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 1131719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 1132719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1133ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_instream_reset(dpcm->h_stream)); 1134e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dpcm->pcm_buf_host_rw_ofs = 0; 1135e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dpcm->pcm_buf_dma_ofs = 0; 1136e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dpcm->pcm_buf_elapsed_dma_ofs = 0; 1137719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1138ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1("Capture Prepare %d\n", substream->number); 1139719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1140719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1141719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1142719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1143719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1144719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void snd_card_asihpi_capture_format(struct snd_card_asihpi *asihpi, 1145719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_stream, 1146719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_hardware *pcmhw) 1147719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1148719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_format hpi_format; 1149719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 format; 1150719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 err; 1151719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control; 1152719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 sample_rate = 48000; 1153719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1154719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* on cards without SRC, must query at valid rate, 1155719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett maybe set by external sync */ 1156ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_mixer_get_control(asihpi->h_mixer, 1157719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, 1158719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_CONTROL_SAMPLECLOCK, &h_control); 1159719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1160719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err) 1161ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_sample_clock_get_sample_rate(h_control, 1162719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &sample_rate); 1163719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1164719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (format = HPI_FORMAT_PCM8_UNSIGNED; 1165719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett format <= HPI_FORMAT_PCM24_SIGNED; format++) { 1166719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1167719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = hpi_format_create(&hpi_format, 2, format, 1168719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett sample_rate, 128000, 0); 1169719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err) 1170ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_instream_query_format(h_stream, 1171719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_format); 1172719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err) 1173719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pcmhw->formats |= 1174719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (1ULL << hpi_to_alsa_formats[format]); 1175719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1176719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1177719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1178719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1179719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic struct snd_pcm_hardware snd_card_asihpi_capture = { 1180719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .channels_min = 1, 1181719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .channels_max = 2, 1182719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .buffer_bytes_max = BUFFER_BYTES_MAX, 1183719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .period_bytes_min = PERIOD_BYTES_MIN, 1184719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN, 1185719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .periods_min = PERIODS_MIN, 1186719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, 1187719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .fifo_size = 0, 1188719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 1189719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1190719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream) 1191719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1192719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 1193719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); 1194719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm; 1195719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 1196719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1197719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); 1198719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (dpcm == NULL) 1199719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -ENOMEM; 1200719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1201ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK1("hpi_instream_open adapter %d stream %d\n", 1202719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett card->adapter_index, substream->number); 1203719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1204719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = hpi_handle_error( 1205ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_instream_open(card->adapter_index, 1206719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett substream->number, &dpcm->h_stream)); 1207719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 1208719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett kfree(dpcm); 1209719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err == HPI_ERROR_OBJ_ALREADY_OPEN) 1210719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EBUSY; 1211719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 1212719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EIO; 1213719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1214719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1215719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett init_timer(&dpcm->timer); 1216719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->timer.data = (unsigned long) dpcm; 1217719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->timer.function = snd_card_asihpi_timer_function; 1218719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dpcm->substream = substream; 1219719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime->private_data = dpcm; 1220719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime->private_free = snd_card_asihpi_runtime_free; 1221719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1222719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_capture.channels_max = card->in_max_chans; 1223719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_capture_format(card, dpcm->h_stream, 1224719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &snd_card_asihpi_capture); 1225719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_pcm_samplerates(card, &snd_card_asihpi_capture); 1226719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_capture.info = SNDRV_PCM_INFO_INTERLEAVED; 1227719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1228719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (card->support_mmap) 1229719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_MMAP | 1230719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_INFO_MMAP_VALID; 1231719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1232e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett if (card->support_grouping) 1233e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_SYNC_START; 1234e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 1235719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett runtime->hw = snd_card_asihpi_capture; 1236719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1237719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (card->support_mmap) 1238719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_pcm_hw_constraint_pow2(runtime, 0, 1239719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_PCM_HW_PARAM_BUFFER_BYTES); 1240719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) 1241719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 1242719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1243719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 1244719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett card->update_interval_frames); 1245719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 1246719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett card->update_interval_frames * 2, UINT_MAX); 1247719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1248719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_set_sync(substream); 1249719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1250719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1251719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1252719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1253719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_capture_close(struct snd_pcm_substream *substream) 1254719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1255719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = substream->runtime->private_data; 1256719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1257ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_instream_close(dpcm->h_stream)); 1258719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1259719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1260719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1261719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_capture_copy(struct snd_pcm_substream *substream, 1262719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int channel, snd_pcm_uframes_t pos, 1263719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett void __user *dst, snd_pcm_uframes_t count) 1264719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1265719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm_runtime *runtime = substream->runtime; 1266719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi_pcm *dpcm = runtime->private_data; 1267e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett u32 len; 1268719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1269e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett len = frames_to_bytes(runtime, count); 1270719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1271ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett VPRINTK2(KERN_INFO "capture copy%d %d bytes\n", substream->number, len); 1272ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_instream_read_buf(dpcm->h_stream, 1273e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett runtime->dma_area, len)); 1274719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1275e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dpcm->pcm_buf_host_rw_ofs = dpcm->pcm_buf_host_rw_ofs + len; 1276719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1277e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett if (copy_to_user(dst, runtime->dma_area, len)) 1278719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EFAULT; 1279719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1280719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1281719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1282719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1283719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = { 1284719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .open = snd_card_asihpi_capture_open, 1285719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .close = snd_card_asihpi_capture_close, 1286719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .ioctl = snd_card_asihpi_capture_ioctl, 1287719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .hw_params = snd_card_asihpi_pcm_hw_params, 1288719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .hw_free = snd_card_asihpi_hw_free, 1289719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .prepare = snd_card_asihpi_capture_prepare, 1290719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .trigger = snd_card_asihpi_trigger, 1291719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .pointer = snd_card_asihpi_capture_pointer, 1292719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 1293719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1294719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic struct snd_pcm_ops snd_card_asihpi_capture_ops = { 1295719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .open = snd_card_asihpi_capture_open, 1296719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .close = snd_card_asihpi_capture_close, 1297719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .ioctl = snd_card_asihpi_capture_ioctl, 1298719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .hw_params = snd_card_asihpi_pcm_hw_params, 1299719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .hw_free = snd_card_asihpi_hw_free, 1300719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .prepare = snd_card_asihpi_capture_prepare, 1301719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .trigger = snd_card_asihpi_trigger, 1302719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .pointer = snd_card_asihpi_capture_pointer, 1303719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .copy = snd_card_asihpi_capture_copy 1304719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 1305719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1306719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi, 1307719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int device, int substreams) 1308719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1309719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_pcm *pcm; 1310719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 1311719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1312e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett err = snd_pcm_new(asihpi->card, "Asihpi PCM", device, 1313719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->num_outstreams, asihpi->num_instreams, 1314719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &pcm); 1315719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) 1316719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 1317719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* pointer to ops struct is stored, dont change ops afterwards! */ 1318719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (asihpi->support_mmap) { 1319719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, 1320719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &snd_card_asihpi_playback_mmap_ops); 1321719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, 1322719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &snd_card_asihpi_capture_mmap_ops); 1323719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else { 1324719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, 1325719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &snd_card_asihpi_playback_ops); 1326719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, 1327719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &snd_card_asihpi_capture_ops); 1328719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1329719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1330719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pcm->private_data = asihpi; 1331719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pcm->info_flags = 0; 1332e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett strcpy(pcm->name, "Asihpi PCM"); 1333719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1334719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /*? do we want to emulate MMAP for non-BBM cards? 1335719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Jack doesn't work with ALSAs MMAP emulation - WHY NOT? */ 1336719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 1337719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_dma_pci_data(asihpi->pci), 1338719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 64*1024, BUFFER_BYTES_MAX); 1339719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1340719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1341719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1342719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1343719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/***************************** MIXER CONTROLS ****************/ 1344719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstruct hpi_control { 1345719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control; 1346719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 control_type; 1347719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 src_node_type; 1348719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 src_node_index; 1349719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 dst_node_type; 1350719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 dst_node_index; 1351719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 band; 1352719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett char name[44]; /* copied to snd_ctl_elem_id.name[44]; */ 1353719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 1354719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1355ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic const char * const asihpi_tuner_band_names[] = { 1356719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "invalid", 1357719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "AM", 1358719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "FM mono", 1359719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "TV NTSC-M", 1360719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "FM stereo", 1361719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "AUX", 1362719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "TV PAL BG", 1363719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "TV PAL I", 1364719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "TV PAL DK", 1365719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "TV SECAM", 1366719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 1367719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1368719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettcompile_time_assert( 1369719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (ARRAY_SIZE(asihpi_tuner_band_names) == 1370719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (HPI_TUNER_BAND_LAST+1)), 1371719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett assert_tuner_band_names_size); 1372719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1373ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic const char * const asihpi_src_names[] = { 1374719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "no source", 1375e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "PCM", 1376e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Line", 1377e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Digital", 1378e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Tuner", 1379719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "RF", 1380e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Clock", 1381e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Bitstream", 1382e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Microphone", 1383e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Cobranet", 1384e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Analog", 1385e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Adapter", 1386719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 1387719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1388719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettcompile_time_assert( 1389719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (ARRAY_SIZE(asihpi_src_names) == 1390168f1b07ccc0e8edecb67fab2d0670861853e2fdEliot Blennerhassett (HPI_SOURCENODE_LAST_INDEX-HPI_SOURCENODE_NONE+1)), 1391719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett assert_src_names_size); 1392719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1393ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic const char * const asihpi_dst_names[] = { 1394719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "no destination", 1395e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "PCM", 1396e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Line", 1397e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Digital", 1398719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "RF", 1399e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Speaker", 1400e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Cobranet Out", 1401e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Analog" 1402719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 1403719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1404719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettcompile_time_assert( 1405719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (ARRAY_SIZE(asihpi_dst_names) == 1406168f1b07ccc0e8edecb67fab2d0670861853e2fdEliot Blennerhassett (HPI_DESTNODE_LAST_INDEX-HPI_DESTNODE_NONE+1)), 1407719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett assert_dst_names_size); 1408719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1409719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic inline int ctl_add(struct snd_card *card, struct snd_kcontrol_new *ctl, 1410719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi) 1411719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1412719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 1413719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1414719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_ctl_add(card, snd_ctl_new1(ctl, asihpi)); 1415719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) 1416719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 1417719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else if (mixer_dump) 1418719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_INFO "added %s(%d)\n", ctl->name, ctl->index); 1419719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1420719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1421719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1422719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1423719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* Convert HPI control name and location into ALSA control name */ 1424719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void asihpi_ctl_init(struct snd_kcontrol_new *snd_control, 1425719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl, 1426719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett char *name) 1427719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1428e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett char *dir = ""; 1429719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett memset(snd_control, 0, sizeof(*snd_control)); 1430719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control->name = hpi_ctl->name; 1431719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control->private_value = hpi_ctl->h_control; 1432719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control->iface = SNDRV_CTL_ELEM_IFACE_MIXER; 1433719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control->index = 0; 1434719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1435e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett if (hpi_ctl->dst_node_type + HPI_DESTNODE_NONE == HPI_DESTNODE_ISTREAM) 1436e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dir = "Capture "; /* On or towards a PCM capture destination*/ 1437e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett else if ((hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) && 1438e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett (!hpi_ctl->dst_node_type)) 1439e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dir = "Capture "; /* On a source node that is not PCM playback */ 1440ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett else if (hpi_ctl->src_node_type && 1441ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett (hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) && 1442e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett (hpi_ctl->dst_node_type)) 1443e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dir = "Monitor Playback "; /* Between an input and an output */ 1444e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett else 1445e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dir = "Playback "; /* PCM Playback source, or output node */ 1446e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett 1447719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (hpi_ctl->src_node_type && hpi_ctl->dst_node_type) 1448e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett sprintf(hpi_ctl->name, "%s%d %s%d %s%s", 1449719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi_src_names[hpi_ctl->src_node_type], 1450719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_ctl->src_node_index, 1451719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi_dst_names[hpi_ctl->dst_node_type], 1452719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_ctl->dst_node_index, 1453e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dir, name); 1454719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else if (hpi_ctl->dst_node_type) { 1455e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett sprintf(hpi_ctl->name, "%s %d %s%s", 1456719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi_dst_names[hpi_ctl->dst_node_type], 1457719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_ctl->dst_node_index, 1458e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dir, name); 1459719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else { 1460e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett sprintf(hpi_ctl->name, "%s %d %s%s", 1461719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi_src_names[hpi_ctl->src_node_type], 1462719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_ctl->src_node_index, 1463e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett dir, name); 1464719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1465ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett /* printk(KERN_INFO "Adding %s %d to %d ", hpi_ctl->name, 1466ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_ctl->wSrcNodeType, hpi_ctl->wDstNodeType); */ 1467719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1468719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1469719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 1470719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Volume controls 1471719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 1472719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#define VOL_STEP_mB 1 1473719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_volume_info(struct snd_kcontrol *kcontrol, 1474719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 1475719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1476719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1477719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 err; 1478719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* native gains are in millibels */ 1479719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short min_gain_mB; 1480719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short max_gain_mB; 1481719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short step_gain_mB; 1482719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1483ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_volume_query_range(h_control, 1484719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &min_gain_mB, &max_gain_mB, &step_gain_mB); 1485719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) { 1486719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett max_gain_mB = 0; 1487719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett min_gain_mB = -10000; 1488719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett step_gain_mB = VOL_STEP_mB; 1489719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1490719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1491719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1492719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 2; 1493719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.min = min_gain_mB / VOL_STEP_mB; 1494719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.max = max_gain_mB / VOL_STEP_mB; 1495719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.step = step_gain_mB / VOL_STEP_mB; 1496719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1497719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1498719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1499719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_volume_get(struct snd_kcontrol *kcontrol, 1500719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1501719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1502719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1503719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short an_gain_mB[HPI_MAX_CHANNELS]; 1504719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1505ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_volume_get_gain(h_control, an_gain_mB)); 1506719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0] = an_gain_mB[0] / VOL_STEP_mB; 1507719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[1] = an_gain_mB[1] / VOL_STEP_mB; 1508719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1509719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1510719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1511719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1512719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_volume_put(struct snd_kcontrol *kcontrol, 1513719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1514719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1515719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int change; 1516719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1517719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short an_gain_mB[HPI_MAX_CHANNELS]; 1518719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1519719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett an_gain_mB[0] = 1520719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (ucontrol->value.integer.value[0]) * VOL_STEP_mB; 1521719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett an_gain_mB[1] = 1522719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (ucontrol->value.integer.value[1]) * VOL_STEP_mB; 1523719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* change = asihpi->mixer_volume[addr][0] != left || 1524719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->mixer_volume[addr][1] != right; 1525719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 1526719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett change = 1; 1527ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_volume_set_gain(h_control, an_gain_mB)); 1528719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return change; 1529719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1530719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1531719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic const DECLARE_TLV_DB_SCALE(db_scale_100, -10000, VOL_STEP_mB, 0); 1532719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1533719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_volume_add(struct snd_card_asihpi *asihpi, 1534719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl) 1535719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1536719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 1537719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_kcontrol_new snd_control; 1538719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1539e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Volume"); 1540719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | 1541719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_CTL_ELEM_ACCESS_TLV_READ; 1542719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_volume_info; 1543719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_volume_get; 1544719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_volume_put; 1545719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.tlv.p = db_scale_100; 1546719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1547719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ctl_add(card, &snd_control, asihpi); 1548719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1549719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1550719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 1551719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Level controls 1552719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 1553719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_level_info(struct snd_kcontrol *kcontrol, 1554719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 1555719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1556719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1557719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 err; 1558719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short min_gain_mB; 1559719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short max_gain_mB; 1560719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short step_gain_mB; 1561719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1562719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = 1563ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_level_query_range(h_control, &min_gain_mB, 1564719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &max_gain_mB, &step_gain_mB); 1565719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) { 1566719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett max_gain_mB = 2400; 1567719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett min_gain_mB = -1000; 1568719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett step_gain_mB = 100; 1569719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1570719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1571719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1572719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 2; 1573719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.min = min_gain_mB / HPI_UNITS_PER_dB; 1574719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.max = max_gain_mB / HPI_UNITS_PER_dB; 1575719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.step = step_gain_mB / HPI_UNITS_PER_dB; 1576719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1577719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1578719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1579719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_level_get(struct snd_kcontrol *kcontrol, 1580719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1581719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1582719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1583719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short an_gain_mB[HPI_MAX_CHANNELS]; 1584719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1585ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_level_get_gain(h_control, an_gain_mB)); 1586719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0] = 1587719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett an_gain_mB[0] / HPI_UNITS_PER_dB; 1588719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[1] = 1589719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett an_gain_mB[1] / HPI_UNITS_PER_dB; 1590719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1591719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1592719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1593719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1594719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_level_put(struct snd_kcontrol *kcontrol, 1595719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1596719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1597719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int change; 1598719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1599719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short an_gain_mB[HPI_MAX_CHANNELS]; 1600719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1601719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett an_gain_mB[0] = 1602719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (ucontrol->value.integer.value[0]) * HPI_UNITS_PER_dB; 1603719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett an_gain_mB[1] = 1604719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (ucontrol->value.integer.value[1]) * HPI_UNITS_PER_dB; 1605719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* change = asihpi->mixer_level[addr][0] != left || 1606719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->mixer_level[addr][1] != right; 1607719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 1608719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett change = 1; 1609ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_level_set_gain(h_control, an_gain_mB)); 1610719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return change; 1611719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1612719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1613719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic const DECLARE_TLV_DB_SCALE(db_scale_level, -1000, 100, 0); 1614719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1615719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_level_add(struct snd_card_asihpi *asihpi, 1616719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl) 1617719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1618719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 1619719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_kcontrol_new snd_control; 1620719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1621719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* can't use 'volume' cos some nodes have volume as well */ 1622e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Level"); 1623719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | 1624719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_CTL_ELEM_ACCESS_TLV_READ; 1625719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_level_info; 1626719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_level_get; 1627719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_level_put; 1628719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.tlv.p = db_scale_level; 1629719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1630719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ctl_add(card, &snd_control, asihpi); 1631719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1632719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1633719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 1634719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett AESEBU controls 1635719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 1636719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1637719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* AESEBU format */ 1638ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic const char * const asihpi_aesebu_format_names[] = { 1639ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett "N/A", "S/PDIF", "AES/EBU" }; 1640719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1641719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_aesebu_format_info(struct snd_kcontrol *kcontrol, 1642719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 1643719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1644719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1645719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 1646719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.items = 3; 1647719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1648719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 1649719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.item = 1650719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.items - 1; 1651719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1652719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett strcpy(uinfo->value.enumerated.name, 1653719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi_aesebu_format_names[uinfo->value.enumerated.item]); 1654719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1655719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1656719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1657719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1658719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_aesebu_format_get(struct snd_kcontrol *kcontrol, 1659719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol, 1660ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett u16 (*func)(u32, u16 *)) 1661719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1662719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1663719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 source, err; 1664719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1665ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = func(h_control, &source); 1666719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1667719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* default to N/A */ 1668719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = 0; 1669719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* return success but set the control to N/A */ 1670719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 1671719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1672719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (source == HPI_AESEBU_FORMAT_SPDIF) 1673719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = 1; 1674719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (source == HPI_AESEBU_FORMAT_AESEBU) 1675719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = 2; 1676719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1677719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1678719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1679719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1680719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_aesebu_format_put(struct snd_kcontrol *kcontrol, 1681719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol, 1682ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett u16 (*func)(u32, u16)) 1683719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1684719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1685719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1686719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* default to S/PDIF */ 1687719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 source = HPI_AESEBU_FORMAT_SPDIF; 1688719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1689719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (ucontrol->value.enumerated.item[0] == 1) 1690719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett source = HPI_AESEBU_FORMAT_SPDIF; 1691719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (ucontrol->value.enumerated.item[0] == 2) 1692719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett source = HPI_AESEBU_FORMAT_AESEBU; 1693719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1694ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (func(h_control, source) != 0) 1695719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 1696719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1697719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 1; 1698719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1699719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1700719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_aesebu_rx_format_get(struct snd_kcontrol *kcontrol, 1701719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) { 1702719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return snd_asihpi_aesebu_format_get(kcontrol, ucontrol, 1703ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_aesebu_receiver_get_format); 1704719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1705719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1706719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_aesebu_rx_format_put(struct snd_kcontrol *kcontrol, 1707719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) { 1708719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return snd_asihpi_aesebu_format_put(kcontrol, ucontrol, 1709ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_aesebu_receiver_set_format); 1710719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1711719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1712719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_aesebu_rxstatus_info(struct snd_kcontrol *kcontrol, 1713719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 1714719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1715719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1716719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 1717719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1718719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.min = 0; 1719719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.max = 0X1F; 1720719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.step = 1; 1721719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1722719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1723719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1724719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1725719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_aesebu_rxstatus_get(struct snd_kcontrol *kcontrol, 1726719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) { 1727719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1728719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1729719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 status; 1730719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1731ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_aesebu_receiver_get_error_status( 1732ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett h_control, &status)); 1733719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0] = status; 1734719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1735719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1736719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1737719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi, 1738719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl) 1739719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1740719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 1741719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_kcontrol_new snd_control; 1742719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1743e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Format"); 1744719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; 1745719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_aesebu_format_info; 1746719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_aesebu_rx_format_get; 1747719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_aesebu_rx_format_put; 1748719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1749719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1750719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (ctl_add(card, &snd_control, asihpi) < 0) 1751719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 1752719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1753e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Status"); 1754719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = 1755719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; 1756719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_aesebu_rxstatus_info; 1757719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_aesebu_rxstatus_get; 1758719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1759719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ctl_add(card, &snd_control, asihpi); 1760719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1761719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1762719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_aesebu_tx_format_get(struct snd_kcontrol *kcontrol, 1763719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) { 1764719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return snd_asihpi_aesebu_format_get(kcontrol, ucontrol, 1765ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_aesebu_transmitter_get_format); 1766719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1767719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1768719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_aesebu_tx_format_put(struct snd_kcontrol *kcontrol, 1769719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) { 1770719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return snd_asihpi_aesebu_format_put(kcontrol, ucontrol, 1771ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_aesebu_transmitter_set_format); 1772719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1773719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1774719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1775719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_aesebu_tx_add(struct snd_card_asihpi *asihpi, 1776719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl) 1777719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1778719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 1779719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_kcontrol_new snd_control; 1780719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1781e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Format"); 1782719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; 1783719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_aesebu_format_info; 1784719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_aesebu_tx_format_get; 1785719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_aesebu_tx_format_put; 1786719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1787719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ctl_add(card, &snd_control, asihpi); 1788719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1789719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1790719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 1791719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Tuner controls 1792719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 1793719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1794719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* Gain */ 1795719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1796719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_tuner_gain_info(struct snd_kcontrol *kcontrol, 1797719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 1798719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1799719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1800719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 err; 1801719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short idx; 1802719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 gain_range[3]; 1803719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1804719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (idx = 0; idx < 3; idx++) { 1805ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_tuner_query_gain(h_control, 1806719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett idx, &gain_range[idx]); 1807719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err != 0) 1808719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 1809719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1810719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1811719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1812719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 1813719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.min = ((int)gain_range[0]) / HPI_UNITS_PER_dB; 1814719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.max = ((int)gain_range[1]) / HPI_UNITS_PER_dB; 1815719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.step = ((int) gain_range[2]) / HPI_UNITS_PER_dB; 1816719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1817719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1818719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1819719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_tuner_gain_get(struct snd_kcontrol *kcontrol, 1820719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1821719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1822719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* 1823719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol); 1824719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 1825719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1826719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short gain; 1827719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1828ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_tuner_get_gain(h_control, &gain)); 1829719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0] = gain / HPI_UNITS_PER_dB; 1830719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1831719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1832719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1833719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1834719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_tuner_gain_put(struct snd_kcontrol *kcontrol, 1835719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1836719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1837719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* 1838719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol); 1839719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 1840719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1841719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short gain; 1842719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1843719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett gain = (ucontrol->value.integer.value[0]) * HPI_UNITS_PER_dB; 1844ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_tuner_set_gain(h_control, gain)); 1845719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1846719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 1; 1847719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1848719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1849719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* Band */ 1850719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1851719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int asihpi_tuner_band_query(struct snd_kcontrol *kcontrol, 1852719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 *band_list, u32 len) { 1853719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1854719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 err = 0; 1855719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 i; 1856719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1857719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (i = 0; i < len; i++) { 1858ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_tuner_query_band( 1859719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett h_control, i, &band_list[i]); 1860719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err != 0) 1861719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 1862719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1863719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1864719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err && (err != HPI_ERROR_INVALID_OBJ_INDEX)) 1865719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EIO; 1866719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1867719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return i; 1868719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1869719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1870719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_tuner_band_info(struct snd_kcontrol *kcontrol, 1871719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 1872719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1873719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 tuner_bands[HPI_TUNER_BAND_LAST]; 1874719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int num_bands = 0; 1875719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1876719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands, 1877719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_TUNER_BAND_LAST); 1878719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1879719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (num_bands < 0) 1880719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return num_bands; 1881719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1882719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1883719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 1884719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.items = num_bands; 1885719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1886719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (num_bands > 0) { 1887719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (uinfo->value.enumerated.item >= 1888719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.items) 1889719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.item = 1890719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.items - 1; 1891719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1892719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett strcpy(uinfo->value.enumerated.name, 1893719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi_tuner_band_names[ 1894719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett tuner_bands[uinfo->value.enumerated.item]]); 1895719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1896719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1897719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1898719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1899719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1900719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_tuner_band_get(struct snd_kcontrol *kcontrol, 1901719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1902719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1903719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1904719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* 1905719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol); 1906719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 1907719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 band, idx; 1908719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 tuner_bands[HPI_TUNER_BAND_LAST]; 1909719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 num_bands = 0; 1910719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1911719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands, 1912719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_TUNER_BAND_LAST); 1913719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1914ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_tuner_get_band(h_control, &band)); 1915719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1916719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = -1; 1917719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (idx = 0; idx < HPI_TUNER_BAND_LAST; idx++) 1918719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (tuner_bands[idx] == band) { 1919719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = idx; 1920719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 1921719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1922719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1923719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1924719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1925719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1926719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_tuner_band_put(struct snd_kcontrol *kcontrol, 1927719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1928719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1929719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* 1930719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol); 1931719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 1932719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1933719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 band; 1934719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 tuner_bands[HPI_TUNER_BAND_LAST]; 1935719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 num_bands = 0; 1936719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1937719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands, 1938719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_TUNER_BAND_LAST); 1939719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1940719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett band = tuner_bands[ucontrol->value.enumerated.item[0]]; 1941ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_tuner_set_band(h_control, band)); 1942719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1943719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 1; 1944719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1945719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1946719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* Freq */ 1947719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1948719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_tuner_freq_info(struct snd_kcontrol *kcontrol, 1949719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 1950719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1951719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1952719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 err; 1953719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 tuner_bands[HPI_TUNER_BAND_LAST]; 1954719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 num_bands = 0, band_iter, idx; 1955719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 freq_range[3], temp_freq_range[3]; 1956719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1957719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands, 1958719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_TUNER_BAND_LAST); 1959719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1960719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett freq_range[0] = INT_MAX; 1961719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett freq_range[1] = 0; 1962719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett freq_range[2] = INT_MAX; 1963719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1964719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (band_iter = 0; band_iter < num_bands; band_iter++) { 1965719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (idx = 0; idx < 3; idx++) { 1966ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_tuner_query_frequency(h_control, 1967719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett idx, tuner_bands[band_iter], 1968719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &temp_freq_range[idx]); 1969719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err != 0) 1970719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 1971719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1972719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1973719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* skip band with bogus stepping */ 1974719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (temp_freq_range[2] <= 0) 1975719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett continue; 1976719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1977719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (temp_freq_range[0] < freq_range[0]) 1978719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett freq_range[0] = temp_freq_range[0]; 1979719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (temp_freq_range[1] > freq_range[1]) 1980719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett freq_range[1] = temp_freq_range[1]; 1981719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (temp_freq_range[2] < freq_range[2]) 1982719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett freq_range[2] = temp_freq_range[2]; 1983719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 1984719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1985719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1986719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 1987719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.min = ((int)freq_range[0]); 1988719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.max = ((int)freq_range[1]); 1989719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.step = ((int)freq_range[2]); 1990719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 1991719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 1992719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1993719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_tuner_freq_get(struct snd_kcontrol *kcontrol, 1994719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 1995719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 1996719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 1997719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 freq; 1998719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 1999ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_tuner_get_frequency(h_control, &freq)); 2000719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0] = freq; 2001719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2002719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2003719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2004719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2005719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_tuner_freq_put(struct snd_kcontrol *kcontrol, 2006719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2007719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2008719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2009719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 freq; 2010719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2011719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett freq = ucontrol->value.integer.value[0]; 2012ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_tuner_set_frequency(h_control, freq)); 2013719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2014719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 1; 2015719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2016719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2017719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* Tuner control group initializer */ 2018719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi, 2019719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl) 2020719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2021719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 2022719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_kcontrol_new snd_control; 2023719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2024719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.private_value = hpi_ctl->h_control; 2025719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; 2026719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2027ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (!hpi_tuner_get_gain(hpi_ctl->h_control, NULL)) { 2028e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Gain"); 2029719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_tuner_gain_info; 2030719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_tuner_gain_get; 2031719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_tuner_gain_put; 2032719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2033719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (ctl_add(card, &snd_control, asihpi) < 0) 2034719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 2035719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2036719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2037e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Band"); 2038719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_tuner_band_info; 2039719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_tuner_band_get; 2040719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_tuner_band_put; 2041719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2042719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (ctl_add(card, &snd_control, asihpi) < 0) 2043719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 2044719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2045e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Freq"); 2046719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_tuner_freq_info; 2047719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_tuner_freq_get; 2048719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_tuner_freq_put; 2049719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2050719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ctl_add(card, &snd_control, asihpi); 2051719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2052719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2053719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 2054719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Meter controls 2055719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 2056719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_meter_info(struct snd_kcontrol *kcontrol, 2057719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 2058719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2059719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 2060719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = HPI_MAX_CHANNELS; 2061719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.min = 0; 2062719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.max = 0x7FFFFFFF; 2063719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2064719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2065719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2066719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* linear values for 10dB steps */ 2067719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int log2lin[] = { 2068719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 0x7FFFFFFF, /* 0dB */ 2069719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 679093956, 2070719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 214748365, 2071719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 67909396, 2072719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 21474837, 2073719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 6790940, 2074719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2147484, /* -60dB */ 2075719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 679094, 2076719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 214748, /* -80 */ 2077719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 67909, 2078719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 21475, /* -100 */ 2079719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 6791, 2080719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2147, 2081719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 679, 2082719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 214, 2083719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 68, 2084719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 21, 2085719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 7, 2086719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2 2087719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 2088719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2089719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_meter_get(struct snd_kcontrol *kcontrol, 2090719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2091719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2092719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2093719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett short an_gain_mB[HPI_MAX_CHANNELS], i; 2094719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 err; 2095719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2096ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_meter_get_peak(h_control, an_gain_mB); 2097719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2098719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (i = 0; i < HPI_MAX_CHANNELS; i++) { 2099719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) { 2100719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[i] = 0; 2101719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else if (an_gain_mB[i] >= 0) { 2102719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[i] = 2103719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett an_gain_mB[i] << 16; 2104719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else { 2105719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* -ve is log value in millibels < -60dB, 2106719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett * convert to (roughly!) linear, 2107719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 2108719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[i] = 2109719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett log2lin[an_gain_mB[i] / -1000]; 2110719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2111719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2112719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2113719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2114719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2115719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_meter_add(struct snd_card_asihpi *asihpi, 2116719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl, int subidx) 2117719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2118719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 2119719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_kcontrol_new snd_control; 2120719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2121e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Meter"); 2122719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = 2123719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; 2124719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_meter_info; 2125719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_meter_get; 2126719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2127719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.index = subidx; 2128719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2129719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ctl_add(card, &snd_control, asihpi); 2130719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2131719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2132719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 2133719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Multiplexer controls 2134719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 2135719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_card_asihpi_mux_count_sources(struct snd_kcontrol *snd_control) 2136719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2137719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = snd_control->private_value; 2138719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control hpi_ctl; 2139719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int s, err; 2140719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (s = 0; s < 32; s++) { 2141ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_multiplexer_query_source(h_control, s, 2142719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_ctl. 2143719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett src_node_type, 2144719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_ctl. 2145719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett src_node_index); 2146719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 2147719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2148719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2149719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return s; 2150719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2151719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2152719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_mux_info(struct snd_kcontrol *kcontrol, 2153719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 2154719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2155719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 2156719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 src_node_type, src_node_index; 2157719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2158719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2159719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2160719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 2161719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.items = 2162719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_asihpi_mux_count_sources(kcontrol); 2163719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2164719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 2165719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.item = 2166719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.items - 1; 2167719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2168719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = 2169ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_multiplexer_query_source(h_control, 2170719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.item, 2171719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &src_node_type, &src_node_index); 2172719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2173719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett sprintf(uinfo->value.enumerated.name, "%s %d", 2174168f1b07ccc0e8edecb67fab2d0670861853e2fdEliot Blennerhassett asihpi_src_names[src_node_type - HPI_SOURCENODE_NONE], 2175719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett src_node_index); 2176719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2177719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2178719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2179719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_mux_get(struct snd_kcontrol *kcontrol, 2180719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2181719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2182719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2183719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 source_type, source_index; 2184719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 src_node_type, src_node_index; 2185719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int s; 2186719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2187ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_multiplexer_get_source(h_control, 2188719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &source_type, &source_index)); 2189719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* Should cache this search result! */ 2190719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (s = 0; s < 256; s++) { 2191ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (hpi_multiplexer_query_source(h_control, s, 2192719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &src_node_type, &src_node_index)) 2193719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2194719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2195719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if ((source_type == src_node_type) 2196719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett && (source_index == src_node_index)) { 2197719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = s; 2198719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2199719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2200719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2201719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printd(KERN_WARNING 2202e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Control %x failed to match mux source %hu %hu\n", 2203719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett h_control, source_type, source_index); 2204719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = 0; 2205719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2206719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2207719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2208719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_mux_put(struct snd_kcontrol *kcontrol, 2209719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2210719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2211719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int change; 2212719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2213719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 source_type, source_index; 2214719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 e; 2215719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2216719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett change = 1; 2217719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2218ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett e = hpi_multiplexer_query_source(h_control, 2219719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0], 2220719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &source_type, &source_index); 2221719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!e) 2222719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error( 2223ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_multiplexer_set_source(h_control, 2224719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett source_type, source_index)); 2225719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return change; 2226719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2227719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2228719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2229719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_mux_add(struct snd_card_asihpi *asihpi, 2230719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl) 2231719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2232719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 2233719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_kcontrol_new snd_control; 2234719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2235e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Route"); 2236719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; 2237719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_mux_info; 2238719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_mux_get; 2239719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_mux_put; 2240719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2241719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ctl_add(card, &snd_control, asihpi); 2242719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2243719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2244719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2245719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 2246719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Channel mode controls 2247719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 2248719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_cmode_info(struct snd_kcontrol *kcontrol, 2249719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 2250719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2251e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett static const char * const mode_names[HPI_CHANNEL_MODE_LAST + 1] = { 2252e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "invalid", 2253e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Normal", "Swap", 2254e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "From Left", "From Right", 2255e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "To Left", "To Right" 2256719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett }; 2257719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2258719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2259719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 mode; 2260719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int i; 2261e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett u16 mode_map[6]; 2262e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett int valid_modes = 0; 2263719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2264719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* HPI channel mode values can be from 1 to 6 2265719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Some adapters only support a contiguous subset 2266719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 2267719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (i = 0; i < HPI_CHANNEL_MODE_LAST; i++) 2268e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett if (!hpi_channel_mode_query_mode( 2269ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett h_control, i, &mode)) { 2270e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett mode_map[valid_modes] = mode; 2271e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett valid_modes++; 2272e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett } 2273719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2274719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2275719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 2276e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett uinfo->value.enumerated.items = valid_modes; 2277719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2278e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett if (uinfo->value.enumerated.item >= valid_modes) 2279e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett uinfo->value.enumerated.item = valid_modes - 1; 2280719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2281719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett strcpy(uinfo->value.enumerated.name, 2282e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett mode_names[mode_map[uinfo->value.enumerated.item]]); 2283719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2284719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2285719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2286719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2287719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_cmode_get(struct snd_kcontrol *kcontrol, 2288719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2289719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2290719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2291719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 mode; 2292719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2293ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (hpi_channel_mode_get(h_control, &mode)) 2294719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett mode = 1; 2295719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2296719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = mode - 1; 2297719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2298719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2299719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2300719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2301719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_cmode_put(struct snd_kcontrol *kcontrol, 2302719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2303719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2304719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int change; 2305719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2306719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2307719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett change = 1; 2308719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2309ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_channel_mode_set(h_control, 2310719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] + 1)); 2311719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return change; 2312719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2313719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2314719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2315719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_cmode_add(struct snd_card_asihpi *asihpi, 2316719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl) 2317719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2318719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 2319719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_kcontrol_new snd_control; 2320719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2321e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Mode"); 2322719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; 2323719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_cmode_info; 2324719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_cmode_get; 2325719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_cmode_put; 2326719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2327719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ctl_add(card, &snd_control, asihpi); 2328719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2329719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2330719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 2331719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Sampleclock source controls 2332719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 2333ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassettstatic char *sampleclock_sources[MAX_CLOCKSOURCES] = { 2334ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett "N/A", "Local PLL", "Digital Sync", "Word External", "Word Header", 2335ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett "SMPTE", "Digital1", "Auto", "Network", "Invalid", 2336ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett "Prev Module", 2337ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett "Digital2", "Digital3", "Digital4", "Digital5", 2338ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett "Digital6", "Digital7", "Digital8"}; 2339719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2340719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_clksrc_info(struct snd_kcontrol *kcontrol, 2341719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 2342719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2343719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi = 2344719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (struct snd_card_asihpi *)(kcontrol->private_data); 2345719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct clk_cache *clkcache = &asihpi->cc; 2346719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2347719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 2348719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.items = clkcache->count; 2349719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2350719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 2351719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.item = 2352719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.enumerated.items - 1; 2353719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2354719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett strcpy(uinfo->value.enumerated.name, 2355719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->s[uinfo->value.enumerated.item].name); 2356719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2357719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2358719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2359719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_clksrc_get(struct snd_kcontrol *kcontrol, 2360719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2361719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2362719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi = 2363719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (struct snd_card_asihpi *)(kcontrol->private_data); 2364719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct clk_cache *clkcache = &asihpi->cc; 2365719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2366719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 source, srcindex = 0; 2367719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int i; 2368719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2369719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = 0; 2370ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (hpi_sample_clock_get_source(h_control, &source)) 2371719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett source = 0; 2372719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2373719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT) 2374ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (hpi_sample_clock_get_source_index(h_control, &srcindex)) 2375719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett srcindex = 0; 2376719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2377719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (i = 0; i < clkcache->count; i++) 2378719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if ((clkcache->s[i].source == source) && 2379719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (clkcache->s[i].index == srcindex)) 2380719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2381719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2382719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.enumerated.item[0] = i; 2383719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2384719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2385719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2386719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2387719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_clksrc_put(struct snd_kcontrol *kcontrol, 2388719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2389719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2390719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi = 2391719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (struct snd_card_asihpi *)(kcontrol->private_data); 2392719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct clk_cache *clkcache = &asihpi->cc; 2393719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int change, item; 2394719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2395719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2396719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett change = 1; 2397719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett item = ucontrol->value.enumerated.item[0]; 2398719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (item >= clkcache->count) 2399719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett item = clkcache->count-1; 2400719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2401ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_sample_clock_set_source( 2402719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett h_control, clkcache->s[item].source)); 2403719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2404719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (clkcache->s[item].source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT) 2405ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_sample_clock_set_source_index( 2406719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett h_control, clkcache->s[item].index)); 2407719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return change; 2408719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2409719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2410719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 2411719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Clkrate controls 2412719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 2413719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* Need to change this to enumerated control with list of rates */ 2414719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_clklocal_info(struct snd_kcontrol *kcontrol, 2415719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 2416719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2417719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 2418719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 2419719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.min = 8000; 2420719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.max = 192000; 2421719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.step = 100; 2422719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2423719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2424719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2425719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2426719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_clklocal_get(struct snd_kcontrol *kcontrol, 2427719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2428719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2429719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2430719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 rate; 2431719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 e; 2432719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2433ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett e = hpi_sample_clock_get_local_rate(h_control, &rate); 2434719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!e) 2435719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0] = rate; 2436719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 2437719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0] = 0; 2438719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2439719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2440719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2441719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_clklocal_put(struct snd_kcontrol *kcontrol, 2442719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2443719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2444719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int change; 2445719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2446719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2447719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* change = asihpi->mixer_clkrate[addr][0] != left || 2448719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->mixer_clkrate[addr][1] != right; 2449719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 2450719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett change = 1; 2451ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_sample_clock_set_local_rate(h_control, 2452719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0])); 2453719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return change; 2454719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2455719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2456719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_clkrate_info(struct snd_kcontrol *kcontrol, 2457719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_info *uinfo) 2458719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2459719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 2460719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->count = 1; 2461719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.min = 8000; 2462719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.max = 192000; 2463719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett uinfo->value.integer.step = 100; 2464719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2465719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2466719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2467719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2468719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_clkrate_get(struct snd_kcontrol *kcontrol, 2469719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_ctl_elem_value *ucontrol) 2470719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2471719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control = kcontrol->private_value; 2472719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 rate; 2473719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 e; 2474719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2475ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett e = hpi_sample_clock_get_sample_rate(h_control, &rate); 2476719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!e) 2477719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0] = rate; 2478719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 2479719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ucontrol->value.integer.value[0] = 0; 2480719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2481719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2482719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2483719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi, 2484719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control *hpi_ctl) 2485719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2486719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 2487719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_kcontrol_new snd_control; 2488719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2489719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct clk_cache *clkcache = &asihpi->cc; 2490719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 hSC = hpi_ctl->h_control; 2491719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int has_aes_in = 0; 2492719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int i, j; 2493719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 source; 2494719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2495719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.private_value = hpi_ctl->h_control; 2496719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2497719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->has_local = 0; 2498719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2499719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (i = 0; i <= HPI_SAMPLECLOCK_SOURCE_LAST; i++) { 2500ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (hpi_sample_clock_query_source(hSC, 2501719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett i, &source)) 2502719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2503719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->s[i].source = source; 2504719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->s[i].index = 0; 2505719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->s[i].name = sampleclock_sources[source]; 2506719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT) 2507719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett has_aes_in = 1; 2508719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (source == HPI_SAMPLECLOCK_SOURCE_LOCAL) 2509719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->has_local = 1; 2510719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2511719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (has_aes_in) 2512719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* already will have picked up index 0 above */ 2513719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (j = 1; j < 8; j++) { 2514ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett if (hpi_sample_clock_query_source_index(hSC, 2515719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett j, HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT, 2516719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &source)) 2517719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2518719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->s[i].source = 2519719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT; 2520719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->s[i].index = j; 2521719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->s[i].name = sampleclock_sources[ 2522719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett j+HPI_SAMPLECLOCK_SOURCE_LAST]; 2523719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett i++; 2524719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2525719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett clkcache->count = i; 2526719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2527e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Source"); 2528719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ; 2529719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_clksrc_info; 2530719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_clksrc_get; 2531719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_clksrc_put; 2532719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (ctl_add(card, &snd_control, asihpi) < 0) 2533719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 2534719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2535719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2536719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (clkcache->has_local) { 2537e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Localrate"); 2538719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ; 2539719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_clklocal_info; 2540719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_clklocal_get; 2541719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.put = snd_asihpi_clklocal_put; 2542719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2543719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2544719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (ctl_add(card, &snd_control, asihpi) < 0) 2545719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 2546719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2547719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2548e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett asihpi_ctl_init(&snd_control, hpi_ctl, "Rate"); 2549719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.access = 2550719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; 2551719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.info = snd_asihpi_clkrate_info; 2552719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_control.get = snd_asihpi_clkrate_get; 2553719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2554719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return ctl_add(card, &snd_control, asihpi); 2555719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2556719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 2557719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Mixer 2558719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 2559719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2560719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi) 2561719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2562719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card = asihpi->card; 2563719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int idx = 0; 2564719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int subindex = 0; 2565719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 2566719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_control hpi_ctl, prev_ctl; 2567719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2568719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (snd_BUG_ON(!asihpi)) 2569719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -EINVAL; 2570e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett strcpy(card->mixername, "Asihpi Mixer"); 2571719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2572719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = 2573ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_mixer_open(asihpi->adapter_index, 2574719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &asihpi->h_mixer); 2575719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error(err); 2576719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 2577719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -err; 2578719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 257921896bc010c17e5ac58951e771496ec2fb1051edTakashi Iwai memset(&prev_ctl, 0, sizeof(prev_ctl)); 258021896bc010c17e5ac58951e771496ec2fb1051edTakashi Iwai prev_ctl.control_type = -1; 258121896bc010c17e5ac58951e771496ec2fb1051edTakashi Iwai 2582719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for (idx = 0; idx < 2000; idx++) { 2583719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = hpi_mixer_get_control_by_index( 2584ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett asihpi->h_mixer, 2585719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett idx, 2586719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_ctl.src_node_type, 2587719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_ctl.src_node_index, 2588719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_ctl.dst_node_type, 2589719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_ctl.dst_node_index, 2590719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_ctl.control_type, 2591719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &hpi_ctl.h_control); 2592719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) { 2593719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err == HPI_ERROR_CONTROL_DISABLED) { 2594719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (mixer_dump) 2595719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_INFO 2596e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Disabled HPI Control(%d)\n", 2597719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett idx); 2598719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett continue; 2599719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } else 2600719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2601719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2602719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2603719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2604168f1b07ccc0e8edecb67fab2d0670861853e2fdEliot Blennerhassett hpi_ctl.src_node_type -= HPI_SOURCENODE_NONE; 2605168f1b07ccc0e8edecb67fab2d0670861853e2fdEliot Blennerhassett hpi_ctl.dst_node_type -= HPI_DESTNODE_NONE; 2606719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2607719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* ASI50xx in SSX mode has multiple meters on the same node. 2608719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett Use subindex to create distinct ALSA controls 2609719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett for any duplicated controls. 2610719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett */ 2611719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if ((hpi_ctl.control_type == prev_ctl.control_type) && 2612719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (hpi_ctl.src_node_type == prev_ctl.src_node_type) && 2613719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (hpi_ctl.src_node_index == prev_ctl.src_node_index) && 2614719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (hpi_ctl.dst_node_type == prev_ctl.dst_node_type) && 2615719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (hpi_ctl.dst_node_index == prev_ctl.dst_node_index)) 2616719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett subindex++; 2617719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 2618719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett subindex = 0; 2619719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2620719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett prev_ctl = hpi_ctl; 2621719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2622719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett switch (hpi_ctl.control_type) { 2623719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_VOLUME: 2624719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_asihpi_volume_add(asihpi, &hpi_ctl); 2625719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2626719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_LEVEL: 2627719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_asihpi_level_add(asihpi, &hpi_ctl); 2628719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2629719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_MULTIPLEXER: 2630719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_asihpi_mux_add(asihpi, &hpi_ctl); 2631719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2632719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_CHANNEL_MODE: 2633719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_asihpi_cmode_add(asihpi, &hpi_ctl); 2634719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2635719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_METER: 2636719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_asihpi_meter_add(asihpi, &hpi_ctl, subindex); 2637719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2638719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_SAMPLECLOCK: 2639719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_asihpi_sampleclock_add( 2640719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi, &hpi_ctl); 2641719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2642719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_CONNECTION: /* ignore these */ 2643719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett continue; 2644719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_TUNER: 2645719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_asihpi_tuner_add(asihpi, &hpi_ctl); 2646719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2647719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_AESEBU_TRANSMITTER: 2648719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_asihpi_aesebu_tx_add(asihpi, &hpi_ctl); 2649719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2650719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_AESEBU_RECEIVER: 2651719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_asihpi_aesebu_rx_add(asihpi, &hpi_ctl); 2652719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett break; 2653719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_VOX: 2654719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_BITSTREAM: 2655719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_MICROPHONE: 2656719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_PARAMETRIC_EQ: 2657719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett case HPI_CONTROL_COMPANDER: 2658719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett default: 2659719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (mixer_dump) 2660719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_INFO 2661e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Untranslated HPI Control" 2662719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "(%d) %d %d %d %d %d\n", 2663719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett idx, 2664719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_ctl.control_type, 2665719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_ctl.src_node_type, 2666719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_ctl.src_node_index, 2667719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_ctl.dst_node_type, 2668719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_ctl.dst_node_index); 2669719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett continue; 2670719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett }; 2671719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) 2672719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 2673719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2674719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (HPI_ERROR_INVALID_OBJ_INDEX != err) 2675719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_handle_error(err); 2676719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2677719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_INFO "%d mixer controls found\n", idx); 2678719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2679719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2680719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2681719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2682719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 2683719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /proc interface 2684719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 2685719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2686719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void 2687719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettsnd_asihpi_proc_read(struct snd_info_entry *entry, 2688719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_info_buffer *buffer) 2689719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2690719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi = entry->private_data; 2691719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 version; 2692719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control; 2693719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 rate = 0; 2694719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 source = 0; 2695719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 2696719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2697719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_iprintf(buffer, "ASIHPI driver proc file\n"); 2698719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_iprintf(buffer, 2699719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "adapter ID=%4X\n_index=%d\n" 2700719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "num_outstreams=%d\n_num_instreams=%d\n", 2701719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->type, asihpi->adapter_index, 2702719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->num_outstreams, asihpi->num_instreams); 2703719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2704719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett version = asihpi->version; 2705719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_iprintf(buffer, 2706719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "serial#=%d\n_hw version %c%d\nDSP code version %03d\n", 2707719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->serial_number, ((version >> 3) & 0xf) + 'A', 2708719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett version & 0x7, 2709719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ((version >> 13) * 100) + ((version >> 7) & 0x3f)); 2710719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2711ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_mixer_get_control(asihpi->h_mixer, 2712719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, 2713719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_CONTROL_SAMPLECLOCK, &h_control); 2714719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2715719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err) { 2716ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_sample_clock_get_sample_rate( 2717719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett h_control, &rate); 2718ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err += hpi_sample_clock_get_source(h_control, &source); 2719719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2720719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err) 2721719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_iprintf(buffer, "sample_clock=%d_hz, source %s\n", 2722719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett rate, sampleclock_sources[source]); 2723719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2724719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2725719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2726719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2727719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2728719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void __devinit snd_asihpi_proc_init(struct snd_card_asihpi *asihpi) 2729719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2730719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_info_entry *entry; 2731719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2732719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!snd_card_proc_new(asihpi->card, "info", &entry)) 2733719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_info_set_text_ops(entry, asihpi, snd_asihpi_proc_read); 2734719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2735719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2736719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 2737719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HWDEP 2738719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 2739719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2740719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_hpi_open(struct snd_hwdep *hw, struct file *file) 2741719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2742719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (enable_hpi_hwdep) 2743719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2744719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 2745719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -ENODEV; 2746719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2747719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2748719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2749719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_hpi_release(struct snd_hwdep *hw, struct file *file) 2750719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2751719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (enable_hpi_hwdep) 2752719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return asihpi_hpi_release(file); 2753719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 2754719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -ENODEV; 2755719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2756719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2757719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int snd_asihpi_hpi_ioctl(struct snd_hwdep *hw, struct file *file, 2758719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett unsigned int cmd, unsigned long arg) 2759719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2760719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (enable_hpi_hwdep) 2761719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return asihpi_hpi_ioctl(file, cmd, arg); 2762719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 2763719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -ENODEV; 2764719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2765719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2766719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2767719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* results in /dev/snd/hwC#D0 file for each card with index # 2768719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett also /proc/asound/hwdep will contain '#-00: asihpi (HPI) for each card' 2769719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett*/ 2770719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi, 2771719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int device, struct snd_hwdep **rhwdep) 2772719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2773719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_hwdep *hw; 2774719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 2775719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2776719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (rhwdep) 2777719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett *rhwdep = NULL; 2778719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_hwdep_new(asihpi->card, "HPI", device, &hw); 2779719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) 2780719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 2781719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett strcpy(hw->name, "asihpi (HPI)"); 2782719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hw->iface = SNDRV_HWDEP_IFACE_LAST; 2783719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hw->ops.open = snd_asihpi_hpi_open; 2784719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hw->ops.ioctl = snd_asihpi_hpi_ioctl; 2785719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hw->ops.release = snd_asihpi_hpi_release; 2786719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hw->private_data = asihpi; 2787719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (rhwdep) 2788719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett *rhwdep = hw; 2789719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2790719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2791719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2792719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/*------------------------------------------------------------ 2793719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett CARD 2794719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ------------------------------------------------------------*/ 2795719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __devinit snd_asihpi_probe(struct pci_dev *pci_dev, 2796719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett const struct pci_device_id *pci_id) 2797719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2798719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int err; 2799719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2800719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u16 version; 2801719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett int pcm_substreams; 2802719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2803719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_adapter *hpi_card; 2804719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card *card; 2805719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct snd_card_asihpi *asihpi; 2806719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2807719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_control; 2808719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett u32 h_stream; 2809719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2810719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett static int dev; 2811719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (dev >= SNDRV_CARDS) 2812719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -ENODEV; 2813719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2814719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* Should this be enable[hpi_card->index] ? */ 2815719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!enable[dev]) { 2816719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dev++; 2817719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return -ENOENT; 2818719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2819719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2820719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = asihpi_adapter_probe(pci_dev, pci_id); 2821719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) 2822719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 2823719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2824719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_card = pci_get_drvdata(pci_dev); 2825719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* first try to give the card the same index as its hardware index */ 2826719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_card_create(hpi_card->index, 2827719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett id[hpi_card->index], THIS_MODULE, 2828719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett sizeof(struct snd_card_asihpi), 2829719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &card); 2830719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) { 2831719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* if that fails, try the default index==next available */ 2832719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = 2833719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_create(index[dev], id[dev], 2834719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett THIS_MODULE, 2835719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett sizeof(struct snd_card_asihpi), 2836719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &card); 2837719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) 2838719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 2839719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_WARNING 2840e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "**** WARNING **** Adapter index %d->ALSA index %d\n", 2841719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_card->index, card->number); 2842719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2843719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 28441225367a481ae751738630158c7ca96aa1c7bac8Eliot Blennerhassett snd_card_set_dev(card, &pci_dev->dev); 28451225367a481ae751738630158c7ca96aa1c7bac8Eliot Blennerhassett 2846719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi = (struct snd_card_asihpi *) card->private_data; 2847719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->card = card; 28481225367a481ae751738630158c7ca96aa1c7bac8Eliot Blennerhassett asihpi->pci = pci_dev; 2849719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->adapter_index = hpi_card->index; 2850ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_adapter_get_info( 2851719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->adapter_index, 2852719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &asihpi->num_outstreams, 2853719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &asihpi->num_instreams, 2854719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &asihpi->version, 2855719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &asihpi->serial_number, &asihpi->type)); 2856719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2857719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett version = asihpi->version; 2858719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_INFO "adapter ID=%4X index=%d num_outstreams=%d " 2859719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett "num_instreams=%d S/N=%d\n" 2860e64b1a28c532009edd6a8a7b906c280fc2a4b90aEliot Blennerhassett "Hw Version %c%d DSP code version %03d\n", 2861719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->type, asihpi->adapter_index, 2862719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->num_outstreams, 2863719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->num_instreams, asihpi->serial_number, 2864719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ((version >> 3) & 0xf) + 'A', 2865719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett version & 0x7, 2866719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ((version >> 13) * 100) + ((version >> 7) & 0x3f)); 2867719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2868719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pcm_substreams = asihpi->num_outstreams; 2869719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (pcm_substreams < asihpi->num_instreams) 2870719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pcm_substreams = asihpi->num_instreams; 2871719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2872ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_adapter_get_property(asihpi->adapter_index, 2873719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_ADAPTER_PROPERTY_CAPS1, 2874719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett NULL, &asihpi->support_grouping); 2875719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 2876719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->support_grouping = 0; 2877719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2878ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_adapter_get_property(asihpi->adapter_index, 2879719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_ADAPTER_PROPERTY_CAPS2, 2880719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &asihpi->support_mrx, NULL); 2881719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 2882719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->support_mrx = 0; 2883719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2884ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_adapter_get_property(asihpi->adapter_index, 2885719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_ADAPTER_PROPERTY_INTERVAL, 2886719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett NULL, &asihpi->update_interval_frames); 2887719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) 2888719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->update_interval_frames = 512; 2889719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2890ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_instream_open(asihpi->adapter_index, 2891719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 0, &h_stream)); 2892719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2893ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_instream_host_buffer_free(h_stream); 2894719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->support_mmap = (!err); 2895719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2896ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett hpi_handle_error(hpi_instream_close(h_stream)); 2897719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2898ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_adapter_get_property(asihpi->adapter_index, 2899719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_ADAPTER_PROPERTY_CURCHANNELS, 2900719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett &asihpi->in_max_chans, &asihpi->out_max_chans); 2901719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err) { 2902719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->in_max_chans = 2; 2903719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->out_max_chans = 2; 2904719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2905719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2906719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_INFO "supports mmap:%d grouping:%d mrx:%d\n", 2907719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->support_mmap, 2908719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->support_grouping, 2909719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi->support_mrx 2910719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett ); 2911719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2912719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2913719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_card_asihpi_pcm_new(asihpi, 0, pcm_substreams); 2914719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) { 2915719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_ERR "pcm_new failed\n"); 2916719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett goto __nodev; 2917719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2918719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_card_asihpi_mixer_new(asihpi); 2919719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (err < 0) { 2920719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_ERR "mixer_new failed\n"); 2921719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett goto __nodev; 2922719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2923719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2924ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett err = hpi_mixer_get_control(asihpi->h_mixer, 2925719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, 2926719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_CONTROL_SAMPLECLOCK, &h_control); 2927719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2928719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err) 2929719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = hpi_sample_clock_set_local_rate( 2930ba94455c29c383713c360537b6323e3bd4c76434Eliot Blennerhassett h_control, adapter_fs); 2931719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2932719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_asihpi_proc_init(asihpi); 2933719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2934719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett /* always create, can be enabled or disabled dynamically 2935719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett by enable_hwdep module param*/ 2936719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_asihpi_hpi_new(asihpi, 0, NULL); 2937719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2938719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (asihpi->support_mmap) 2939719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett strcpy(card->driver, "ASIHPI-MMAP"); 2940719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett else 2941719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett strcpy(card->driver, "ASIHPI"); 2942719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2943719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett sprintf(card->shortname, "AudioScience ASI%4X", asihpi->type); 2944719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett sprintf(card->longname, "%s %i", 2945719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett card->shortname, asihpi->adapter_index); 2946719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett err = snd_card_register(card); 2947719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett if (!err) { 2948719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_card->snd_card_asihpi = card; 2949719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett dev++; 2950719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return 0; 2951719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett } 2952719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett__nodev: 2953719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_free(card); 2954719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_printk(KERN_ERR "snd_asihpi_probe error %d\n", err); 2955719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return err; 2956719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2957719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2958719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2959719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void __devexit snd_asihpi_remove(struct pci_dev *pci_dev) 2960719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2961719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett struct hpi_adapter *hpi_card = pci_get_drvdata(pci_dev); 2962719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2963719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett snd_card_free(hpi_card->snd_card_asihpi); 2964719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett hpi_card->snd_card_asihpi = NULL; 2965719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi_adapter_remove(pci_dev); 2966719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2967719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2968719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic DEFINE_PCI_DEVICE_TABLE(asihpi_pci_tbl) = { 2969719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett {HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_DSP6205, 2970719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0, 2971719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (kernel_ulong_t)HPI_6205}, 2972719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett {HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_PCI2040, 2973719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0, 2974719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett (kernel_ulong_t)HPI_6000}, 2975719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett {0,} 2976719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 2977719f82d3987aad4cc9f46d19c35f362672545cadEliot BlennerhassettMODULE_DEVICE_TABLE(pci, asihpi_pci_tbl); 2978719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2979719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic struct pci_driver driver = { 2980719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .name = "asihpi", 2981719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .id_table = asihpi_pci_tbl, 2982719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .probe = snd_asihpi_probe, 2983719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .remove = __devexit_p(snd_asihpi_remove), 2984719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#ifdef CONFIG_PM 2985719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett/* .suspend = snd_asihpi_suspend, 2986719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett .resume = snd_asihpi_resume, */ 2987719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett#endif 2988719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett}; 2989719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2990719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic int __init snd_asihpi_init(void) 2991719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2992719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi_init(); 2993719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett return pci_register_driver(&driver); 2994719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 2995719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2996719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettstatic void __exit snd_asihpi_exit(void) 2997719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett{ 2998719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 2999719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett pci_unregister_driver(&driver); 3000719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett asihpi_exit(); 3001719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett} 3002719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 3003719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettmodule_init(snd_asihpi_init) 3004719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassettmodule_exit(snd_asihpi_exit) 3005719f82d3987aad4cc9f46d19c35f362672545cadEliot Blennerhassett 3006