]> git.pld-linux.org Git - packages/kernel.git/commitdiff
- from https://www.linuxant.com/alsa-driver/
authorElan Ruusamäe <glen@pld-linux.org>
Sat, 13 Aug 2011 09:07:09 +0000 (09:07 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
  https://www.linuxant.com/alsa-driver/alsa-driver-1.0.23-1.patch

Changed files:
    alsa-driver-linuxant.patch -> 1.1

alsa-driver-linuxant.patch [new file with mode: 0644]

diff --git a/alsa-driver-linuxant.patch b/alsa-driver-linuxant.patch
new file mode 100644 (file)
index 0000000..4d90b4d
--- /dev/null
@@ -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@gmail.com>
+  *                  Takashi Iwai <tiwai@suse.de>
+  *                  Tobin Davis  <tdavis@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;
++}
++
+ /*
+  * EAPD control
+  * the private value = nid | (invert << 8)
+@@ -762,13 +1040,15 @@
+ static void cxt5045_hp_automic(struct hda_codec *codec)
+ {
+       static struct hda_verb mic_jack_on[] = {
+-              {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+-              {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
++              {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | AC_AMP_MUTE},
++              {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT},
++              {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
+               {}
+       };
+       static struct hda_verb mic_jack_off[] = {
+-              {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+-              {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
++              {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | AC_AMP_MUTE},
++              {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT},
++              {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
+               {}
+       };
+       unsigned int present;
+@@ -798,14 +1078,19 @@
+ static void cxt5045_hp_unsol_event(struct hda_codec *codec,
+                                  unsigned int res)
+ {
+-      res >>= 26;
+-      switch (res) {
++      switch (res >> 26) {
+       case CONEXANT_HP_EVENT:
++              //printk("%s: CONEXANT_HP_EVENT\n", __FUNCTION__);
+               cxt5045_hp_automute(codec);
+               break;
+       case CONEXANT_MIC_EVENT:
++              //printk("%s: CONEXANT_MIC_EVENT\n", __FUNCTION__);
+               cxt5045_hp_automic(codec);
+               break;
++      default:
++              //printk("%s: CONEXANT_OTHER_EVENT\n", __FUNCTION__);
++              conexant_unsol_event(codec, res);
++              break;
+       }
+ }
+@@ -1209,6 +1494,15 @@
+               break;
+       }
++      if(codec->mfg) {
++              int (*cnxthwhda_probe)(void *codec, struct device *hwDev, void **ppDevNode);
++              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__);
++      }
++
+       return 0;
+ }
+@@ -1247,7 +1541,7 @@
+        * the headphone jack
+        */
+       bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE;
+-      /* NOTE: Conexat codec needs the index for *OUTPUT* amp of
++      /* NOTE: Conexant codec needs the index for *OUTPUT* amp of
+        * pin widgets unlike other codecs.  In this case, we need to
+        * set index 0x01 for the volume from the mixer amp 0x19.
+        */
+@@ -1591,6 +1885,16 @@
+               codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
+ #endif        
+       }
++
++      if(codec->mfg) {
++              int (*cnxthwhda_probe)(void *codec, struct device *hwDev, void **ppDevNode);
++              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__);
++      }
++
+       spec->vmaster_nid = 0x13;
+       switch (codec->subsystem_id >> 16) {
+@@ -1707,6 +2011,9 @@
+       case CXT5051_PORTC_EVENT:
+               cxt5051_portc_automic(codec);
+               break;
++      default:
++              conexant_unsol_event(codec, res);
++              break;
+       }
+       conexant_report_jack(codec, nid);
+ }
+@@ -1902,6 +2209,7 @@
+               cxt5051_portb_automic(codec);
+               cxt5051_portc_automic(codec);
+       }
++
+       return 0;
+ }
+@@ -1997,6 +2305,15 @@
+               break;
+       }
++      if(codec->mfg) {
++              int (*cnxthwhda_probe)(void *codec, struct device *hwDev, void **ppDevNode);
++              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__);
++      }
++
+       return 0;
+ }
+@@ -3100,6 +3417,423 @@
+ /*
+  */
++typedef enum {
++      OsHdaStreamStateReset = 0,
++      OsHdaStreamStateStop  = 1,
++      OsHdaStreamStateRun   = 2
++} OSHDA_STREAM_STATE;
++
++static __shimcall__
++unsigned int conexant_hsfmodem_OsHdaCodecGetAddr(PHDAOSHAL pHdaOsHal)
++{
++      return ((struct hda_codec *)pHdaOsHal->hda_codec)->addr;
++}
++
++static __shimcall__
++unsigned int conexant_hsfmodem_OsHdaCodecGetVendorId(PHDAOSHAL pHdaOsHal)
++{
++      return ((struct hda_codec *)pHdaOsHal->hda_codec)->vendor_id;
++}
++
++static __shimcall__
++unsigned int conexant_hsfmodem_OsHdaCodecGetSubsystemId(PHDAOSHAL pHdaOsHal)
++{
++      return ((struct hda_codec *)pHdaOsHal->hda_codec)->subsystem_id;
++}
++
++static __shimcall__
++unsigned int conexant_hsfmodem_OsHdaCodecGetRevisionId(PHDAOSHAL pHdaOsHal)
++{
++      return ((struct hda_codec *)pHdaOsHal->hda_codec)->revision_id;
++}
++
++static __shimcall__
++unsigned int conexant_hsfmodem_OsHdaCodecRead(PHDAOSHAL pHdaOsHal, unsigned short nid, int direct, unsigned int verb, unsigned int para)
++{
++#if 1
++      return snd_hda_codec_read((struct hda_codec *)pHdaOsHal->hda_codec, nid, direct, verb, para);
++#else
++      unsigned int res;
++
++      res = snd_hda_codec_read((struct hda_codec *)pHdaOsHal->hda_codec, nid, direct, verb, para);
++
++      printk(KERN_DEBUG"%s: nid=%x direct=%d verb=0x%x para=0x%x res=0x%08x\n", __FUNCTION__, nid, direct, verb, para, res);
++
++      return res;
++#endif
++}
++
++static __shimcall__
++unsigned int conexant_hsfmodem_OsHdaCodecWallclock(PHDAOSHAL pHdaOsHal)
++{
++      return snd_hda_codec_wallclock((struct hda_codec *)pHdaOsHal->hda_codec);
++}
++
++static __shimcall__
++void conexant_hsfmodem_OsHdaCodecSetEventCallback(PHDAOSHAL pHdaOsHal, void (*cbHdaEvent)(void *Context, unsigned int res), void *cbHdaEventContext, unsigned char *cbHdaTag)
++{
++      struct conexant_spec *spec = ((struct hda_codec *)pHdaOsHal->hda_codec)->spec;
++
++      *cbHdaTag = ((struct hda_codec *)pHdaOsHal->hda_codec)->mfg;
++
++      spec->modem_cbHdaTag = *cbHdaTag;
++      spec->modem_cbHdaEventContext = cbHdaEventContext;
++      spec->modem_cbHdaEvent = (void*)cbHdaEvent;
++}
++
++static __shimcall__
++void conexant_hsfmodem_OsHdaCodecClearEventCallback(PHDAOSHAL pHdaOsHal, unsigned char cbHdaTag)
++{
++      struct conexant_spec *spec = ((struct hda_codec *)pHdaOsHal->hda_codec)->spec;
++
++      if(spec) {
++              spec->modem_cbHdaEvent = NULL;
++              spec->modem_cbHdaEventContext = NULL;
++              spec->modem_cbHdaTag = 0;
++      }
++}
++
++
++#include <sound/pcm_params.h>
++
++static int snd_interval_refine_set(struct snd_interval *i, unsigned int val)
++{
++      struct snd_interval t;
++      t.empty = 0;
++      t.min = t.max = val;
++      t.openmin = t.openmax = 0;
++      t.integer = 1;
++      return snd_interval_refine(i, &t);
++}
++
++static int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params,
++                               snd_pcm_hw_param_t var, unsigned int val,
++                               int dir)
++{
++      int changed;
++      if (hw_is_mask(var)) {
++              struct snd_mask *m = hw_param_mask(params, var);
++              if (val == 0 && dir < 0) {
++                      changed = -EINVAL;
++                      snd_mask_none(m);
++              } else {
++                      if (dir > 0)
++                              val++;
++                      else if (dir < 0)
++                              val--;
++                      changed = snd_mask_refine_set(hw_param_mask(params, var), val);
++              }
++      } else if (hw_is_interval(var)) {
++              struct snd_interval *i = hw_param_interval(params, var);
++              if (val == 0 && dir < 0) {
++                      changed = -EINVAL;
++                      snd_interval_none(i);
++              } else if (dir == 0)
++                      changed = snd_interval_refine_set(i, val);
++              else {
++                      struct snd_interval t;
++                      t.openmin = 1;
++                      t.openmax = 1;
++                      t.empty = 0;
++                      t.integer = 0;
++                      if (dir < 0) {
++                              t.min = val - 1;
++                              t.max = val;
++                      } else {
++                              t.min = val;
++                              t.max = val+1;
++                      }
++                      changed = snd_interval_refine(i, &t);
++              }
++      } else
++              return -EINVAL;
++      if (changed) {
++              params->cmask |= 1 << var;
++              params->rmask |= 1 << var;
++      }
++      return changed;
++}
++
++static int conexant_modem_snd_pcm_change_params(struct snd_pcm_substream *substream, int hw_param_buffer_bytes)
++{
++      struct snd_pcm_hw_params *sparams;
++      int err;
++
++      sparams = kmalloc(sizeof(*sparams), GFP_KERNEL);
++      if (/*!params ||*/ !sparams) {
++              return -ENOMEM;
++      }
++
++      _snd_pcm_hw_params_any(sparams);
++      _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
++                            hw_param_buffer_bytes, 0);
++
++      snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
++
++      if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, sparams)) < 0) {
++              printk(KERN_ERR"%s: SNDRV_PCM_IOCTL_HW_PARAMS failed (%d)\n", __FUNCTION__, err);
++              //return err;
++      }
++
++      return 0;
++}
++
++static int conexant_modem_snd_pcm_prepare_substream(PHDAOSHAL pHdaOsHal, struct snd_pcm_substream *substream)
++{
++      int err;
++      struct conexant_spec *spec = ((struct hda_codec *)pHdaOsHal->hda_codec)->spec;
++
++      if(spec->modem_do_prepare[substream->stream]) {
++              err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL);
++              if (err < 0) {
++                      printk(KERN_ERR"%s: SNDRV_PCM_IOCTL_PREPARE failed (%d)\n", __FUNCTION__, err);
++                      return err;
++              }
++              spec->modem_do_prepare[substream->stream] = 0;
++      }
++
++      return 0;
++}
++
++static __shimcall__
++int conexant_hsfmodem_OsHdaCodecOpenDMA(PHDAOSHAL pHdaOsHal, int hw_param_buffer_bytes, void **ppPlaybackStream, void **ppCaptureStream)
++{
++      int i, err;
++      struct hda_codec *codec = (struct hda_codec *)pHdaOsHal->hda_codec;
++      struct hda_pcm *info = codec->pcm_info;
++      struct snd_pcm *pcm;
++      struct conexant_spec *spec = codec->spec;
++
++      struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
++      static struct file fil;
++
++      for(i = 0; i < codec->num_pcms && info[i].pcm_type != HDA_PCM_TYPE_MODEM; i++);
++      if(i == codec->num_pcms) {
++              printk(KERN_ERR"%s: modem pcm not found\n", __FUNCTION__);
++              return -ENOENT;
++      }
++      pcm = info[i].pcm;
++
++      if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_PLAYBACK, &fil, &psubstream)) < 0) {
++              printk(KERN_ERR"%s: snd_pcm_open_substream STREAM_PLAYBACK failed (%d)\n", __FUNCTION__, err);
++              return err;
++      }
++
++      if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_CAPTURE, &fil, &csubstream)) < 0) {
++              printk(KERN_ERR"%s: snd_pcm_open_substream STREAM_CAPTURE failed (%d)\n", __FUNCTION__, err);
++              return err;
++      }
++
++      err = conexant_modem_snd_pcm_change_params(psubstream, hw_param_buffer_bytes);
++      if (err < 0) {
++              printk(KERN_ERR"%s: conexant_modem_snd_pcm_change_params STREAM_PLAYBACK failed (%d)\n", __FUNCTION__, err);
++      }
++
++      err = conexant_modem_snd_pcm_change_params(csubstream, hw_param_buffer_bytes);
++      if (err < 0) {
++              printk(KERN_ERR"%s: conexant_modem_snd_pcm_change_params STREAM_CAPTURE failed (%d)\n", __FUNCTION__, err);
++      }
++
++#if 0
++      printk(KERN_DEBUG"%s: psubstream=%p dma_buffer_p=%p area=%p addr=0x%lx bytes=%d\n", __FUNCTION__,
++                      psubstream,
++                      psubstream->runtime->dma_buffer_p,
++                      psubstream->runtime->dma_area,
++                      (unsigned long)psubstream->runtime->dma_addr,
++                      psubstream->runtime->dma_bytes);
++
++      printk(KERN_DEBUG"%s: csubstream=%p dma_buffer_p=%p area=%p addr=0x%lx bytes=%d\n", __FUNCTION__,
++                      csubstream,
++                      csubstream->runtime->dma_buffer_p,
++                      csubstream->runtime->dma_area,
++                      (unsigned long)csubstream->runtime->dma_addr,
++                      csubstream->runtime->dma_bytes);
++#endif
++
++      spec->modem_do_prepare[psubstream->stream] = 1;
++      spec->modem_do_prepare[csubstream->stream] = 1;
++
++      if ((err = conexant_modem_snd_pcm_prepare_substream(pHdaOsHal, psubstream)) < 0)
++              return err;
++
++      if ((err = conexant_modem_snd_pcm_prepare_substream(pHdaOsHal, csubstream)) < 0)
++              return err;
++
++      *ppPlaybackStream = psubstream;
++      *ppCaptureStream = csubstream;
++
++      return 0;
++}
++
++static void conexant_modem_snd_pcm_close_stream(struct snd_pcm_substream *substream)
++{
++#if SNDRV_PCM_VERSION <= SNDRV_PROTOCOL_VERSION(2, 0, 7)
++      snd_pcm_stream_lock_irq(substream);
++      if (snd_pcm_running(substream))
++              snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
++      snd_pcm_stream_unlock_irq(substream);
++
++      if (substream->ops->hw_free != NULL)
++              substream->ops->hw_free(substream);
++
++      substream->ops->close(substream);
++#endif
++      //printk(KERN_DEBUG"%s: substream=%p refcount=%d\n", __FUNCTION__, substream, substream->ref_count);
++      snd_pcm_release_substream(substream);
++}
++
++static __shimcall__
++void conexant_hsfmodem_OsHdaCodecCloseDMA(PHDAOSHAL pHdaOsHal, void *pPlaybackStream, void *pCaptureStream)
++{
++      //printk(KERN_DEBUG"%s: pHdaOsHal=%p pPlaybackStream=%p pCaptureStream=%p\n", __FUNCTION__, pHdaOsHal, pPlaybackStream, pCaptureStream);
++      if(pHdaOsHal) {
++              if(pPlaybackStream)
++                      conexant_modem_snd_pcm_close_stream(pPlaybackStream);
++              if(pCaptureStream)
++                      conexant_modem_snd_pcm_close_stream(pCaptureStream);
++      }
++}
++
++ static __shimcall__
++void conexant_hsfmodem_OsHdaCodecDMAInfo(PHDAOSHAL pHdaOsHal, void *Stream, unsigned char *StreamID, unsigned long *FifoSize, short unsigned int **ppBufAddr)
++{
++      struct conexant_spec *spec = ((struct hda_codec *)pHdaOsHal->hda_codec)->spec;
++      struct snd_pcm_substream *substream = (struct snd_pcm_substream *)Stream;
++
++#if 0
++      printk(KERN_DEBUG"%s: substream=%p stream=%u id/tag=%u fifo_size=%u bufAddr=%p\n", __FUNCTION__,
++                      substream,
++                      substream->stream,
++                      spec->modem_stream_tags[substream->stream],
++                      substream->runtime->hw.fifo_size,
++                      substream->runtime->dma_area);
++#endif
++
++      *StreamID = spec->modem_stream_tags[substream->stream];
++      *FifoSize = substream->runtime->hw.fifo_size; // XXX
++      *ppBufAddr = (short unsigned int *)substream->runtime->dma_area;
++}
++
++static __shimcall__
++int conexant_hsfmodem_OsHdaCodecSetDMAState(PHDAOSHAL pHdaOsHal, OSHDA_STREAM_STATE streamState, void *pPlaybackStream, void *pCaptureStream)
++{
++      struct conexant_spec *spec = ((struct hda_codec *)pHdaOsHal->hda_codec)->spec;
++      struct snd_pcm_substream *psubstream = (struct snd_pcm_substream *)pPlaybackStream;
++      struct snd_pcm_substream *csubstream = (struct snd_pcm_substream *)pCaptureStream;
++      int err = 0, cmd;
++      unsigned long flags, flags2;
++
++      switch(streamState) {
++              case OsHdaStreamStateRun:
++//                    printk(KERN_DEBUG"%s: Run\n", __FUNCTION__);
++                      if ((err = conexant_modem_snd_pcm_prepare_substream(pHdaOsHal, psubstream)) < 0)
++                              return err;
++                      if ((err = conexant_modem_snd_pcm_prepare_substream(pHdaOsHal, csubstream)) < 0)
++                              return err;
++
++                      cmd = SNDRV_PCM_IOCTL_START;
++                      psubstream->runtime->start_threshold = 1;
++                      psubstream->runtime->stop_threshold = psubstream->runtime->boundary;
++                      csubstream->runtime->start_threshold = 1;
++                      csubstream->runtime->stop_threshold = csubstream->runtime->boundary;
++                      break;
++              case OsHdaStreamStateStop:
++//                    printk(KERN_DEBUG"%s: Stop\n", __FUNCTION__);
++                      cmd = SNDRV_PCM_IOCTL_DROP;
++                      break;
++              case OsHdaStreamStateReset:
++//                    printk(KERN_DEBUG"%s: Reset\n", __FUNCTION__);
++                      cmd = SNDRV_PCM_IOCTL_RESET;
++                      psubstream->runtime->start_threshold = psubstream->runtime->boundary;
++                      csubstream->runtime->start_threshold = csubstream->runtime->boundary;
++                      break;
++              default:
++                      printk(KERN_ERR"%s: unknown state %d\n", __FUNCTION__, streamState);
++                      return -ENOSYS;
++      }
++
++      switch(cmd) {
++              case SNDRV_PCM_IOCTL_START:
++                      snd_pcm_stream_lock_irqsave(psubstream, flags);
++                      snd_pcm_stream_lock_irqsave(csubstream, flags2);
++                      psubstream->ops->trigger(psubstream, SNDRV_PCM_TRIGGER_START);
++                      csubstream->ops->trigger(csubstream, SNDRV_PCM_TRIGGER_START);
++                      snd_pcm_stream_unlock_irqrestore(csubstream, flags2);
++                      snd_pcm_stream_unlock_irqrestore(psubstream, flags);
++                      break;
++              case SNDRV_PCM_IOCTL_DROP:
++                      snd_pcm_stream_lock_irqsave(psubstream, flags);
++                      snd_pcm_stream_lock_irqsave(csubstream, flags2);
++                      psubstream->runtime->start_threshold = psubstream->runtime->boundary;
++                      csubstream->runtime->start_threshold = csubstream->runtime->boundary;
++                      psubstream->ops->trigger(psubstream, SNDRV_PCM_TRIGGER_STOP);
++                      csubstream->ops->trigger(csubstream, SNDRV_PCM_TRIGGER_STOP);
++                      snd_pcm_stream_unlock_irqrestore(csubstream, flags2);
++                      snd_pcm_stream_unlock_irqrestore(psubstream, flags);
++                      break;
++              case SNDRV_PCM_IOCTL_RESET:
++                      //psubstream->ops->trigger(psubstream, SNDRV_PCM_TRIGGER_STOP);
++                      //csubstream->ops->trigger(csubstream, SNDRV_PCM_TRIGGER_STOP);
++                      /*FALLTHROUGH*/
++              default:
++                      err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL);
++                      if (err < 0) {
++                              printk(KERN_ERR"%s: snd_pcm_kernel_ioctl (playback) failed (%d)\n", __FUNCTION__, err);
++                      }
++
++                      err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL);
++                      if (err < 0) {
++                              printk(KERN_ERR"%s: snd_pcm_kernel_ioctl (capture) failed (%d)\n", __FUNCTION__, err);
++                      }
++                      break;
++      }
++
++      if(cmd != SNDRV_PCM_IOCTL_START) {
++              spec->modem_do_prepare[psubstream->stream] = 1;
++              spec->modem_do_prepare[csubstream->stream] = 1;
++      }
++ 
++      return err;
++}
++
++static __shimcall__
++unsigned long conexant_hsfmodem_OsHdaCodecGetDMAPos(PHDAOSHAL pHdaOsHal, void *Stream)
++{
++      struct hda_codec *codec = (struct hda_codec *)pHdaOsHal->hda_codec;
++      struct snd_pcm_substream *substream = (struct snd_pcm_substream *)Stream;
++      int ret;
++
++      if(codec->bus->ops.get_linkpos)
++              ret = codec->bus->ops.get_linkpos(substream);
++      else
++              ret = frames_to_bytes(substream->runtime, substream->ops->pointer(substream));
++
++      //printk(KERN_DEBUG"%s: substream=%p pos=%ld, ret=%d\n", __FUNCTION__, substream, pos, ret);
++
++      return ret;
++}
++
++
++static void *conexant_hsfmodem_interface_funcs[] = {
++      conexant_hsfmodem_OsHdaCodecGetAddr,
++      conexant_hsfmodem_OsHdaCodecGetVendorId,
++      conexant_hsfmodem_OsHdaCodecGetSubsystemId,
++      conexant_hsfmodem_OsHdaCodecGetRevisionId,
++      conexant_hsfmodem_OsHdaCodecRead,
++      conexant_hsfmodem_OsHdaCodecWallclock,
++      conexant_hsfmodem_OsHdaCodecSetEventCallback,
++      conexant_hsfmodem_OsHdaCodecClearEventCallback,
++      conexant_hsfmodem_OsHdaCodecOpenDMA,
++      conexant_hsfmodem_OsHdaCodecCloseDMA,
++      conexant_hsfmodem_OsHdaCodecDMAInfo,
++      conexant_hsfmodem_OsHdaCodecSetDMAState,
++      conexant_hsfmodem_OsHdaCodecGetDMAPos,
++      NULL
++};
++
++/*
++ */
++
+ static struct hda_codec_preset snd_hda_preset_conexant[] = {
+       { .id = 0x14f15045, .name = "CX20549 (Venice)",
+         .patch = patch_cxt5045 },
+@@ -3113,18 +3847,28 @@
+         .patch = patch_cxt5066 },
+       { .id = 0x14f15069, .name = "CX20585",
+         .patch = patch_cxt5066 },
++      { .id = 0x14f12bfa, .mfg = 2, .name = "HSF",
++        .patch = patch_cxthsfmodem },
++      { .id = 0x14f12c06, .mfg = 2, .name = "HSF",
++        .patch = patch_cxthsfmodem },
++      { .id = 0x14f10000, .mask = 0xffff0000, .mfg = 2, .name = "HSF",
++        .patch = patch_cxthsfmodem },
+       {} /* terminator */
+ };
++
+ MODULE_ALIAS("snd-hda-codec-id:14f15045");
+ MODULE_ALIAS("snd-hda-codec-id:14f15047");
+ MODULE_ALIAS("snd-hda-codec-id:14f15051");
+ MODULE_ALIAS("snd-hda-codec-id:14f15066");
+ MODULE_ALIAS("snd-hda-codec-id:14f15067");
+ MODULE_ALIAS("snd-hda-codec-id:14f15069");
++MODULE_ALIAS("snd-hda-codec-id:14f12bfa");
++MODULE_ALIAS("snd-hda-codec-id:14f12c06");
++MODULE_ALIAS("snd-hda-codec-id:14f1*");
+ MODULE_LICENSE("GPL");
+-MODULE_DESCRIPTION("Conexant HD-audio codec");
++MODULE_DESCRIPTION("Conexant HD-audio and modem codec");
+ static struct hda_codec_preset_list conexant_list = {
+       .preset = snd_hda_preset_conexant,
This page took 0.143182 seconds and 4 git commands to generate.