⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 patch_cnxthsf.c

📁 一个Linux下的软猫驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * HD audio interface patch for Conexant HSF modems *  * Copyright (c) 2005-2006 Linuxant inc. *  * 1.  General Public License. This program is free software, and may * be redistributed or modified subject to the terms of the GNU General * Public License (version 2) or the GNU Lesser General Public License, * or (at your option) any later versions ("Open Source" code). You may * obtain a copy of the GNU General Public License at * http://www.fsf.org/copyleft/gpl.html and a copy of the GNU Lesser * General Public License at http://www.fsf.org/copyleft/less.html, * or you may alternatively write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA. *  * 2.   Disclaimer of Warranties. LINUXANT AND OTHER CONTRIBUTORS MAKE NO * REPRESENTATION ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. * IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTIES OF ANY KIND. * LINUXANT AND OTHER CONTRIBUTORS DISCLAIMS ALL WARRANTIES WITH REGARD TO * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE, GOOD TITLE AND AGAINST INFRINGEMENT. *  * This software has not been formally tested, and there is no guarantee that * it is free of errors including, but not limited to, bugs, defects, * interrupted operation, or unexpected results. Any use of this software is * at user's own risk. *  * 3.   No Liability. *  * (a) Conexant or contributors shall not be responsible for any loss or * damage to Company, its customers, or any third parties for any reason * whatsoever, and LINUXANT OR CONTRIBUTORS SHALL NOT BE LIABLE FOR ANY * ACTUAL, DIRECT, INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL, OR CONSEQUENTIAL * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED, WHETHER IN CONTRACT, STRICT OR OTHER LEGAL THEORY OF * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. *  * (b) User agrees to hold Conexant and contributors harmless from any * liability, loss, cost, damage or expense, including attorney's fees, * as a result of any claims which may be made by any person, including * but not limited to User, its agents and employees, its customers, or * any third parties that arise out of or result from the manufacture, * delivery, actual or alleged ownership, performance, use, operation * or possession of the software furnished hereunder, whether such claims * are based on negligence, breach of contract, absolute liability or any * other legal theory. *  * 4.   Notices. User hereby agrees not to remove, alter or destroy any * copyright, trademark, credits, other proprietary notices or confidential * legends placed upon, contained within or associated with the Software, * and shall include all such unaltered copyright, trademark, credits, * other proprietary notices or confidential legends on or in every copy of * the Software. *  */#include <sound/driver.h>#include <linux/init.h>#include <sound/core.h>#include "hda_codec.h"#include "hda_local.h"#if defined(__i386__)#define __shimcall__ __attribute__((regparm(0)))#define __kernelcall__#define __kernelcallregparm__ __attribute__((regparm(3)))#define __kernelcallstkparm__ __attribute__((regparm(0)))#else#define __shimcall__#define __kernelcall__#define __kernelcallregparm__#define __kernelcallstkparm__#endifstruct cnxthsf_spec {	void *pDevNode;	unsigned int stream_tags[2];	int do_prepare[2];	void (*cbHdaEvent)(void *Context, unsigned int res) __shimcall__;	void *cbHdaEventContext;	unsigned char cbHdaTag;	struct hda_pcm pcm;};static int cnxthsf_pcm_prepare(struct hda_pcm_stream *hinfo,			      struct hda_codec *codec,			      unsigned int stream_tag,			      unsigned int format,			      snd_pcm_substream_t *substream){	struct cnxthsf_spec *spec = codec->spec;//printk(KERN_DEBUG"%s: codec=%p stream=%d stream_tag=%x format=0x%x substream=%p\n", __FUNCTION__, codec, substream->stream, stream_tag, format, substream);	spec->stream_tags[substream->stream] = stream_tag;	return 0;}static int cnxthsf_pcm_open(struct hda_pcm_stream *hinfo, struct hda_codec *codec,			    snd_pcm_substream_t *substream){	static unsigned int rates[] = { 16000 };	static snd_pcm_hw_constraint_list_t hw_constraints_rates = {		.count = ARRAY_SIZE(rates),		.list = rates,		.mask = 0,	};//printk(KERN_DEBUG"%s: codec=%p substream=%p\n", __FUNCTION__, codec, substream);#if 0 // XXX	//substream->runtime->hw.periods_min = 1;	substream->runtime->hw.period_bytes_min = 256; //4096;#endif	return snd_pcm_hw_constraint_list(substream->runtime, 0,			SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);}#if 0static int cnxthsf_pcm_close(struct hda_pcm_stream *info, struct hda_codec *codec, snd_pcm_substream_t *substream){}static int cnxthsf_pcm_cleanup(struct hda_pcm_stream *info, struct hda_codec *codec, snd_pcm_substream_t *substream){}#endifstatic struct hda_pcm_stream cnxthsf_pcm = {	.substreams = 1,	.channels_min = 1,	.channels_max = 1,	.nid = 0x1,	.rates = SNDRV_PCM_RATE_16000,	.formats = SNDRV_PCM_FMTBIT_S16_LE,	.maxbps = 16,	.ops = {		.open = cnxthsf_pcm_open,		//.close = cnxthsf_pcm_close,		.prepare = cnxthsf_pcm_prepare,		//.cleanup = cnxthsf_pcm_cleanup,	},};static int cnxthsf_build_pcms(struct hda_codec *codec){	struct cnxthsf_spec *spec = codec->spec;	struct hda_pcm *info = &spec->pcm;//printk(KERN_DEBUG"%s: codec=%p mfg=%d\n", __FUNCTION__, codec, codec->mfg);	cnxthsf_pcm.nid = codec->mfg;	codec->num_pcms = 1;	codec->pcm_info = info;	info->name = "HSF Modem";	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cnxthsf_pcm;	info->stream[SNDRV_PCM_STREAM_CAPTURE]  = cnxthsf_pcm;	info->is_modem = 1;	return 0;}static int cnxthsf_init(struct hda_codec *codec){	int ret;	struct cnxthsf_spec *spec = codec->spec;	int (*cnxthwhda_probe)(void *codec, struct device *hwDev, void **ppDevNode);//printk(KERN_DEBUG"%s: codec=%p\n", __FUNCTION__, codec);	cnxthwhda_probe = (void*)symbol_request(cnxthwhda_probe);	if(!cnxthwhda_probe) {		printk(KERN_ERR"%s: symbol_request(cnxthwhda_probe) failed\n", __FUNCTION__);		return -ENOENT;	}	ret = cnxthwhda_probe(codec, codec->bus->card->dev, &spec->pDevNode);	if(ret) {		printk(KERN_ERR"%s: cnxthwhda_probe() failed: %d\n", __FUNCTION__, ret);		symbol_put(cnxthwhda_probe);		return ret;	}	return ret;}static int cnxthsf_exit(struct hda_codec *codec){	struct cnxthsf_spec *spec = codec->spec;//printk(KERN_DEBUG"%s: codec=%p spec=%p\n", __FUNCTION__, codec, spec);	if(spec && spec->pDevNode) {		void (*cnxthwhda_remove)(void *ptr);		cnxthwhda_remove = (void*)symbol_request(cnxthwhda_remove);		if(cnxthwhda_remove) {			cnxthwhda_remove(spec->pDevNode);			spec->pDevNode = NULL;			symbol_put(cnxthwhda_remove);			symbol_put(cnxthwhda_probe);		} else {			printk(KERN_ERR"%s: symbol_request(cnxthwhda_remove) failed\n", __FUNCTION__);		}	}	return 0;}static void cnxthsf_free(struct hda_codec *codec){	struct cnxthsf_spec *spec = codec->spec;//printk(KERN_DEBUG"%s: codec=%p spec=%p\n", __FUNCTION__, codec, spec);	if(spec) {		codec->spec = NULL;		memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));		kfree(spec);	}}static void cnxthsf_unsol_event(struct hda_codec *codec, unsigned int res){	struct cnxthsf_spec *spec = codec->spec;	//printk(KERN_DEBUG"%s: codec=%p res=0x%02x spec=%p cbHdaEvent=%p\n", __FUNCTION__, codec, res, spec, spec->cbHdaEvent);	if(spec && spec->cbHdaEvent) {		if(((res >> 26) & 0x3f) == spec->cbHdaTag) {			//printk(KERN_DEBUG"%s: res=0x%02x cbHdaEvent=%p\n", __FUNCTION__, res, spec->cbHdaEvent);//			printk(KERN_DEBUG"%s: calling cbHdaEvent=%p ctx=%p\n", __FUNCTION__, spec->cbHdaEvent, spec->cbHdaEventContext);			spec->cbHdaEvent(spec->cbHdaEventContext, res);		} else {			printk(KERN_DEBUG"%s: ignoring res=0x08%x\n", __FUNCTION__, res);		}	}}static int cnxthsf_suspend(struct hda_codec *codec, pm_message_t state){	struct cnxthsf_spec *spec = codec->spec;	int (*cnxthwhda_suspend)(void *devnode, pm_message_t state);	int ret;	printk(KERN_DEBUG"%s: codec=%p spec=%p state=0x%x\n", __FUNCTION__, codec, spec, *((u32 *)&state));	if(!spec || !spec->pDevNode) {		return -EINVAL;	}	cnxthwhda_suspend = (void*)symbol_request(cnxthwhda_suspend);	if(!cnxthwhda_suspend) {		printk(KERN_ERR"%s: symbol_request(cnxthwhda_suspend) failed\n", __FUNCTION__);		return -ENOSYS;	}	ret = cnxthwhda_suspend(spec->pDevNode, state);	symbol_put(cnxthwhda_suspend);	return ret;}static int cnxthsf_resume (struct hda_codec *codec){	struct cnxthsf_spec *spec = codec->spec;	int (*cnxthwhda_resume)(void *devnode);	int ret;	printk(KERN_DEBUG"%s: codec=%p spec=%p\n", __FUNCTION__, codec, spec);	if(!spec || !spec->pDevNode) {		return -EINVAL;	}	cnxthwhda_resume = (void*)symbol_request(cnxthwhda_resume);	if(!cnxthwhda_resume) {		printk(KERN_ERR"%s: symbol_request(cnxthwhda_resume) failed\n", __FUNCTION__);		return -ENOSYS;	}	ret = cnxthwhda_resume(spec->pDevNode);	symbol_put(cnxthwhda_resume);	return ret;}static struct hda_codec_ops cnxthsf_patch_ops = {	.build_pcms = cnxthsf_build_pcms,	.init = cnxthsf_init,	.exit = cnxthsf_exit,	.free = cnxthsf_free,	.unsol_event = cnxthsf_unsol_event,#ifdef CONFIG_PM	.suspend = cnxthsf_suspend,	.resume = cnxthsf_resume,#endif};      static int patch_cnxthsf(struct hda_codec *codec){	struct cnxthsf_spec *spec;	int (*cnxthwhda_probe)(void *codec, struct device *hwDev, void **ppDevNode);//printk(KERN_DEBUG"%s: codec=%p\n", __FUNCTION__, codec);	if(!codec->mfg) { // we only support modems		return -ENODEV;	}	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);	if (spec == NULL)		return -ENOMEM;	codec->spec = spec;	codec->patch_ops = cnxthsf_patch_ops;	cnxthwhda_probe = (void*)symbol_request(cnxthwhda_probe);	if(cnxthwhda_probe) {		symbol_put(cnxthwhda_probe);	} else {		printk(KERN_ERR"%s: symbol_request(cnxthwhda_probe) failed\n", __FUNCTION__);		codec->spec = NULL;		memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));		kfree(spec);		return -ENOENT;	}	return 0;}struct hda_codec_preset snd_hda_preset_cnxthsf[] = { 	{ .id = 0x14f10000, .mask = 0xffff0000, .mfg = 2, .name = "HSF", .patch = patch_cnxthsf },	{}};typedef unsigned long   ULONG,  *PULONG;#include "../../include/oshda.h"__shimcall__unsigned int OsHdaCodecGetAddr(PHDAOSHAL pHdaOsHal){	return ((struct hda_codec *)pHdaOsHal->hda_codec)->addr;}EXPORT_SYMBOL(OsHdaCodecGetAddr);__shimcall__unsigned int OsHdaCodecGetVendorId(PHDAOSHAL pHdaOsHal){	return ((struct hda_codec *)pHdaOsHal->hda_codec)->vendor_id;}EXPORT_SYMBOL(OsHdaCodecGetVendorId);__shimcall__unsigned int OsHdaCodecGetSubsystemId(PHDAOSHAL pHdaOsHal){	return ((struct hda_codec *)pHdaOsHal->hda_codec)->subsystem_id;}EXPORT_SYMBOL(OsHdaCodecGetSubsystemId);__shimcall__

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -