sound/hda/codecs/si3054.c

Source file repositories/reference/linux-study-clean/sound/hda/codecs/si3054.c

File Facts

System
Linux kernel
Corpus path
sound/hda/codecs/si3054.c
Extension
.c
Size
8355 bytes
Lines
304
Domain
Driver Families
Bucket
sound/hda
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct si3054_spec {
	unsigned international;
};


/*
 * Modem mixer
 */

#define PRIVATE_VALUE(reg,mask) ((reg<<16)|(mask&0xffff))
#define PRIVATE_REG(val) ((val>>16)&0xffff)
#define PRIVATE_MASK(val) (val&0xffff)

#define si3054_switch_info	snd_ctl_boolean_mono_info

static int si3054_switch_get(struct snd_kcontrol *kcontrol,
		               struct snd_ctl_elem_value *uvalue)
{
	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
	u16 reg  = PRIVATE_REG(kcontrol->private_value);
	u16 mask = PRIVATE_MASK(kcontrol->private_value);
	uvalue->value.integer.value[0] = (GET_REG(codec, reg)) & mask ? 1 : 0 ;
	return 0;
}

static int si3054_switch_put(struct snd_kcontrol *kcontrol,
		               struct snd_ctl_elem_value *uvalue)
{
	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
	u16 reg  = PRIVATE_REG(kcontrol->private_value);
	u16 mask = PRIVATE_MASK(kcontrol->private_value);
	if (uvalue->value.integer.value[0])
		SET_REG_CACHE(codec, reg, (GET_REG(codec, reg)) | mask);
	else
		SET_REG_CACHE(codec, reg, (GET_REG(codec, reg)) & ~mask);
	return 0;
}

#define SI3054_KCONTROL(kname,reg,mask) { \
	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
	.name = kname, \
	.subdevice = HDA_SUBDEV_NID_FLAG | reg, \
	.info = si3054_switch_info, \
	.get  = si3054_switch_get, \
	.put  = si3054_switch_put, \
	.private_value = PRIVATE_VALUE(reg,mask), \
}
		

static const struct snd_kcontrol_new si3054_modem_mixer[] = {
	SI3054_KCONTROL("Off-hook Switch", SI3054_GPIO_CONTROL, SI3054_GPIO_OH),
	SI3054_KCONTROL("Caller ID Switch", SI3054_GPIO_CONTROL, SI3054_GPIO_CID),
	{}
};

static int si3054_build_controls(struct hda_codec *codec)
{
	return snd_hda_add_new_ctls(codec, si3054_modem_mixer);
}


/*
 * PCM callbacks
 */

static int si3054_pcm_prepare(struct hda_pcm_stream *hinfo,
			      struct hda_codec *codec,
			      unsigned int stream_tag,
			      unsigned int format,
			      struct snd_pcm_substream *substream)
{
	u16 val;

	SET_REG(codec, SI3054_LINE_RATE, substream->runtime->rate);
	val = GET_REG(codec, SI3054_LINE_LEVEL);
	val &= 0xff << (8 * (substream->stream != SNDRV_PCM_STREAM_PLAYBACK));
	val |= ((stream_tag & 0xf) << 4) << (8 * (substream->stream == SNDRV_PCM_STREAM_PLAYBACK));
	SET_REG(codec, SI3054_LINE_LEVEL, val);

	snd_hda_codec_setup_stream(codec, hinfo->nid,
				   stream_tag, 0, format);
	return 0;
}

static int si3054_pcm_open(struct hda_pcm_stream *hinfo,
			   struct hda_codec *codec,
			    struct snd_pcm_substream *substream)
{
	static const unsigned int rates[] = { 8000, 9600, 16000 };
	static const struct snd_pcm_hw_constraint_list hw_constraints_rates = {

Annotation

Implementation Notes