diff options
Diffstat (limited to 'sound/soc/sunxi')
-rw-r--r-- | sound/soc/sunxi/Kconfig | 1 | ||||
-rw-r--r-- | sound/soc/sunxi/sun4i-codec.c | 31 | ||||
-rw-r--r-- | sound/soc/sunxi/sun4i-i2s.c | 77 | ||||
-rw-r--r-- | sound/soc/sunxi/sun4i-spdif.c | 60 | ||||
-rw-r--r-- | sound/soc/sunxi/sun50i-codec-analog.c | 50 | ||||
-rw-r--r-- | sound/soc/sunxi/sun8i-codec-analog.c | 11 | ||||
-rw-r--r-- | sound/soc/sunxi/sun8i-codec.c | 11 |
7 files changed, 169 insertions, 72 deletions
diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig index 8134c3c94229..9cd7009cb570 100644 --- a/sound/soc/sunxi/Kconfig +++ b/sound/soc/sunxi/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only menu "Allwinner SoC Audio support" depends on ARCH_SUNXI || COMPILE_TEST diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 28d2f7713f8d..619073e7d972 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright 2014 Emilio López <emilio@elopez.com.ar> * Copyright 2014 Jon Smirl <jonsmirl@gmail.com> @@ -6,16 +7,6 @@ * Copyright 2016 Chen-Yu Tsai <wens@csie.org> * * Based on the Allwinner SDK driver, released under the GPL. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/init.h> @@ -1305,15 +1296,25 @@ static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev, { struct snd_soc_dai_link *link = devm_kzalloc(dev, sizeof(*link), GFP_KERNEL); - if (!link) + struct snd_soc_dai_link_component *dlc = devm_kzalloc(dev, + 3 * sizeof(*dlc), GFP_KERNEL); + if (!link || !dlc) return NULL; + link->cpus = &dlc[0]; + link->codecs = &dlc[1]; + link->platforms = &dlc[2]; + + link->num_cpus = 1; + link->num_codecs = 1; + link->num_platforms = 1; + link->name = "cdc"; link->stream_name = "CDC PCM"; - link->codec_dai_name = "Codec"; - link->cpu_dai_name = dev_name(dev); - link->codec_name = dev_name(dev); - link->platform_name = dev_name(dev); + link->codecs->dai_name = "Codec"; + link->cpus->dai_name = dev_name(dev); + link->codecs->name = dev_name(dev); + link->platforms->name = dev_name(dev); link->dai_fmt = SND_SOC_DAIFMT_I2S; *num_links = 1; diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index bc128e2a6096..9b2232908b65 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2015 Andrea Venturi * Andrea Venturi <be17068@iperbole.bo.it> * * Copyright (C) 2016 Maxime Ripard * Maxime Ripard <maxime.ripard@free-electrons.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. */ #include <linux/clk.h> @@ -118,6 +114,8 @@ #define SUN8I_I2S_RX_CHAN_SEL_REG 0x54 #define SUN8I_I2S_RX_CHAN_MAP_REG 0x58 +struct sun4i_i2s; + /** * struct sun4i_i2s_quirks - Differences between SoC variants. * @@ -131,7 +129,6 @@ * @sun4i_i2s_regmap: regmap config to use. * @mclk_offset: Value by which mclkdiv needs to be adjusted. * @bclk_offset: Value by which bclkdiv needs to be adjusted. - * @fmt_offset: Value by which wss and sr needs to be adjusted. * @field_clkdiv_mclk_en: regmap field to enable mclk output. * @field_fmt_wss: regmap field to set word select size. * @field_fmt_sr: regmap field to set sample resolution. @@ -154,7 +151,6 @@ struct sun4i_i2s_quirks { const struct regmap_config *sun4i_i2s_regmap; unsigned int mclk_offset; unsigned int bclk_offset; - unsigned int fmt_offset; /* Register fields for i2s */ struct reg_field field_clkdiv_mclk_en; @@ -167,6 +163,9 @@ struct sun4i_i2s_quirks { struct reg_field field_rxchanmap; struct reg_field field_txchansel; struct reg_field field_rxchansel; + + s8 (*get_sr)(const struct sun4i_i2s *, int); + s8 (*get_wss)(const struct sun4i_i2s *, int); }; struct sun4i_i2s { @@ -349,6 +348,39 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai, return 0; } +static s8 sun4i_i2s_get_sr(const struct sun4i_i2s *i2s, int width) +{ + if (width < 16 || width > 24) + return -EINVAL; + + if (width % 4) + return -EINVAL; + + return (width - 16) / 4; +} + +static s8 sun4i_i2s_get_wss(const struct sun4i_i2s *i2s, int width) +{ + if (width < 16 || width > 32) + return -EINVAL; + + if (width % 4) + return -EINVAL; + + return (width - 16) / 4; +} + +static s8 sun8i_i2s_get_sr_wss(const struct sun4i_i2s *i2s, int width) +{ + if (width % 4) + return -EINVAL; + + if (width < 8 || width > 32) + return -EINVAL; + + return (width - 8) / 4 + 1; +} + static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -400,22 +432,16 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, } i2s->playback_dma_data.addr_width = width; - switch (params_width(params)) { - case 16: - sr = 0; - wss = 0; - break; + sr = i2s->variant->get_sr(i2s, params_width(params)); + if (sr < 0) + return -EINVAL; - default: - dev_err(dai->dev, "Unsupported sample width: %d\n", - params_width(params)); + wss = i2s->variant->get_wss(i2s, params_width(params)); + if (wss < 0) return -EINVAL; - } - regmap_field_write(i2s->field_fmt_wss, - wss + i2s->variant->fmt_offset); - regmap_field_write(i2s->field_fmt_sr, - sr + i2s->variant->fmt_offset); + regmap_field_write(i2s->field_fmt_wss, wss); + regmap_field_write(i2s->field_fmt_sr, sr); return sun4i_i2s_set_clk_rate(dai, params_rate(params), params_width(params)); @@ -895,6 +921,8 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = { .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), + .get_sr = sun4i_i2s_get_sr, + .get_wss = sun4i_i2s_get_wss, }; static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { @@ -912,6 +940,8 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), + .get_sr = sun4i_i2s_get_sr, + .get_wss = sun4i_i2s_get_wss, }; static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = { @@ -929,6 +959,8 @@ static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = { .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), + .get_sr = sun8i_i2s_get_sr_wss, + .get_wss = sun8i_i2s_get_sr_wss, }; static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { @@ -937,7 +969,6 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { .sun4i_i2s_regmap = &sun8i_i2s_regmap_config, .mclk_offset = 1, .bclk_offset = 2, - .fmt_offset = 3, .has_fmt_set_lrck_period = true, .has_chcfg = true, .has_chsel_tx_chen = true, @@ -952,6 +983,8 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { .field_rxchanmap = REG_FIELD(SUN8I_I2S_RX_CHAN_MAP_REG, 0, 31), .field_txchansel = REG_FIELD(SUN8I_I2S_TX_CHAN_SEL_REG, 0, 2), .field_rxchansel = REG_FIELD(SUN8I_I2S_RX_CHAN_SEL_REG, 0, 2), + .get_sr = sun8i_i2s_get_sr_wss, + .get_wss = sun8i_i2s_get_sr_wss, }; static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { @@ -969,6 +1002,8 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), + .get_sr = sun8i_i2s_get_sr_wss, + .get_wss = sun8i_i2s_get_sr_wss, }; static int sun4i_i2s_init_regmap_fields(struct device *dev, diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c index b4af4aabead1..cbe598b0fb10 100644 --- a/sound/soc/sunxi/sun4i-spdif.c +++ b/sound/soc/sunxi/sun4i-spdif.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * ALSA SoC SPDIF Audio Layer * @@ -5,16 +6,6 @@ * Copyright 2015 Marcus Cooper <codekipper@gmail.com> * * Based on the Allwinner SDK driver, released under the GPL. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/clk.h> @@ -75,6 +66,18 @@ #define SUN4I_SPDIF_FCTL_RXOM(v) ((v) << 0) #define SUN4I_SPDIF_FCTL_RXOM_MASK GENMASK(1, 0) +#define SUN50I_H6_SPDIF_FCTL (0x14) + #define SUN50I_H6_SPDIF_FCTL_HUB_EN BIT(31) + #define SUN50I_H6_SPDIF_FCTL_FTX BIT(30) + #define SUN50I_H6_SPDIF_FCTL_FRX BIT(29) + #define SUN50I_H6_SPDIF_FCTL_TXTL(v) ((v) << 12) + #define SUN50I_H6_SPDIF_FCTL_TXTL_MASK GENMASK(19, 12) + #define SUN50I_H6_SPDIF_FCTL_RXTL(v) ((v) << 4) + #define SUN50I_H6_SPDIF_FCTL_RXTL_MASK GENMASK(10, 4) + #define SUN50I_H6_SPDIF_FCTL_TXIM BIT(2) + #define SUN50I_H6_SPDIF_FCTL_RXOM(v) ((v) << 0) + #define SUN50I_H6_SPDIF_FCTL_RXOM_MASK GENMASK(1, 0) + #define SUN4I_SPDIF_FSTA (0x18) #define SUN4I_SPDIF_FSTA_TXE BIT(14) #define SUN4I_SPDIF_FSTA_TXECNTSHT (8) @@ -161,6 +164,19 @@ #define SUN4I_SPDIF_SAMFREQ_176_4KHZ 0xc #define SUN4I_SPDIF_SAMFREQ_192KHZ 0xe +/** + * struct sun4i_spdif_quirks - Differences between SoC variants. + * + * @reg_dac_tx_data: TX FIFO offset for DMA config. + * @has_reset: SoC needs reset deasserted. + * @val_fctl_ftx: TX FIFO flush bitmask. + */ +struct sun4i_spdif_quirks { + unsigned int reg_dac_txdata; + bool has_reset; + unsigned int val_fctl_ftx; +}; + struct sun4i_spdif_dev { struct platform_device *pdev; struct clk *spdif_clk; @@ -169,16 +185,19 @@ struct sun4i_spdif_dev { struct snd_soc_dai_driver cpu_dai_drv; struct regmap *regmap; struct snd_dmaengine_dai_dma_data dma_params_tx; + const struct sun4i_spdif_quirks *quirks; }; static void sun4i_spdif_configure(struct sun4i_spdif_dev *host) { + const struct sun4i_spdif_quirks *quirks = host->quirks; + /* soft reset SPDIF */ regmap_write(host->regmap, SUN4I_SPDIF_CTL, SUN4I_SPDIF_CTL_RESET); /* flush TX FIFO */ regmap_update_bits(host->regmap, SUN4I_SPDIF_FCTL, - SUN4I_SPDIF_FCTL_FTX, SUN4I_SPDIF_FCTL_FTX); + quirks->val_fctl_ftx, quirks->val_fctl_ftx); /* clear TX counter */ regmap_write(host->regmap, SUN4I_SPDIF_TXCNT, 0); @@ -405,25 +424,29 @@ static struct snd_soc_dai_driver sun4i_spdif_dai = { .name = "spdif", }; -struct sun4i_spdif_quirks { - unsigned int reg_dac_txdata; /* TX FIFO offset for DMA config */ - bool has_reset; -}; - static const struct sun4i_spdif_quirks sun4i_a10_spdif_quirks = { .reg_dac_txdata = SUN4I_SPDIF_TXFIFO, + .val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX, }; static const struct sun4i_spdif_quirks sun6i_a31_spdif_quirks = { .reg_dac_txdata = SUN4I_SPDIF_TXFIFO, + .val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX, .has_reset = true, }; static const struct sun4i_spdif_quirks sun8i_h3_spdif_quirks = { .reg_dac_txdata = SUN8I_SPDIF_TXFIFO, + .val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX, .has_reset = true, }; +static const struct sun4i_spdif_quirks sun50i_h6_spdif_quirks = { + .reg_dac_txdata = SUN8I_SPDIF_TXFIFO, + .val_fctl_ftx = SUN50I_H6_SPDIF_FCTL_FTX, + .has_reset = true, +}; + static const struct of_device_id sun4i_spdif_of_match[] = { { .compatible = "allwinner,sun4i-a10-spdif", @@ -437,6 +460,10 @@ static const struct of_device_id sun4i_spdif_of_match[] = { .compatible = "allwinner,sun8i-h3-spdif", .data = &sun8i_h3_spdif_quirks, }, + { + .compatible = "allwinner,sun50i-h6-spdif", + .data = &sun50i_h6_spdif_quirks, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, sun4i_spdif_of_match); @@ -501,6 +528,7 @@ static int sun4i_spdif_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to determine the quirks to use\n"); return -ENODEV; } + host->quirks = quirks; host->regmap = devm_regmap_init_mmio(&pdev->dev, base, &sun4i_spdif_regmap_config); diff --git a/sound/soc/sunxi/sun50i-codec-analog.c b/sound/soc/sunxi/sun50i-codec-analog.c index d105c90c3706..6d1de565350e 100644 --- a/sound/soc/sunxi/sun50i-codec-analog.c +++ b/sound/soc/sunxi/sun50i-codec-analog.c @@ -49,6 +49,15 @@ #define SUN50I_ADDA_OR_MIX_CTRL_DACR 1 #define SUN50I_ADDA_OR_MIX_CTRL_DACL 0 +#define SUN50I_ADDA_EARPIECE_CTRL0 0x03 +#define SUN50I_ADDA_EARPIECE_CTRL0_EAR_RAMP_TIME 4 +#define SUN50I_ADDA_EARPIECE_CTRL0_ESPSR 0 + +#define SUN50I_ADDA_EARPIECE_CTRL1 0x04 +#define SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_EN 7 +#define SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_MUTE 6 +#define SUN50I_ADDA_EARPIECE_CTRL1_ESP_VOL 0 + #define SUN50I_ADDA_LINEOUT_CTRL0 0x05 #define SUN50I_ADDA_LINEOUT_CTRL0_LEN 7 #define SUN50I_ADDA_LINEOUT_CTRL0_REN 6 @@ -172,6 +181,10 @@ static const DECLARE_TLV_DB_RANGE(sun50i_codec_lineout_vol_scale, 2, 31, TLV_DB_SCALE_ITEM(-4350, 150, 0), ); +static const DECLARE_TLV_DB_RANGE(sun50i_codec_earpiece_vol_scale, + 0, 1, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), + 2, 31, TLV_DB_SCALE_ITEM(-4350, 150, 0), +); /* volume / mute controls */ static const struct snd_kcontrol_new sun50i_a64_codec_controls[] = { @@ -225,6 +238,15 @@ static const struct snd_kcontrol_new sun50i_a64_codec_controls[] = { SUN50I_ADDA_LINEOUT_CTRL0_LEN, SUN50I_ADDA_LINEOUT_CTRL0_REN, 1, 0), + SOC_SINGLE_TLV("Earpiece Playback Volume", + SUN50I_ADDA_EARPIECE_CTRL1, + SUN50I_ADDA_EARPIECE_CTRL1_ESP_VOL, 0x1f, 0, + sun50i_codec_earpiece_vol_scale), + + SOC_SINGLE("Earpiece Playback Switch", + SUN50I_ADDA_EARPIECE_CTRL1, + SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_MUTE, 1, 0), + }; static const char * const sun50i_codec_hp_src_enum_text[] = { @@ -257,6 +279,20 @@ static const struct snd_kcontrol_new sun50i_codec_lineout_src[] = { sun50i_codec_lineout_src_enum), }; +static const char * const sun50i_codec_earpiece_src_enum_text[] = { + "DACR", "DACL", "Right Mixer", "Left Mixer", +}; + +static SOC_ENUM_SINGLE_DECL(sun50i_codec_earpiece_src_enum, + SUN50I_ADDA_EARPIECE_CTRL0, + SUN50I_ADDA_EARPIECE_CTRL0_ESPSR, + sun50i_codec_earpiece_src_enum_text); + +static const struct snd_kcontrol_new sun50i_codec_earpiece_src[] = { + SOC_DAPM_ENUM("Earpiece Source Playback Route", + sun50i_codec_earpiece_src_enum), +}; + static const struct snd_soc_dapm_widget sun50i_a64_codec_widgets[] = { /* DAC */ SND_SOC_DAPM_DAC("Left DAC", NULL, SUN50I_ADDA_MIX_DAC_CTRL, @@ -285,6 +321,12 @@ static const struct snd_soc_dapm_widget sun50i_a64_codec_widgets[] = { SND_SOC_NOPM, 0, 0, sun50i_codec_lineout_src), SND_SOC_DAPM_OUTPUT("LINEOUT"), + SND_SOC_DAPM_MUX("Earpiece Source Playback Route", + SND_SOC_NOPM, 0, 0, sun50i_codec_earpiece_src), + SND_SOC_DAPM_OUT_DRV("Earpiece Amp", SUN50I_ADDA_EARPIECE_CTRL1, + SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_EN, 0, NULL, 0), + SND_SOC_DAPM_OUTPUT("EARPIECE"), + /* Microphone inputs */ SND_SOC_DAPM_INPUT("MIC1"), @@ -388,6 +430,14 @@ static const struct snd_soc_dapm_route sun50i_a64_codec_routes[] = { { "Line Out Source Playback Route", "Mono Differential", "Right Mixer" }, { "LINEOUT", NULL, "Line Out Source Playback Route" }, + + /* Earpiece Routes */ + { "Earpiece Source Playback Route", "DACL", "Left DAC" }, + { "Earpiece Source Playback Route", "DACR", "Right DAC" }, + { "Earpiece Source Playback Route", "Left Mixer", "Left Mixer" }, + { "Earpiece Source Playback Route", "Right Mixer", "Right Mixer" }, + { "Earpiece Amp", NULL, "Earpiece Source Playback Route" }, + { "EARPIECE", NULL, "Earpiece Amp" }, }; static const struct snd_soc_component_driver sun50i_codec_analog_cmpnt_drv = { diff --git a/sound/soc/sunxi/sun8i-codec-analog.c b/sound/soc/sunxi/sun8i-codec-analog.c index 916a46bbc1c8..e92aeedd6feb 100644 --- a/sound/soc/sunxi/sun8i-codec-analog.c +++ b/sound/soc/sunxi/sun8i-codec-analog.c @@ -1,18 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * This driver supports the analog controls for the internal codec * found in Allwinner's A31s, A23, A33 and H3 SoCs. * * Copyright 2016 Chen-Yu Tsai <wens@csie.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/io.h> diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 92c5de026c43..0e0e8ebaa571 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * This driver supports the digital controls for the internal codec * found in Allwinner's A33 SoCs. @@ -6,16 +7,6 @@ * Reuuimlla Technology Co., Ltd. <www.reuuimllatech.com> * huangxin <huangxin@Reuuimllatech.com> * Mylène Josserand <mylene.josserand@free-electrons.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/module.h> |