brintos

brintos / linux-shallow public Read only

0
0
Text · 80.5 KiB · fdd4fe1 Raw
2964 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 *  Asihpi soundcard4 *  Copyright (c) by AudioScience Inc <support@audioscience.com>5 *6 *  The following is not a condition of use, merely a request:7 *  If you modify this program, particularly if you fix errors, AudioScience Inc8 *  would appreciate it if you grant us the right to use those modifications9 *  for any purpose including commercial applications.10 */11 12#include "hpi_internal.h"13#include "hpi_version.h"14#include "hpimsginit.h"15#include "hpioctl.h"16#include "hpicmn.h"17 18#include <linux/pci.h>19#include <linux/init.h>20#include <linux/jiffies.h>21#include <linux/slab.h>22#include <linux/time.h>23#include <linux/wait.h>24#include <linux/module.h>25#include <sound/core.h>26#include <sound/control.h>27#include <sound/pcm.h>28#include <sound/pcm_params.h>29#include <sound/info.h>30#include <sound/initval.h>31#include <sound/tlv.h>32#include <sound/hwdep.h>33 34MODULE_LICENSE("GPL");35MODULE_AUTHOR("AudioScience inc. <support@audioscience.com>");36MODULE_DESCRIPTION("AudioScience ALSA ASI5xxx ASI6xxx ASI87xx ASI89xx "37			HPI_VER_STRING);38 39#ifdef ASIHPI_VERBOSE_DEBUG40#define asihpi_dbg(format, args...) pr_debug(format, ##args)41#else42#define asihpi_dbg(format, args...) do { } while (0)43#endif44 45static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* index 0-MAX */46static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */47static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;48static bool enable_hpi_hwdep = 1;49 50module_param_array(index, int, NULL, 0444);51MODULE_PARM_DESC(index, "ALSA index value for AudioScience soundcard.");52 53module_param_array(id, charp, NULL, 0444);54MODULE_PARM_DESC(id, "ALSA ID string for AudioScience soundcard.");55 56module_param_array(enable, bool, NULL, 0444);57MODULE_PARM_DESC(enable, "ALSA enable AudioScience soundcard.");58 59module_param(enable_hpi_hwdep, bool, 0644);60MODULE_PARM_DESC(enable_hpi_hwdep,61		"ALSA enable HPI hwdep for AudioScience soundcard ");62 63/* identify driver */64#ifdef KERNEL_ALSA_BUILD65static char *build_info = "Built using headers from kernel source";66module_param(build_info, charp, 0444);67MODULE_PARM_DESC(build_info, "Built using headers from kernel source");68#else69static char *build_info = "Built within ALSA source";70module_param(build_info, charp, 0444);71MODULE_PARM_DESC(build_info, "Built within ALSA source");72#endif73 74/* set to 1 to dump every control from adapter to log */75static const int mixer_dump;76 77#define DEFAULT_SAMPLERATE 4410078static int adapter_fs = DEFAULT_SAMPLERATE;79 80/* defaults */81#define PERIODS_MIN 282#define PERIOD_BYTES_MIN  204883#define BUFFER_BYTES_MAX (512 * 1024)84 85#define MAX_CLOCKSOURCES (HPI_SAMPLECLOCK_SOURCE_LAST + 1 + 7)86 87struct clk_source {88	int source;89	int index;90	const char *name;91};92 93struct clk_cache {94	int count;95	int has_local;96	struct clk_source s[MAX_CLOCKSOURCES];97};98 99/* Per card data */100struct snd_card_asihpi {101	struct snd_card *card;102	struct pci_dev *pci;103	struct hpi_adapter *hpi;104 105	/* In low latency mode there is only one stream, a pointer to its106	 * private data is stored here on trigger and cleared on stop.107	 * The interrupt handler uses it as a parameter when calling108	 * snd_card_asihpi_timer_function().109	 */110	struct snd_card_asihpi_pcm *llmode_streampriv;111	void (*pcm_start)(struct snd_pcm_substream *substream);112	void (*pcm_stop)(struct snd_pcm_substream *substream);113 114	u32 h_mixer;115	struct clk_cache cc;116 117	u16 can_dma;118	u16 support_grouping;119	u16 support_mrx;120	u16 update_interval_frames;121	u16 in_max_chans;122	u16 out_max_chans;123	u16 in_min_chans;124	u16 out_min_chans;125};126 127/* Per stream data */128struct snd_card_asihpi_pcm {129	struct timer_list timer;130	unsigned int respawn_timer;131	unsigned int hpi_buffer_attached;132	unsigned int buffer_bytes;133	unsigned int period_bytes;134	unsigned int bytes_per_sec;135	unsigned int pcm_buf_host_rw_ofs; /* Host R/W pos */136	unsigned int pcm_buf_dma_ofs;	/* DMA R/W offset in buffer */137	unsigned int pcm_buf_elapsed_dma_ofs;	/* DMA R/W offset in buffer */138	unsigned int drained_count;139	struct snd_pcm_substream *substream;140	u32 h_stream;141	struct hpi_format format;142};143 144/* universal stream verbs work with out or in stream handles */145 146/* Functions to allow driver to give a buffer to HPI for busmastering */147 148static u16 hpi_stream_host_buffer_attach(149	u32 h_stream,   /* handle to outstream. */150	u32 size_in_bytes, /* size in bytes of bus mastering buffer */151	u32 pci_address152)153{154	struct hpi_message hm;155	struct hpi_response hr;156	unsigned int obj = hpi_handle_object(h_stream);157 158	if (!h_stream)159		return HPI_ERROR_INVALID_OBJ;160	hpi_init_message_response(&hm, &hr, obj,161			obj == HPI_OBJ_OSTREAM ?162				HPI_OSTREAM_HOSTBUFFER_ALLOC :163				HPI_ISTREAM_HOSTBUFFER_ALLOC);164 165	hpi_handle_to_indexes(h_stream, &hm.adapter_index,166				&hm.obj_index);167 168	hm.u.d.u.buffer.buffer_size = size_in_bytes;169	hm.u.d.u.buffer.pci_address = pci_address;170	hm.u.d.u.buffer.command = HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER;171	hpi_send_recv(&hm, &hr);172	return hr.error;173}174 175static u16 hpi_stream_host_buffer_detach(u32  h_stream)176{177	struct hpi_message hm;178	struct hpi_response hr;179	unsigned int obj = hpi_handle_object(h_stream);180 181	if (!h_stream)182		return HPI_ERROR_INVALID_OBJ;183 184	hpi_init_message_response(&hm, &hr,  obj,185			obj == HPI_OBJ_OSTREAM ?186				HPI_OSTREAM_HOSTBUFFER_FREE :187				HPI_ISTREAM_HOSTBUFFER_FREE);188 189	hpi_handle_to_indexes(h_stream, &hm.adapter_index,190				&hm.obj_index);191	hm.u.d.u.buffer.command = HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER;192	hpi_send_recv(&hm, &hr);193	return hr.error;194}195 196static inline u16 hpi_stream_start(u32 h_stream)197{198	if (hpi_handle_object(h_stream) ==  HPI_OBJ_OSTREAM)199		return hpi_outstream_start(h_stream);200	else201		return hpi_instream_start(h_stream);202}203 204static inline u16 hpi_stream_stop(u32 h_stream)205{206	if (hpi_handle_object(h_stream) ==  HPI_OBJ_OSTREAM)207		return hpi_outstream_stop(h_stream);208	else209		return hpi_instream_stop(h_stream);210}211 212static inline u16 hpi_stream_get_info_ex(213    u32 h_stream,214    u16        *pw_state,215    u32        *pbuffer_size,216    u32        *pdata_in_buffer,217    u32        *psample_count,218    u32        *pauxiliary_data219)220{221	u16 e;222	if (hpi_handle_object(h_stream)  ==  HPI_OBJ_OSTREAM)223		e = hpi_outstream_get_info_ex(h_stream, pw_state,224					pbuffer_size, pdata_in_buffer,225					psample_count, pauxiliary_data);226	else227		e = hpi_instream_get_info_ex(h_stream, pw_state,228					pbuffer_size, pdata_in_buffer,229					psample_count, pauxiliary_data);230	return e;231}232 233static inline u16 hpi_stream_group_add(234					u32 h_master,235					u32 h_stream)236{237	if (hpi_handle_object(h_master) ==  HPI_OBJ_OSTREAM)238		return hpi_outstream_group_add(h_master, h_stream);239	else240		return hpi_instream_group_add(h_master, h_stream);241}242 243static inline u16 hpi_stream_group_reset(u32 h_stream)244{245	if (hpi_handle_object(h_stream) ==  HPI_OBJ_OSTREAM)246		return hpi_outstream_group_reset(h_stream);247	else248		return hpi_instream_group_reset(h_stream);249}250 251static u16 handle_error(u16 err, int line, char *filename)252{253	if (err)254		pr_warn("in file %s, line %d: HPI error %d\n",255			filename, line, err);256	return err;257}258 259#define hpi_handle_error(x)  handle_error(x, __LINE__, __FILE__)260 261/***************************** GENERAL PCM ****************/262 263static void print_hwparams(struct snd_pcm_substream *substream,264				struct snd_pcm_hw_params *p)265{266	struct device *dev = substream->pcm->card->dev;267	char name[16];268 269	snd_pcm_debug_name(substream, name, sizeof(name));270	dev_dbg(dev, "%s HWPARAMS\n", name);271	dev_dbg(dev, " samplerate=%dHz channels=%d format=%d subformat=%d\n",272		params_rate(p), params_channels(p),273		params_format(p), params_subformat(p));274	dev_dbg(dev, " buffer=%dB period=%dB period_size=%dB periods=%d\n",275		params_buffer_bytes(p), params_period_bytes(p),276		params_period_size(p), params_periods(p));277	dev_dbg(dev, " buffer_size=%d access=%d data_rate=%dB/s\n",278		params_buffer_size(p), params_access(p),279		params_rate(p) * params_channels(p) *280		snd_pcm_format_width(params_format(p)) / 8);281}282 283#define INVALID_FORMAT	(__force snd_pcm_format_t)(-1)284 285static const snd_pcm_format_t hpi_to_alsa_formats[] = {286	INVALID_FORMAT,		/* INVALID */287	SNDRV_PCM_FORMAT_U8,	/* HPI_FORMAT_PCM8_UNSIGNED        1 */288	SNDRV_PCM_FORMAT_S16,	/* HPI_FORMAT_PCM16_SIGNED         2 */289	INVALID_FORMAT,		/* HPI_FORMAT_MPEG_L1              3 */290	SNDRV_PCM_FORMAT_MPEG,	/* HPI_FORMAT_MPEG_L2              4 */291	SNDRV_PCM_FORMAT_MPEG,	/* HPI_FORMAT_MPEG_L3              5 */292	INVALID_FORMAT,		/* HPI_FORMAT_DOLBY_AC2            6 */293	INVALID_FORMAT,		/* HPI_FORMAT_DOLBY_AC3            7 */294	SNDRV_PCM_FORMAT_S16_BE,/* HPI_FORMAT_PCM16_BIGENDIAN      8 */295	INVALID_FORMAT,		/* HPI_FORMAT_AA_TAGIT1_HITS       9 */296	INVALID_FORMAT,		/* HPI_FORMAT_AA_TAGIT1_INSERTS   10 */297	SNDRV_PCM_FORMAT_S32,	/* HPI_FORMAT_PCM32_SIGNED        11 */298	INVALID_FORMAT,		/* HPI_FORMAT_RAW_BITSTREAM       12 */299	INVALID_FORMAT,		/* HPI_FORMAT_AA_TAGIT1_HITS_EX1  13 */300	SNDRV_PCM_FORMAT_FLOAT,	/* HPI_FORMAT_PCM32_FLOAT         14 */301#if 1302	/* ALSA can't handle 3 byte sample size together with power-of-2303	 *  constraint on buffer_bytes, so disable this format304	 */305	INVALID_FORMAT306#else307	/* SNDRV_PCM_FORMAT_S24_3LE */ /* HPI_FORMAT_PCM24_SIGNED 15 */308#endif309};310 311 312static int snd_card_asihpi_format_alsa2hpi(struct snd_card_asihpi *asihpi,313					   snd_pcm_format_t alsa_format,314					   u16 *hpi_format)315{316	u16 format;317 318	for (format = HPI_FORMAT_PCM8_UNSIGNED;319	     format <= HPI_FORMAT_PCM24_SIGNED; format++) {320		if (hpi_to_alsa_formats[format] == alsa_format) {321			*hpi_format = format;322			return 0;323		}324	}325 326	dev_dbg(asihpi->card->dev, "failed match for alsa format %d\n",327		alsa_format);328	*hpi_format = 0;329	return -EINVAL;330}331 332static void snd_card_asihpi_pcm_samplerates(struct snd_card_asihpi *asihpi,333					 struct snd_pcm_hardware *pcmhw)334{335	u16 err;336	u32 h_control;337	u32 sample_rate;338	int idx;339	unsigned int rate_min = 200000;340	unsigned int rate_max = 0;341	unsigned int rates = 0;342 343	if (asihpi->support_mrx) {344		rates |= SNDRV_PCM_RATE_CONTINUOUS;345		rates |= SNDRV_PCM_RATE_8000_96000;346		rate_min = 8000;347		rate_max = 100000;348	} else {349		/* on cards without SRC,350		   valid rates are determined by sampleclock */351		err = hpi_mixer_get_control(asihpi->h_mixer,352					  HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,353					  HPI_CONTROL_SAMPLECLOCK, &h_control);354		if (err) {355			dev_err(&asihpi->pci->dev,356				"No local sampleclock, err %d\n", err);357		}358 359		for (idx = -1; idx < 100; idx++) {360			if (idx == -1) {361				if (hpi_sample_clock_get_sample_rate(h_control,362								&sample_rate))363					continue;364			} else if (hpi_sample_clock_query_local_rate(h_control,365							idx, &sample_rate)) {366				break;367			}368 369			rate_min = min(rate_min, sample_rate);370			rate_max = max(rate_max, sample_rate);371 372			switch (sample_rate) {373			case 5512:374				rates |= SNDRV_PCM_RATE_5512;375				break;376			case 8000:377				rates |= SNDRV_PCM_RATE_8000;378				break;379			case 11025:380				rates |= SNDRV_PCM_RATE_11025;381				break;382			case 16000:383				rates |= SNDRV_PCM_RATE_16000;384				break;385			case 22050:386				rates |= SNDRV_PCM_RATE_22050;387				break;388			case 32000:389				rates |= SNDRV_PCM_RATE_32000;390				break;391			case 44100:392				rates |= SNDRV_PCM_RATE_44100;393				break;394			case 48000:395				rates |= SNDRV_PCM_RATE_48000;396				break;397			case 64000:398				rates |= SNDRV_PCM_RATE_64000;399				break;400			case 88200:401				rates |= SNDRV_PCM_RATE_88200;402				break;403			case 96000:404				rates |= SNDRV_PCM_RATE_96000;405				break;406			case 176400:407				rates |= SNDRV_PCM_RATE_176400;408				break;409			case 192000:410				rates |= SNDRV_PCM_RATE_192000;411				break;412			default: /* some other rate */413				rates |= SNDRV_PCM_RATE_KNOT;414			}415		}416	}417 418	pcmhw->rates = rates;419	pcmhw->rate_min = rate_min;420	pcmhw->rate_max = rate_max;421}422 423static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,424					 struct snd_pcm_hw_params *params)425{426	struct snd_pcm_runtime *runtime = substream->runtime;427	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;428	struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);429	int err;430	u16 format;431	int width;432	unsigned int bytes_per_sec;433 434	print_hwparams(substream, params);435	err = snd_card_asihpi_format_alsa2hpi(card, params_format(params), &format);436	if (err)437		return err;438 439	hpi_handle_error(hpi_format_create(&dpcm->format,440			params_channels(params),441			format, params_rate(params), 0, 0));442 443	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {444		if (hpi_instream_reset(dpcm->h_stream) != 0)445			return -EINVAL;446 447		if (hpi_instream_set_format(448			dpcm->h_stream, &dpcm->format) != 0)449			return -EINVAL;450	}451 452	dpcm->hpi_buffer_attached = 0;453	if (card->can_dma) {454		err = hpi_stream_host_buffer_attach(dpcm->h_stream,455			params_buffer_bytes(params),  runtime->dma_addr);456		if (err == 0) {457			dev_dbg(card->card->dev,458				"stream_host_buffer_attach success %u %lu\n",459				params_buffer_bytes(params),460				(unsigned long)runtime->dma_addr);461		} else {462			dev_dbg(card->card->dev,463				"stream_host_buffer_attach error %d\n", err);464			return -ENOMEM;465		}466 467		err = hpi_stream_get_info_ex(dpcm->h_stream, NULL,468				&dpcm->hpi_buffer_attached, NULL, NULL, NULL);469	}470	bytes_per_sec = params_rate(params) * params_channels(params);471	width = snd_pcm_format_width(params_format(params));472	bytes_per_sec *= width;473	bytes_per_sec /= 8;474	if (width < 0 || bytes_per_sec == 0)475		return -EINVAL;476 477	dpcm->bytes_per_sec = bytes_per_sec;478	dpcm->buffer_bytes = params_buffer_bytes(params);479	dpcm->period_bytes = params_period_bytes(params);480 481	return 0;482}483 484static int485snd_card_asihpi_hw_free(struct snd_pcm_substream *substream)486{487	struct snd_pcm_runtime *runtime = substream->runtime;488	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;489	if (dpcm->hpi_buffer_attached)490		hpi_stream_host_buffer_detach(dpcm->h_stream);491 492	return 0;493}494 495static void snd_card_asihpi_runtime_free(struct snd_pcm_runtime *runtime)496{497	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;498	kfree(dpcm);499}500 501static void snd_card_asihpi_pcm_timer_start(struct snd_pcm_substream *502					    substream)503{504	struct snd_pcm_runtime *runtime = substream->runtime;505	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;506	int expiry;507 508	expiry = HZ / 200;509 510	expiry = max(expiry, 1); /* don't let it be zero! */511	mod_timer(&dpcm->timer, jiffies + expiry);512	dpcm->respawn_timer = 1;513}514 515static void snd_card_asihpi_pcm_timer_stop(struct snd_pcm_substream *substream)516{517	struct snd_pcm_runtime *runtime = substream->runtime;518	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;519 520	dpcm->respawn_timer = 0;521	del_timer(&dpcm->timer);522}523 524static void snd_card_asihpi_pcm_int_start(struct snd_pcm_substream *substream)525{526	struct snd_card_asihpi_pcm *dpcm;527	struct snd_card_asihpi *card;528 529	dpcm = (struct snd_card_asihpi_pcm *)substream->runtime->private_data;530	card = snd_pcm_substream_chip(substream);531 532	WARN_ON(in_interrupt());533	card->llmode_streampriv = dpcm;534 535	hpi_handle_error(hpi_adapter_set_property(card->hpi->adapter->index,536		HPI_ADAPTER_PROPERTY_IRQ_RATE,537		card->update_interval_frames, 0));538}539 540static void snd_card_asihpi_pcm_int_stop(struct snd_pcm_substream *substream)541{542	struct snd_card_asihpi *card;543 544	card = snd_pcm_substream_chip(substream);545 546	hpi_handle_error(hpi_adapter_set_property(card->hpi->adapter->index,547		HPI_ADAPTER_PROPERTY_IRQ_RATE, 0, 0));548 549	card->llmode_streampriv = NULL;550}551 552static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,553					   int cmd)554{555	struct snd_card_asihpi_pcm *dpcm = substream->runtime->private_data;556	struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);557	struct snd_pcm_substream *s;558	u16 e;559	char name[16];560 561	snd_pcm_debug_name(substream, name, sizeof(name));562 563	switch (cmd) {564	case SNDRV_PCM_TRIGGER_START:565		dev_dbg(card->card->dev, "%s trigger start\n", name);566		snd_pcm_group_for_each_entry(s, substream) {567			struct snd_pcm_runtime *runtime = s->runtime;568			struct snd_card_asihpi_pcm *ds = runtime->private_data;569 570			if (snd_pcm_substream_chip(s) != card)571				continue;572 573			/* don't link Cap and Play */574			if (substream->stream != s->stream)575				continue;576 577			ds->drained_count = 0;578			if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {579				/* How do I know how much valid data is present580				* in buffer? Must be at least one period!581				* Guessing 2 periods, but if582				* buffer is bigger it may contain even more583				* data??584				*/585				unsigned int preload = ds->period_bytes * 1;586				asihpi_dbg("%d preload %d\n", s->number, preload);587				hpi_handle_error(hpi_outstream_write_buf(588						ds->h_stream,589						&runtime->dma_area[0],590						preload,591						&ds->format));592				ds->pcm_buf_host_rw_ofs = preload;593			}594 595			if (card->support_grouping) {596				dev_dbg(card->card->dev, "%d group\n", s->number);597				e = hpi_stream_group_add(598					dpcm->h_stream,599					ds->h_stream);600				if (!e) {601					snd_pcm_trigger_done(s, substream);602				} else {603					hpi_handle_error(e);604					break;605				}606			} else607				break;608		}609		/* start the master stream */610		card->pcm_start(substream);611		if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) ||612			!card->can_dma)613			hpi_handle_error(hpi_stream_start(dpcm->h_stream));614		break;615 616	case SNDRV_PCM_TRIGGER_STOP:617		dev_dbg(card->card->dev, "%s trigger stop\n", name);618		card->pcm_stop(substream);619		snd_pcm_group_for_each_entry(s, substream) {620			if (snd_pcm_substream_chip(s) != card)621				continue;622			/* don't link Cap and Play */623			if (substream->stream != s->stream)624				continue;625 626			/*? workaround linked streams don't627			transition to SETUP 20070706*/628			__snd_pcm_set_state(s->runtime, SNDRV_PCM_STATE_SETUP);629 630			if (card->support_grouping) {631				dev_dbg(card->card->dev, "%d group\n", s->number);632				snd_pcm_trigger_done(s, substream);633			} else634				break;635		}636 637		/* _prepare and _hwparams reset the stream */638		hpi_handle_error(hpi_stream_stop(dpcm->h_stream));639		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)640			hpi_handle_error(641				hpi_outstream_reset(dpcm->h_stream));642 643		if (card->support_grouping)644			hpi_handle_error(hpi_stream_group_reset(dpcm->h_stream));645		break;646 647	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:648		dev_dbg(card->card->dev, "%s trigger pause release\n", name);649		card->pcm_start(substream);650		hpi_handle_error(hpi_stream_start(dpcm->h_stream));651		break;652	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:653		dev_dbg(card->card->dev, "%s trigger pause push\n", name);654		card->pcm_stop(substream);655		hpi_handle_error(hpi_stream_stop(dpcm->h_stream));656		break;657	default:658		dev_dbg(card->card->dev, "\tINVALID\n");659		return -EINVAL;660	}661 662	return 0;663}664 665/*algorithm outline666 Without linking degenerates to getting single stream pos etc667 Without mmap 2nd loop degenerates to snd_pcm_period_elapsed668*/669/*670pcm_buf_dma_ofs=get_buf_pos(s);671for_each_linked_stream(s) {672	pcm_buf_dma_ofs=get_buf_pos(s);673	min_buf_pos = modulo_min(min_buf_pos, pcm_buf_dma_ofs, buffer_bytes)674	new_data = min(new_data, calc_new_data(pcm_buf_dma_ofs,irq_pos)675}676timer.expires = jiffies + predict_next_period_ready(min_buf_pos);677for_each_linked_stream(s) {678	s->pcm_buf_dma_ofs = min_buf_pos;679	if (new_data > period_bytes) {680		if (mmap) {681			irq_pos = (irq_pos + period_bytes) % buffer_bytes;682			if (playback) {683				write(period_bytes);684			} else {685				read(period_bytes);686			}687		}688		snd_pcm_period_elapsed(s);689	}690}691*/692 693/** Minimum of 2 modulo values.  Works correctly when the difference between694* the values is less than half the modulus695*/696static inline unsigned int modulo_min(unsigned int a, unsigned int b,697					unsigned long int modulus)698{699	unsigned int result;700	if (((a-b) % modulus) < (modulus/2))701		result = b;702	else703		result = a;704 705	return result;706}707 708/** Timer function, equivalent to interrupt service routine for cards709*/710static void snd_card_asihpi_timer_function(struct timer_list *t)711{712	struct snd_card_asihpi_pcm *dpcm = from_timer(dpcm, t, timer);713	struct snd_pcm_substream *substream = dpcm->substream;714	struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);715	struct snd_pcm_runtime *runtime;716	struct snd_pcm_substream *s;717	unsigned int newdata = 0;718	unsigned int pcm_buf_dma_ofs, min_buf_pos = 0;719	unsigned int remdata, xfercount, next_jiffies;720	int first = 1;721	u16 state;722	u32 buffer_size, bytes_avail, samples_played, on_card_bytes;723	char name[16];724 725 726	snd_pcm_debug_name(substream, name, sizeof(name));727 728	/* find minimum newdata and buffer pos in group */729	snd_pcm_group_for_each_entry(s, substream) {730		struct snd_card_asihpi_pcm *ds = s->runtime->private_data;731		runtime = s->runtime;732 733		if (snd_pcm_substream_chip(s) != card)734			continue;735 736		/* don't link Cap and Play */737		if (substream->stream != s->stream)738			continue;739 740		hpi_handle_error(hpi_stream_get_info_ex(741					ds->h_stream, &state,742					&buffer_size, &bytes_avail,743					&samples_played, &on_card_bytes));744 745		/* number of bytes in on-card buffer */746		runtime->delay = on_card_bytes;747 748		if (!card->can_dma)749			on_card_bytes = bytes_avail;750 751		if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {752			pcm_buf_dma_ofs = ds->pcm_buf_host_rw_ofs - bytes_avail;753			if (state == HPI_STATE_STOPPED) {754				if (bytes_avail == 0) {755					hpi_handle_error(hpi_stream_start(ds->h_stream));756					dev_dbg(card->card->dev,757						"P%d start\n", s->number);758					ds->drained_count = 0;759				}760			} else if (state == HPI_STATE_DRAINED) {761				dev_dbg(card->card->dev,762					"P%d drained\n", s->number);763				ds->drained_count++;764				if (ds->drained_count > 20) {765					snd_pcm_stop_xrun(s);766					continue;767				}768			} else {769				ds->drained_count = 0;770			}771		} else772			pcm_buf_dma_ofs = bytes_avail + ds->pcm_buf_host_rw_ofs;773 774		if (first) {775			/* can't statically init min when wrap is involved */776			min_buf_pos = pcm_buf_dma_ofs;777			newdata = (pcm_buf_dma_ofs - ds->pcm_buf_elapsed_dma_ofs) % ds->buffer_bytes;778			first = 0;779		} else {780			min_buf_pos =781				modulo_min(min_buf_pos, pcm_buf_dma_ofs, UINT_MAX+1L);782			newdata = min(783				(pcm_buf_dma_ofs - ds->pcm_buf_elapsed_dma_ofs) % ds->buffer_bytes,784				newdata);785		}786 787		asihpi_dbg(788			"timer1, %s, %d, S=%d, elap=%d, rw=%d, dsp=%d, left=%d, aux=%d, space=%d, hw_ptr=%ld, appl_ptr=%ld\n",789			name, s->number, state,790			ds->pcm_buf_elapsed_dma_ofs,791			ds->pcm_buf_host_rw_ofs,792			pcm_buf_dma_ofs,793			(int)bytes_avail,794 795			(int)on_card_bytes,796			buffer_size-bytes_avail,797			(unsigned long)frames_to_bytes(runtime,798						runtime->status->hw_ptr),799			(unsigned long)frames_to_bytes(runtime,800						runtime->control->appl_ptr)801		);802	}803	pcm_buf_dma_ofs = min_buf_pos;804 805	remdata = newdata % dpcm->period_bytes;806	xfercount = newdata - remdata; /* a multiple of period_bytes */807	/* come back when on_card_bytes has decreased enough to allow808	   write to happen, or when data has been consumed to make another809	   period810	*/811	if (xfercount && (on_card_bytes  > dpcm->period_bytes))812		next_jiffies = ((on_card_bytes - dpcm->period_bytes) * HZ / dpcm->bytes_per_sec);813	else814		next_jiffies = ((dpcm->period_bytes - remdata) * HZ / dpcm->bytes_per_sec);815 816	next_jiffies = max(next_jiffies, 1U);817	dpcm->timer.expires = jiffies + next_jiffies;818	asihpi_dbg("timer2, jif=%d, buf_pos=%d, newdata=%d, xfer=%d\n",819			next_jiffies, pcm_buf_dma_ofs, newdata, xfercount);820 821	snd_pcm_group_for_each_entry(s, substream) {822		struct snd_card_asihpi_pcm *ds = s->runtime->private_data;823 824		/* don't link Cap and Play */825		if (substream->stream != s->stream)826			continue;827 828		/* Store dma offset for use by pointer callback */829		ds->pcm_buf_dma_ofs = pcm_buf_dma_ofs;830 831		if (xfercount &&832			/* Limit use of on card fifo for playback */833			((on_card_bytes <= ds->period_bytes) ||834			(s->stream == SNDRV_PCM_STREAM_CAPTURE)))835 836		{837 838			unsigned int buf_ofs = ds->pcm_buf_host_rw_ofs % ds->buffer_bytes;839			unsigned int xfer1, xfer2;840			char *pd = &s->runtime->dma_area[buf_ofs];841 842			if (card->can_dma) { /* buffer wrap is handled at lower level */843				xfer1 = xfercount;844				xfer2 = 0;845			} else {846				xfer1 = min(xfercount, ds->buffer_bytes - buf_ofs);847				xfer2 = xfercount - xfer1;848			}849 850			if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {851				asihpi_dbg("write1, P=%d, xfer=%d, buf_ofs=%d\n",852					s->number, xfer1, buf_ofs);853				hpi_handle_error(854					hpi_outstream_write_buf(855						ds->h_stream, pd, xfer1,856						&ds->format));857 858				if (xfer2) {859					pd = s->runtime->dma_area;860 861					asihpi_dbg("write2, P=%d, xfer=%d, buf_ofs=%d\n",862							s->number,863							xfercount - xfer1, buf_ofs);864					hpi_handle_error(865						hpi_outstream_write_buf(866							ds->h_stream, pd,867							xfercount - xfer1,868							&ds->format));869				}870			} else {871				asihpi_dbg("read1, C=%d, xfer=%d\n",872					s->number, xfer1);873				hpi_handle_error(874					hpi_instream_read_buf(875						ds->h_stream,876						pd, xfer1));877				if (xfer2) {878					pd = s->runtime->dma_area;879					asihpi_dbg("read2, C=%d, xfer=%d\n",880						s->number, xfer2);881					hpi_handle_error(882						hpi_instream_read_buf(883							ds->h_stream,884							pd, xfer2));885				}886			}887			/* ? host_rw_ofs always ahead of elapsed_dma_ofs by preload size? */888			ds->pcm_buf_host_rw_ofs += xfercount;889			ds->pcm_buf_elapsed_dma_ofs += xfercount;890			snd_pcm_period_elapsed(s);891		}892	}893 894	if (!card->hpi->interrupt_mode && dpcm->respawn_timer)895		add_timer(&dpcm->timer);896}897 898static void snd_card_asihpi_isr(struct hpi_adapter *a)899{900	struct snd_card_asihpi *asihpi;901 902	WARN_ON(!a || !a->snd_card || !a->snd_card->private_data);903	asihpi = (struct snd_card_asihpi *)a->snd_card->private_data;904	if (asihpi->llmode_streampriv)905		snd_card_asihpi_timer_function(906			&asihpi->llmode_streampriv->timer);907}908 909/***************************** PLAYBACK OPS ****************/910static int snd_card_asihpi_playback_prepare(struct snd_pcm_substream *911					    substream)912{913	struct snd_pcm_runtime *runtime = substream->runtime;914	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;915 916	hpi_handle_error(hpi_outstream_reset(dpcm->h_stream));917	dpcm->pcm_buf_host_rw_ofs = 0;918	dpcm->pcm_buf_dma_ofs = 0;919	dpcm->pcm_buf_elapsed_dma_ofs = 0;920	return 0;921}922 923static snd_pcm_uframes_t924snd_card_asihpi_playback_pointer(struct snd_pcm_substream *substream)925{926	struct snd_pcm_runtime *runtime = substream->runtime;927	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;928	snd_pcm_uframes_t ptr;929	char name[16];930	snd_pcm_debug_name(substream, name, sizeof(name));931 932	ptr = bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs  % dpcm->buffer_bytes);933	asihpi_dbg("%s, pointer=%ld\n", name, (unsigned long)ptr);934	return ptr;935}936 937static u64 snd_card_asihpi_playback_formats(struct snd_card_asihpi *asihpi,938						u32 h_stream)939{940	struct hpi_format hpi_format;941	u16 format;942	u16 err;943	u32 h_control;944	u32 sample_rate = 48000;945	u64 formats = 0;946 947	/* on cards without SRC, must query at valid rate,948	* maybe set by external sync949	*/950	err = hpi_mixer_get_control(asihpi->h_mixer,951				  HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,952				  HPI_CONTROL_SAMPLECLOCK, &h_control);953 954	if (!err)955		err = hpi_sample_clock_get_sample_rate(h_control,956				&sample_rate);957 958	for (format = HPI_FORMAT_PCM8_UNSIGNED;959	     format <= HPI_FORMAT_PCM24_SIGNED; format++) {960		err = hpi_format_create(&hpi_format, asihpi->out_max_chans,961					format, sample_rate, 128000, 0);962		if (!err)963			err = hpi_outstream_query_format(h_stream, &hpi_format);964		if (!err && (hpi_to_alsa_formats[format] != INVALID_FORMAT))965			formats |= pcm_format_to_bits(hpi_to_alsa_formats[format]);966	}967	return formats;968}969 970static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream)971{972	struct snd_pcm_runtime *runtime = substream->runtime;973	struct snd_card_asihpi_pcm *dpcm;974	struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);975	struct snd_pcm_hardware snd_card_asihpi_playback;976	int err;977 978	dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);979	if (dpcm == NULL)980		return -ENOMEM;981 982	err = hpi_outstream_open(card->hpi->adapter->index,983			      substream->number, &dpcm->h_stream);984	hpi_handle_error(err);985	if (err)986		kfree(dpcm);987	if (err == HPI_ERROR_OBJ_ALREADY_OPEN)988		return -EBUSY;989	if (err)990		return -EIO;991 992	/*? also check ASI5000 samplerate source993	    If external, only support external rate.994	    If internal and other stream playing, can't switch995	*/996 997	timer_setup(&dpcm->timer, snd_card_asihpi_timer_function, 0);998	dpcm->substream = substream;999	runtime->private_data = dpcm;1000	runtime->private_free = snd_card_asihpi_runtime_free;1001 1002	memset(&snd_card_asihpi_playback, 0, sizeof(snd_card_asihpi_playback));1003	if (!card->hpi->interrupt_mode) {1004		snd_card_asihpi_playback.buffer_bytes_max = BUFFER_BYTES_MAX;1005		snd_card_asihpi_playback.period_bytes_min = PERIOD_BYTES_MIN;1006		snd_card_asihpi_playback.period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN;1007		snd_card_asihpi_playback.periods_min = PERIODS_MIN;1008		snd_card_asihpi_playback.periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN;1009	} else {1010		size_t pbmin = card->update_interval_frames *1011			card->out_max_chans;1012		snd_card_asihpi_playback.buffer_bytes_max = BUFFER_BYTES_MAX;1013		snd_card_asihpi_playback.period_bytes_min = pbmin;1014		snd_card_asihpi_playback.period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN;1015		snd_card_asihpi_playback.periods_min = PERIODS_MIN;1016		snd_card_asihpi_playback.periods_max = BUFFER_BYTES_MAX / pbmin;1017	}1018 1019	/* snd_card_asihpi_playback.fifo_size = 0; */1020	snd_card_asihpi_playback.channels_max = card->out_max_chans;1021	snd_card_asihpi_playback.channels_min = card->out_min_chans;1022	snd_card_asihpi_playback.formats =1023			snd_card_asihpi_playback_formats(card, dpcm->h_stream);1024 1025	snd_card_asihpi_pcm_samplerates(card,  &snd_card_asihpi_playback);1026 1027	snd_card_asihpi_playback.info = SNDRV_PCM_INFO_INTERLEAVED |1028					SNDRV_PCM_INFO_DOUBLE |1029					SNDRV_PCM_INFO_BATCH |1030					SNDRV_PCM_INFO_BLOCK_TRANSFER |1031					SNDRV_PCM_INFO_PAUSE |1032					SNDRV_PCM_INFO_MMAP |1033					SNDRV_PCM_INFO_MMAP_VALID;1034 1035	if (card->support_grouping) {1036		snd_card_asihpi_playback.info |= SNDRV_PCM_INFO_SYNC_START;1037		snd_pcm_set_sync(substream);1038	}1039 1040	/* struct is copied, so can create initializer dynamically */1041	runtime->hw = snd_card_asihpi_playback;1042 1043	if (card->can_dma)1044		err = snd_pcm_hw_constraint_pow2(runtime, 0,1045					SNDRV_PCM_HW_PARAM_BUFFER_BYTES);1046	if (err < 0)1047		return err;1048 1049	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,1050		card->update_interval_frames);1051 1052	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,1053		card->update_interval_frames, UINT_MAX);1054 1055	return 0;1056}1057 1058static int snd_card_asihpi_playback_close(struct snd_pcm_substream *substream)1059{1060	struct snd_pcm_runtime *runtime = substream->runtime;1061	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;1062 1063	hpi_handle_error(hpi_outstream_close(dpcm->h_stream));1064	return 0;1065}1066 1067static const struct snd_pcm_ops snd_card_asihpi_playback_mmap_ops = {1068	.open = snd_card_asihpi_playback_open,1069	.close = snd_card_asihpi_playback_close,1070	.hw_params = snd_card_asihpi_pcm_hw_params,1071	.hw_free = snd_card_asihpi_hw_free,1072	.prepare = snd_card_asihpi_playback_prepare,1073	.trigger = snd_card_asihpi_trigger,1074	.pointer = snd_card_asihpi_playback_pointer,1075};1076 1077/***************************** CAPTURE OPS ****************/1078static snd_pcm_uframes_t1079snd_card_asihpi_capture_pointer(struct snd_pcm_substream *substream)1080{1081	struct snd_pcm_runtime *runtime = substream->runtime;1082	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;1083	char name[16];1084	snd_pcm_debug_name(substream, name, sizeof(name));1085 1086	asihpi_dbg("%s, pointer=%d\n", name, dpcm->pcm_buf_dma_ofs);1087	/* NOTE Unlike playback can't use actual samples_played1088		for the capture position, because those samples aren't yet in1089		the local buffer available for reading.1090	*/1091	return bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes);1092}1093 1094static int snd_card_asihpi_capture_prepare(struct snd_pcm_substream *substream)1095{1096	struct snd_pcm_runtime *runtime = substream->runtime;1097	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;1098 1099	hpi_handle_error(hpi_instream_reset(dpcm->h_stream));1100	dpcm->pcm_buf_host_rw_ofs = 0;1101	dpcm->pcm_buf_dma_ofs = 0;1102	dpcm->pcm_buf_elapsed_dma_ofs = 0;1103 1104	return 0;1105}1106 1107static u64 snd_card_asihpi_capture_formats(struct snd_card_asihpi *asihpi,1108					u32 h_stream)1109{1110	struct hpi_format hpi_format;1111	u16 format;1112	u16 err;1113	u32 h_control;1114	u32 sample_rate = 48000;1115	u64 formats = 0;1116 1117	/* on cards without SRC, must query at valid rate,1118		maybe set by external sync */1119	err = hpi_mixer_get_control(asihpi->h_mixer,1120				  HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,1121				  HPI_CONTROL_SAMPLECLOCK, &h_control);1122 1123	if (!err)1124		err = hpi_sample_clock_get_sample_rate(h_control,1125			&sample_rate);1126 1127	for (format = HPI_FORMAT_PCM8_UNSIGNED;1128		format <= HPI_FORMAT_PCM24_SIGNED; format++) {1129 1130		err = hpi_format_create(&hpi_format, asihpi->in_max_chans,1131					format, sample_rate, 128000, 0);1132		if (!err)1133			err = hpi_instream_query_format(h_stream, &hpi_format);1134		if (!err && (hpi_to_alsa_formats[format] != INVALID_FORMAT))1135			formats |= pcm_format_to_bits(hpi_to_alsa_formats[format]);1136	}1137	return formats;1138}1139 1140static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream)1141{1142	struct snd_pcm_runtime *runtime = substream->runtime;1143	struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);1144	struct snd_card_asihpi_pcm *dpcm;1145	struct snd_pcm_hardware snd_card_asihpi_capture;1146	int err;1147 1148	dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);1149	if (dpcm == NULL)1150		return -ENOMEM;1151 1152 1153	dev_dbg(card->card->dev, "capture open adapter %d stream %d\n",1154		card->hpi->adapter->index, substream->number);1155 1156	err = hpi_handle_error(1157	    hpi_instream_open(card->hpi->adapter->index,1158			     substream->number, &dpcm->h_stream));1159	if (err)1160		kfree(dpcm);1161	if (err == HPI_ERROR_OBJ_ALREADY_OPEN)1162		return -EBUSY;1163	if (err)1164		return -EIO;1165 1166	timer_setup(&dpcm->timer, snd_card_asihpi_timer_function, 0);1167	dpcm->substream = substream;1168	runtime->private_data = dpcm;1169	runtime->private_free = snd_card_asihpi_runtime_free;1170 1171	memset(&snd_card_asihpi_capture, 0, sizeof(snd_card_asihpi_capture));1172	if (!card->hpi->interrupt_mode) {1173		snd_card_asihpi_capture.buffer_bytes_max = BUFFER_BYTES_MAX;1174		snd_card_asihpi_capture.period_bytes_min = PERIOD_BYTES_MIN;1175		snd_card_asihpi_capture.period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN;1176		snd_card_asihpi_capture.periods_min = PERIODS_MIN;1177		snd_card_asihpi_capture.periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN;1178	} else {1179		size_t pbmin = card->update_interval_frames *1180			card->out_max_chans;1181		snd_card_asihpi_capture.buffer_bytes_max = BUFFER_BYTES_MAX;1182		snd_card_asihpi_capture.period_bytes_min = pbmin;1183		snd_card_asihpi_capture.period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN;1184		snd_card_asihpi_capture.periods_min = PERIODS_MIN;1185		snd_card_asihpi_capture.periods_max = BUFFER_BYTES_MAX / pbmin;1186	}1187	/* snd_card_asihpi_capture.fifo_size = 0; */1188	snd_card_asihpi_capture.channels_max = card->in_max_chans;1189	snd_card_asihpi_capture.channels_min = card->in_min_chans;1190	snd_card_asihpi_capture.formats =1191		snd_card_asihpi_capture_formats(card, dpcm->h_stream);1192	snd_card_asihpi_pcm_samplerates(card,  &snd_card_asihpi_capture);1193	snd_card_asihpi_capture.info = SNDRV_PCM_INFO_INTERLEAVED |1194					SNDRV_PCM_INFO_MMAP |1195					SNDRV_PCM_INFO_MMAP_VALID;1196 1197	if (card->support_grouping)1198		snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_SYNC_START;1199 1200	runtime->hw = snd_card_asihpi_capture;1201 1202	if (card->can_dma)1203		err = snd_pcm_hw_constraint_pow2(runtime, 0,1204					SNDRV_PCM_HW_PARAM_BUFFER_BYTES);1205	if (err < 0)1206		return err;1207 1208	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,1209		card->update_interval_frames);1210	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,1211		card->update_interval_frames, UINT_MAX);1212 1213	snd_pcm_set_sync(substream);1214 1215	return 0;1216}1217 1218static int snd_card_asihpi_capture_close(struct snd_pcm_substream *substream)1219{1220	struct snd_card_asihpi_pcm *dpcm = substream->runtime->private_data;1221 1222	hpi_handle_error(hpi_instream_close(dpcm->h_stream));1223	return 0;1224}1225 1226static const struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = {1227	.open = snd_card_asihpi_capture_open,1228	.close = snd_card_asihpi_capture_close,1229	.hw_params = snd_card_asihpi_pcm_hw_params,1230	.hw_free = snd_card_asihpi_hw_free,1231	.prepare = snd_card_asihpi_capture_prepare,1232	.trigger = snd_card_asihpi_trigger,1233	.pointer = snd_card_asihpi_capture_pointer,1234};1235 1236static int snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi, int device)1237{1238	struct snd_pcm *pcm;1239	int err;1240	u16 num_instreams, num_outstreams, x16;1241	u32 x32;1242 1243	err = hpi_adapter_get_info(asihpi->hpi->adapter->index,1244			&num_outstreams, &num_instreams,1245			&x16, &x32, &x16);1246 1247	err = snd_pcm_new(asihpi->card, "Asihpi PCM", device,1248			num_outstreams,	num_instreams, &pcm);1249	if (err < 0)1250		return err;1251 1252	/* pointer to ops struct is stored, dont change ops afterwards! */1253	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,1254			&snd_card_asihpi_playback_mmap_ops);1255	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,1256			&snd_card_asihpi_capture_mmap_ops);1257 1258	pcm->private_data = asihpi;1259	pcm->info_flags = 0;1260	strcpy(pcm->name, "Asihpi PCM");1261 1262	/*? do we want to emulate MMAP for non-BBM cards?1263	Jack doesn't work with ALSAs MMAP emulation - WHY NOT? */1264	snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,1265				       &asihpi->pci->dev,1266				       64*1024, BUFFER_BYTES_MAX);1267 1268	return 0;1269}1270 1271/***************************** MIXER CONTROLS ****************/1272struct hpi_control {1273	u32 h_control;1274	u16 control_type;1275	u16 src_node_type;1276	u16 src_node_index;1277	u16 dst_node_type;1278	u16 dst_node_index;1279	u16 band;1280	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* copied to snd_ctl_elem_id.name[44]; */1281};1282 1283static const char * const asihpi_tuner_band_names[] = {1284	"invalid",1285	"AM",1286	"FM mono",1287	"TV NTSC-M",1288	"FM stereo",1289	"AUX",1290	"TV PAL BG",1291	"TV PAL I",1292	"TV PAL DK",1293	"TV SECAM",1294	"TV DAB",1295};1296/* Number of strings must match the enumerations for HPI_TUNER_BAND in hpi.h */1297compile_time_assert(1298	(ARRAY_SIZE(asihpi_tuner_band_names) ==1299		(HPI_TUNER_BAND_LAST+1)),1300	assert_tuner_band_names_size);1301 1302static const char * const asihpi_src_names[] = {1303	"no source",1304	"PCM",1305	"Line",1306	"Digital",1307	"Tuner",1308	"RF",1309	"Clock",1310	"Bitstream",1311	"Mic",1312	"Net",1313	"Analog",1314	"Adapter",1315	"RTP",1316	"Internal",1317	"AVB",1318	"BLU-Link"1319};1320/* Number of strings must match the enumerations for HPI_SOURCENODES in hpi.h */1321compile_time_assert(1322	(ARRAY_SIZE(asihpi_src_names) ==1323		(HPI_SOURCENODE_LAST_INDEX-HPI_SOURCENODE_NONE+1)),1324	assert_src_names_size);1325 1326static const char * const asihpi_dst_names[] = {1327	"no destination",1328	"PCM",1329	"Line",1330	"Digital",1331	"RF",1332	"Speaker",1333	"Net",1334	"Analog",1335	"RTP",1336	"AVB",1337	"Internal",1338	"BLU-Link"1339};1340/* Number of strings must match the enumerations for HPI_DESTNODES in hpi.h */1341compile_time_assert(1342	(ARRAY_SIZE(asihpi_dst_names) ==1343		(HPI_DESTNODE_LAST_INDEX-HPI_DESTNODE_NONE+1)),1344	assert_dst_names_size);1345 1346static inline int ctl_add(struct snd_card *card, struct snd_kcontrol_new *ctl,1347				struct snd_card_asihpi *asihpi)1348{1349	int err;1350 1351	err = snd_ctl_add(card, snd_ctl_new1(ctl, asihpi));1352	if (err < 0)1353		return err;1354	else if (mixer_dump)1355		dev_info(&asihpi->pci->dev, "added %s(%d)\n", ctl->name, ctl->index);1356 1357	return 0;1358}1359 1360/* Convert HPI control name and location into ALSA control name */1361static void asihpi_ctl_init(struct snd_kcontrol_new *snd_control,1362				struct hpi_control *hpi_ctl,1363				char *name)1364{1365	char *dir;1366	memset(snd_control, 0, sizeof(*snd_control));1367	snd_control->name = hpi_ctl->name;1368	snd_control->private_value = hpi_ctl->h_control;1369	snd_control->iface = SNDRV_CTL_ELEM_IFACE_MIXER;1370	snd_control->index = 0;1371 1372	if (hpi_ctl->src_node_type + HPI_SOURCENODE_NONE == HPI_SOURCENODE_CLOCK_SOURCE)1373		dir = ""; /* clock is neither capture nor playback */1374	else if (hpi_ctl->dst_node_type + HPI_DESTNODE_NONE == HPI_DESTNODE_ISTREAM)1375		dir = "Capture ";  /* On or towards a PCM capture destination*/1376	else if ((hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) &&1377		(!hpi_ctl->dst_node_type))1378		dir = "Capture "; /* On a source node that is not PCM playback */1379	else if (hpi_ctl->src_node_type &&1380		(hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) &&1381		(hpi_ctl->dst_node_type))1382		dir = "Monitor Playback "; /* Between an input and an output */1383	else1384		dir = "Playback "; /* PCM Playback source, or  output node */1385 1386	if (hpi_ctl->src_node_type && hpi_ctl->dst_node_type)1387		sprintf(hpi_ctl->name, "%s %d %s %d %s%s",1388			asihpi_src_names[hpi_ctl->src_node_type],1389			hpi_ctl->src_node_index,1390			asihpi_dst_names[hpi_ctl->dst_node_type],1391			hpi_ctl->dst_node_index,1392			dir, name);1393	else if (hpi_ctl->dst_node_type) {1394		sprintf(hpi_ctl->name, "%s %d %s%s",1395		asihpi_dst_names[hpi_ctl->dst_node_type],1396		hpi_ctl->dst_node_index,1397		dir, name);1398	} else {1399		sprintf(hpi_ctl->name, "%s %d %s%s",1400		asihpi_src_names[hpi_ctl->src_node_type],1401		hpi_ctl->src_node_index,1402		dir, name);1403	}1404}1405 1406/*------------------------------------------------------------1407   Volume controls1408 ------------------------------------------------------------*/1409#define VOL_STEP_mB 11410static int snd_asihpi_volume_info(struct snd_kcontrol *kcontrol,1411				  struct snd_ctl_elem_info *uinfo)1412{1413	u32 h_control = kcontrol->private_value;1414	u32 count;1415	u16 err;1416	/* native gains are in millibels */1417	short min_gain_mB;1418	short max_gain_mB;1419	short step_gain_mB;1420 1421	err = hpi_volume_query_range(h_control,1422			&min_gain_mB, &max_gain_mB, &step_gain_mB);1423	if (err) {1424		max_gain_mB = 0;1425		min_gain_mB = -10000;1426		step_gain_mB = VOL_STEP_mB;1427	}1428 1429	err = hpi_meter_query_channels(h_control, &count);1430	if (err)1431		count = HPI_MAX_CHANNELS;1432 1433	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;1434	uinfo->count = count;1435	uinfo->value.integer.min = min_gain_mB / VOL_STEP_mB;1436	uinfo->value.integer.max = max_gain_mB / VOL_STEP_mB;1437	uinfo->value.integer.step = step_gain_mB / VOL_STEP_mB;1438	return 0;1439}1440 1441static int snd_asihpi_volume_get(struct snd_kcontrol *kcontrol,1442				 struct snd_ctl_elem_value *ucontrol)1443{1444	u32 h_control = kcontrol->private_value;1445	short an_gain_mB[HPI_MAX_CHANNELS];1446 1447	hpi_handle_error(hpi_volume_get_gain(h_control, an_gain_mB));1448	ucontrol->value.integer.value[0] = an_gain_mB[0] / VOL_STEP_mB;1449	ucontrol->value.integer.value[1] = an_gain_mB[1] / VOL_STEP_mB;1450 1451	return 0;1452}1453 1454static int snd_asihpi_volume_put(struct snd_kcontrol *kcontrol,1455				 struct snd_ctl_elem_value *ucontrol)1456{1457	u32 h_control = kcontrol->private_value;1458	short an_gain_mB[HPI_MAX_CHANNELS];1459 1460	an_gain_mB[0] =1461	    (ucontrol->value.integer.value[0]) * VOL_STEP_mB;1462	an_gain_mB[1] =1463	    (ucontrol->value.integer.value[1]) * VOL_STEP_mB;1464	/*  change = asihpi->mixer_volume[addr][0] != left ||1465	   asihpi->mixer_volume[addr][1] != right;1466	 */1467	hpi_handle_error(hpi_volume_set_gain(h_control, an_gain_mB));1468	return 1;1469}1470 1471static const DECLARE_TLV_DB_SCALE(db_scale_100, -10000, VOL_STEP_mB, 0);1472 1473#define snd_asihpi_volume_mute_info	snd_ctl_boolean_mono_info1474 1475static int snd_asihpi_volume_mute_get(struct snd_kcontrol *kcontrol,1476				 struct snd_ctl_elem_value *ucontrol)1477{1478	u32 h_control = kcontrol->private_value;1479	u32 mute;1480 1481	hpi_handle_error(hpi_volume_get_mute(h_control, &mute));1482	ucontrol->value.integer.value[0] = mute ? 0 : 1;1483 1484	return 0;1485}1486 1487static int snd_asihpi_volume_mute_put(struct snd_kcontrol *kcontrol,1488				 struct snd_ctl_elem_value *ucontrol)1489{1490	u32 h_control = kcontrol->private_value;1491	/* HPI currently only supports all or none muting of multichannel volume1492	ALSA Switch element has opposite sense to HPI mute: on==unmuted, off=muted1493	*/1494	int mute =  ucontrol->value.integer.value[0] ? 0 : HPI_BITMASK_ALL_CHANNELS;1495	hpi_handle_error(hpi_volume_set_mute(h_control, mute));1496	return 1;1497}1498 1499static int snd_asihpi_volume_add(struct snd_card_asihpi *asihpi,1500				 struct hpi_control *hpi_ctl)1501{1502	struct snd_card *card = asihpi->card;1503	struct snd_kcontrol_new snd_control;1504	int err;1505	u32 mute;1506 1507	asihpi_ctl_init(&snd_control, hpi_ctl, "Volume");1508	snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |1509				SNDRV_CTL_ELEM_ACCESS_TLV_READ;1510	snd_control.info = snd_asihpi_volume_info;1511	snd_control.get = snd_asihpi_volume_get;1512	snd_control.put = snd_asihpi_volume_put;1513	snd_control.tlv.p = db_scale_100;1514 1515	err = ctl_add(card, &snd_control, asihpi);1516	if (err)1517		return err;1518 1519	if (hpi_volume_get_mute(hpi_ctl->h_control, &mute) == 0) {1520		asihpi_ctl_init(&snd_control, hpi_ctl, "Switch");1521		snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;1522		snd_control.info = snd_asihpi_volume_mute_info;1523		snd_control.get = snd_asihpi_volume_mute_get;1524		snd_control.put = snd_asihpi_volume_mute_put;1525		err = ctl_add(card, &snd_control, asihpi);1526	}1527	return err;1528}1529 1530/*------------------------------------------------------------1531   Level controls1532 ------------------------------------------------------------*/1533static int snd_asihpi_level_info(struct snd_kcontrol *kcontrol,1534				 struct snd_ctl_elem_info *uinfo)1535{1536	u32 h_control = kcontrol->private_value;1537	u16 err;1538	short min_gain_mB;1539	short max_gain_mB;1540	short step_gain_mB;1541 1542	err =1543	    hpi_level_query_range(h_control, &min_gain_mB,1544			       &max_gain_mB, &step_gain_mB);1545	if (err) {1546		max_gain_mB = 2400;1547		min_gain_mB = -1000;1548		step_gain_mB = 100;1549	}1550 1551	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;1552	uinfo->count = 2;1553	uinfo->value.integer.min = min_gain_mB / HPI_UNITS_PER_dB;1554	uinfo->value.integer.max = max_gain_mB / HPI_UNITS_PER_dB;1555	uinfo->value.integer.step = step_gain_mB / HPI_UNITS_PER_dB;1556	return 0;1557}1558 1559static int snd_asihpi_level_get(struct snd_kcontrol *kcontrol,1560				struct snd_ctl_elem_value *ucontrol)1561{1562	u32 h_control = kcontrol->private_value;1563	short an_gain_mB[HPI_MAX_CHANNELS];1564 1565	hpi_handle_error(hpi_level_get_gain(h_control, an_gain_mB));1566	ucontrol->value.integer.value[0] =1567	    an_gain_mB[0] / HPI_UNITS_PER_dB;1568	ucontrol->value.integer.value[1] =1569	    an_gain_mB[1] / HPI_UNITS_PER_dB;1570 1571	return 0;1572}1573 1574static int snd_asihpi_level_put(struct snd_kcontrol *kcontrol,1575				struct snd_ctl_elem_value *ucontrol)1576{1577	int change;1578	u32 h_control = kcontrol->private_value;1579	short an_gain_mB[HPI_MAX_CHANNELS];1580 1581	an_gain_mB[0] =1582	    (ucontrol->value.integer.value[0]) * HPI_UNITS_PER_dB;1583	an_gain_mB[1] =1584	    (ucontrol->value.integer.value[1]) * HPI_UNITS_PER_dB;1585	/*  change = asihpi->mixer_level[addr][0] != left ||1586	   asihpi->mixer_level[addr][1] != right;1587	 */1588	change = 1;1589	hpi_handle_error(hpi_level_set_gain(h_control, an_gain_mB));1590	return change;1591}1592 1593static const DECLARE_TLV_DB_SCALE(db_scale_level, -1000, 100, 0);1594 1595static int snd_asihpi_level_add(struct snd_card_asihpi *asihpi,1596				struct hpi_control *hpi_ctl)1597{1598	struct snd_card *card = asihpi->card;1599	struct snd_kcontrol_new snd_control;1600 1601	/* can't use 'volume' cos some nodes have volume as well */1602	asihpi_ctl_init(&snd_control, hpi_ctl, "Level");1603	snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |1604				SNDRV_CTL_ELEM_ACCESS_TLV_READ;1605	snd_control.info = snd_asihpi_level_info;1606	snd_control.get = snd_asihpi_level_get;1607	snd_control.put = snd_asihpi_level_put;1608	snd_control.tlv.p = db_scale_level;1609 1610	return ctl_add(card, &snd_control, asihpi);1611}1612 1613/*------------------------------------------------------------1614   AESEBU controls1615 ------------------------------------------------------------*/1616 1617/* AESEBU format */1618static const char * const asihpi_aesebu_format_names[] = {1619	"N/A", "S/PDIF", "AES/EBU" };1620 1621static int snd_asihpi_aesebu_format_info(struct snd_kcontrol *kcontrol,1622				  struct snd_ctl_elem_info *uinfo)1623{1624	return snd_ctl_enum_info(uinfo, 1, 3, asihpi_aesebu_format_names);1625}1626 1627static int snd_asihpi_aesebu_format_get(struct snd_kcontrol *kcontrol,1628			struct snd_ctl_elem_value *ucontrol,1629			u16 (*func)(u32, u16 *))1630{1631	u32 h_control = kcontrol->private_value;1632	u16 source, err;1633 1634	err = func(h_control, &source);1635 1636	/* default to N/A */1637	ucontrol->value.enumerated.item[0] = 0;1638	/* return success but set the control to N/A */1639	if (err)1640		return 0;1641	if (source == HPI_AESEBU_FORMAT_SPDIF)1642		ucontrol->value.enumerated.item[0] = 1;1643	if (source == HPI_AESEBU_FORMAT_AESEBU)1644		ucontrol->value.enumerated.item[0] = 2;1645 1646	return 0;1647}1648 1649static int snd_asihpi_aesebu_format_put(struct snd_kcontrol *kcontrol,1650			struct snd_ctl_elem_value *ucontrol,1651			 u16 (*func)(u32, u16))1652{1653	u32 h_control = kcontrol->private_value;1654 1655	/* default to S/PDIF */1656	u16 source = HPI_AESEBU_FORMAT_SPDIF;1657 1658	if (ucontrol->value.enumerated.item[0] == 1)1659		source = HPI_AESEBU_FORMAT_SPDIF;1660	if (ucontrol->value.enumerated.item[0] == 2)1661		source = HPI_AESEBU_FORMAT_AESEBU;1662 1663	if (func(h_control, source) != 0)1664		return -EINVAL;1665 1666	return 1;1667}1668 1669static int snd_asihpi_aesebu_rx_format_get(struct snd_kcontrol *kcontrol,1670				 struct snd_ctl_elem_value *ucontrol) {1671	return snd_asihpi_aesebu_format_get(kcontrol, ucontrol,1672					hpi_aesebu_receiver_get_format);1673}1674 1675static int snd_asihpi_aesebu_rx_format_put(struct snd_kcontrol *kcontrol,1676				 struct snd_ctl_elem_value *ucontrol) {1677	return snd_asihpi_aesebu_format_put(kcontrol, ucontrol,1678					hpi_aesebu_receiver_set_format);1679}1680 1681static int snd_asihpi_aesebu_rxstatus_info(struct snd_kcontrol *kcontrol,1682				  struct snd_ctl_elem_info *uinfo)1683{1684	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;1685	uinfo->count = 1;1686 1687	uinfo->value.integer.min = 0;1688	uinfo->value.integer.max = 0X1F;1689	uinfo->value.integer.step = 1;1690 1691	return 0;1692}1693 1694static int snd_asihpi_aesebu_rxstatus_get(struct snd_kcontrol *kcontrol,1695				 struct snd_ctl_elem_value *ucontrol) {1696 1697	u32 h_control = kcontrol->private_value;1698	u16 status;1699 1700	hpi_handle_error(hpi_aesebu_receiver_get_error_status(1701					 h_control, &status));1702	ucontrol->value.integer.value[0] = status;1703	return 0;1704}1705 1706static int snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi,1707				    struct hpi_control *hpi_ctl)1708{1709	struct snd_card *card = asihpi->card;1710	struct snd_kcontrol_new snd_control;1711 1712	asihpi_ctl_init(&snd_control, hpi_ctl, "Format");1713	snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;1714	snd_control.info = snd_asihpi_aesebu_format_info;1715	snd_control.get = snd_asihpi_aesebu_rx_format_get;1716	snd_control.put = snd_asihpi_aesebu_rx_format_put;1717 1718 1719	if (ctl_add(card, &snd_control, asihpi) < 0)1720		return -EINVAL;1721 1722	asihpi_ctl_init(&snd_control, hpi_ctl, "Status");1723	snd_control.access =1724	    SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ;1725	snd_control.info = snd_asihpi_aesebu_rxstatus_info;1726	snd_control.get = snd_asihpi_aesebu_rxstatus_get;1727 1728	return ctl_add(card, &snd_control, asihpi);1729}1730 1731static int snd_asihpi_aesebu_tx_format_get(struct snd_kcontrol *kcontrol,1732				 struct snd_ctl_elem_value *ucontrol) {1733	return snd_asihpi_aesebu_format_get(kcontrol, ucontrol,1734					hpi_aesebu_transmitter_get_format);1735}1736 1737static int snd_asihpi_aesebu_tx_format_put(struct snd_kcontrol *kcontrol,1738				 struct snd_ctl_elem_value *ucontrol) {1739	return snd_asihpi_aesebu_format_put(kcontrol, ucontrol,1740					hpi_aesebu_transmitter_set_format);1741}1742 1743 1744static int snd_asihpi_aesebu_tx_add(struct snd_card_asihpi *asihpi,1745				    struct hpi_control *hpi_ctl)1746{1747	struct snd_card *card = asihpi->card;1748	struct snd_kcontrol_new snd_control;1749 1750	asihpi_ctl_init(&snd_control, hpi_ctl, "Format");1751	snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;1752	snd_control.info = snd_asihpi_aesebu_format_info;1753	snd_control.get = snd_asihpi_aesebu_tx_format_get;1754	snd_control.put = snd_asihpi_aesebu_tx_format_put;1755 1756	return ctl_add(card, &snd_control, asihpi);1757}1758 1759/*------------------------------------------------------------1760   Tuner controls1761 ------------------------------------------------------------*/1762 1763/* Gain */1764 1765static int snd_asihpi_tuner_gain_info(struct snd_kcontrol *kcontrol,1766				  struct snd_ctl_elem_info *uinfo)1767{1768	u32 h_control = kcontrol->private_value;1769	u16 err;1770	short idx;1771	u16 gain_range[3];1772 1773	for (idx = 0; idx < 3; idx++) {1774		err = hpi_tuner_query_gain(h_control,1775					  idx, &gain_range[idx]);1776		if (err != 0)1777			return err;1778	}1779 1780	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;1781	uinfo->count = 1;1782	uinfo->value.integer.min = ((int)gain_range[0]) / HPI_UNITS_PER_dB;1783	uinfo->value.integer.max = ((int)gain_range[1]) / HPI_UNITS_PER_dB;1784	uinfo->value.integer.step = ((int) gain_range[2]) / HPI_UNITS_PER_dB;1785	return 0;1786}1787 1788static int snd_asihpi_tuner_gain_get(struct snd_kcontrol *kcontrol,1789				 struct snd_ctl_elem_value *ucontrol)1790{1791	/*1792	struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol);1793	*/1794	u32 h_control = kcontrol->private_value;1795	short gain;1796 1797	hpi_handle_error(hpi_tuner_get_gain(h_control, &gain));1798	ucontrol->value.integer.value[0] = gain / HPI_UNITS_PER_dB;1799 1800	return 0;1801}1802 1803static int snd_asihpi_tuner_gain_put(struct snd_kcontrol *kcontrol,1804				 struct snd_ctl_elem_value *ucontrol)1805{1806	/*1807	struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol);1808	*/1809	u32 h_control = kcontrol->private_value;1810	short gain;1811 1812	gain = (ucontrol->value.integer.value[0]) * HPI_UNITS_PER_dB;1813	hpi_handle_error(hpi_tuner_set_gain(h_control, gain));1814 1815	return 1;1816}1817 1818/* Band  */1819 1820static int asihpi_tuner_band_query(struct snd_kcontrol *kcontrol,1821					u16 *band_list, u32 len) {1822	u32 h_control = kcontrol->private_value;1823	u16 err = 0;1824	u32 i;1825 1826	for (i = 0; i < len; i++) {1827		err = hpi_tuner_query_band(1828				h_control, i, &band_list[i]);1829		if (err != 0)1830			break;1831	}1832 1833	if (err && (err != HPI_ERROR_INVALID_OBJ_INDEX))1834		return -EIO;1835 1836	return i;1837}1838 1839static int snd_asihpi_tuner_band_info(struct snd_kcontrol *kcontrol,1840				  struct snd_ctl_elem_info *uinfo)1841{1842	u16 tuner_bands[HPI_TUNER_BAND_LAST];1843	int num_bands = 0;1844 1845	num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands,1846				HPI_TUNER_BAND_LAST);1847 1848	if (num_bands < 0)1849		return num_bands;1850 1851	return snd_ctl_enum_info(uinfo, 1, num_bands, asihpi_tuner_band_names);1852}1853 1854static int snd_asihpi_tuner_band_get(struct snd_kcontrol *kcontrol,1855				 struct snd_ctl_elem_value *ucontrol)1856{1857	u32 h_control = kcontrol->private_value;1858	/*1859	struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol);1860	*/1861	u16 band, idx;1862	u16 tuner_bands[HPI_TUNER_BAND_LAST];1863	__always_unused u32 num_bands;1864 1865	num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands,1866				HPI_TUNER_BAND_LAST);1867 1868	hpi_handle_error(hpi_tuner_get_band(h_control, &band));1869 1870	ucontrol->value.enumerated.item[0] = -1;1871	for (idx = 0; idx < HPI_TUNER_BAND_LAST; idx++)1872		if (tuner_bands[idx] == band) {1873			ucontrol->value.enumerated.item[0] = idx;1874			break;1875		}1876 1877	return 0;1878}1879 1880static int snd_asihpi_tuner_band_put(struct snd_kcontrol *kcontrol,1881				 struct snd_ctl_elem_value *ucontrol)1882{1883	/*1884	struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol);1885	*/1886	u32 h_control = kcontrol->private_value;1887	unsigned int idx;1888	u16 band;1889	u16 tuner_bands[HPI_TUNER_BAND_LAST];1890	__always_unused u32 num_bands;1891 1892	num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands,1893			HPI_TUNER_BAND_LAST);1894 1895	idx = ucontrol->value.enumerated.item[0];1896	if (idx >= ARRAY_SIZE(tuner_bands))1897		idx = ARRAY_SIZE(tuner_bands) - 1;1898	band = tuner_bands[idx];1899	hpi_handle_error(hpi_tuner_set_band(h_control, band));1900 1901	return 1;1902}1903 1904/* Freq */1905 1906static int snd_asihpi_tuner_freq_info(struct snd_kcontrol *kcontrol,1907				  struct snd_ctl_elem_info *uinfo)1908{1909	u32 h_control = kcontrol->private_value;1910	u16 err;1911	u16 tuner_bands[HPI_TUNER_BAND_LAST];1912	u16 num_bands = 0, band_iter, idx;1913	u32 freq_range[3], temp_freq_range[3];1914 1915	num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands,1916			HPI_TUNER_BAND_LAST);1917 1918	freq_range[0] = INT_MAX;1919	freq_range[1] = 0;1920	freq_range[2] = INT_MAX;1921 1922	for (band_iter = 0; band_iter < num_bands; band_iter++) {1923		for (idx = 0; idx < 3; idx++) {1924			err = hpi_tuner_query_frequency(h_control,1925				idx, tuner_bands[band_iter],1926				&temp_freq_range[idx]);1927			if (err != 0)1928				return err;1929		}1930 1931		/* skip band with bogus stepping */1932		if (temp_freq_range[2] <= 0)1933			continue;1934 1935		if (temp_freq_range[0] < freq_range[0])1936			freq_range[0] = temp_freq_range[0];1937		if (temp_freq_range[1] > freq_range[1])1938			freq_range[1] = temp_freq_range[1];1939		if (temp_freq_range[2] < freq_range[2])1940			freq_range[2] = temp_freq_range[2];1941	}1942 1943	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;1944	uinfo->count = 1;1945	uinfo->value.integer.min = ((int)freq_range[0]);1946	uinfo->value.integer.max = ((int)freq_range[1]);1947	uinfo->value.integer.step = ((int)freq_range[2]);1948	return 0;1949}1950 1951static int snd_asihpi_tuner_freq_get(struct snd_kcontrol *kcontrol,1952				 struct snd_ctl_elem_value *ucontrol)1953{1954	u32 h_control = kcontrol->private_value;1955	u32 freq;1956 1957	hpi_handle_error(hpi_tuner_get_frequency(h_control, &freq));1958	ucontrol->value.integer.value[0] = freq;1959 1960	return 0;1961}1962 1963static int snd_asihpi_tuner_freq_put(struct snd_kcontrol *kcontrol,1964				 struct snd_ctl_elem_value *ucontrol)1965{1966	u32 h_control = kcontrol->private_value;1967	u32 freq;1968 1969	freq = ucontrol->value.integer.value[0];1970	hpi_handle_error(hpi_tuner_set_frequency(h_control, freq));1971 1972	return 1;1973}1974 1975/* Tuner control group initializer  */1976static int snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi,1977				struct hpi_control *hpi_ctl)1978{1979	struct snd_card *card = asihpi->card;1980	struct snd_kcontrol_new snd_control;1981 1982	snd_control.private_value = hpi_ctl->h_control;1983	snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;1984 1985	if (!hpi_tuner_get_gain(hpi_ctl->h_control, NULL)) {1986		asihpi_ctl_init(&snd_control, hpi_ctl, "Gain");1987		snd_control.info = snd_asihpi_tuner_gain_info;1988		snd_control.get = snd_asihpi_tuner_gain_get;1989		snd_control.put = snd_asihpi_tuner_gain_put;1990 1991		if (ctl_add(card, &snd_control, asihpi) < 0)1992			return -EINVAL;1993	}1994 1995	asihpi_ctl_init(&snd_control, hpi_ctl, "Band");1996	snd_control.info = snd_asihpi_tuner_band_info;1997	snd_control.get = snd_asihpi_tuner_band_get;1998	snd_control.put = snd_asihpi_tuner_band_put;1999 2000	if (ctl_add(card, &snd_control, asihpi) < 0)2001		return -EINVAL;2002 2003	asihpi_ctl_init(&snd_control, hpi_ctl, "Freq");2004	snd_control.info = snd_asihpi_tuner_freq_info;2005	snd_control.get = snd_asihpi_tuner_freq_get;2006	snd_control.put = snd_asihpi_tuner_freq_put;2007 2008	return ctl_add(card, &snd_control, asihpi);2009}2010 2011/*------------------------------------------------------------2012   Meter controls2013 ------------------------------------------------------------*/2014static int snd_asihpi_meter_info(struct snd_kcontrol *kcontrol,2015				 struct snd_ctl_elem_info *uinfo)2016{2017	u32 h_control = kcontrol->private_value;2018	u32 count;2019	u16 err;2020	err = hpi_meter_query_channels(h_control, &count);2021	if (err)2022		count = HPI_MAX_CHANNELS;2023 2024	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;2025	uinfo->count = count;2026	uinfo->value.integer.min = 0;2027	uinfo->value.integer.max = 0x7FFFFFFF;2028	return 0;2029}2030 2031/* linear values for 10dB steps */2032static const int log2lin[] = {2033	0x7FFFFFFF, /* 0dB */2034	679093956,2035	214748365,2036	 67909396,2037	 21474837,2038	  6790940,2039	  2147484, /* -60dB */2040	   679094,2041	   214748, /* -80 */2042	    67909,2043	    21475, /* -100 */2044	     6791,2045	     2147,2046	      679,2047	      214,2048	       68,2049	       21,2050		7,2051		22052};2053 2054static int snd_asihpi_meter_get(struct snd_kcontrol *kcontrol,2055				struct snd_ctl_elem_value *ucontrol)2056{2057	u32 h_control = kcontrol->private_value;2058	short an_gain_mB[HPI_MAX_CHANNELS], i;2059	u16 err;2060 2061	err = hpi_meter_get_peak(h_control, an_gain_mB);2062 2063	for (i = 0; i < HPI_MAX_CHANNELS; i++) {2064		if (err) {2065			ucontrol->value.integer.value[i] = 0;2066		} else if (an_gain_mB[i] >= 0) {2067			ucontrol->value.integer.value[i] =2068				an_gain_mB[i] << 16;2069		} else {2070			/* -ve is log value in millibels < -60dB,2071			* convert to (roughly!) linear,2072			*/2073			ucontrol->value.integer.value[i] =2074					log2lin[an_gain_mB[i] / -1000];2075		}2076	}2077	return 0;2078}2079 2080static int snd_asihpi_meter_add(struct snd_card_asihpi *asihpi,2081				struct hpi_control *hpi_ctl, int subidx)2082{2083	struct snd_card *card = asihpi->card;2084	struct snd_kcontrol_new snd_control;2085 2086	asihpi_ctl_init(&snd_control, hpi_ctl, "Meter");2087	snd_control.access =2088	    SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ;2089	snd_control.info = snd_asihpi_meter_info;2090	snd_control.get = snd_asihpi_meter_get;2091 2092	snd_control.index = subidx;2093 2094	return ctl_add(card, &snd_control, asihpi);2095}2096 2097/*------------------------------------------------------------2098   Multiplexer controls2099 ------------------------------------------------------------*/2100static int snd_card_asihpi_mux_count_sources(struct snd_kcontrol *snd_control)2101{2102	u32 h_control = snd_control->private_value;2103	struct hpi_control hpi_ctl;2104	int s, err;2105	for (s = 0; s < 32; s++) {2106		err = hpi_multiplexer_query_source(h_control, s,2107						  &hpi_ctl.2108						  src_node_type,2109						  &hpi_ctl.2110						  src_node_index);2111		if (err)2112			break;2113	}2114	return s;2115}2116 2117static int snd_asihpi_mux_info(struct snd_kcontrol *kcontrol,2118			       struct snd_ctl_elem_info *uinfo)2119{2120	u16 src_node_type, src_node_index;2121	u32 h_control = kcontrol->private_value;2122 2123	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;2124	uinfo->count = 1;2125	uinfo->value.enumerated.items =2126	    snd_card_asihpi_mux_count_sources(kcontrol);2127 2128	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)2129		uinfo->value.enumerated.item =2130		    uinfo->value.enumerated.items - 1;2131 2132	hpi_multiplexer_query_source(h_control,2133				     uinfo->value.enumerated.item,2134				     &src_node_type, &src_node_index);2135 2136	sprintf(uinfo->value.enumerated.name, "%s %d",2137		asihpi_src_names[src_node_type - HPI_SOURCENODE_NONE],2138		src_node_index);2139	return 0;2140}2141 2142static int snd_asihpi_mux_get(struct snd_kcontrol *kcontrol,2143			      struct snd_ctl_elem_value *ucontrol)2144{2145	u32 h_control = kcontrol->private_value;2146	u16 source_type, source_index;2147	u16 src_node_type, src_node_index;2148	int s;2149 2150	hpi_handle_error(hpi_multiplexer_get_source(h_control,2151				&source_type, &source_index));2152	/* Should cache this search result! */2153	for (s = 0; s < 256; s++) {2154		if (hpi_multiplexer_query_source(h_control, s,2155					    &src_node_type, &src_node_index))2156			break;2157 2158		if ((source_type == src_node_type)2159		    && (source_index == src_node_index)) {2160			ucontrol->value.enumerated.item[0] = s;2161			return 0;2162		}2163	}2164	pr_warn("%s: Control %x failed to match mux source %hu %hu\n",2165		__func__, h_control, source_type, source_index);2166	ucontrol->value.enumerated.item[0] = 0;2167	return 0;2168}2169 2170static int snd_asihpi_mux_put(struct snd_kcontrol *kcontrol,2171			      struct snd_ctl_elem_value *ucontrol)2172{2173	int change;2174	u32 h_control = kcontrol->private_value;2175	u16 source_type, source_index;2176	u16 e;2177 2178	change = 1;2179 2180	e = hpi_multiplexer_query_source(h_control,2181				    ucontrol->value.enumerated.item[0],2182				    &source_type, &source_index);2183	if (!e)2184		hpi_handle_error(2185			hpi_multiplexer_set_source(h_control,2186						source_type, source_index));2187	return change;2188}2189 2190 2191static int  snd_asihpi_mux_add(struct snd_card_asihpi *asihpi,2192			       struct hpi_control *hpi_ctl)2193{2194	struct snd_card *card = asihpi->card;2195	struct snd_kcontrol_new snd_control;2196 2197	asihpi_ctl_init(&snd_control, hpi_ctl, "Route");2198	snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;2199	snd_control.info = snd_asihpi_mux_info;2200	snd_control.get = snd_asihpi_mux_get;2201	snd_control.put = snd_asihpi_mux_put;2202 2203	return ctl_add(card, &snd_control, asihpi);2204 2205}2206 2207/*------------------------------------------------------------2208   Channel mode controls2209 ------------------------------------------------------------*/2210static int snd_asihpi_cmode_info(struct snd_kcontrol *kcontrol,2211				 struct snd_ctl_elem_info *uinfo)2212{2213	static const char * const mode_names[HPI_CHANNEL_MODE_LAST + 1] = {2214		"invalid",2215		"Normal", "Swap",2216		"From Left", "From Right",2217		"To Left", "To Right"2218	};2219 2220	u32 h_control = kcontrol->private_value;2221	u16 mode;2222	int i;2223	const char *mapped_names[6];2224	int valid_modes = 0;2225 2226	/* HPI channel mode values can be from 1 to 62227	Some adapters only support a contiguous subset2228	*/2229	for (i = 0; i < HPI_CHANNEL_MODE_LAST; i++)2230		if (!hpi_channel_mode_query_mode(2231			h_control, i, &mode)) {2232			mapped_names[valid_modes] = mode_names[mode];2233			valid_modes++;2234			}2235 2236	if (!valid_modes)2237		return -EINVAL;2238 2239	return snd_ctl_enum_info(uinfo, 1, valid_modes, mapped_names);2240}2241 2242static int snd_asihpi_cmode_get(struct snd_kcontrol *kcontrol,2243				struct snd_ctl_elem_value *ucontrol)2244{2245	u32 h_control = kcontrol->private_value;2246	u16 mode;2247 2248	if (hpi_channel_mode_get(h_control, &mode))2249		mode = 1;2250 2251	ucontrol->value.enumerated.item[0] = mode - 1;2252 2253	return 0;2254}2255 2256static int snd_asihpi_cmode_put(struct snd_kcontrol *kcontrol,2257				struct snd_ctl_elem_value *ucontrol)2258{2259	int change;2260	u32 h_control = kcontrol->private_value;2261 2262	change = 1;2263 2264	hpi_handle_error(hpi_channel_mode_set(h_control,2265			   ucontrol->value.enumerated.item[0] + 1));2266	return change;2267}2268 2269 2270static int snd_asihpi_cmode_add(struct snd_card_asihpi *asihpi,2271				struct hpi_control *hpi_ctl)2272{2273	struct snd_card *card = asihpi->card;2274	struct snd_kcontrol_new snd_control;2275 2276	asihpi_ctl_init(&snd_control, hpi_ctl, "Mode");2277	snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;2278	snd_control.info = snd_asihpi_cmode_info;2279	snd_control.get = snd_asihpi_cmode_get;2280	snd_control.put = snd_asihpi_cmode_put;2281 2282	return ctl_add(card, &snd_control, asihpi);2283}2284 2285/*------------------------------------------------------------2286   Sampleclock source  controls2287 ------------------------------------------------------------*/2288static const char * const sampleclock_sources[] = {2289	"N/A", "Local PLL", "Digital Sync", "Word External", "Word Header",2290	"SMPTE", "Digital1", "Auto", "Network", "Invalid",2291	"Prev Module", "BLU-Link",2292	"Digital2", "Digital3", "Digital4", "Digital5",2293	"Digital6", "Digital7", "Digital8"};2294 2295	/* Number of strings must match expected enumerated values */2296	compile_time_assert(2297		(ARRAY_SIZE(sampleclock_sources) == MAX_CLOCKSOURCES),2298		assert_sampleclock_sources_size);2299 2300static int snd_asihpi_clksrc_info(struct snd_kcontrol *kcontrol,2301				  struct snd_ctl_elem_info *uinfo)2302{2303	struct snd_card_asihpi *asihpi =2304			(struct snd_card_asihpi *)(kcontrol->private_data);2305	struct clk_cache *clkcache = &asihpi->cc;2306	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;2307	uinfo->count = 1;2308	uinfo->value.enumerated.items = clkcache->count;2309 2310	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)2311		uinfo->value.enumerated.item =2312				uinfo->value.enumerated.items - 1;2313 2314	strcpy(uinfo->value.enumerated.name,2315	       clkcache->s[uinfo->value.enumerated.item].name);2316	return 0;2317}2318 2319static int snd_asihpi_clksrc_get(struct snd_kcontrol *kcontrol,2320				 struct snd_ctl_elem_value *ucontrol)2321{2322	struct snd_card_asihpi *asihpi =2323			(struct snd_card_asihpi *)(kcontrol->private_data);2324	struct clk_cache *clkcache = &asihpi->cc;2325	u32 h_control = kcontrol->private_value;2326	u16 source, srcindex = 0;2327	int i;2328 2329	ucontrol->value.enumerated.item[0] = 0;2330	if (hpi_sample_clock_get_source(h_control, &source))2331		source = 0;2332 2333	if (source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT)2334		if (hpi_sample_clock_get_source_index(h_control, &srcindex))2335			srcindex = 0;2336 2337	for (i = 0; i < clkcache->count; i++)2338		if ((clkcache->s[i].source == source) &&2339			(clkcache->s[i].index == srcindex))2340			break;2341 2342	ucontrol->value.enumerated.item[0] = i;2343 2344	return 0;2345}2346 2347static int snd_asihpi_clksrc_put(struct snd_kcontrol *kcontrol,2348				 struct snd_ctl_elem_value *ucontrol)2349{2350	struct snd_card_asihpi *asihpi =2351			(struct snd_card_asihpi *)(kcontrol->private_data);2352	struct clk_cache *clkcache = &asihpi->cc;2353	unsigned int item;2354	int change;2355	u32 h_control = kcontrol->private_value;2356 2357	change = 1;2358	item = ucontrol->value.enumerated.item[0];2359	if (item >= clkcache->count)2360		item = clkcache->count-1;2361 2362	hpi_handle_error(hpi_sample_clock_set_source(2363				h_control, clkcache->s[item].source));2364 2365	if (clkcache->s[item].source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT)2366		hpi_handle_error(hpi_sample_clock_set_source_index(2367				h_control, clkcache->s[item].index));2368	return change;2369}2370 2371/*------------------------------------------------------------2372   Clkrate controls2373 ------------------------------------------------------------*/2374/* Need to change this to enumerated control with list of rates */2375static int snd_asihpi_clklocal_info(struct snd_kcontrol *kcontrol,2376				   struct snd_ctl_elem_info *uinfo)2377{2378	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;2379	uinfo->count = 1;2380	uinfo->value.integer.min = 8000;2381	uinfo->value.integer.max = 192000;2382	uinfo->value.integer.step = 100;2383 2384	return 0;2385}2386 2387static int snd_asihpi_clklocal_get(struct snd_kcontrol *kcontrol,2388				  struct snd_ctl_elem_value *ucontrol)2389{2390	u32 h_control = kcontrol->private_value;2391	u32 rate;2392	u16 e;2393 2394	e = hpi_sample_clock_get_local_rate(h_control, &rate);2395	if (!e)2396		ucontrol->value.integer.value[0] = rate;2397	else2398		ucontrol->value.integer.value[0] = 0;2399	return 0;2400}2401 2402static int snd_asihpi_clklocal_put(struct snd_kcontrol *kcontrol,2403				  struct snd_ctl_elem_value *ucontrol)2404{2405	int change;2406	u32 h_control = kcontrol->private_value;2407 2408	/*  change = asihpi->mixer_clkrate[addr][0] != left ||2409	   asihpi->mixer_clkrate[addr][1] != right;2410	 */2411	change = 1;2412	hpi_handle_error(hpi_sample_clock_set_local_rate(h_control,2413				      ucontrol->value.integer.value[0]));2414	return change;2415}2416 2417static int snd_asihpi_clkrate_info(struct snd_kcontrol *kcontrol,2418				   struct snd_ctl_elem_info *uinfo)2419{2420	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;2421	uinfo->count = 1;2422	uinfo->value.integer.min = 8000;2423	uinfo->value.integer.max = 192000;2424	uinfo->value.integer.step = 100;2425 2426	return 0;2427}2428 2429static int snd_asihpi_clkrate_get(struct snd_kcontrol *kcontrol,2430				  struct snd_ctl_elem_value *ucontrol)2431{2432	u32 h_control = kcontrol->private_value;2433	u32 rate;2434	u16 e;2435 2436	e = hpi_sample_clock_get_sample_rate(h_control, &rate);2437	if (!e)2438		ucontrol->value.integer.value[0] = rate;2439	else2440		ucontrol->value.integer.value[0] = 0;2441	return 0;2442}2443 2444static int snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,2445				      struct hpi_control *hpi_ctl)2446{2447	struct snd_card *card;2448	struct snd_kcontrol_new snd_control;2449 2450	struct clk_cache *clkcache;2451	u32 hSC =  hpi_ctl->h_control;2452	int has_aes_in = 0;2453	int i, j;2454	u16 source;2455 2456	if (snd_BUG_ON(!asihpi))2457		return -EINVAL;2458	card = asihpi->card;2459	clkcache = &asihpi->cc;2460	snd_control.private_value = hpi_ctl->h_control;2461 2462	clkcache->has_local = 0;2463 2464	for (i = 0; i <= HPI_SAMPLECLOCK_SOURCE_LAST; i++) {2465		if  (hpi_sample_clock_query_source(hSC,2466				i, &source))2467			break;2468		clkcache->s[i].source = source;2469		clkcache->s[i].index = 0;2470		clkcache->s[i].name = sampleclock_sources[source];2471		if (source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT)2472			has_aes_in = 1;2473		if (source == HPI_SAMPLECLOCK_SOURCE_LOCAL)2474			clkcache->has_local = 1;2475	}2476	if (has_aes_in)2477		/* already will have picked up index 0 above */2478		for (j = 1; j < 8; j++) {2479			if (hpi_sample_clock_query_source_index(hSC,2480				j, HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT,2481				&source))2482				break;2483			clkcache->s[i].source =2484				HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT;2485			clkcache->s[i].index = j;2486			clkcache->s[i].name = sampleclock_sources[2487					j+HPI_SAMPLECLOCK_SOURCE_LAST];2488			i++;2489		}2490	clkcache->count = i;2491 2492	asihpi_ctl_init(&snd_control, hpi_ctl, "Source");2493	snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ;2494	snd_control.info = snd_asihpi_clksrc_info;2495	snd_control.get = snd_asihpi_clksrc_get;2496	snd_control.put = snd_asihpi_clksrc_put;2497	if (ctl_add(card, &snd_control, asihpi) < 0)2498		return -EINVAL;2499 2500 2501	if (clkcache->has_local) {2502		asihpi_ctl_init(&snd_control, hpi_ctl, "Localrate");2503		snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ;2504		snd_control.info = snd_asihpi_clklocal_info;2505		snd_control.get = snd_asihpi_clklocal_get;2506		snd_control.put = snd_asihpi_clklocal_put;2507 2508 2509		if (ctl_add(card, &snd_control, asihpi) < 0)2510			return -EINVAL;2511	}2512 2513	asihpi_ctl_init(&snd_control, hpi_ctl, "Rate");2514	snd_control.access =2515	    SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ;2516	snd_control.info = snd_asihpi_clkrate_info;2517	snd_control.get = snd_asihpi_clkrate_get;2518 2519	return ctl_add(card, &snd_control, asihpi);2520}2521/*------------------------------------------------------------2522   Mixer2523 ------------------------------------------------------------*/2524 2525static int snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)2526{2527	struct snd_card *card;2528	unsigned int idx = 0;2529	unsigned int subindex = 0;2530	int err;2531	struct hpi_control hpi_ctl, prev_ctl;2532 2533	if (snd_BUG_ON(!asihpi))2534		return -EINVAL;2535	card = asihpi->card;2536	strcpy(card->mixername, "Asihpi Mixer");2537 2538	err =2539	    hpi_mixer_open(asihpi->hpi->adapter->index,2540			  &asihpi->h_mixer);2541	hpi_handle_error(err);2542	if (err)2543		return -err;2544 2545	memset(&prev_ctl, 0, sizeof(prev_ctl));2546	prev_ctl.control_type = -1;2547 2548	for (idx = 0; idx < 2000; idx++) {2549		err = hpi_mixer_get_control_by_index(2550				asihpi->h_mixer,2551				idx,2552				&hpi_ctl.src_node_type,2553				&hpi_ctl.src_node_index,2554				&hpi_ctl.dst_node_type,2555				&hpi_ctl.dst_node_index,2556				&hpi_ctl.control_type,2557				&hpi_ctl.h_control);2558		if (err) {2559			if (err == HPI_ERROR_CONTROL_DISABLED) {2560				if (mixer_dump)2561					dev_info(&asihpi->pci->dev,2562						   "Disabled HPI Control(%d)\n",2563						   idx);2564				continue;2565			} else2566				break;2567 2568		}2569 2570		hpi_ctl.src_node_type -= HPI_SOURCENODE_NONE;2571		hpi_ctl.dst_node_type -= HPI_DESTNODE_NONE;2572 2573		/* ASI50xx in SSX mode has multiple meters on the same node.2574		   Use subindex to create distinct ALSA controls2575		   for any duplicated controls.2576		*/2577		if ((hpi_ctl.control_type == prev_ctl.control_type) &&2578		    (hpi_ctl.src_node_type == prev_ctl.src_node_type) &&2579		    (hpi_ctl.src_node_index == prev_ctl.src_node_index) &&2580		    (hpi_ctl.dst_node_type == prev_ctl.dst_node_type) &&2581		    (hpi_ctl.dst_node_index == prev_ctl.dst_node_index))2582			subindex++;2583		else2584			subindex = 0;2585 2586		prev_ctl = hpi_ctl;2587 2588		switch (hpi_ctl.control_type) {2589		case HPI_CONTROL_VOLUME:2590			err = snd_asihpi_volume_add(asihpi, &hpi_ctl);2591			break;2592		case HPI_CONTROL_LEVEL:2593			err = snd_asihpi_level_add(asihpi, &hpi_ctl);2594			break;2595		case HPI_CONTROL_MULTIPLEXER:2596			err = snd_asihpi_mux_add(asihpi, &hpi_ctl);2597			break;2598		case HPI_CONTROL_CHANNEL_MODE:2599			err = snd_asihpi_cmode_add(asihpi, &hpi_ctl);2600			break;2601		case HPI_CONTROL_METER:2602			err = snd_asihpi_meter_add(asihpi, &hpi_ctl, subindex);2603			break;2604		case HPI_CONTROL_SAMPLECLOCK:2605			err = snd_asihpi_sampleclock_add(2606						asihpi, &hpi_ctl);2607			break;2608		case HPI_CONTROL_CONNECTION:	/* ignore these */2609			continue;2610		case HPI_CONTROL_TUNER:2611			err = snd_asihpi_tuner_add(asihpi, &hpi_ctl);2612			break;2613		case HPI_CONTROL_AESEBU_TRANSMITTER:2614			err = snd_asihpi_aesebu_tx_add(asihpi, &hpi_ctl);2615			break;2616		case HPI_CONTROL_AESEBU_RECEIVER:2617			err = snd_asihpi_aesebu_rx_add(asihpi, &hpi_ctl);2618			break;2619		case HPI_CONTROL_VOX:2620		case HPI_CONTROL_BITSTREAM:2621		case HPI_CONTROL_MICROPHONE:2622		case HPI_CONTROL_PARAMETRIC_EQ:2623		case HPI_CONTROL_COMPANDER:2624		default:2625			if (mixer_dump)2626				dev_info(&asihpi->pci->dev,2627					"Untranslated HPI Control (%d) %d %d %d %d %d\n",2628					idx,2629					hpi_ctl.control_type,2630					hpi_ctl.src_node_type,2631					hpi_ctl.src_node_index,2632					hpi_ctl.dst_node_type,2633					hpi_ctl.dst_node_index);2634			continue;2635		}2636		if (err < 0)2637			return err;2638	}2639	if (HPI_ERROR_INVALID_OBJ_INDEX != err)2640		hpi_handle_error(err);2641 2642	dev_info(&asihpi->pci->dev, "%d mixer controls found\n", idx);2643 2644	return 0;2645}2646 2647/*------------------------------------------------------------2648   /proc interface2649 ------------------------------------------------------------*/2650 2651static void2652snd_asihpi_proc_read(struct snd_info_entry *entry,2653			struct snd_info_buffer *buffer)2654{2655	struct snd_card_asihpi *asihpi = entry->private_data;2656	u32 h_control;2657	u32 rate = 0;2658	u16 source = 0;2659 2660	u16 num_outstreams;2661	u16 num_instreams;2662	u16 version;2663	u32 serial_number;2664	u16 type;2665 2666	int err;2667 2668	snd_iprintf(buffer, "ASIHPI driver proc file\n");2669 2670	hpi_handle_error(hpi_adapter_get_info(asihpi->hpi->adapter->index,2671			&num_outstreams, &num_instreams,2672			&version, &serial_number, &type));2673 2674	snd_iprintf(buffer,2675			"Adapter type ASI%4X\nHardware Index %d\n"2676			"%d outstreams\n%d instreams\n",2677			type, asihpi->hpi->adapter->index,2678			num_outstreams, num_instreams);2679 2680	snd_iprintf(buffer,2681		"Serial#%d\nHardware version %c%d\nDSP code version %03d\n",2682		serial_number, ((version >> 3) & 0xf) + 'A', version & 0x7,2683		((version >> 13) * 100) + ((version >> 7) & 0x3f));2684 2685	err = hpi_mixer_get_control(asihpi->h_mixer,2686				  HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,2687				  HPI_CONTROL_SAMPLECLOCK, &h_control);2688 2689	if (!err) {2690		err = hpi_sample_clock_get_sample_rate(h_control, &rate);2691		err += hpi_sample_clock_get_source(h_control, &source);2692 2693		if (!err)2694			snd_iprintf(buffer, "Sample Clock %dHz, source %s\n",2695			rate, sampleclock_sources[source]);2696	}2697}2698 2699static void snd_asihpi_proc_init(struct snd_card_asihpi *asihpi)2700{2701	snd_card_ro_proc_new(asihpi->card, "info", asihpi,2702			     snd_asihpi_proc_read);2703}2704 2705/*------------------------------------------------------------2706   HWDEP2707 ------------------------------------------------------------*/2708 2709static int snd_asihpi_hpi_open(struct snd_hwdep *hw, struct file *file)2710{2711	if (enable_hpi_hwdep)2712		return 0;2713	else2714		return -ENODEV;2715 2716}2717 2718static int snd_asihpi_hpi_release(struct snd_hwdep *hw, struct file *file)2719{2720	if (enable_hpi_hwdep)2721		return asihpi_hpi_release(file);2722	else2723		return -ENODEV;2724}2725 2726static int snd_asihpi_hpi_ioctl(struct snd_hwdep *hw, struct file *file,2727				unsigned int cmd, unsigned long arg)2728{2729	if (enable_hpi_hwdep)2730		return asihpi_hpi_ioctl(file, cmd, arg);2731	else2732		return -ENODEV;2733}2734 2735 2736/* results in /dev/snd/hwC#D0 file for each card with index #2737   also /proc/asound/hwdep will contain '#-00: asihpi (HPI) for each card'2738*/2739static int snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi, int device)2740{2741	struct snd_hwdep *hw;2742	int err;2743 2744	err = snd_hwdep_new(asihpi->card, "HPI", device, &hw);2745	if (err < 0)2746		return err;2747	strcpy(hw->name, "asihpi (HPI)");2748	hw->iface = SNDRV_HWDEP_IFACE_LAST;2749	hw->ops.open = snd_asihpi_hpi_open;2750	hw->ops.ioctl = snd_asihpi_hpi_ioctl;2751	hw->ops.release = snd_asihpi_hpi_release;2752	hw->private_data = asihpi;2753	return 0;2754}2755 2756/*------------------------------------------------------------2757   CARD2758 ------------------------------------------------------------*/2759static int snd_asihpi_probe(struct pci_dev *pci_dev,2760			    const struct pci_device_id *pci_id)2761{2762	int err;2763	struct hpi_adapter *hpi;2764	struct snd_card *card;2765	struct snd_card_asihpi *asihpi;2766 2767	u32 h_control;2768	u32 h_stream;2769	u32 adapter_index;2770 2771	static int dev;2772	if (dev >= SNDRV_CARDS)2773		return -ENODEV;2774 2775	/* Should this be enable[hpi->index] ? */2776	if (!enable[dev]) {2777		dev++;2778		return -ENOENT;2779	}2780 2781	/* Initialise low-level HPI driver */2782	err = asihpi_adapter_probe(pci_dev, pci_id);2783	if (err < 0)2784		return err;2785 2786	hpi = pci_get_drvdata(pci_dev);2787	adapter_index = hpi->adapter->index;2788	/* first try to give the card the same index as its hardware index */2789	err = snd_card_new(&pci_dev->dev, adapter_index, id[adapter_index],2790			   THIS_MODULE, sizeof(struct snd_card_asihpi), &card);2791	if (err < 0) {2792		/* if that fails, try the default index==next available */2793		err = snd_card_new(&pci_dev->dev, index[dev], id[dev],2794				   THIS_MODULE, sizeof(struct snd_card_asihpi),2795				   &card);2796		if (err < 0)2797			return err;2798		dev_warn(&pci_dev->dev, "Adapter index %d->ALSA index %d\n",2799			adapter_index, card->number);2800	}2801 2802	asihpi = card->private_data;2803	asihpi->card = card;2804	asihpi->pci = pci_dev;2805	asihpi->hpi = hpi;2806	hpi->snd_card = card;2807 2808	err = hpi_adapter_get_property(adapter_index,2809		HPI_ADAPTER_PROPERTY_CAPS1,2810		NULL, &asihpi->support_grouping);2811	if (err)2812		asihpi->support_grouping = 0;2813 2814	err = hpi_adapter_get_property(adapter_index,2815		HPI_ADAPTER_PROPERTY_CAPS2,2816		&asihpi->support_mrx, NULL);2817	if (err)2818		asihpi->support_mrx = 0;2819 2820	err = hpi_adapter_get_property(adapter_index,2821		HPI_ADAPTER_PROPERTY_INTERVAL,2822		NULL, &asihpi->update_interval_frames);2823	if (err)2824		asihpi->update_interval_frames = 512;2825 2826	if (hpi->interrupt_mode) {2827		asihpi->pcm_start = snd_card_asihpi_pcm_int_start;2828		asihpi->pcm_stop = snd_card_asihpi_pcm_int_stop;2829		hpi->interrupt_callback = snd_card_asihpi_isr;2830	} else {2831		asihpi->pcm_start = snd_card_asihpi_pcm_timer_start;2832		asihpi->pcm_stop = snd_card_asihpi_pcm_timer_stop;2833	}2834 2835	hpi_handle_error(hpi_instream_open(adapter_index,2836			     0, &h_stream));2837 2838	err = hpi_instream_host_buffer_free(h_stream);2839	asihpi->can_dma = (!err);2840 2841	hpi_handle_error(hpi_instream_close(h_stream));2842 2843	if (!asihpi->can_dma)2844		asihpi->update_interval_frames *= 2;2845 2846	err = hpi_adapter_get_property(adapter_index,2847		HPI_ADAPTER_PROPERTY_CURCHANNELS,2848		&asihpi->in_max_chans, &asihpi->out_max_chans);2849	if (err) {2850		asihpi->in_max_chans = 2;2851		asihpi->out_max_chans = 2;2852	}2853 2854	if (asihpi->out_max_chans > 2) { /* assume LL mode */2855		asihpi->out_min_chans = asihpi->out_max_chans;2856		asihpi->in_min_chans = asihpi->in_max_chans;2857		asihpi->support_grouping = 0;2858	} else {2859		asihpi->out_min_chans = 1;2860		asihpi->in_min_chans = 1;2861	}2862 2863	dev_info(&pci_dev->dev, "Has dma:%d, grouping:%d, mrx:%d, uif:%d\n",2864			asihpi->can_dma,2865			asihpi->support_grouping,2866			asihpi->support_mrx,2867			asihpi->update_interval_frames2868	      );2869 2870	err = snd_card_asihpi_pcm_new(asihpi, 0);2871	if (err < 0) {2872		dev_err(&pci_dev->dev, "pcm_new failed\n");2873		goto __nodev;2874	}2875	err = snd_card_asihpi_mixer_new(asihpi);2876	if (err < 0) {2877		dev_err(&pci_dev->dev, "mixer_new failed\n");2878		goto __nodev;2879	}2880 2881	err = hpi_mixer_get_control(asihpi->h_mixer,2882				  HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,2883				  HPI_CONTROL_SAMPLECLOCK, &h_control);2884 2885	if (!err)2886		err = hpi_sample_clock_set_local_rate(2887			h_control, adapter_fs);2888 2889	snd_asihpi_proc_init(asihpi);2890 2891	/* always create, can be enabled or disabled dynamically2892	    by enable_hwdep  module param*/2893	snd_asihpi_hpi_new(asihpi, 0);2894 2895	strcpy(card->driver, "ASIHPI");2896 2897	sprintf(card->shortname, "AudioScience ASI%4X",2898			asihpi->hpi->adapter->type);2899	sprintf(card->longname, "%s %i",2900			card->shortname, adapter_index);2901	err = snd_card_register(card);2902 2903	if (!err) {2904		dev++;2905		return 0;2906	}2907__nodev:2908	snd_card_free(card);2909	dev_err(&pci_dev->dev, "snd_asihpi_probe error %d\n", err);2910	return err;2911 2912}2913 2914static void snd_asihpi_remove(struct pci_dev *pci_dev)2915{2916	struct hpi_adapter *hpi = pci_get_drvdata(pci_dev);2917 2918	/* Stop interrupts */2919	if (hpi->interrupt_mode) {2920		hpi->interrupt_callback = NULL;2921		hpi_handle_error(hpi_adapter_set_property(hpi->adapter->index,2922			HPI_ADAPTER_PROPERTY_IRQ_RATE, 0, 0));2923	}2924 2925	snd_card_free(hpi->snd_card);2926	hpi->snd_card = NULL;2927	asihpi_adapter_remove(pci_dev);2928}2929 2930static const struct pci_device_id asihpi_pci_tbl[] = {2931	{HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_DSP6205,2932		HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0,2933		(kernel_ulong_t)HPI_6205},2934	{HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_PCI2040,2935		HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0,2936		(kernel_ulong_t)HPI_6000},2937	{0,}2938};2939MODULE_DEVICE_TABLE(pci, asihpi_pci_tbl);2940 2941static struct pci_driver driver = {2942	.name = KBUILD_MODNAME,2943	.id_table = asihpi_pci_tbl,2944	.probe = snd_asihpi_probe,2945	.remove = snd_asihpi_remove,2946};2947 2948static int __init snd_asihpi_init(void)2949{2950	asihpi_init();2951	return pci_register_driver(&driver);2952}2953 2954static void __exit snd_asihpi_exit(void)2955{2956 2957	pci_unregister_driver(&driver);2958	asihpi_exit();2959}2960 2961module_init(snd_asihpi_init)2962module_exit(snd_asihpi_exit)2963 2964