xref: /kernel/linux/linux-5.10/sound/pci/hda/hda_beep.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Digital Beep Input Interface for HD-audio codec
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Author: Matt Ranostay <matt.ranostay@konsulko.com>
68c2ecf20Sopenharmony_ci * Copyright (c) 2008 Embedded Alley Solutions Inc
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/input.h>
108c2ecf20Sopenharmony_ci#include <linux/slab.h>
118c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
128c2ecf20Sopenharmony_ci#include <linux/export.h>
138c2ecf20Sopenharmony_ci#include <sound/core.h>
148c2ecf20Sopenharmony_ci#include "hda_beep.h"
158c2ecf20Sopenharmony_ci#include "hda_local.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_cienum {
188c2ecf20Sopenharmony_ci	DIGBEEP_HZ_STEP = 46875,	/* 46.875 Hz */
198c2ecf20Sopenharmony_ci	DIGBEEP_HZ_MIN = 93750,		/* 93.750 Hz */
208c2ecf20Sopenharmony_ci	DIGBEEP_HZ_MAX = 12000000,	/* 12 KHz */
218c2ecf20Sopenharmony_ci};
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/* generate or stop tone */
248c2ecf20Sopenharmony_cistatic void generate_tone(struct hda_beep *beep, int tone)
258c2ecf20Sopenharmony_ci{
268c2ecf20Sopenharmony_ci	struct hda_codec *codec = beep->codec;
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	if (tone && !beep->playing) {
298c2ecf20Sopenharmony_ci		snd_hda_power_up(codec);
308c2ecf20Sopenharmony_ci		if (beep->power_hook)
318c2ecf20Sopenharmony_ci			beep->power_hook(beep, true);
328c2ecf20Sopenharmony_ci		beep->playing = 1;
338c2ecf20Sopenharmony_ci	}
348c2ecf20Sopenharmony_ci	snd_hda_codec_write(codec, beep->nid, 0,
358c2ecf20Sopenharmony_ci			    AC_VERB_SET_BEEP_CONTROL, tone);
368c2ecf20Sopenharmony_ci	if (!tone && beep->playing) {
378c2ecf20Sopenharmony_ci		beep->playing = 0;
388c2ecf20Sopenharmony_ci		if (beep->power_hook)
398c2ecf20Sopenharmony_ci			beep->power_hook(beep, false);
408c2ecf20Sopenharmony_ci		snd_hda_power_down(codec);
418c2ecf20Sopenharmony_ci	}
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistatic void snd_hda_generate_beep(struct work_struct *work)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	struct hda_beep *beep =
478c2ecf20Sopenharmony_ci		container_of(work, struct hda_beep, beep_work);
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	if (beep->enabled)
508c2ecf20Sopenharmony_ci		generate_tone(beep, beep->tone);
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci/* (non-standard) Linear beep tone calculation for IDT/STAC codecs
548c2ecf20Sopenharmony_ci *
558c2ecf20Sopenharmony_ci * The tone frequency of beep generator on IDT/STAC codecs is
568c2ecf20Sopenharmony_ci * defined from the 8bit tone parameter, in Hz,
578c2ecf20Sopenharmony_ci *    freq = 48000 * (257 - tone) / 1024
588c2ecf20Sopenharmony_ci * that is from 12kHz to 93.75Hz in steps of 46.875 Hz
598c2ecf20Sopenharmony_ci */
608c2ecf20Sopenharmony_cistatic int beep_linear_tone(struct hda_beep *beep, int hz)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	if (hz <= 0)
638c2ecf20Sopenharmony_ci		return 0;
648c2ecf20Sopenharmony_ci	hz *= 1000; /* fixed point */
658c2ecf20Sopenharmony_ci	hz = hz - DIGBEEP_HZ_MIN
668c2ecf20Sopenharmony_ci		+ DIGBEEP_HZ_STEP / 2; /* round to nearest step */
678c2ecf20Sopenharmony_ci	if (hz < 0)
688c2ecf20Sopenharmony_ci		hz = 0; /* turn off PC beep*/
698c2ecf20Sopenharmony_ci	else if (hz >= (DIGBEEP_HZ_MAX - DIGBEEP_HZ_MIN))
708c2ecf20Sopenharmony_ci		hz = 1; /* max frequency */
718c2ecf20Sopenharmony_ci	else {
728c2ecf20Sopenharmony_ci		hz /= DIGBEEP_HZ_STEP;
738c2ecf20Sopenharmony_ci		hz = 255 - hz;
748c2ecf20Sopenharmony_ci	}
758c2ecf20Sopenharmony_ci	return hz;
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci/* HD-audio standard beep tone parameter calculation
798c2ecf20Sopenharmony_ci *
808c2ecf20Sopenharmony_ci * The tone frequency in Hz is calculated as
818c2ecf20Sopenharmony_ci *   freq = 48000 / (tone * 4)
828c2ecf20Sopenharmony_ci * from 47Hz to 12kHz
838c2ecf20Sopenharmony_ci */
848c2ecf20Sopenharmony_cistatic int beep_standard_tone(struct hda_beep *beep, int hz)
858c2ecf20Sopenharmony_ci{
868c2ecf20Sopenharmony_ci	if (hz <= 0)
878c2ecf20Sopenharmony_ci		return 0; /* disabled */
888c2ecf20Sopenharmony_ci	hz = 12000 / hz;
898c2ecf20Sopenharmony_ci	if (hz > 0xff)
908c2ecf20Sopenharmony_ci		return 0xff;
918c2ecf20Sopenharmony_ci	if (hz <= 0)
928c2ecf20Sopenharmony_ci		return 1;
938c2ecf20Sopenharmony_ci	return hz;
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_cistatic int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
978c2ecf20Sopenharmony_ci				unsigned int code, int hz)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	struct hda_beep *beep = input_get_drvdata(dev);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	switch (code) {
1028c2ecf20Sopenharmony_ci	case SND_BELL:
1038c2ecf20Sopenharmony_ci		if (hz)
1048c2ecf20Sopenharmony_ci			hz = 1000;
1058c2ecf20Sopenharmony_ci		fallthrough;
1068c2ecf20Sopenharmony_ci	case SND_TONE:
1078c2ecf20Sopenharmony_ci		if (beep->linear_tone)
1088c2ecf20Sopenharmony_ci			beep->tone = beep_linear_tone(beep, hz);
1098c2ecf20Sopenharmony_ci		else
1108c2ecf20Sopenharmony_ci			beep->tone = beep_standard_tone(beep, hz);
1118c2ecf20Sopenharmony_ci		break;
1128c2ecf20Sopenharmony_ci	default:
1138c2ecf20Sopenharmony_ci		return -1;
1148c2ecf20Sopenharmony_ci	}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	/* schedule beep event */
1178c2ecf20Sopenharmony_ci	schedule_work(&beep->beep_work);
1188c2ecf20Sopenharmony_ci	return 0;
1198c2ecf20Sopenharmony_ci}
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_cistatic void turn_on_beep(struct hda_beep *beep)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	if (beep->keep_power_at_enable)
1248c2ecf20Sopenharmony_ci		snd_hda_power_up_pm(beep->codec);
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cistatic void turn_off_beep(struct hda_beep *beep)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	cancel_work_sync(&beep->beep_work);
1308c2ecf20Sopenharmony_ci	if (beep->playing) {
1318c2ecf20Sopenharmony_ci		/* turn off beep */
1328c2ecf20Sopenharmony_ci		generate_tone(beep, 0);
1338c2ecf20Sopenharmony_ci	}
1348c2ecf20Sopenharmony_ci	if (beep->keep_power_at_enable)
1358c2ecf20Sopenharmony_ci		snd_hda_power_down_pm(beep->codec);
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci/**
1398c2ecf20Sopenharmony_ci * snd_hda_enable_beep_device - Turn on/off beep sound
1408c2ecf20Sopenharmony_ci * @codec: the HDA codec
1418c2ecf20Sopenharmony_ci * @enable: flag to turn on/off
1428c2ecf20Sopenharmony_ci */
1438c2ecf20Sopenharmony_ciint snd_hda_enable_beep_device(struct hda_codec *codec, int enable)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	struct hda_beep *beep = codec->beep;
1468c2ecf20Sopenharmony_ci	if (!beep)
1478c2ecf20Sopenharmony_ci		return 0;
1488c2ecf20Sopenharmony_ci	enable = !!enable;
1498c2ecf20Sopenharmony_ci	if (beep->enabled != enable) {
1508c2ecf20Sopenharmony_ci		beep->enabled = enable;
1518c2ecf20Sopenharmony_ci		if (enable)
1528c2ecf20Sopenharmony_ci			turn_on_beep(beep);
1538c2ecf20Sopenharmony_ci		else
1548c2ecf20Sopenharmony_ci			turn_off_beep(beep);
1558c2ecf20Sopenharmony_ci		return 1;
1568c2ecf20Sopenharmony_ci	}
1578c2ecf20Sopenharmony_ci	return 0;
1588c2ecf20Sopenharmony_ci}
1598c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_hda_enable_beep_device);
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_cistatic int beep_dev_register(struct snd_device *device)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	struct hda_beep *beep = device->device_data;
1648c2ecf20Sopenharmony_ci	int err;
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	err = input_register_device(beep->dev);
1678c2ecf20Sopenharmony_ci	if (!err)
1688c2ecf20Sopenharmony_ci		beep->registered = true;
1698c2ecf20Sopenharmony_ci	return err;
1708c2ecf20Sopenharmony_ci}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_cistatic int beep_dev_disconnect(struct snd_device *device)
1738c2ecf20Sopenharmony_ci{
1748c2ecf20Sopenharmony_ci	struct hda_beep *beep = device->device_data;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	if (beep->registered)
1778c2ecf20Sopenharmony_ci		input_unregister_device(beep->dev);
1788c2ecf20Sopenharmony_ci	else
1798c2ecf20Sopenharmony_ci		input_free_device(beep->dev);
1808c2ecf20Sopenharmony_ci	if (beep->enabled)
1818c2ecf20Sopenharmony_ci		turn_off_beep(beep);
1828c2ecf20Sopenharmony_ci	return 0;
1838c2ecf20Sopenharmony_ci}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_cistatic int beep_dev_free(struct snd_device *device)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci	struct hda_beep *beep = device->device_data;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	beep->codec->beep = NULL;
1908c2ecf20Sopenharmony_ci	kfree(beep);
1918c2ecf20Sopenharmony_ci	return 0;
1928c2ecf20Sopenharmony_ci}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci/**
1958c2ecf20Sopenharmony_ci * snd_hda_attach_beep_device - Attach a beep input device
1968c2ecf20Sopenharmony_ci * @codec: the HDA codec
1978c2ecf20Sopenharmony_ci * @nid: beep NID
1988c2ecf20Sopenharmony_ci *
1998c2ecf20Sopenharmony_ci * Attach a beep object to the given widget.  If beep hint is turned off
2008c2ecf20Sopenharmony_ci * explicitly or beep_mode of the codec is turned off, this doesn't nothing.
2018c2ecf20Sopenharmony_ci *
2028c2ecf20Sopenharmony_ci * Currently, only one beep device is allowed to each codec.
2038c2ecf20Sopenharmony_ci */
2048c2ecf20Sopenharmony_ciint snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
2058c2ecf20Sopenharmony_ci{
2068c2ecf20Sopenharmony_ci	static const struct snd_device_ops ops = {
2078c2ecf20Sopenharmony_ci		.dev_register = beep_dev_register,
2088c2ecf20Sopenharmony_ci		.dev_disconnect = beep_dev_disconnect,
2098c2ecf20Sopenharmony_ci		.dev_free = beep_dev_free,
2108c2ecf20Sopenharmony_ci	};
2118c2ecf20Sopenharmony_ci	struct input_dev *input_dev;
2128c2ecf20Sopenharmony_ci	struct hda_beep *beep;
2138c2ecf20Sopenharmony_ci	int err;
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	if (!snd_hda_get_bool_hint(codec, "beep"))
2168c2ecf20Sopenharmony_ci		return 0; /* disabled explicitly by hints */
2178c2ecf20Sopenharmony_ci	if (codec->beep_mode == HDA_BEEP_MODE_OFF)
2188c2ecf20Sopenharmony_ci		return 0; /* disabled by module option */
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	beep = kzalloc(sizeof(*beep), GFP_KERNEL);
2218c2ecf20Sopenharmony_ci	if (beep == NULL)
2228c2ecf20Sopenharmony_ci		return -ENOMEM;
2238c2ecf20Sopenharmony_ci	snprintf(beep->phys, sizeof(beep->phys),
2248c2ecf20Sopenharmony_ci		"card%d/codec#%d/beep0", codec->card->number, codec->addr);
2258c2ecf20Sopenharmony_ci	/* enable linear scale */
2268c2ecf20Sopenharmony_ci	snd_hda_codec_write_cache(codec, nid, 0,
2278c2ecf20Sopenharmony_ci		AC_VERB_SET_DIGI_CONVERT_2, 0x01);
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	beep->nid = nid;
2308c2ecf20Sopenharmony_ci	beep->codec = codec;
2318c2ecf20Sopenharmony_ci	codec->beep = beep;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	INIT_WORK(&beep->beep_work, &snd_hda_generate_beep);
2348c2ecf20Sopenharmony_ci	mutex_init(&beep->mutex);
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	input_dev = input_allocate_device();
2378c2ecf20Sopenharmony_ci	if (!input_dev) {
2388c2ecf20Sopenharmony_ci		err = -ENOMEM;
2398c2ecf20Sopenharmony_ci		goto err_free;
2408c2ecf20Sopenharmony_ci	}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	/* setup digital beep device */
2438c2ecf20Sopenharmony_ci	input_dev->name = "HDA Digital PCBeep";
2448c2ecf20Sopenharmony_ci	input_dev->phys = beep->phys;
2458c2ecf20Sopenharmony_ci	input_dev->id.bustype = BUS_PCI;
2468c2ecf20Sopenharmony_ci	input_dev->dev.parent = &codec->card->card_dev;
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	input_dev->id.vendor = codec->core.vendor_id >> 16;
2498c2ecf20Sopenharmony_ci	input_dev->id.product = codec->core.vendor_id & 0xffff;
2508c2ecf20Sopenharmony_ci	input_dev->id.version = 0x01;
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	input_dev->evbit[0] = BIT_MASK(EV_SND);
2538c2ecf20Sopenharmony_ci	input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
2548c2ecf20Sopenharmony_ci	input_dev->event = snd_hda_beep_event;
2558c2ecf20Sopenharmony_ci	input_set_drvdata(input_dev, beep);
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	beep->dev = input_dev;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	err = snd_device_new(codec->card, SNDRV_DEV_JACK, beep, &ops);
2608c2ecf20Sopenharmony_ci	if (err < 0)
2618c2ecf20Sopenharmony_ci		goto err_input;
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	return 0;
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci err_input:
2668c2ecf20Sopenharmony_ci	input_free_device(beep->dev);
2678c2ecf20Sopenharmony_ci err_free:
2688c2ecf20Sopenharmony_ci	kfree(beep);
2698c2ecf20Sopenharmony_ci	codec->beep = NULL;
2708c2ecf20Sopenharmony_ci	return err;
2718c2ecf20Sopenharmony_ci}
2728c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_hda_attach_beep_device);
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci/**
2758c2ecf20Sopenharmony_ci * snd_hda_detach_beep_device - Detach the beep device
2768c2ecf20Sopenharmony_ci * @codec: the HDA codec
2778c2ecf20Sopenharmony_ci */
2788c2ecf20Sopenharmony_civoid snd_hda_detach_beep_device(struct hda_codec *codec)
2798c2ecf20Sopenharmony_ci{
2808c2ecf20Sopenharmony_ci	if (!codec->bus->shutdown && codec->beep)
2818c2ecf20Sopenharmony_ci		snd_device_free(codec->card, codec->beep);
2828c2ecf20Sopenharmony_ci}
2838c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_hda_detach_beep_device);
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_cistatic bool ctl_has_mute(struct snd_kcontrol *kcontrol)
2868c2ecf20Sopenharmony_ci{
2878c2ecf20Sopenharmony_ci	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2888c2ecf20Sopenharmony_ci	return query_amp_caps(codec, get_amp_nid(kcontrol),
2898c2ecf20Sopenharmony_ci			      get_amp_direction(kcontrol)) & AC_AMPCAP_MUTE;
2908c2ecf20Sopenharmony_ci}
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci/* get/put callbacks for beep mute mixer switches */
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci/**
2958c2ecf20Sopenharmony_ci * snd_hda_mixer_amp_switch_get_beep - Get callback for beep controls
2968c2ecf20Sopenharmony_ci * @kcontrol: ctl element
2978c2ecf20Sopenharmony_ci * @ucontrol: pointer to get/store the data
2988c2ecf20Sopenharmony_ci */
2998c2ecf20Sopenharmony_ciint snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol,
3008c2ecf20Sopenharmony_ci				      struct snd_ctl_elem_value *ucontrol)
3018c2ecf20Sopenharmony_ci{
3028c2ecf20Sopenharmony_ci	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3038c2ecf20Sopenharmony_ci	struct hda_beep *beep = codec->beep;
3048c2ecf20Sopenharmony_ci	int chs = get_amp_channels(kcontrol);
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	if (beep && (!beep->enabled || !ctl_has_mute(kcontrol))) {
3078c2ecf20Sopenharmony_ci		if (chs & 1)
3088c2ecf20Sopenharmony_ci			ucontrol->value.integer.value[0] = beep->enabled;
3098c2ecf20Sopenharmony_ci		if (chs & 2)
3108c2ecf20Sopenharmony_ci			ucontrol->value.integer.value[1] = beep->enabled;
3118c2ecf20Sopenharmony_ci		return 0;
3128c2ecf20Sopenharmony_ci	}
3138c2ecf20Sopenharmony_ci	return snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
3148c2ecf20Sopenharmony_ci}
3158c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_get_beep);
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci/**
3188c2ecf20Sopenharmony_ci * snd_hda_mixer_amp_switch_put_beep - Put callback for beep controls
3198c2ecf20Sopenharmony_ci * @kcontrol: ctl element
3208c2ecf20Sopenharmony_ci * @ucontrol: pointer to get/store the data
3218c2ecf20Sopenharmony_ci */
3228c2ecf20Sopenharmony_ciint snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
3238c2ecf20Sopenharmony_ci				      struct snd_ctl_elem_value *ucontrol)
3248c2ecf20Sopenharmony_ci{
3258c2ecf20Sopenharmony_ci	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3268c2ecf20Sopenharmony_ci	struct hda_beep *beep = codec->beep;
3278c2ecf20Sopenharmony_ci	if (beep) {
3288c2ecf20Sopenharmony_ci		u8 chs = get_amp_channels(kcontrol);
3298c2ecf20Sopenharmony_ci		int enable = 0;
3308c2ecf20Sopenharmony_ci		long *valp = ucontrol->value.integer.value;
3318c2ecf20Sopenharmony_ci		if (chs & 1) {
3328c2ecf20Sopenharmony_ci			enable |= *valp;
3338c2ecf20Sopenharmony_ci			valp++;
3348c2ecf20Sopenharmony_ci		}
3358c2ecf20Sopenharmony_ci		if (chs & 2)
3368c2ecf20Sopenharmony_ci			enable |= *valp;
3378c2ecf20Sopenharmony_ci		snd_hda_enable_beep_device(codec, enable);
3388c2ecf20Sopenharmony_ci	}
3398c2ecf20Sopenharmony_ci	if (!ctl_has_mute(kcontrol))
3408c2ecf20Sopenharmony_ci		return 0;
3418c2ecf20Sopenharmony_ci	return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3428c2ecf20Sopenharmony_ci}
3438c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_put_beep);
344