diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2015-09-15 04:26:36 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-09-17 07:33:08 -0400 |
commit | b07570628471777aabb5695284e1af4533e502da (patch) | |
tree | 8a0699b1be2d78e54da8687800edaeba2cf290ef /sound/soc/codecs/ak4613.c | |
parent | 6ff33f3902c3b1c5d0db6b1e2c70b6d76fba357f (diff) |
ASoC: add ak4613 support
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/codecs/ak4613.c')
-rw-r--r-- | sound/soc/codecs/ak4613.c | 469 |
1 files changed, 469 insertions, 0 deletions
diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c new file mode 100644 index 000000000000..fd96a8f9e2d3 --- /dev/null +++ b/sound/soc/codecs/ak4613.c | |||
@@ -0,0 +1,469 @@ | |||
1 | /* | ||
2 | * ak4613.c -- Asahi Kasei ALSA Soc Audio driver | ||
3 | * | ||
4 | * Copyright (C) 2015 Renesas Electronics Corporation | ||
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
6 | * | ||
7 | * Based on ak4642.c by Kuninori Morimoto | ||
8 | * Based on wm8731.c by Richard Purdie | ||
9 | * Based on ak4535.c by Richard Purdie | ||
10 | * Based on wm8753.c by Liam Girdwood | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | #include <linux/clk.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/of_device.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/regmap.h> | ||
23 | #include <sound/soc.h> | ||
24 | #include <sound/pcm_params.h> | ||
25 | |||
26 | #define PW_MGMT1 0x00 /* Power Management 1 */ | ||
27 | #define PW_MGMT2 0x01 /* Power Management 2 */ | ||
28 | #define PW_MGMT3 0x02 /* Power Management 3 */ | ||
29 | #define CTRL1 0x03 /* Control 1 */ | ||
30 | #define CTRL2 0x04 /* Control 2 */ | ||
31 | #define DEMP1 0x05 /* De-emphasis1 */ | ||
32 | #define DEMP2 0x06 /* De-emphasis2 */ | ||
33 | #define OFD 0x07 /* Overflow Detect */ | ||
34 | #define ZRD 0x08 /* Zero Detect */ | ||
35 | #define ICTRL 0x09 /* Input Control */ | ||
36 | #define OCTRL 0x0a /* Output Control */ | ||
37 | #define LOUT1 0x0b /* LOUT1 Volume Control */ | ||
38 | #define ROUT1 0x0c /* ROUT1 Volume Control */ | ||
39 | #define LOUT2 0x0d /* LOUT2 Volume Control */ | ||
40 | #define ROUT2 0x0e /* ROUT2 Volume Control */ | ||
41 | #define LOUT3 0x0f /* LOUT3 Volume Control */ | ||
42 | #define ROUT3 0x10 /* ROUT3 Volume Control */ | ||
43 | #define LOUT4 0x11 /* LOUT4 Volume Control */ | ||
44 | #define ROUT4 0x12 /* ROUT4 Volume Control */ | ||
45 | #define LOUT5 0x13 /* LOUT5 Volume Control */ | ||
46 | #define ROUT5 0x14 /* ROUT5 Volume Control */ | ||
47 | #define LOUT6 0x15 /* LOUT6 Volume Control */ | ||
48 | #define ROUT6 0x16 /* ROUT6 Volume Control */ | ||
49 | |||
50 | /* PW_MGMT1 */ | ||
51 | #define RSTN BIT(0) | ||
52 | #define PMDAC BIT(1) | ||
53 | #define PMADC BIT(2) | ||
54 | #define PMVR BIT(3) | ||
55 | |||
56 | /* PW_MGMT2 */ | ||
57 | #define PMAD_ALL 0x7 | ||
58 | |||
59 | /* PW_MGMT3 */ | ||
60 | #define PMDA_ALL 0x3f | ||
61 | |||
62 | /* CTRL1 */ | ||
63 | #define DIF0 BIT(3) | ||
64 | #define DIF1 BIT(4) | ||
65 | #define DIF2 BIT(5) | ||
66 | #define TDM0 BIT(6) | ||
67 | #define TDM1 BIT(7) | ||
68 | #define NO_FMT (0xff) | ||
69 | #define FMT_MASK (0xf8) | ||
70 | |||
71 | /* CTRL2 */ | ||
72 | #define DFS_NORMAL_SPEED (0 << 2) | ||
73 | #define DFS_DOUBLE_SPEED (1 << 2) | ||
74 | #define DFS_QUAD_SPEED (2 << 2) | ||
75 | |||
76 | struct ak4613_priv { | ||
77 | struct mutex lock; | ||
78 | |||
79 | unsigned int fmt; | ||
80 | u8 fmt_ctrl; | ||
81 | int cnt; | ||
82 | }; | ||
83 | |||
84 | struct ak4613_formats { | ||
85 | unsigned int width; | ||
86 | unsigned int fmt; | ||
87 | }; | ||
88 | |||
89 | struct ak4613_interface { | ||
90 | struct ak4613_formats capture; | ||
91 | struct ak4613_formats playback; | ||
92 | }; | ||
93 | |||
94 | static const struct reg_default ak4613_reg[] = { | ||
95 | { 0x0, 0x0f }, { 0x1, 0x07 }, { 0x2, 0x3f }, { 0x3, 0x20 }, | ||
96 | { 0x4, 0x20 }, { 0x5, 0x55 }, { 0x6, 0x05 }, { 0x7, 0x07 }, | ||
97 | { 0x8, 0x0f }, { 0x9, 0x07 }, { 0xa, 0x3f }, { 0xb, 0x00 }, | ||
98 | { 0xc, 0x00 }, { 0xd, 0x00 }, { 0xe, 0x00 }, { 0xf, 0x00 }, | ||
99 | { 0x10, 0x00 }, { 0x11, 0x00 }, { 0x12, 0x00 }, { 0x13, 0x00 }, | ||
100 | { 0x14, 0x00 }, { 0x15, 0x00 }, { 0x16, 0x00 }, | ||
101 | }; | ||
102 | |||
103 | #define AUDIO_IFACE_IDX_TO_VAL(i) (i << 3) | ||
104 | #define AUDIO_IFACE(b, fmt) { b, SND_SOC_DAIFMT_##fmt } | ||
105 | static const struct ak4613_interface ak4613_iface[] = { | ||
106 | /* capture */ /* playback */ | ||
107 | [0] = { AUDIO_IFACE(24, LEFT_J), AUDIO_IFACE(16, RIGHT_J) }, | ||
108 | [1] = { AUDIO_IFACE(24, LEFT_J), AUDIO_IFACE(20, RIGHT_J) }, | ||
109 | [2] = { AUDIO_IFACE(24, LEFT_J), AUDIO_IFACE(24, RIGHT_J) }, | ||
110 | [3] = { AUDIO_IFACE(24, LEFT_J), AUDIO_IFACE(24, LEFT_J) }, | ||
111 | [4] = { AUDIO_IFACE(24, I2S), AUDIO_IFACE(24, I2S) }, | ||
112 | }; | ||
113 | |||
114 | static const struct regmap_config ak4613_regmap_cfg = { | ||
115 | .reg_bits = 8, | ||
116 | .val_bits = 8, | ||
117 | .max_register = 0x16, | ||
118 | .reg_defaults = ak4613_reg, | ||
119 | .num_reg_defaults = ARRAY_SIZE(ak4613_reg), | ||
120 | }; | ||
121 | |||
122 | static const struct of_device_id ak4613_of_match[] = { | ||
123 | { .compatible = "asahi-kasei,ak4613", .data = &ak4613_regmap_cfg }, | ||
124 | {}, | ||
125 | }; | ||
126 | MODULE_DEVICE_TABLE(of, ak4613_of_match); | ||
127 | |||
128 | static const struct i2c_device_id ak4613_i2c_id[] = { | ||
129 | { "ak4613", (kernel_ulong_t)&ak4613_regmap_cfg }, | ||
130 | { } | ||
131 | }; | ||
132 | MODULE_DEVICE_TABLE(i2c, ak4613_i2c_id); | ||
133 | |||
134 | static const struct snd_soc_dapm_widget ak4613_dapm_widgets[] = { | ||
135 | |||
136 | /* Outputs */ | ||
137 | SND_SOC_DAPM_OUTPUT("LOUT1"), | ||
138 | SND_SOC_DAPM_OUTPUT("LOUT2"), | ||
139 | SND_SOC_DAPM_OUTPUT("LOUT3"), | ||
140 | SND_SOC_DAPM_OUTPUT("LOUT4"), | ||
141 | SND_SOC_DAPM_OUTPUT("LOUT5"), | ||
142 | SND_SOC_DAPM_OUTPUT("LOUT6"), | ||
143 | |||
144 | SND_SOC_DAPM_OUTPUT("ROUT1"), | ||
145 | SND_SOC_DAPM_OUTPUT("ROUT2"), | ||
146 | SND_SOC_DAPM_OUTPUT("ROUT3"), | ||
147 | SND_SOC_DAPM_OUTPUT("ROUT4"), | ||
148 | SND_SOC_DAPM_OUTPUT("ROUT5"), | ||
149 | SND_SOC_DAPM_OUTPUT("ROUT6"), | ||
150 | |||
151 | /* Inputs */ | ||
152 | SND_SOC_DAPM_INPUT("LIN1"), | ||
153 | SND_SOC_DAPM_INPUT("LIN2"), | ||
154 | |||
155 | SND_SOC_DAPM_INPUT("RIN1"), | ||
156 | SND_SOC_DAPM_INPUT("RIN2"), | ||
157 | |||
158 | /* DAC */ | ||
159 | SND_SOC_DAPM_DAC("DAC1", NULL, PW_MGMT3, 0, 0), | ||
160 | SND_SOC_DAPM_DAC("DAC2", NULL, PW_MGMT3, 1, 0), | ||
161 | SND_SOC_DAPM_DAC("DAC3", NULL, PW_MGMT3, 2, 0), | ||
162 | SND_SOC_DAPM_DAC("DAC4", NULL, PW_MGMT3, 3, 0), | ||
163 | SND_SOC_DAPM_DAC("DAC5", NULL, PW_MGMT3, 4, 0), | ||
164 | SND_SOC_DAPM_DAC("DAC6", NULL, PW_MGMT3, 5, 0), | ||
165 | |||
166 | /* ADC */ | ||
167 | SND_SOC_DAPM_ADC("ADC1", NULL, PW_MGMT2, 0, 0), | ||
168 | SND_SOC_DAPM_ADC("ADC2", NULL, PW_MGMT2, 1, 0), | ||
169 | }; | ||
170 | |||
171 | static const struct snd_soc_dapm_route ak4613_intercon[] = { | ||
172 | {"LOUT1", NULL, "DAC1"}, | ||
173 | {"LOUT2", NULL, "DAC2"}, | ||
174 | {"LOUT3", NULL, "DAC3"}, | ||
175 | {"LOUT4", NULL, "DAC4"}, | ||
176 | {"LOUT5", NULL, "DAC5"}, | ||
177 | {"LOUT6", NULL, "DAC6"}, | ||
178 | |||
179 | {"ROUT1", NULL, "DAC1"}, | ||
180 | {"ROUT2", NULL, "DAC2"}, | ||
181 | {"ROUT3", NULL, "DAC3"}, | ||
182 | {"ROUT4", NULL, "DAC4"}, | ||
183 | {"ROUT5", NULL, "DAC5"}, | ||
184 | {"ROUT6", NULL, "DAC6"}, | ||
185 | |||
186 | {"DAC1", NULL, "Playback"}, | ||
187 | {"DAC2", NULL, "Playback"}, | ||
188 | {"DAC3", NULL, "Playback"}, | ||
189 | {"DAC4", NULL, "Playback"}, | ||
190 | {"DAC5", NULL, "Playback"}, | ||
191 | {"DAC6", NULL, "Playback"}, | ||
192 | |||
193 | {"Capture", NULL, "ADC1"}, | ||
194 | {"Capture", NULL, "ADC2"}, | ||
195 | |||
196 | {"ADC1", NULL, "LIN1"}, | ||
197 | {"ADC2", NULL, "LIN2"}, | ||
198 | |||
199 | {"ADC1", NULL, "RIN1"}, | ||
200 | {"ADC2", NULL, "RIN2"}, | ||
201 | }; | ||
202 | |||
203 | static void ak4613_dai_shutdown(struct snd_pcm_substream *substream, | ||
204 | struct snd_soc_dai *dai) | ||
205 | { | ||
206 | struct snd_soc_codec *codec = dai->codec; | ||
207 | struct ak4613_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
208 | struct device *dev = codec->dev; | ||
209 | |||
210 | mutex_lock(&priv->lock); | ||
211 | priv->cnt--; | ||
212 | if (priv->cnt < 0) { | ||
213 | dev_err(dev, "unexpected counter error\n"); | ||
214 | priv->cnt = 0; | ||
215 | } | ||
216 | if (!priv->cnt) | ||
217 | priv->fmt_ctrl = NO_FMT; | ||
218 | mutex_unlock(&priv->lock); | ||
219 | } | ||
220 | |||
221 | static int ak4613_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
222 | { | ||
223 | struct snd_soc_codec *codec = dai->codec; | ||
224 | struct ak4613_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
225 | |||
226 | fmt &= SND_SOC_DAIFMT_FORMAT_MASK; | ||
227 | |||
228 | switch (fmt) { | ||
229 | case SND_SOC_DAIFMT_RIGHT_J: | ||
230 | case SND_SOC_DAIFMT_LEFT_J: | ||
231 | case SND_SOC_DAIFMT_I2S: | ||
232 | priv->fmt = fmt; | ||
233 | |||
234 | break; | ||
235 | default: | ||
236 | return -EINVAL; | ||
237 | } | ||
238 | |||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static int ak4613_dai_hw_params(struct snd_pcm_substream *substream, | ||
243 | struct snd_pcm_hw_params *params, | ||
244 | struct snd_soc_dai *dai) | ||
245 | { | ||
246 | struct snd_soc_codec *codec = dai->codec; | ||
247 | struct ak4613_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
248 | const struct ak4613_formats *fmts; | ||
249 | struct device *dev = codec->dev; | ||
250 | unsigned int width = params_width(params); | ||
251 | unsigned int fmt = priv->fmt; | ||
252 | unsigned int rate; | ||
253 | int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
254 | int i, ret; | ||
255 | u8 fmt_ctrl, ctrl2; | ||
256 | |||
257 | rate = params_rate(params); | ||
258 | switch (rate) { | ||
259 | case 32000: | ||
260 | case 44100: | ||
261 | case 48000: | ||
262 | ctrl2 = DFS_NORMAL_SPEED; | ||
263 | break; | ||
264 | case 88200: | ||
265 | case 96000: | ||
266 | ctrl2 = DFS_DOUBLE_SPEED; | ||
267 | break; | ||
268 | case 176400: | ||
269 | case 192000: | ||
270 | ctrl2 = DFS_QUAD_SPEED; | ||
271 | break; | ||
272 | default: | ||
273 | return -EINVAL; | ||
274 | } | ||
275 | |||
276 | /* | ||
277 | * FIXME | ||
278 | * | ||
279 | * It doesn't support TDM at this point | ||
280 | */ | ||
281 | fmt_ctrl = NO_FMT; | ||
282 | for (i = 0; i < ARRAY_SIZE(ak4613_iface); i++) { | ||
283 | fmts = (is_play) ? &ak4613_iface[i].playback : | ||
284 | &ak4613_iface[i].capture; | ||
285 | |||
286 | if (fmts->fmt != fmt) | ||
287 | continue; | ||
288 | |||
289 | if (fmt == SND_SOC_DAIFMT_RIGHT_J) { | ||
290 | if (fmts->width != width) | ||
291 | continue; | ||
292 | } else { | ||
293 | if (fmts->width < width) | ||
294 | continue; | ||
295 | } | ||
296 | |||
297 | fmt_ctrl = AUDIO_IFACE_IDX_TO_VAL(i); | ||
298 | break; | ||
299 | } | ||
300 | |||
301 | ret = -EINVAL; | ||
302 | if (fmt_ctrl == NO_FMT) | ||
303 | goto hw_params_end; | ||
304 | |||
305 | mutex_lock(&priv->lock); | ||
306 | if ((priv->fmt_ctrl == NO_FMT) || | ||
307 | (priv->fmt_ctrl == fmt_ctrl)) { | ||
308 | priv->fmt_ctrl = fmt_ctrl; | ||
309 | priv->cnt++; | ||
310 | ret = 0; | ||
311 | } | ||
312 | mutex_unlock(&priv->lock); | ||
313 | |||
314 | if (ret < 0) | ||
315 | goto hw_params_end; | ||
316 | |||
317 | snd_soc_update_bits(codec, CTRL1, FMT_MASK, fmt_ctrl); | ||
318 | snd_soc_write(codec, CTRL2, ctrl2); | ||
319 | |||
320 | hw_params_end: | ||
321 | if (ret < 0) | ||
322 | dev_warn(dev, "unsupported data width/format combination\n"); | ||
323 | |||
324 | return ret; | ||
325 | } | ||
326 | |||
327 | static int ak4613_set_bias_level(struct snd_soc_codec *codec, | ||
328 | enum snd_soc_bias_level level) | ||
329 | { | ||
330 | u8 mgmt1 = 0; | ||
331 | |||
332 | switch (level) { | ||
333 | case SND_SOC_BIAS_ON: | ||
334 | mgmt1 |= RSTN; | ||
335 | /* fall through */ | ||
336 | case SND_SOC_BIAS_PREPARE: | ||
337 | mgmt1 |= PMADC | PMDAC; | ||
338 | /* fall through */ | ||
339 | case SND_SOC_BIAS_STANDBY: | ||
340 | mgmt1 |= PMVR; | ||
341 | /* fall through */ | ||
342 | case SND_SOC_BIAS_OFF: | ||
343 | default: | ||
344 | break; | ||
345 | } | ||
346 | |||
347 | snd_soc_write(codec, PW_MGMT1, mgmt1); | ||
348 | |||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | static const struct snd_soc_dai_ops ak4613_dai_ops = { | ||
353 | .shutdown = ak4613_dai_shutdown, | ||
354 | .set_fmt = ak4613_dai_set_fmt, | ||
355 | .hw_params = ak4613_dai_hw_params, | ||
356 | }; | ||
357 | |||
358 | #define AK4613_PCM_RATE (SNDRV_PCM_RATE_32000 |\ | ||
359 | SNDRV_PCM_RATE_44100 |\ | ||
360 | SNDRV_PCM_RATE_48000 |\ | ||
361 | SNDRV_PCM_RATE_64000 |\ | ||
362 | SNDRV_PCM_RATE_88200 |\ | ||
363 | SNDRV_PCM_RATE_96000 |\ | ||
364 | SNDRV_PCM_RATE_176400 |\ | ||
365 | SNDRV_PCM_RATE_192000) | ||
366 | #define AK4613_PCM_FMTBIT (SNDRV_PCM_FMTBIT_S16_LE |\ | ||
367 | SNDRV_PCM_FMTBIT_S24_LE) | ||
368 | |||
369 | static struct snd_soc_dai_driver ak4613_dai = { | ||
370 | .name = "ak4613-hifi", | ||
371 | .playback = { | ||
372 | .stream_name = "Playback", | ||
373 | .channels_min = 2, | ||
374 | .channels_max = 2, | ||
375 | .rates = AK4613_PCM_RATE, | ||
376 | .formats = AK4613_PCM_FMTBIT, | ||
377 | }, | ||
378 | .capture = { | ||
379 | .stream_name = "Capture", | ||
380 | .channels_min = 2, | ||
381 | .channels_max = 2, | ||
382 | .rates = AK4613_PCM_RATE, | ||
383 | .formats = AK4613_PCM_FMTBIT, | ||
384 | }, | ||
385 | .ops = &ak4613_dai_ops, | ||
386 | .symmetric_rates = 1, | ||
387 | }; | ||
388 | |||
389 | static int ak4613_resume(struct snd_soc_codec *codec) | ||
390 | { | ||
391 | struct regmap *regmap = dev_get_regmap(codec->dev, NULL); | ||
392 | |||
393 | regcache_mark_dirty(regmap); | ||
394 | return regcache_sync(regmap); | ||
395 | } | ||
396 | |||
397 | static struct snd_soc_codec_driver soc_codec_dev_ak4613 = { | ||
398 | .resume = ak4613_resume, | ||
399 | .set_bias_level = ak4613_set_bias_level, | ||
400 | .dapm_widgets = ak4613_dapm_widgets, | ||
401 | .num_dapm_widgets = ARRAY_SIZE(ak4613_dapm_widgets), | ||
402 | .dapm_routes = ak4613_intercon, | ||
403 | .num_dapm_routes = ARRAY_SIZE(ak4613_intercon), | ||
404 | }; | ||
405 | |||
406 | static int ak4613_i2c_probe(struct i2c_client *i2c, | ||
407 | const struct i2c_device_id *id) | ||
408 | { | ||
409 | struct device *dev = &i2c->dev; | ||
410 | struct device_node *np = dev->of_node; | ||
411 | const struct regmap_config *regmap_cfg; | ||
412 | struct regmap *regmap; | ||
413 | struct ak4613_priv *priv; | ||
414 | |||
415 | regmap_cfg = NULL; | ||
416 | if (np) { | ||
417 | const struct of_device_id *of_id; | ||
418 | |||
419 | of_id = of_match_device(ak4613_of_match, dev); | ||
420 | if (of_id) | ||
421 | regmap_cfg = of_id->data; | ||
422 | } else { | ||
423 | regmap_cfg = (const struct regmap_config *)id->driver_data; | ||
424 | } | ||
425 | |||
426 | if (!regmap_cfg) | ||
427 | return -EINVAL; | ||
428 | |||
429 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
430 | if (!priv) | ||
431 | return -ENOMEM; | ||
432 | |||
433 | priv->fmt_ctrl = NO_FMT; | ||
434 | priv->cnt = 0; | ||
435 | |||
436 | mutex_init(&priv->lock); | ||
437 | |||
438 | i2c_set_clientdata(i2c, priv); | ||
439 | |||
440 | regmap = devm_regmap_init_i2c(i2c, regmap_cfg); | ||
441 | if (IS_ERR(regmap)) | ||
442 | return PTR_ERR(regmap); | ||
443 | |||
444 | return snd_soc_register_codec(dev, &soc_codec_dev_ak4613, | ||
445 | &ak4613_dai, 1); | ||
446 | } | ||
447 | |||
448 | static int ak4613_i2c_remove(struct i2c_client *client) | ||
449 | { | ||
450 | snd_soc_unregister_codec(&client->dev); | ||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | static struct i2c_driver ak4613_i2c_driver = { | ||
455 | .driver = { | ||
456 | .name = "ak4613-codec", | ||
457 | .owner = THIS_MODULE, | ||
458 | .of_match_table = ak4613_of_match, | ||
459 | }, | ||
460 | .probe = ak4613_i2c_probe, | ||
461 | .remove = ak4613_i2c_remove, | ||
462 | .id_table = ak4613_i2c_id, | ||
463 | }; | ||
464 | |||
465 | module_i2c_driver(ak4613_i2c_driver); | ||
466 | |||
467 | MODULE_DESCRIPTION("Soc AK4613 driver"); | ||
468 | MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); | ||
469 | MODULE_LICENSE("GPL v2"); | ||