packages: kernel/alsa-driver-linuxant.patch (NEW) - from https://www.linuxa...

glen glen at pld-linux.org
Sat Aug 13 11:07:14 CEST 2011


Author: glen                         Date: Sat Aug 13 09:07:14 2011 GMT
Module: packages                      Tag: HEAD
---- Log message:
- from https://www.linuxant.com/alsa-driver/
  https://www.linuxant.com/alsa-driver/alsa-driver-1.0.23-1.patch

---- Files affected:
packages/kernel:
   alsa-driver-linuxant.patch (NONE -> 1.1)  (NEW)

---- Diffs:

================================================================
Index: packages/kernel/alsa-driver-linuxant.patch
diff -u /dev/null packages/kernel/alsa-driver-linuxant.patch:1.1
--- /dev/null	Sat Aug 13 11:07:14 2011
+++ packages/kernel/alsa-driver-linuxant.patch	Sat Aug 13 11:07:09 2011
@@ -0,0 +1,1168 @@
+diff -urN --show-c-function alsa-driver-git20100411/alsa-kernel/pci/hda/hda_codec.c alsa-driver-git20100411-hda/alsa-kernel/pci/hda/hda_codec.c
+--- alsa-driver-git20100411/alsa-kernel/pci/hda/hda_codec.c	2010-04-11 13:42:02.000000000 -0400
++++ alsa-driver-git20100411-hda/alsa-kernel/pci/hda/hda_codec.c	2010-04-11 14:26:02.000000000 -0400
+@@ -225,6 +225,25 @@ static int codec_exec_verb(struct hda_co
+ }
+ 
+ /**
++ * snd_hda_codec_wallclock - get the wallclock counter
++ * @codec: the HDA codec
++ *
++ * Get the wallclock counter
++ *
++ * Returns the obtained value, or -1 for an error.
++ */
++unsigned int snd_hda_codec_wallclock(struct hda_codec *codec)
++{
++	u32 res;
++	if(codec->bus->ops.get_wallclock)
++		res = codec->bus->ops.get_wallclock(codec);
++	else
++		res = (u32)-1;
++	return res;
++}
++EXPORT_SYMBOL_HDA(snd_hda_codec_wallclock);
++
++/**
+  * snd_hda_codec_read - send a command and get the response
+  * @codec: the HDA codec
+  * @nid: NID to send the command
+@@ -497,6 +516,22 @@ static int init_unsol_queue(struct hda_b
+ 	return 0;
+ }
+ 
++void snd_hda_codec_remove_notify_all(struct hda_bus *bus)
++{
++	struct list_head *p, *n;
++
++	if (! bus)
++		return;
++	list_for_each_safe(p, n, &bus->codec_list) {
++		struct hda_codec *codec = list_entry(p, struct hda_codec, list);
++
++		if (codec && codec->patch_ops.exit) {
++			codec->patch_ops.exit(codec);
++		}
++	}
++}
++EXPORT_SYMBOL_HDA(snd_hda_codec_remove_notify_all);
++
+ /*
+  * destructor
+  */
+@@ -1118,7 +1153,8 @@ int snd_hda_codec_configure(struct hda_c
+ 	}
+ 	if (codec->preset && codec->preset->patch) {
+ 		err = codec->preset->patch(codec);
+-		goto patched;
++		if (err != -ENOSYS)
++			goto patched;
+ 	}
+ 
+ 	/* call the default parser */
+@@ -1876,6 +1912,7 @@ int snd_hda_codec_reset(struct hda_codec
+ {
+ 	struct snd_card *card = codec->bus->card;
+ 	int i, pcm;
++	int err;
+ 
+ 	if (hda_lock_devices(card) < 0)
+ 		return -EBUSY;
+@@ -1897,6 +1934,12 @@ int snd_hda_codec_reset(struct hda_codec
+ 
+ 	/* OK, let it free */
+ 
++	if (codec->patch_ops.exit) {
++		err = codec->patch_ops.exit(codec);
++		if (err < 0)
++			return err;
++	}
++
+ #ifdef CONFIG_SND_HDA_POWER_SAVE
+ 	cancel_delayed_work(&codec->power_work);
+ 	flush_workqueue(codec->bus->workq);
+diff -urN --show-c-function alsa-driver-git20100411/alsa-kernel/pci/hda/hda_codec.h alsa-driver-git20100411-hda/alsa-kernel/pci/hda/hda_codec.h
+--- alsa-driver-git20100411/alsa-kernel/pci/hda/hda_codec.h	2010-04-11 13:42:02.000000000 -0400
++++ alsa-driver-git20100411-hda/alsa-kernel/pci/hda/hda_codec.h	2010-04-11 14:26:02.000000000 -0400
+@@ -580,6 +580,10 @@ struct hda_bus_ops {
+ 	int (*command)(struct hda_bus *bus, unsigned int cmd);
+ 	/* get a response from the last command */
+ 	unsigned int (*get_response)(struct hda_bus *bus, unsigned int addr);
++	/* get the wall clock counter */
++	u32 (*get_wallclock)(struct hda_codec *codec);
++	/* get the link position counter */
++	u32 (*get_linkpos)(struct snd_pcm_substream *substream);
+ 	/* free the private data */
+ 	void (*private_free)(struct hda_bus *);
+ 	/* attach a PCM stream */
+@@ -677,6 +681,7 @@ struct hda_codec_ops {
+ 	int (*build_controls)(struct hda_codec *codec);
+ 	int (*build_pcms)(struct hda_codec *codec);
+ 	int (*init)(struct hda_codec *codec);
++	int (*exit)(struct hda_codec *codec);
+ 	void (*free)(struct hda_codec *codec);
+ 	void (*unsol_event)(struct hda_codec *codec, unsigned int res);
+ #ifdef SND_HDA_NEEDS_RESUME
+@@ -850,11 +855,13 @@ int snd_hda_bus_new(struct snd_card *car
+ 		    struct hda_bus **busp);
+ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
+ 		      struct hda_codec **codecp);
++void snd_hda_codec_remove_notify_all(struct hda_bus *bus);
+ int snd_hda_codec_configure(struct hda_codec *codec);
+ 
+ /*
+  * low level functions
+  */
++unsigned int snd_hda_codec_wallclock(struct hda_codec *codec);
+ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
+ 				int direct,
+ 				unsigned int verb, unsigned int parm);
+diff -urN --show-c-function alsa-driver-git20100411/alsa-kernel/pci/hda/hda_intel.c alsa-driver-git20100411-hda/alsa-kernel/pci/hda/hda_intel.c
+--- alsa-driver-git20100411/alsa-kernel/pci/hda/hda_intel.c	2010-04-11 13:42:02.000000000 -0400
++++ alsa-driver-git20100411-hda/alsa-kernel/pci/hda/hda_intel.c	2010-04-11 14:26:02.000000000 -0400
+@@ -49,6 +49,7 @@
+ #include <sound/core.h>
+ #include <sound/initval.h>
+ #include "hda_codec.h"
++#include "hda_local.h"
+ 
+ 
+ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+@@ -514,6 +515,20 @@ static int azx_send_cmd(struct hda_bus *
+  * Interface for HD codec
+  */
+ 
++static u32 azx_get_wallclock(struct hda_codec *codec)
++{
++	struct azx *chip = codec->bus->private_data;
++
++	return azx_readl(chip, WALCLK);
++}
++
++static u32 azx_get_linkpos(struct snd_pcm_substream *substream)
++{
++	struct azx_dev *azx_dev = get_azx_dev(substream);
++
++	return azx_sd_readl(azx_dev, SD_LPIB);
++}
++
+ /*
+  * CORB / RIRB interface
+  */
+@@ -1388,6 +1403,8 @@ static int __devinit azx_codec_create(st
+ 	bus_temp.pci = chip->pci;
+ 	bus_temp.ops.command = azx_send_cmd;
+ 	bus_temp.ops.get_response = azx_get_response;
++	bus_temp.ops.get_wallclock = azx_get_wallclock;
++	bus_temp.ops.get_linkpos = azx_get_linkpos;
+ 	bus_temp.ops.attach_pcm = azx_attach_pcm_stream;
+ 	bus_temp.ops.bus_reset = azx_bus_reset;
+ #ifdef CONFIG_SND_HDA_POWER_SAVE
+@@ -2702,6 +2719,10 @@ out_free:
+ 
+ static void __devexit azx_remove(struct pci_dev *pci)
+ {
++	struct snd_card *card = pci_get_drvdata(pci);
++	struct azx *chip = card->private_data;
++
++	snd_hda_codec_remove_notify_all(chip->bus);
+ 	snd_card_free(pci_get_drvdata(pci));
+ 	pci_set_drvdata(pci, NULL);
+ }
+diff -urN --show-c-function alsa-driver-git20100411/alsa-kernel/pci/hda/patch_conexant.c alsa-driver-git20100411-hda/alsa-kernel/pci/hda/patch_conexant.c
+--- alsa-driver-git20100411/alsa-kernel/pci/hda/patch_conexant.c	2010-04-11 13:42:02.000000000 -0400
++++ alsa-driver-git20100411-hda/alsa-kernel/pci/hda/patch_conexant.c	2010-04-13 20:41:48.000000000 -0400
+@@ -1,10 +1,12 @@
+ /*
+- * HD audio interface patch for Conexant HDA audio codec
++ * HD audio interface patch for Conexant HDA audio/modem codec
+  *
+  * Copyright (c) 2006 Pototskiy Akex <alex.pototskiy at gmail.com>
+  * 		      Takashi Iwai <tiwai at suse.de>
+  * 		      Tobin Davis  <tdavis at dsl-only.net>
+  *
++ * Copyright (c) 2005-2010 Linuxant inc.
++ *
+  *  This driver is free software; you can redistribute it and/or modify
+  *  it under the terms of the GNU General Public License as published by
+  *  the Free Software Foundation; either version 2 of the License, or
+@@ -49,6 +51,14 @@
+ #define AUTO_MIC_PORTB		(1 << 1)
+ #define AUTO_MIC_PORTC		(1 << 2)
+ 
++#if defined(__i386__)
++#define __shimcall__ __attribute__((regparm(0)))
++#else
++#define __shimcall__
++#endif
++
++//#define CONFIG_SND_DEBUG
++
+ struct conexant_jack {
+ 
+ 	hda_nid_t nid;
+@@ -99,7 +109,7 @@
+ 	int num_channel_mode;
+ 
+ 	/* PCM information */
+-	struct hda_pcm pcm_rec[2];	/* used in build_pcms() */
++	struct hda_pcm pcm_rec[3];	/* used in build_pcms() */
+ 
+ 	unsigned int spdif_route;
+ 
+@@ -131,6 +141,14 @@
+ 	unsigned int dc_enable;
+ 	unsigned int dc_input_bias; /* offset into cxt5066_olpc_dc_bias */
+ 	unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */
++
++	/* HSF modem */
++	void *modem_devnode;
++	unsigned int modem_stream_tags[2];
++	int modem_do_prepare[2];
++	void (*modem_cbHdaEvent)(void *Context, unsigned int res) __shimcall__;
++	void *modem_cbHdaEventContext;
++	unsigned char modem_cbHdaTag;
+ };
+ 
+ static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
+@@ -221,6 +239,42 @@
+ 	return 0;
+ }
+ 
++#if defined(__i386__)
++#define __shimcall__ __attribute__((regparm(0)))
++#else
++#define __shimcall__
++#endif
++
++//#define CONFIG_SND_DEBUG
++static int conexant_modem_pcm_prepare(struct hda_pcm_stream *hinfo,
++			      struct hda_codec *codec,
++			      unsigned int stream_tag,
++			      unsigned int format,
++			      struct snd_pcm_substream *substream)
++{
++	struct conexant_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->modem_stream_tags[substream->stream] = stream_tag;
++
++	return 0;
++}
++
++static int conexant_modem_pcm_open(struct hda_pcm_stream *hinfo, struct hda_codec *codec,
++			    struct snd_pcm_substream *substream)
++{
++	static unsigned int rates[] = { 16000 };
++	static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
++		.count = ARRAY_SIZE(rates),
++		.list = rates,
++		.mask = 0,
++	};
++
++	//printk(KERN_DEBUG"%s: codec=%p substream=%p\n", __FUNCTION__, codec, substream);
++
++	return snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
++}
+ 
+ 
+ static struct hda_pcm_stream conexant_pcm_analog_playback = {
+@@ -301,33 +355,50 @@
+ 	},
+ };
+ 
++static struct hda_pcm_stream conexant_modem_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 = conexant_modem_pcm_open,
++		.prepare = conexant_modem_pcm_prepare,
++	},
++};
++
+ static int conexant_build_pcms(struct hda_codec *codec)
+ {
+ 	struct conexant_spec *spec = codec->spec;
+ 	struct hda_pcm *info = spec->pcm_rec;
+ 
+-	codec->num_pcms = 1;
++	codec->num_pcms = 0;
+ 	codec->pcm_info = info;
+ 
+-	info->name = "CONEXANT Analog";
+-	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_pcm_analog_playback;
+-	info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
+-		spec->multiout.max_channels;
+-	info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
+-		spec->multiout.dac_nids[0];
+-	if (codec->vendor_id == 0x14f15051)
+-		info->stream[SNDRV_PCM_STREAM_CAPTURE] =
+-			cx5051_pcm_analog_capture;
+-	else
+-		info->stream[SNDRV_PCM_STREAM_CAPTURE] =
+-			conexant_pcm_analog_capture;
+-	info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
+-	info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
++	if (codec->afg) {
++		info->name = "CONEXANT Analog";
++		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_pcm_analog_playback;
++		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
++			spec->multiout.max_channels;
++		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
++			spec->multiout.dac_nids[0];
++		if (codec->vendor_id == 0x14f15051)
++			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
++				cx5051_pcm_analog_capture;
++		else
++			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
++				conexant_pcm_analog_capture;
++		info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
++		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
+ 
+-	if (spec->multiout.dig_out_nid) {
+ 		info++;
+ 		codec->num_pcms++;
+-		info->name = "Conexant Digital";
++	}
++
++	if (spec->multiout.dig_out_nid) {
++		info->name = "Conexant Digital Audio";
+ 		info->pcm_type = HDA_PCM_TYPE_SPDIF;
+ 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
+ 			conexant_pcm_digital_playback;
+@@ -339,6 +410,23 @@
+ 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
+ 				spec->dig_in_nid;
+ 		}
++
++		info++;
++		codec->num_pcms++;
++	}
++
++	if (codec->mfg) {
++		conexant_modem_pcm.nid = codec->mfg;
++
++		info->name = "Conexant HSF Modem";
++		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_modem_pcm;
++		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = conexant_modem_pcm.nid;
++		info->stream[SNDRV_PCM_STREAM_CAPTURE]  = conexant_modem_pcm;
++		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid  = conexant_modem_pcm.nid;
++		info->pcm_type = HDA_PCM_TYPE_MODEM;
++
++		info++;
++		codec->num_pcms++;
+ 	}
+ 
+ 	return 0;
+@@ -476,20 +564,68 @@
+ }
+ #endif
+ 
++static void *conexant_hsfmodem_interface_funcs[];
++
+ static int conexant_init(struct hda_codec *codec)
+ {
+ 	struct conexant_spec *spec = codec->spec;
+-	int i;
++	int i, ret;
+ 
++	//printk(KERN_DEBUG"%s: codec=%p\n", __FUNCTION__, codec);
++	if(codec->mfg) {
++		int (*cnxthwhda_probe)(void *codec, struct device *hwDev, void **ppDevNode, void **ppInterfaceFuncs);
++
++	    	//snd_hda_codec_write(codec, AC_NODE_ROOT, 0, AC_VERB_SET_CODEC_RESET, 0);
++
++		cnxthwhda_probe = (void*)symbol_request(cnxthwhda_probe);
++		if(!cnxthwhda_probe) {
++			printk(KERN_ERR"%s: Conexant HSF modem detected but driver not present\n", __FUNCTION__);
++			if(!codec->afg)
++				return -ENOENT;
++		} else {
++			ret = cnxthwhda_probe(codec, codec->bus->card->dev, &spec->modem_devnode, conexant_hsfmodem_interface_funcs);
++			if(ret) {
++				printk(KERN_ERR"%s: cnxthwhda_probe() failed: %d\n", __FUNCTION__, ret);
++				symbol_put(cnxthwhda_probe);
++				if(!codec->afg)
++					return ret;
++			}
++		}
++	}
++  
+ 	for (i = 0; i < spec->num_init_verbs; i++)
+ 		snd_hda_sequence_write(codec, spec->init_verbs[i]);
+ 	return 0;
+ }
+ 
++static int conexant_exit(struct hda_codec *codec)
++{
++	struct conexant_spec *spec = codec->spec;
++
++	//printk(KERN_DEBUG"%s: codec=%p spec=%p\n", __FUNCTION__, codec, spec);
++
++	if(codec->mfg && spec && spec->modem_devnode) {
++		void (*cnxthwhda_remove)(void *ptr);
++
++		cnxthwhda_remove = (void*)symbol_request(cnxthwhda_remove);
++		if(cnxthwhda_remove) {
++			cnxthwhda_remove(spec->modem_devnode);
++			spec->modem_devnode = 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 conexant_free(struct hda_codec *codec)
+ {
+-#ifdef CONFIG_SND_HDA_INPUT_JACK
+ 	struct conexant_spec *spec = codec->spec;
++
++#ifdef CONFIG_SND_HDA_INPUT_JACK
+ 	if (spec->jacks.list) {
+ 		struct conexant_jack *jacks = spec->jacks.list;
+ 		int i;
+@@ -501,9 +637,114 @@
+ 	}
+ #endif
+ 	snd_hda_detach_beep_device(codec);
+-	kfree(codec->spec);
++
++	if (spec) {
++		codec->spec = NULL;
++		memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
++		kfree(codec->spec);
++	}
+ }
+ 
++static void conexant_unsol_event(struct hda_codec *codec, unsigned int res)
++{
++	struct conexant_spec *spec = codec->spec;
++
++	//printk(KERN_DEBUG"%s: codec=%p res=0x%02x spec=%p cbHdaEvent=%p\n", __FUNCTION__, codec, res, spec, spec->modem_cbHdaEvent);
++
++	if(codec->mfg && spec && spec->modem_cbHdaEvent) {
++		if(((res >> 26) & 0x3f) == spec->modem_cbHdaTag) {
++			//printk(KERN_DEBUG"%s: res=0x%02x cbHdaEvent=%p\n", __FUNCTION__, res, spec->modem_cbHdaEvent);
++			//printk(KERN_DEBUG"%s: calling cbHdaEvent=%p ctx=%p\n", __FUNCTION__, spec->modem_cbHdaEvent, spec->modem_cbHdaEventContext);
++			spec->modem_cbHdaEvent(spec->modem_cbHdaEventContext, res);
++		} else {
++			printk(KERN_DEBUG"%s: ignoring res=0x08%x\n", __FUNCTION__, res);
++		}
++	}
++}
++
++typedef struct tagHDAOSHAL {
++	void *hda_codec;
++	int bInSuspendResume;
++} HDAOSHAL, *PHDAOSHAL;
++
++typedef struct tagOS_DEVNODE {
++	void *hwDev;
++	// intentionally left incomplete
++} OS_DEVNODE, *POS_DEVNODE;
++
++#ifdef CONFIG_PM
++static int conexant_suspend(struct hda_codec *codec, pm_message_t state)
++{
++	struct conexant_spec *spec = codec->spec;
++	int (*cnxthwhda_suspend)(void *devnode, pm_message_t state);
++	int ret = 0;
++
++	//printk(KERN_DEBUG"%s: codec=%p spec=%p state=0x%x\n", __FUNCTION__, codec, spec, *((u32 *)&state));
++
++	if(spec && spec->modem_devnode) {
++		cnxthwhda_suspend = (void*)symbol_request(cnxthwhda_suspend);
++		if(!cnxthwhda_suspend) {
++			printk(KERN_ERR"%s: symbol_request(cnxthwhda_suspend) failed\n", __FUNCTION__);
++			return -ENOSYS;
++		}
++
++		if(((POS_DEVNODE)spec->modem_devnode)->hwDev) {
++			((PHDAOSHAL)((POS_DEVNODE)spec->modem_devnode)->hwDev)->bInSuspendResume++;
++		}
++		ret = cnxthwhda_suspend(spec->modem_devnode, state);
++		if(((POS_DEVNODE)spec->modem_devnode)->hwDev) {
++			((PHDAOSHAL)((POS_DEVNODE)spec->modem_devnode)->hwDev)->bInSuspendResume--;
++		}
++		symbol_put(cnxthwhda_suspend);
++	}
++
++	return ret;
++}
++  
++static int conexant_resume(struct hda_codec *codec)
++{
++	struct conexant_spec *spec = codec->spec;
++	int ret = 0;
++	hda_nid_t mfg;
++
++	mfg = codec->mfg;
++	codec->mfg = 0;
++	codec->patch_ops.init(codec);
++	codec->mfg = mfg;
++
++	snd_hda_codec_resume_amp(codec);
++	snd_hda_codec_resume_cache(codec);
++
++	if(spec && spec->modem_devnode) {
++		int (*cnxthwhda_resume)(void *devnode);
++
++		//printk(KERN_DEBUG"%s: codec=%p spec=%p\n", __FUNCTION__, codec, spec);
++
++		cnxthwhda_resume = (void*)symbol_request(cnxthwhda_resume);
++		if(!cnxthwhda_resume) {
++			printk(KERN_ERR"%s: symbol_request(cnxthwhda_resume) failed\n", __FUNCTION__);
++			return -ENOSYS;
++		}
++
++    	//snd_hda_codec_write(codec, AC_NODE_ROOT, 0, AC_VERB_SET_CODEC_RESET, 0);
++
++		if(((POS_DEVNODE)spec->modem_devnode)->hwDev) {
++			((PHDAOSHAL)((POS_DEVNODE)spec->modem_devnode)->hwDev)->bInSuspendResume++;
++		}
++
++		ret = cnxthwhda_resume(spec->modem_devnode);
++
++		if(((POS_DEVNODE)spec->modem_devnode)->hwDev) {
++			((PHDAOSHAL)((POS_DEVNODE)spec->modem_devnode)->hwDev)->bInSuspendResume--;
++		}
++
++		symbol_put(cnxthwhda_resume);
++	}
++
++	return ret;
++}
++#endif
++
+ static struct snd_kcontrol_new cxt_capture_mixers[] = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+@@ -587,9 +828,46 @@
+ 	.build_controls = conexant_build_controls,
+ 	.build_pcms = conexant_build_pcms,
+ 	.init = conexant_init,
++	.exit = conexant_exit,
+ 	.free = conexant_free,
++	.unsol_event = conexant_unsol_event,
++#ifdef CONFIG_PM
++	.suspend = conexant_suspend,
++	.resume = conexant_resume,
++#endif
+ };
+ 
++static int patch_cxthsfmodem(struct hda_codec *codec)
++{
++	struct conexant_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 here
++		return -ENODEV;
++	}
++
++	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
++	if (!spec)
++		return -ENOMEM;
++	codec->spec = spec;
++
++	codec->patch_ops = conexant_patch_ops;
++
++	cnxthwhda_probe = (void*)symbol_request(cnxthwhda_probe);
++	if(cnxthwhda_probe) {
++		symbol_put(cnxthwhda_probe);
++	} else {
++		printk(KERN_ERR"%s: Conexant HSF modem detected but driver not present\n", __FUNCTION__);
++		codec->spec = NULL;
++		memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
++		kfree(spec);
++		return -ENOSYS;
++	}
++
++	return 0;
<<Diff was trimmed, longer than 597 lines>>


More information about the pld-cvs-commit mailing list