[alsa-devel] [PATCH - ASIHPI 7/8] Support variable size cached control information.

linux at audioscience.com linux at audioscience.com
Thu Jun 5 06:07:00 CEST 2008


From: Eliot Blennerhassett <linux at audioscience.com>


Signed-off-by: Eliot Blennerhassett <eblennerhassett at audioscience.com>

diff --git a/pci/asihpi/hpi6000.c b/pci/asihpi/hpi6000.c
index ec2ae66..6d1834e 100644
--- a/pci/asihpi/hpi6000.c
+++ b/pci/asihpi/hpi6000.c
@@ -158,6 +158,7 @@ struct hpi_hw_obj {
 	u16 wDspCrashed;	/* when '1' DSP has crashed/died/OTL */
 
 	struct hpi_control_cache_single aControlCache[HPI_NMIXER_CONTROLS];
+	struct hpi_control_cache *pCache;
 };
 
 static u16 Hpi6000_DspBlockWrite32(
@@ -319,8 +320,7 @@ static void ControlMessage(
 			}
 
 			if (HpiCheckControlCache
-				(&((struct hpi_hw_obj *)pao->priv)->
-					aControlCache[phm->u.c.wControlIndex],
+				(((struct hpi_hw_obj *)pao->priv)->pCache,
 					phm, phr))
 				break;
 		}
@@ -331,8 +331,8 @@ static void ControlMessage(
 		break;
 	case HPI_CONTROL_SET_STATE:
 		HW_Message(pao, phm, phr);
-		HpiSyncControlCache(&((struct hpi_hw_obj *)pao->priv)->
-			aControlCache[phm->u.c.wControlIndex], phm, phr);
+		HpiSyncControlCache(
+			((struct hpi_hw_obj *)pao->priv)->pCache, phm, phr);
 		break;
 	default:
 		phr->wError = HPI_ERROR_INVALID_FUNC;
@@ -431,7 +431,7 @@ void HPI_6000(
 	/* subsytem messages get executed by every HPI. */
 	/* All other messages are ignored unless the adapter index matches */
 	/* an adapter in the HPI */
-	HPI_DEBUG_LOG(DEBUG, "O %d,F %d\n", phm->wObject, phm->wFunction);
+	HPI_DEBUG_LOG(DEBUG, "O %d,F %x\n", phm->wObject, phm->wFunction);
 
 	/* if Dsp has crashed then do not communicate with it any more */
 	if (phm->wObject != HPI_OBJ_SUBSYSTEM) {
@@ -573,15 +573,19 @@ static void SubSysDeleteAdapter(
 )
 {
 	struct hpi_adapter_obj *pao = NULL;
-	void *priv;
+	struct hpi_hw_obj *phw;
 
 	pao = HpiFindAdapter(phm->wAdapterIndex);
 	if (!pao)
 		return;
 
-	priv = pao->priv;
+	phw = (struct hpi_hw_obj *)pao->priv;
+
+	if (pao->wHasControlCache)
+		HpiFreeControlCache(phw->pCache);
+
 	HpiDeleteAdapter(pao);
-	kfree(priv);
+	kfree(phw);
 
 	phr->wError = 0;
 }
@@ -594,6 +598,8 @@ static short CreateAdapterObj(
 {
 	short nBootError = 0;
 	u32 dwDspIndex = 0;
+	u32 dwControlCacheSize = 0;
+	u32 dwControlCacheCount = 0;
 	struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
 
 	/* init error reporting */
@@ -693,10 +699,18 @@ static short CreateAdapterObj(
 		sizeof(struct hpi_control_cache_single) *
 		HPI_NMIXER_CONTROLS);
 	/* Read the control cache length to figure out if it is turned on */
-	if (HpiReadWord
-		(&phw->ado[0], HPI_HIF_ADDR(dwControlCacheSizeInBytes)))
+	dwControlCacheSize = HpiReadWord(&phw->ado[0],
+		HPI_HIF_ADDR(dwControlCacheSizeInBytes));
+	if (dwControlCacheSize) {
+		dwControlCacheCount = HpiReadWord(&phw->ado[0],
+			HPI_HIF_ADDR(dwControlCacheCount));
 		pao->wHasControlCache = 1;
-	else
+
+		phw->pCache = HpiAllocControlCache(dwControlCacheCount,
+			dwControlCacheSize, (struct hpi_control_cache_info *)
+			&phw->aControlCache[0]
+			);
+	} else
 		pao->wHasControlCache = 0;
 
 	HPI_DEBUG_LOG(DEBUG, "Get adapter info ASI%04X index %d\n",
diff --git a/pci/asihpi/hpi6000.h b/pci/asihpi/hpi6000.h
index ba75b0b..348ad8d 100644
--- a/pci/asihpi/hpi6000.h
+++ b/pci/asihpi/hpi6000.h
@@ -45,6 +45,7 @@ struct hpi_hif_6000 {
 	u32 dwControlCacheIsDirty;
 	u32 dwControlCacheAddress;
 	u32 dwControlCacheSizeInBytes;
+	u32 dwControlCacheCount;
 };
 
 #define HPI_HIF_PACK_ADAPTER_INFO(adapter, versionMajor, versionMinor) \
diff --git a/pci/asihpi/hpi6205.c b/pci/asihpi/hpi6205.c
index b74add0..ff010a7 100644
--- a/pci/asihpi/hpi6205.c
+++ b/pci/asihpi/hpi6205.c
@@ -126,8 +126,10 @@ struct hpi_hw_obj {
 
 	struct consistent_dma_area hControlCache;
 	struct consistent_dma_area hAsyncEventBuffer;
-	struct hpi_control_cache_single *pControlCache;
+/*      struct hpi_control_cache_single *pControlCache; */
 	struct hpi_async_event *pAsyncEventBuffer;
+	struct hpi_control_cache *pCache;
+
 };
 
 /*****************************************************************************/
@@ -172,12 +174,6 @@ static void SubSysDeleteAdapter(
 	struct hpi_response *phr
 );
 
-static void AdapterGetAsserts(
-	struct hpi_adapter_obj *pao,
-	struct hpi_message *phm,
-	struct hpi_response *phr
-);
-
 static u16 CreateAdapterObj(
 	struct hpi_adapter_obj *pao,
 	u32 *pdwOsErrorCode
@@ -325,9 +321,7 @@ static void ControlMessage(
 	case HPI_CONTROL_GET_STATE:
 		if (pao->wHasControlCache) {
 			rmb();	/* make sure we see updates DMAed from DSP */
-			if (HpiCheckControlCache
-				(&pHw6205->pControlCache[phm->u.c.
-						wControlIndex], phm, phr))
+			if (HpiCheckControlCache(pHw6205->pCache, phm, phr))
 				break;
 		}
 		HW_Message(pao, phm, phr);
@@ -338,9 +332,7 @@ static void ControlMessage(
 	case HPI_CONTROL_SET_STATE:
 		HW_Message(pao, phm, phr);
 		if (pao->wHasControlCache)
-			HpiSyncControlCache(&pHw6205->
-				pControlCache[phm->u.c.
-					wControlIndex], phm, phr);
+			HpiSyncControlCache(pHw6205->pCache, phm, phr);
 		break;
 	default:
 		phr->wError = HPI_ERROR_INVALID_FUNC;
@@ -354,14 +346,7 @@ static void AdapterMessage(
 	struct hpi_response *phr
 )
 {
-
 	switch (phm->wFunction) {
-	case HPI_ADAPTER_GET_INFO:
-		HW_Message(pao, phm, phr);
-		break;
-	case HPI_ADAPTER_GET_ASSERT:
-		AdapterGetAsserts(pao, phm, phr);
-		break;
 	default:
 		HW_Message(pao, phm, phr);
 		break;
@@ -506,6 +491,7 @@ void HPI_6205(
 			AdapterMessage(pao, phm, phr);
 			break;
 
+		case HPI_OBJ_CONTROLEX:
 		case HPI_OBJ_CONTROL:
 			ControlMessage(pao, phm, phr);
 			break;
@@ -694,20 +680,25 @@ static u16 CreateAdapterObj(
 	 * Allocate bus mastering control cache buffer and tell the DSP about it
 	 */
 	if (interface->aControlCache.dwNumberOfControls) {
+		void *pControlCacheVirtual;
+
 		err = HpiOs_LockedMem_Alloc(&pHw6205->hControlCache,
-			interface->aControlCache.
-			dwNumberOfControls *
-			sizeof(struct hpi_control_cache_single),
+			interface->aControlCache.dwSizeInBytes,
 			pao->Pci.pOsData);
 		if (!err)
 			err = HpiOs_LockedMem_GetVirtAddr(&pHw6205->
-				hControlCache, (void *)
-				&pHw6205->pControlCache);
-		if (!err)
-			memset((void *)pHw6205->pControlCache, 0,
-				interface->aControlCache.
-				dwNumberOfControls *
-				sizeof(struct hpi_control_cache_single));
+				hControlCache, &pControlCacheVirtual);
+		if (!err) {
+			memset(pControlCacheVirtual, 0,
+				interface->aControlCache.dwSizeInBytes);
+
+			pHw6205->pCache =
+				HpiAllocControlCache(interface->aControlCache.
+				dwNumberOfControls,
+				interface->aControlCache.dwSizeInBytes,
+				(struct hpi_control_cache_info *)
+				pControlCacheVirtual);
+		}
 		if (!err) {
 			err = HpiOs_LockedMem_GetPhysAddr(&pHw6205->
 				hControlCache, &dwPhysAddr);
@@ -718,10 +709,8 @@ static u16 CreateAdapterObj(
 		if (!err)
 			pao->wHasControlCache = 1;
 		else {
-			if (HpiOs_LockedMem_Valid(&pHw6205->hControlCache)) {
+			if (HpiOs_LockedMem_Valid(&pHw6205->hControlCache))
 				HpiOs_LockedMem_Free(&pHw6205->hControlCache);
-				pHw6205->pControlCache = NULL;
-			}
 			pao->wHasControlCache = 0;
 		}
 	}
@@ -816,7 +805,7 @@ static void DeleteAdapterObj(
 
 	if (HpiOs_LockedMem_Valid(&pHw6205->hControlCache)) {
 		HpiOs_LockedMem_Free(&pHw6205->hControlCache);
-		pHw6205->pControlCache = NULL;
+		HpiFreeControlCache(pHw6205->pCache);
 	}
 
 	if (HpiOs_LockedMem_Valid(&pHw6205->hLockedMem)) {
@@ -846,19 +835,6 @@ static void DeleteAdapterObj(
 }
 
 /*****************************************************************************/
-/* ADAPTER */
-
-static void AdapterGetAsserts(
-	struct hpi_adapter_obj *pao,
-	struct hpi_message *phm,
-	struct hpi_response *phr
-)
-{
-	HW_Message(pao, phm, phr);	/*get DSP asserts */
-	return;
-}
-
-/*****************************************************************************/
 /* OutStream Host buffer functions */
 
 /** Allocate or attach buffer for busmastering
diff --git a/pci/asihpi/hpi6205.h b/pci/asihpi/hpi6205.h
index c5309cb..2c92d59 100644
--- a/pci/asihpi/hpi6205.h
+++ b/pci/asihpi/hpi6205.h
@@ -67,7 +67,7 @@ This is used for dynamic control cache allocation
 struct controlcache_6205 {
 	u32 dwNumberOfControls;
 	u32 dwPhysicalPCI32address;
-	u32 dwSpare;
+	u32 dwSizeInBytes;
 };
 
 /*********************************************************************
diff --git a/pci/asihpi/hpicmn.c b/pci/asihpi/hpicmn.c
index 29fe40f..af83a2e 100644
--- a/pci/asihpi/hpicmn.c
+++ b/pci/asihpi/hpicmn.c
@@ -21,6 +21,7 @@
 (C) Copyright AudioScience Inc. 1998-2003
 *******************************************************************************/
 #define SOURCEFILE_NAME "hpicmn.c"
+
 #include "hpi.h"
 #include "hpidebug.h"
 #include "hpicmn.h"
@@ -106,12 +107,16 @@ struct hpi_adapter_obj *HpiFindAdapter(
 
 	pao = &adapters.adapter[wAdapterIndex];
 	if (pao->wAdapterType != 0) {
-		HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
-			wAdapterIndex);
+		/*
+		   HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
+		   wAdapterIndex);
+		 */
 		return (pao);
 	} else {
-		HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
-			wAdapterIndex);
+		/*
+		   HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
+		   wAdapterIndex);
+		 */
 		return (NULL);
 	}
 }
@@ -171,25 +176,141 @@ static void SubSysGetAdapters(
 	phr->wError = 0;	/* the function completed OK; */
 }
 
-/**
-* CheckControlCache checks if a given struct hpi_control_cache_single control
-* value is in the cache and fills the struct hpi_response accordingly.
-* It returns nonzero if a cache hit occurred, zero otherwise.
+static unsigned int ControlCacheAllocCheck(
+	struct hpi_control_cache *pC
+)
+{
+	unsigned int i;
+	int nCached = 0;
+	if (!pC)
+		return 0;
+	if ((!pC->dwInit) &&
+		(pC->pCache != NULL) &&
+		(pC->dwControlCount) && (pC->dwCacheSizeInBytes)
+		) {
+		u32 *pMasterCache;
+		pC->dwInit = 1;
+
+		pMasterCache = (u32 *)pC->pCache;
+		for (i = 0; i < pC->dwControlCount; i++) {
+			struct hpi_control_cache_info *info =
+				(struct hpi_control_cache_info *)pMasterCache;
+
+			if (info->ControlType) {
+				pC->pInfo[i] = info;
+				nCached++;
+			} else
+				pC->pInfo[i] = NULL;
+
+			if (info->nSizeIn32bitWords)
+				pMasterCache += info->nSizeIn32bitWords;
+			else
+				pMasterCache +=
+					sizeof(struct
+					hpi_control_cache_single) /
+					sizeof(u32);
+
+		}
+		/*
+		   We didn't find anything to cache, so try again later !
+		 */
+		if (!nCached)
+			pC->dwInit = 0;
+	}
+	return pC->dwInit;
+}
+
+/** Find a control.
+*/
+static short FindControl(
+	struct hpi_message *phm,
+	struct hpi_control_cache *pCache,
+	struct hpi_control_cache_info **pI,
+	u16 *pwControlIndex
+)
+{
+	if (phm->wObject == HPI_OBJ_CONTROL) {
+		*pwControlIndex = phm->u.c.wControlIndex;
+	} else {	/* controlex */
+		*pwControlIndex = phm->u.cx.wControlIndex;
+		HPI_DEBUG_LOG(VERBOSE,
+			"HpiCheckControlCache() ControlEx %d\n",
+			*pwControlIndex);
+	}
+
+	if (!ControlCacheAllocCheck(pCache)) {
+		HPI_DEBUG_LOG(VERBOSE,
+			"ControlCacheAllocCheck() failed. adap%d ci%d\n",
+			phm->wAdapterIndex, *pwControlIndex);
+		return 0;
+	}
+
+	*pI = pCache->pInfo[*pwControlIndex];
+	if (!*pI) {
+		HPI_DEBUG_LOG(VERBOSE,
+			"Uncached Adap %d, Control %d\n",
+			phm->wAdapterIndex, *pwControlIndex);
+		return 0;
+	} else {
+		HPI_DEBUG_LOG(VERBOSE,
+			"HpiCheckControlCache() Type %d\n",
+			(*pI)->ControlType);
+	}
+	return 1;
+}
+
+/** Used by the kernel driver to figure out if a buffer needs mapping.
+ */
+short HpiCheckBufferMapping(
+	struct hpi_control_cache *pCache,
+	struct hpi_message *phm,
+	void **p,
+	unsigned int *pN
+)
+{
+	*pN = 0;
+	*p = NULL;
+	if ((phm->wFunction == HPI_CONTROL_GET_STATE) &&
+		(phm->wObject == HPI_OBJ_CONTROLEX)
+		) {
+		u16 wControlIndex;
+		struct hpi_control_cache_info *pI;
+
+		if (!FindControl(phm, pCache, &pI, &wControlIndex))
+			return 0;
+	}
+	return 0;
+}
+
+/** CheckControlCache checks the cache and fills the struct hpi_response
+* accordingly. It returns one if a cache hit occurred, zero otherwise.
 */
 short HpiCheckControlCache(
-	struct hpi_control_cache_single *pC,
+	struct hpi_control_cache *pCache,
 	struct hpi_message *phm,
 	struct hpi_response *phr
 )
 {
 	short found = 1;
-	/* if the control type in the cache is non-zero then */
-	/* we have cached control information to process */
+	u16 wControlIndex;
+	struct hpi_control_cache_info *pI;
+	struct hpi_control_cache_single *pC;
+
+	if (!FindControl(phm, pCache, &pI, &wControlIndex))
+		return 0;
+
 	phr->wSize =
 		sizeof(struct hpi_response_header) +
 		sizeof(struct hpi_control_res);
 	phr->wError = 0;
-	switch (pC->ControlType) {
+
+	/* pC is the default cached control strucure. May be cast to
+	   something else in the following switch statement.
+	 */
+	pC = (struct hpi_control_cache_single *)pI;
+
+	switch (pI->ControlType) {
+
 	case HPI_CONTROL_METER:
 		if (phm->u.c.wAttribute == HPI_METER_PEAK) {
 			phr->u.c.anLogValue[0] = pC->u.p.anLogPeak[0];
@@ -198,45 +319,50 @@ short HpiCheckControlCache(
 			phr->u.c.anLogValue[0] = pC->u.p.anLogRMS[0];
 			phr->u.c.anLogValue[1] = pC->u.p.anLogRMS[1];
 		} else
-			found = 0;	/* signal that message was not cached */
+			found = 0;
 		break;
 	case HPI_CONTROL_VOLUME:
 		if (phm->u.c.wAttribute == HPI_VOLUME_GAIN) {
 			phr->u.c.anLogValue[0] = pC->u.v.anLog[0];
 			phr->u.c.anLogValue[1] = pC->u.v.anLog[1];
 		} else
-			found = 0;	/* signal that message was not cached */
+			found = 0;
 		break;
 	case HPI_CONTROL_MULTIPLEXER:
 		if (phm->u.c.wAttribute == HPI_MULTIPLEXER_SOURCE) {
 			phr->u.c.dwParam1 = pC->u.x.wSourceNodeType;
 			phr->u.c.dwParam2 = pC->u.x.wSourceNodeIndex;
 		} else
-			found = 0;	/* signal that message was not cached */
+			found = 0;
 		break;
 	case HPI_CONTROL_CHANNEL_MODE:
 		if (phm->u.c.wAttribute == HPI_CHANNEL_MODE_MODE)
 			phr->u.c.dwParam1 = pC->u.m.wMode;
 		else
-			found = 0;	/* signal that message was not cached */
-
+			found = 0;
+		break;
 	case HPI_CONTROL_LEVEL:
 		if (phm->u.c.wAttribute == HPI_LEVEL_GAIN) {
 			phr->u.c.anLogValue[0] = pC->u.l.anLog[0];
 			phr->u.c.anLogValue[1] = pC->u.l.anLog[1];
 		} else
-			found = 0;	/* signal that message was not cached */
+			found = 0;
 		break;
 	case HPI_CONTROL_TUNER:
-		if (phm->u.c.wAttribute == HPI_TUNER_FREQ)
-			phr->u.c.dwParam1 = pC->u.t.dwFreqInkHz;
-		else if (phm->u.c.wAttribute == HPI_TUNER_BAND)
-			phr->u.c.dwParam1 = pC->u.t.wBand;
-		else if ((phm->u.c.wAttribute == HPI_TUNER_LEVEL) &&
-			(phm->u.c.dwParam1 == HPI_TUNER_LEVEL_AVERAGE))
-			phr->u.c.dwParam1 = pC->u.t.wLevel;
-		else
-			found = 0;	/* signal that message was not cached */
+		{
+			struct hpi_control_cache_single *pCT =
+				(struct hpi_control_cache_single *)pI;
+			if (phm->u.c.wAttribute == HPI_TUNER_FREQ)
+				phr->u.c.dwParam1 = pCT->u.t.dwFreqInkHz;
+			else if (phm->u.c.wAttribute == HPI_TUNER_BAND)
+				phr->u.c.dwParam1 = pCT->u.t.wBand;
+			else if ((phm->u.c.wAttribute == HPI_TUNER_LEVEL) &&
+				(phm->u.c.dwParam1 ==
+					HPI_TUNER_LEVEL_AVERAGE))
+				phr->u.c.dwParam1 = pCT->u.t.wLevel;
+			else
+				found = 0;
+		}
 		break;
 	case HPI_CONTROL_AESEBU_RECEIVER:
 		if (phm->u.c.wAttribute == HPI_AESEBURX_ERRORSTATUS)
@@ -244,26 +370,26 @@ short HpiCheckControlCache(
 		else if (phm->u.c.wAttribute == HPI_AESEBURX_FORMAT)
 			phr->u.c.dwParam1 = pC->u.aes3rx.dwSource;
 		else
-			found = 0;	/* signal that message was not cached */
+			found = 0;
 		break;
 	case HPI_CONTROL_AESEBU_TRANSMITTER:
 		if (phm->u.c.wAttribute == HPI_AESEBUTX_FORMAT)
 			phr->u.c.dwParam1 = pC->u.aes3tx.dwFormat;
 		else
-			found = 0;	/* signal that message was not cached */
+			found = 0;
 		break;
 	case HPI_CONTROL_TONEDETECTOR:
 		if (phm->u.c.wAttribute == HPI_TONEDETECTOR_STATE)
 			phr->u.c.dwParam1 = pC->u.tone.wState;
 		else
-			found = 0;	/* signal that message was not cached */
+			found = 0;
 		break;
 	case HPI_CONTROL_SILENCEDETECTOR:
 		if (phm->u.c.wAttribute == HPI_SILENCEDETECTOR_STATE) {
 			phr->u.c.dwParam1 = pC->u.silence.dwState;
 			phr->u.c.dwParam2 = pC->u.silence.dwCount;
 		} else
-			found = 0;	/* signal that message was not cached */
+			found = 0;
 		break;
 	case HPI_CONTROL_SAMPLECLOCK:
 		if (phm->u.c.wAttribute == HPI_SAMPLECLOCK_SOURCE)
@@ -278,17 +404,105 @@ short HpiCheckControlCache(
 		} else if (phm->u.c.wAttribute == HPI_SAMPLECLOCK_SAMPLERATE)
 			phr->u.c.dwParam1 = pC->u.clk.dwSampleRate;
 		else
-			found = 0;	/* signal that message was not cached */
+			found = 0;
+		break;
+#ifndef HPI_OS_WIN16	/* SGT - below does not compile in Borland C */
+	case HPI_CONTROL_PAD:
+		{
+			struct hpi_control_cache_pad *pPad =
+				(struct hpi_control_cache_pad *)pC;
+
+			if (!(pPad->dwFieldValidFlags &
+					(1 << HPI_CTL_ATTR_INDEX(phm->u.c.
+							wAttribute)))) {
+				/* attribute not supported */
+				phr->wError =
+					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
+				break;
+			}
+
+			if (phm->u.c.wAttribute == HPI_PAD_PROGRAM_ID)
+				phr->u.c.dwParam1 = pPad->dwPI;
+			else if (phm->u.c.wAttribute == HPI_PAD_PROGRAM_TYPE)
+				phr->u.c.dwParam1 = pPad->dwPTY;
+			else {
+				struct attribs {
+					u8 *pData;
+					unsigned int nSize;
+				};
+				struct attribs aDesc[] = {
+					{NULL, 0},
+					/* HPI_PAD_CHANNEL_NAME */
+					{pPad->cChannel, sizeof(pPad->
+								cChannel)}
+					,
+					/* HPI_PAD_ARTIST */
+					{pPad->cArtist, sizeof(pPad->cArtist)}
+					,
+					/* HPI_PAD_TITLE */
+					{pPad->cTitle, sizeof(pPad->cTitle)}
+					,
+					/* HPI_PAD_COMMENT */
+					{pPad->cComment, sizeof(pPad->
+								cComment)}
+					,
+				};
+
+				const u32 dwAttribute = phm->u.c.wAttribute;
+				const u32 dwIndex =
+					HPI_CTL_ATTR_INDEX(dwAttribute);
+				const u32 dwOffset = phm->u.c.dwParam1;
+				int nStringLength = 0;
+				int nRemainingChars = 0;
+
+				HPI_DEBUG_LOG(VERBOSE, "PADS control\n");
+
+				/* check the field type */
+				HPI_DEBUG_LOG(VERBOSE,
+					"PADS HPI_PADS_ %d\n", dwAttribute);
+
+				switch (dwAttribute) {
+				case HPI_PAD_CHANNEL_NAME:
+				case HPI_PAD_ARTIST:
+				case HPI_PAD_TITLE:
+				case HPI_PAD_COMMENT:
+					break;
+				default:
+					phr->wError = HPI_ERROR_INVALID_FUNC;
+				}
+				if (phr->wError)
+					break;
+
+				nStringLength = strlen(aDesc[dwIndex].pData);
+				if (dwOffset > (unsigned)nStringLength) {
+					phr->wError =
+						HPI_ERROR_INVALID_CONTROL_VALUE;
+					break;
+				}
+				HPI_DEBUG_LOG(VERBOSE,
+					"PADS memcpy (%d), offset %d \n",
+					8, dwOffset);
+				memcpy(&phr->u.cu.chars8.szData[0],
+					&aDesc[dwIndex].pData[dwOffset], 8);
+				nRemainingChars =
+					nStringLength - dwOffset - 8;
+				if (nRemainingChars < 0)
+					nRemainingChars = 0;
+				phr->u.cu.chars8.dwRemainingChars =
+					nRemainingChars;
+			}
+		}
 		break;
+#endif
 	default:
-		found = 0;	/* signal that message was not cached */
+		found = 0;
 		break;
 	}
-	if (found == 0)
-		HPI_DEBUG_LOG(VERBOSE, "Adap %d, Control %d, "
-			"Control type %d, Cached %d\n",
-			phm->wAdapterIndex, pC->ControlIndex,
-			pC->ControlType, found);
+	if (pI->ControlType && !found)
+		HPI_DEBUG_LOG(VERBOSE,
+			"Uncached Adap %d, Control %d, Control type %d\n",
+			phm->wAdapterIndex, pI->ControlIndex,
+			pI->ControlType);
 
 	return found;
 }
@@ -300,15 +514,24 @@ Volume and Level return the limited values in the response, so use these
 Multiplexer does so use sent values
 */
 void HpiSyncControlCache(
-	struct hpi_control_cache_single *pC,
+	struct hpi_control_cache *pCache,
 	struct hpi_message *phm,
 	struct hpi_response *phr
 )
 {
-	if (phr->wError)
+	u16 wControlIndex;
+	struct hpi_control_cache_single *pC;
+	struct hpi_control_cache_info *pI;
+
+	if (!FindControl(phm, pCache, &pI, &wControlIndex))
 		return;
 
-	switch (pC->ControlType) {
+	/* pC is the default cached control strucure.
+	   May be cast to something else in the following switch statement.
+	 */
+	pC = (struct hpi_control_cache_single *)pI;
+
+	switch (pI->ControlType) {
 	case HPI_CONTROL_VOLUME:
 		if (phm->u.c.wAttribute == HPI_VOLUME_GAIN) {
 			pC->u.v.anLog[0] = phr->u.c.anLogValue[0];
@@ -323,8 +546,8 @@ void HpiSyncControlCache(
 		}
 		break;
 	case HPI_CONTROL_CHANNEL_MODE:
-		/* mux does not return its setting on Set command. */
-		if (phm->u.c.wAttribute == HPI_MULTIPLEXER_SOURCE)
+		/* mode does not return its setting on Set command. */
+		if (phm->u.c.wAttribute == HPI_CHANNEL_MODE_MODE)
 			pC->u.m.wMode = (u16)phm->u.c.dwParam1;
 		break;
 	case HPI_CONTROL_LEVEL:
@@ -340,6 +563,7 @@ void HpiSyncControlCache(
 	case HPI_CONTROL_AESEBU_RECEIVER:
 		if (phm->u.c.wAttribute == HPI_AESEBURX_FORMAT)
 			pC->u.aes3rx.dwSource = phm->u.c.dwParam1;
+		break;
 	case HPI_CONTROL_SAMPLECLOCK:
 		if (phm->u.c.wAttribute == HPI_SAMPLECLOCK_SOURCE)
 			pC->u.clk.wSource = (u16)phm->u.c.dwParam1;
@@ -358,6 +582,35 @@ void HpiSyncControlCache(
 		break;
 	}
 }
+struct hpi_control_cache *HpiAllocControlCache(
+	const u32 dwNumberOfControls,
+	const u32 dwSizeInBytes,
+	struct hpi_control_cache_info *pDSPControlBuffer
+)
+{
+	struct hpi_control_cache *pCache =
+		kmalloc(sizeof(*pCache), GFP_KERNEL);
+	pCache->dwCacheSizeInBytes = dwSizeInBytes;
+	pCache->dwControlCount = dwNumberOfControls;
+	pCache->pCache = (struct hpi_control_cache_single *)pDSPControlBuffer;
+	pCache->dwInit = 0;
+	pCache->pInfo =
+		kmalloc(sizeof(*pCache->pInfo) * pCache->dwControlCount,
+		GFP_KERNEL);
+	return pCache;
+}
+
+void HpiFreeControlCache(
+	struct hpi_control_cache *pCache
+)
+{
+	if ((pCache->dwInit) && (pCache->pInfo)) {
+		kfree(pCache->pInfo);
+		pCache->pInfo = NULL;
+		pCache->dwInit = 0;
+		kfree(pCache);
+	}
+}
 
 static void SubSysMessage(
 	struct hpi_message *phm,
diff --git a/pci/asihpi/hpicmn.h b/pci/asihpi/hpicmn.h
index 4b7692a..b0763e2 100644
--- a/pci/asihpi/hpicmn.h
+++ b/pci/asihpi/hpicmn.h
@@ -32,6 +32,18 @@ struct hpi_adapter_obj {
 	void *priv;
 };
 
+struct hpi_control_cache {
+	u32 dwInit;	       /**< indicates whether the
+				structures are initialized */
+	u32 dwControlCount;
+	u32 dwCacheSizeInBytes;
+	struct hpi_control_cache_info
+	**pInfo;		/**< pointer to allocated memory of
+				lookup pointers. */
+	struct hpi_control_cache_single
+	*pCache;		/**< pointer to DSP's control cache. */
+};
+
 struct hpi_adapter_obj *HpiFindAdapter(
 	u16 wAdapterIndex
 );
@@ -44,12 +56,22 @@ void HpiDeleteAdapter(
 );
 
 short HpiCheckControlCache(
-	struct hpi_control_cache_single *pC,
+	struct hpi_control_cache *pC,
 	struct hpi_message *phm,
 	struct hpi_response *phr
 );
+struct hpi_control_cache *HpiAllocControlCache(
+	const u32 dwNumberOfControls,
+	const u32 dwSizeInBytes,
+	struct hpi_control_cache_info
+	*pDSPControlBuffer
+);
+void HpiFreeControlCache(
+	struct hpi_control_cache *pCache
+);
+
 void HpiSyncControlCache(
-	struct hpi_control_cache_single *pC,
+	struct hpi_control_cache *pC,
 	struct hpi_message *phm,
 	struct hpi_response *phr
 );
@@ -57,3 +79,9 @@ u16 HpiValidateResponse(
 	struct hpi_message *phm,
 	struct hpi_response *phr
 );
+short HpiCheckBufferMapping(
+	struct hpi_control_cache *pCache,
+	struct hpi_message *phm,
+	void **p,
+	unsigned int *pN
+);
-- 
1.5.4.3



More information about the Alsa-devel mailing list