1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include <linux/module.h>
24#include <sound/core.h>
25#include <sound/initval.h>
26#include <sound/ac97_codec.h>
27
28#include "stk1160.h"
29#include "stk1160-reg.h"
30
31static struct snd_ac97 *stk1160_ac97;
32
33static void stk1160_write_ac97(struct snd_ac97 *ac97, u16 reg, u16 value)
34{
35 struct stk1160 *dev = ac97->private_data;
36
37
38 stk1160_write_reg(dev, STK1160_AC97_ADDR, reg);
39
40
41 stk1160_write_reg(dev, STK1160_AC97_CMD, value & 0xff);
42 stk1160_write_reg(dev, STK1160_AC97_CMD + 1, (value & 0xff00) >> 8);
43
44
45
46
47
48 stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8c);
49}
50
51static u16 stk1160_read_ac97(struct snd_ac97 *ac97, u16 reg)
52{
53 struct stk1160 *dev = ac97->private_data;
54 u8 vall = 0;
55 u8 valh = 0;
56
57
58 stk1160_write_reg(dev, STK1160_AC97_ADDR, reg);
59
60
61
62
63
64 stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8b);
65
66
67 stk1160_read_reg(dev, STK1160_AC97_CMD, &vall);
68 stk1160_read_reg(dev, STK1160_AC97_CMD + 1, &valh);
69
70 return (valh << 8) | vall;
71}
72
73static void stk1160_reset_ac97(struct snd_ac97 *ac97)
74{
75 struct stk1160 *dev = ac97->private_data;
76
77 stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x94);
78 stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x88);
79
80
81 stk1160_write_reg(dev, STK1160_AC97CTL_1 + 2, 0x01);
82}
83
84static struct snd_ac97_bus_ops stk1160_ac97_ops = {
85 .read = stk1160_read_ac97,
86 .write = stk1160_write_ac97,
87 .reset = stk1160_reset_ac97,
88};
89
90int stk1160_ac97_register(struct stk1160 *dev)
91{
92 struct snd_card *card = NULL;
93 struct snd_ac97_bus *ac97_bus;
94 struct snd_ac97_template ac97_template;
95 int rc;
96
97
98
99
100
101 rc = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
102 THIS_MODULE, 0, &card);
103 if (rc < 0)
104 return rc;
105
106 snd_card_set_dev(card, dev->dev);
107
108
109 snprintf(card->shortname, sizeof(card->shortname),
110 "stk1160-mixer");
111 snprintf(card->longname, sizeof(card->longname),
112 "stk1160 ac97 codec mixer control");
113 strncpy(card->driver, dev->dev->driver->name, sizeof(card->driver));
114
115 rc = snd_ac97_bus(card, 0, &stk1160_ac97_ops, NULL, &ac97_bus);
116 if (rc)
117 goto err;
118
119
120 memset(&ac97_template, 0, sizeof(ac97_template));
121 ac97_template.private_data = dev;
122 ac97_template.scaps = AC97_SCAP_SKIP_MODEM;
123 rc = snd_ac97_mixer(ac97_bus, &ac97_template, &stk1160_ac97);
124 if (rc)
125 goto err;
126
127 dev->snd_card = card;
128 rc = snd_card_register(card);
129 if (rc)
130 goto err;
131
132 return 0;
133
134err:
135 dev->snd_card = NULL;
136 snd_card_free(card);
137 return rc;
138}
139
140int stk1160_ac97_unregister(struct stk1160 *dev)
141{
142 struct snd_card *card = dev->snd_card;
143
144
145
146
147
148 if (card && dev->udev)
149 snd_card_free(card);
150
151 return 0;
152}
153