Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Digital Beep Input Interface for HD-audio codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Author: Matt Ranostay <matt.ranostay@konsulko.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright (c) 2008 Embedded Alley Solutions Inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include "hda_beep.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include "hda_local.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 	DIGBEEP_HZ_STEP = 46875,	/* 46.875 Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 	DIGBEEP_HZ_MIN = 93750,		/* 93.750 Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	DIGBEEP_HZ_MAX = 12000000,	/* 12 KHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) /* generate or stop tone */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) static void generate_tone(struct hda_beep *beep, int tone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	struct hda_codec *codec = beep->codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	if (tone && !beep->playing) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 		snd_hda_power_up(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 		if (beep->power_hook)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 			beep->power_hook(beep, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 		beep->playing = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	snd_hda_codec_write(codec, beep->nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 			    AC_VERB_SET_BEEP_CONTROL, tone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	if (!tone && beep->playing) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 		beep->playing = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 		if (beep->power_hook)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 			beep->power_hook(beep, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		snd_hda_power_down(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) static void snd_hda_generate_beep(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	struct hda_beep *beep =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		container_of(work, struct hda_beep, beep_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	if (beep->enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		generate_tone(beep, beep->tone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) /* (non-standard) Linear beep tone calculation for IDT/STAC codecs 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * The tone frequency of beep generator on IDT/STAC codecs is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * defined from the 8bit tone parameter, in Hz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  *    freq = 48000 * (257 - tone) / 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  * that is from 12kHz to 93.75Hz in steps of 46.875 Hz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) static int beep_linear_tone(struct hda_beep *beep, int hz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	if (hz <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	hz *= 1000; /* fixed point */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	hz = hz - DIGBEEP_HZ_MIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		+ DIGBEEP_HZ_STEP / 2; /* round to nearest step */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	if (hz < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		hz = 0; /* turn off PC beep*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	else if (hz >= (DIGBEEP_HZ_MAX - DIGBEEP_HZ_MIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		hz = 1; /* max frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		hz /= DIGBEEP_HZ_STEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		hz = 255 - hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	return hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) /* HD-audio standard beep tone parameter calculation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  * The tone frequency in Hz is calculated as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  *   freq = 48000 / (tone * 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  * from 47Hz to 12kHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) static int beep_standard_tone(struct hda_beep *beep, int hz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	if (hz <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		return 0; /* disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	hz = 12000 / hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	if (hz > 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		return 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	if (hz <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	return hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 				unsigned int code, int hz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	struct hda_beep *beep = input_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	switch (code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	case SND_BELL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		if (hz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 			hz = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	case SND_TONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		if (beep->linear_tone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 			beep->tone = beep_linear_tone(beep, hz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 			beep->tone = beep_standard_tone(beep, hz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	/* schedule beep event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	schedule_work(&beep->beep_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static void turn_off_beep(struct hda_beep *beep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	cancel_work_sync(&beep->beep_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	if (beep->playing) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		/* turn off beep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		generate_tone(beep, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)  * snd_hda_enable_beep_device - Turn on/off beep sound
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)  * @codec: the HDA codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)  * @enable: flag to turn on/off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int snd_hda_enable_beep_device(struct hda_codec *codec, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	struct hda_beep *beep = codec->beep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	if (!beep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	enable = !!enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	if (beep->enabled != enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		beep->enabled = enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		if (!enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 			turn_off_beep(beep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) EXPORT_SYMBOL_GPL(snd_hda_enable_beep_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static int beep_dev_register(struct snd_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	struct hda_beep *beep = device->device_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	err = input_register_device(beep->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		beep->registered = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static int beep_dev_disconnect(struct snd_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	struct hda_beep *beep = device->device_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	if (beep->registered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		input_unregister_device(beep->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		input_free_device(beep->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	turn_off_beep(beep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static int beep_dev_free(struct snd_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	struct hda_beep *beep = device->device_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	beep->codec->beep = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	kfree(beep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)  * snd_hda_attach_beep_device - Attach a beep input device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)  * @codec: the HDA codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)  * @nid: beep NID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)  * Attach a beep object to the given widget.  If beep hint is turned off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)  * explicitly or beep_mode of the codec is turned off, this doesn't nothing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)  * Currently, only one beep device is allowed to each codec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	static const struct snd_device_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		.dev_register = beep_dev_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		.dev_disconnect = beep_dev_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		.dev_free = beep_dev_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	struct input_dev *input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	struct hda_beep *beep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	if (!snd_hda_get_bool_hint(codec, "beep"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		return 0; /* disabled explicitly by hints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	if (codec->beep_mode == HDA_BEEP_MODE_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		return 0; /* disabled by module option */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	beep = kzalloc(sizeof(*beep), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	if (beep == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	snprintf(beep->phys, sizeof(beep->phys),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		"card%d/codec#%d/beep0", codec->card->number, codec->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	/* enable linear scale */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	snd_hda_codec_write_cache(codec, nid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		AC_VERB_SET_DIGI_CONVERT_2, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	beep->nid = nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	beep->codec = codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	codec->beep = beep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	INIT_WORK(&beep->beep_work, &snd_hda_generate_beep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	mutex_init(&beep->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	input_dev = input_allocate_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	if (!input_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	/* setup digital beep device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	input_dev->name = "HDA Digital PCBeep";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	input_dev->phys = beep->phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	input_dev->id.bustype = BUS_PCI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	input_dev->dev.parent = &codec->card->card_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	input_dev->id.vendor = codec->core.vendor_id >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	input_dev->id.product = codec->core.vendor_id & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	input_dev->id.version = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	input_dev->evbit[0] = BIT_MASK(EV_SND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	input_dev->event = snd_hda_beep_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	input_set_drvdata(input_dev, beep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	beep->dev = input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	err = snd_device_new(codec->card, SNDRV_DEV_JACK, beep, &ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		goto err_input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)  err_input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	input_free_device(beep->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)  err_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	kfree(beep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	codec->beep = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) EXPORT_SYMBOL_GPL(snd_hda_attach_beep_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)  * snd_hda_detach_beep_device - Detach the beep device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)  * @codec: the HDA codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) void snd_hda_detach_beep_device(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	if (!codec->bus->shutdown && codec->beep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		snd_device_free(codec->card, codec->beep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) EXPORT_SYMBOL_GPL(snd_hda_detach_beep_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static bool ctl_has_mute(struct snd_kcontrol *kcontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	return query_amp_caps(codec, get_amp_nid(kcontrol),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 			      get_amp_direction(kcontrol)) & AC_AMPCAP_MUTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /* get/put callbacks for beep mute mixer switches */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)  * snd_hda_mixer_amp_switch_get_beep - Get callback for beep controls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)  * @kcontrol: ctl element
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)  * @ucontrol: pointer to get/store the data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 				      struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	struct hda_beep *beep = codec->beep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	int chs = get_amp_channels(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	if (beep && (!beep->enabled || !ctl_has_mute(kcontrol))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		if (chs & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 			ucontrol->value.integer.value[0] = beep->enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		if (chs & 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 			ucontrol->value.integer.value[1] = beep->enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	return snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_get_beep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)  * snd_hda_mixer_amp_switch_put_beep - Put callback for beep controls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)  * @kcontrol: ctl element
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)  * @ucontrol: pointer to get/store the data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 				      struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	struct hda_beep *beep = codec->beep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	if (beep) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 		u8 chs = get_amp_channels(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		int enable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		long *valp = ucontrol->value.integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		if (chs & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 			enable |= *valp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 			valp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		if (chs & 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 			enable |= *valp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		snd_hda_enable_beep_device(codec, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	if (!ctl_has_mute(kcontrol))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_put_beep);