diff options
Diffstat (limited to 'sound/pci/hda/hda_beep.c')
| -rw-r--r-- | sound/pci/hda/hda_beep.c | 33 |
1 files changed, 18 insertions, 15 deletions
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 1e7de08e77cb..4cdac3a71cae 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c | |||
| @@ -33,30 +33,36 @@ enum { | |||
| 33 | DIGBEEP_HZ_MAX = 12000000, /* 12 KHz */ | 33 | DIGBEEP_HZ_MAX = 12000000, /* 12 KHz */ |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | static void snd_hda_generate_beep(struct work_struct *work) | 36 | /* generate or stop tone */ |
| 37 | static void generate_tone(struct hda_beep *beep, int tone) | ||
| 37 | { | 38 | { |
| 38 | struct hda_beep *beep = | ||
| 39 | container_of(work, struct hda_beep, beep_work); | ||
| 40 | struct hda_codec *codec = beep->codec; | 39 | struct hda_codec *codec = beep->codec; |
| 41 | int tone; | ||
| 42 | 40 | ||
| 43 | if (!beep->enabled) | ||
| 44 | return; | ||
| 45 | |||
| 46 | tone = beep->tone; | ||
| 47 | if (tone && !beep->playing) { | 41 | if (tone && !beep->playing) { |
| 48 | snd_hda_power_up(codec); | 42 | snd_hda_power_up(codec); |
| 43 | if (beep->power_hook) | ||
| 44 | beep->power_hook(beep, true); | ||
| 49 | beep->playing = 1; | 45 | beep->playing = 1; |
| 50 | } | 46 | } |
| 51 | /* generate tone */ | ||
| 52 | snd_hda_codec_write(codec, beep->nid, 0, | 47 | snd_hda_codec_write(codec, beep->nid, 0, |
| 53 | AC_VERB_SET_BEEP_CONTROL, tone); | 48 | AC_VERB_SET_BEEP_CONTROL, tone); |
| 54 | if (!tone && beep->playing) { | 49 | if (!tone && beep->playing) { |
| 55 | beep->playing = 0; | 50 | beep->playing = 0; |
| 51 | if (beep->power_hook) | ||
| 52 | beep->power_hook(beep, false); | ||
| 56 | snd_hda_power_down(codec); | 53 | snd_hda_power_down(codec); |
| 57 | } | 54 | } |
| 58 | } | 55 | } |
| 59 | 56 | ||
| 57 | static void snd_hda_generate_beep(struct work_struct *work) | ||
| 58 | { | ||
| 59 | struct hda_beep *beep = | ||
| 60 | container_of(work, struct hda_beep, beep_work); | ||
| 61 | |||
| 62 | if (beep->enabled) | ||
| 63 | generate_tone(beep, beep->tone); | ||
| 64 | } | ||
| 65 | |||
| 60 | /* (non-standard) Linear beep tone calculation for IDT/STAC codecs | 66 | /* (non-standard) Linear beep tone calculation for IDT/STAC codecs |
| 61 | * | 67 | * |
| 62 | * The tone frequency of beep generator on IDT/STAC codecs is | 68 | * The tone frequency of beep generator on IDT/STAC codecs is |
| @@ -130,10 +136,7 @@ static void turn_off_beep(struct hda_beep *beep) | |||
| 130 | cancel_work_sync(&beep->beep_work); | 136 | cancel_work_sync(&beep->beep_work); |
| 131 | if (beep->playing) { | 137 | if (beep->playing) { |
| 132 | /* turn off beep */ | 138 | /* turn off beep */ |
| 133 | snd_hda_codec_write(beep->codec, beep->nid, 0, | 139 | generate_tone(beep, 0); |
| 134 | AC_VERB_SET_BEEP_CONTROL, 0); | ||
| 135 | beep->playing = 0; | ||
| 136 | snd_hda_power_down(beep->codec); | ||
| 137 | } | 140 | } |
| 138 | } | 141 | } |
| 139 | 142 | ||
| @@ -160,6 +163,7 @@ static int snd_hda_do_attach(struct hda_beep *beep) | |||
| 160 | input_dev->name = "HDA Digital PCBeep"; | 163 | input_dev->name = "HDA Digital PCBeep"; |
| 161 | input_dev->phys = beep->phys; | 164 | input_dev->phys = beep->phys; |
| 162 | input_dev->id.bustype = BUS_PCI; | 165 | input_dev->id.bustype = BUS_PCI; |
| 166 | input_dev->dev.parent = &codec->card->card_dev; | ||
| 163 | 167 | ||
| 164 | input_dev->id.vendor = codec->vendor_id >> 16; | 168 | input_dev->id.vendor = codec->vendor_id >> 16; |
| 165 | input_dev->id.product = codec->vendor_id & 0xffff; | 169 | input_dev->id.product = codec->vendor_id & 0xffff; |
| @@ -168,7 +172,6 @@ static int snd_hda_do_attach(struct hda_beep *beep) | |||
| 168 | input_dev->evbit[0] = BIT_MASK(EV_SND); | 172 | input_dev->evbit[0] = BIT_MASK(EV_SND); |
| 169 | input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); | 173 | input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); |
| 170 | input_dev->event = snd_hda_beep_event; | 174 | input_dev->event = snd_hda_beep_event; |
| 171 | input_dev->dev.parent = &codec->dev; | ||
| 172 | input_set_drvdata(input_dev, beep); | 175 | input_set_drvdata(input_dev, beep); |
| 173 | 176 | ||
| 174 | beep->dev = input_dev; | 177 | beep->dev = input_dev; |
| @@ -224,7 +227,7 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) | |||
| 224 | if (beep == NULL) | 227 | if (beep == NULL) |
| 225 | return -ENOMEM; | 228 | return -ENOMEM; |
| 226 | snprintf(beep->phys, sizeof(beep->phys), | 229 | snprintf(beep->phys, sizeof(beep->phys), |
| 227 | "card%d/codec#%d/beep0", codec->bus->card->number, codec->addr); | 230 | "card%d/codec#%d/beep0", codec->card->number, codec->addr); |
| 228 | /* enable linear scale */ | 231 | /* enable linear scale */ |
| 229 | snd_hda_codec_write_cache(codec, nid, 0, | 232 | snd_hda_codec_write_cache(codec, nid, 0, |
| 230 | AC_VERB_SET_DIGI_CONVERT_2, 0x01); | 233 | AC_VERB_SET_DIGI_CONVERT_2, 0x01); |
