[alsa-devel] [PATCH 00/11] enable imx6q_sabrelite sgtl5000 audio support
It's based on Dong Aisheng's early pinctrl patch and Sascha's v2 convert to common clk patch.
You can also get at: https://github.com/riczhao/kernel-imx/tree/topics/audio
Richard Zhao (11): dma: imx-sdma: make channel0 operations atomic ASoC: imx-sgtl5000: add of_node_put when probe fail. ASoC: fsl: add sgtl5000 clock support for imx-sgtl5000 i2c: imx: add pinctrl support ARM: imx6q: move imx6q_sabrelite specific code to a dedicated function ARM: dts: imx6q-sabrelite: add ssi device ARM: dts: imx6q-sabrelite: add audmux device ASoC: imx-audmux: add pinctrl support ARM: imx6q: add ssi1 clk_lookup ARM: imx6q_sabrelite: clkdev_add cko1 for sgtl5000 ARM: dts: imx6q-sabrelite: add sound device imx6q-sabrelite-sgtl5000
arch/arm/boot/dts/imx6q-sabrelite.dts | 30 ++++++++++++++++ arch/arm/boot/dts/imx6q.dtsi | 46 +++++++++++++++++++++++-- arch/arm/mach-imx/clk-imx6q.c | 4 ++ arch/arm/mach-imx/mach-imx6q.c | 37 +++++++++++++++++++- drivers/dma/imx-sdma.c | 57 ++++++++++++++++++------------- drivers/i2c/busses/i2c-imx.c | 9 +++++ sound/soc/fsl/imx-audmux.c | 8 ++++ sound/soc/fsl/imx-sgtl5000.c | 61 +++++++++++++++++++++++++-------- 8 files changed, 208 insertions(+), 44 deletions(-)
Thanks Richard
device_prep_dma_cyclic may be call in audio trigger function which is atomic context, so we make it atomic too.
- change channel0 lock to spinlock. - Use polling to wait for channel0 finish running.
Signed-off-by: Lothar Waßmann LW@KARO-electronics.de Signed-off-by: Richard Zhao richard.zhao@freescale.com --- drivers/dma/imx-sdma.c | 57 +++++++++++++++++++++++++++-------------------- 1 files changed, 33 insertions(+), 24 deletions(-)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index fddccae..fc49ffa 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -24,7 +24,7 @@ #include <linux/mm.h> #include <linux/interrupt.h> #include <linux/clk.h> -#include <linux/wait.h> +#include <linux/delay.h> #include <linux/sched.h> #include <linux/semaphore.h> #include <linux/spinlock.h> @@ -324,7 +324,7 @@ struct sdma_engine { struct dma_device dma_device; struct clk *clk_ipg; struct clk *clk_ahb; - struct mutex channel_0_lock; + spinlock_t channel_0_lock; struct sdma_script_start_addrs *script_addrs; };
@@ -402,19 +402,31 @@ static void sdma_enable_channel(struct sdma_engine *sdma, int channel) }
/* - * sdma_run_channel - run a channel and wait till it's done + * sdma_run_channel0 - run a channel and wait till it's done */ -static int sdma_run_channel(struct sdma_channel *sdmac) +static int sdma_run_channel0(struct sdma_channel *sdmac) { struct sdma_engine *sdma = sdmac->sdma; int channel = sdmac->channel; int ret; + unsigned long timeout = 500;
- init_completion(&sdmac->done); - + if (channel) + return -EINVAL; sdma_enable_channel(sdma, channel);
- ret = wait_for_completion_timeout(&sdmac->done, HZ); + while (!(ret = readl_relaxed(sdma->regs + SDMA_H_INTR) & 1)) { + if (timeout-- <= 0) + break; + udelay(1); + } + + if (ret) { + /* Clear the interrupt status */ + writel_relaxed(ret, sdma->regs + SDMA_H_INTR); + } else { + dev_err(sdma->dev, "Timeout waiting for CH0 ready\n"); + }
return ret ? 0 : -ETIMEDOUT; } @@ -426,17 +438,17 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size, void *buf_virt; dma_addr_t buf_phys; int ret; - - mutex_lock(&sdma->channel_0_lock); + unsigned long flags;
buf_virt = dma_alloc_coherent(NULL, size, &buf_phys, GFP_KERNEL); if (!buf_virt) { - ret = -ENOMEM; - goto err_out; + return -ENOMEM; }
+ spin_lock_irqsave(&sdma->channel_0_lock, flags); + bd0->mode.command = C0_SETPM; bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD; bd0->mode.count = size / 2; @@ -445,12 +457,11 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
memcpy(buf_virt, buf, size);
- ret = sdma_run_channel(&sdma->channel[0]); + ret = sdma_run_channel0(&sdma->channel[0]);
- dma_free_coherent(NULL, size, buf_virt, buf_phys); + spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
-err_out: - mutex_unlock(&sdma->channel_0_lock); + dma_free_coherent(NULL, size, buf_virt, buf_phys);
return ret; } @@ -539,10 +550,6 @@ static void mxc_sdma_handle_channel(struct sdma_channel *sdmac) { complete(&sdmac->done);
- /* not interested in channel 0 interrupts */ - if (sdmac->channel == 0) - return; - if (sdmac->flags & IMX_DMA_SG_LOOP) sdma_handle_channel_loop(sdmac); else @@ -555,6 +562,8 @@ static irqreturn_t sdma_int_handler(int irq, void *dev_id) unsigned long stat;
stat = readl_relaxed(sdma->regs + SDMA_H_INTR); + /* not interested in channel 0 interrupts */ + stat &= ~1; writel_relaxed(stat, sdma->regs + SDMA_H_INTR);
while (stat) { @@ -660,6 +669,7 @@ static int sdma_load_context(struct sdma_channel *sdmac) struct sdma_context_data *context = sdma->context; struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd; int ret; + unsigned long flags;
if (sdmac->direction == DMA_DEV_TO_MEM) { load_address = sdmac->pc_from_device; @@ -677,7 +687,7 @@ static int sdma_load_context(struct sdma_channel *sdmac) dev_dbg(sdma->dev, "event_mask0 = 0x%08x\n", (u32)sdmac->event_mask[0]); dev_dbg(sdma->dev, "event_mask1 = 0x%08x\n", (u32)sdmac->event_mask[1]);
- mutex_lock(&sdma->channel_0_lock); + spin_lock_irqsave(&sdma->channel_0_lock, flags);
memset(context, 0, sizeof(*context)); context->channel_state.pc = load_address; @@ -696,10 +706,9 @@ static int sdma_load_context(struct sdma_channel *sdmac) bd0->mode.count = sizeof(*context) / 4; bd0->buffer_addr = sdma->context_phys; bd0->ext_buffer_addr = 2048 + (sizeof(*context) / 4) * channel; + ret = sdma_run_channel0(&sdma->channel[0]);
- ret = sdma_run_channel(&sdma->channel[0]); - - mutex_unlock(&sdma->channel_0_lock); + spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
return ret; } @@ -1305,7 +1314,7 @@ static int __init sdma_probe(struct platform_device *pdev) if (!sdma) return -ENOMEM;
- mutex_init(&sdma->channel_0_lock); + spin_lock_init(&sdma->channel_0_lock);
sdma->dev = &pdev->dev;
Signed-off-by: Richard Zhao richard.zhao@freescale.com --- sound/soc/fsl/imx-sgtl5000.c | 29 ++++++++++++++++++----------- 1 files changed, 18 insertions(+), 11 deletions(-)
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index e1a7441..73b935e 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -103,24 +103,28 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0); if (!ssi_np || !codec_np) { dev_err(&pdev->dev, "phandle missing or invalid\n"); - return -EINVAL; + ret = -EINVAL; + goto fail; }
ssi_pdev = of_find_device_by_node(ssi_np); if (!ssi_pdev) { dev_err(&pdev->dev, "failed to find SSI platform device\n"); - return -EINVAL; + ret = -EINVAL; + goto fail; }
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; + if (!data) { + ret = -ENOMEM; + goto fail; + }
ret = of_property_read_u32(codec_np, "clock-frequency", &data->clk_frequency); if (ret) { dev_err(&pdev->dev, "clock-frequency missing or invalid\n"); - return ret; + goto fail; }
data->dai.name = "HiFi"; @@ -136,10 +140,10 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) data->card.dev = &pdev->dev; ret = snd_soc_of_parse_card_name(&data->card, "model"); if (ret) - return ret; + goto fail; ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing"); if (ret) - return ret; + goto fail; data->card.num_links = 1; data->card.dai_link = &data->dai; data->card.dapm_widgets = imx_sgtl5000_dapm_widgets; @@ -148,14 +152,17 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) ret = snd_soc_register_card(&data->card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); - return ret; + goto fail; }
platform_set_drvdata(pdev, data); - of_node_put(ssi_np); - of_node_put(codec_np); +fail: + if (ssi_np) + of_node_put(ssi_np); + if (codec_np) + of_node_put(codec_np);
- return 0; + return ret; }
static int __devexit imx_sgtl5000_remove(struct platform_device *pdev)
From: Richard Zhao richard.zhao@linaro.org
It tries to clk_get the clock. And if it failed, it assumes the clock by default enabled.
Signed-off-by: Richard Zhao richard.zhao@freescale.com --- sound/soc/fsl/imx-sgtl5000.c | 40 ++++++++++++++++++++++++++++++++-------- 1 files changed, 32 insertions(+), 8 deletions(-)
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index 73b935e..3a729ca 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -13,6 +13,8 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_platform.h> +#include <linux/of_i2c.h> +#include <linux/clk.h> #include <sound/soc.h>
#include "../codecs/sgtl5000.h" @@ -25,6 +27,7 @@ struct imx_sgtl5000_data { struct snd_soc_card card; char codec_dai_name[DAI_NAME_SIZE]; char platform_name[DAI_NAME_SIZE]; + struct clk *codec_clk; unsigned int clk_frequency; };
@@ -58,6 +61,7 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct device_node *ssi_np, *codec_np; struct platform_device *ssi_pdev; + struct i2c_client *codec_dev; struct imx_sgtl5000_data *data; int int_port, ext_port; int ret; @@ -113,6 +117,11 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) ret = -EINVAL; goto fail; } + codec_dev = of_find_i2c_device_by_node(codec_np); + if (!codec_dev) { + dev_err(&pdev->dev, "failed to find codec platform device\n"); + return -EINVAL; + }
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) { @@ -120,11 +129,20 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) goto fail; }
- ret = of_property_read_u32(codec_np, "clock-frequency", - &data->clk_frequency); - if (ret) { - dev_err(&pdev->dev, "clock-frequency missing or invalid\n"); - goto fail; + data->codec_clk = clk_get(&codec_dev->dev, NULL); + if (IS_ERR(data->codec_clk)) { + /* assuming clock enabled by default */ + data->codec_clk = NULL; + ret = of_property_read_u32(codec_np, "clock-frequency", + &data->clk_frequency); + if (ret) { + dev_err(&codec_dev->dev, + "clock-frequency missing or invalid\n"); + goto fail; + } + } else { + data->clk_frequency = clk_get_rate(data->codec_clk); + clk_prepare_enable(data->codec_clk); }
data->dai.name = "HiFi"; @@ -140,10 +158,10 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) data->card.dev = &pdev->dev; ret = snd_soc_of_parse_card_name(&data->card, "model"); if (ret) - goto fail; + goto clk_fail; ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing"); if (ret) - goto fail; + goto clk_fail; data->card.num_links = 1; data->card.dai_link = &data->dai; data->card.dapm_widgets = imx_sgtl5000_dapm_widgets; @@ -152,10 +170,12 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev) ret = snd_soc_register_card(&data->card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); - goto fail; + goto clk_fail; }
platform_set_drvdata(pdev, data); +clk_fail: + clk_put(data->codec_clk); fail: if (ssi_np) of_node_put(ssi_np); @@ -169,6 +189,10 @@ static int __devexit imx_sgtl5000_remove(struct platform_device *pdev) { struct imx_sgtl5000_data *data = platform_get_drvdata(pdev);
+ if (data->codec_clk) { + clk_disable_unprepare(data->codec_clk); + clk_put(data->codec_clk); + } snd_soc_unregister_card(&data->card);
return 0;
Signed-off-by: Richard Zhao richard.zhao@freescale.com --- arch/arm/boot/dts/imx6q-sabrelite.dts | 2 ++ arch/arm/boot/dts/imx6q.dtsi | 16 ++++++++++++++++ drivers/i2c/busses/i2c-imx.c | 9 +++++++++ 3 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts index 4663a4e..4e13293 100644 --- a/arch/arm/boot/dts/imx6q-sabrelite.dts +++ b/arch/arm/boot/dts/imx6q-sabrelite.dts @@ -50,6 +50,8 @@ i2c@021a0000 { /* I2C1 */ status = "okay"; clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1_1>;
codec: sgtl5000@0a { compatible = "fsl,sgtl5000"; diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index 2ba32e7..fe8c80d 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -390,6 +390,22 @@ reg = <0x020e0000 0x4000>;
/* shared pinctrl settings */ + i2c1 { + pinctrl_i2c1_1: i2c1grp-1 { + fsl,pins = "MX6Q_PAD_EIM_D21", + "MX6Q_PAD_EIM_D28"; + fsl,hysteresis = <1>; + fsl,mux = <0x16 0x11>; + fsl,pull = <2>; + fsl,pue = <1>; + fsl,pke = <1>; + fsl,open-drain = <1>; + fsl,speed = <2>; + fsl,drive-strength = <6>; + fsl,slew-rate = <1>; + }; + }; + uart4 { pinctrl_uart4_1: uart4grp-1 { fsl,pins = "MX6Q_PAD_KEY_COL0", diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index dfb84b7..7a52067 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -48,6 +48,7 @@ #include <linux/platform_device.h> #include <linux/clk.h> #include <linux/slab.h> +#include <linux/pinctrl/consumer.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/of_i2c.h> @@ -470,6 +471,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev) struct imx_i2c_struct *i2c_imx; struct resource *res; struct imxi2c_platform_data *pdata = pdev->dev.platform_data; + struct pinctrl *pct; void __iomem *base; resource_size_t res_size; int irq, bitrate; @@ -520,6 +522,13 @@ static int __init i2c_imx_probe(struct platform_device *pdev) i2c_imx->base = base; i2c_imx->res = res;
+ pct = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pct)) { + dev_err(&pdev->dev, "can't get/select pinctrl\n"); + ret = PTR_ERR(pct); + goto fail3; + } + /* Get I2C clock */ i2c_imx->clk = clk_get(&pdev->dev, "i2c_clk"); if (IS_ERR(i2c_imx->clk)) {
It'll be easier to add other board specific code.
Signed-off-by: Richard Zhao richard.zhao@freescale.com --- arch/arm/mach-imx/mach-imx6q.c | 9 +++++++-- 1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index da6c1d9..d25c5d8 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -75,11 +75,16 @@ static int ksz9021rn_phy_fixup(struct phy_device *phydev) return 0; }
+static void __init imx6q_sabrelite_init(void) +{ + phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK, + ksz9021rn_phy_fixup); +} + static void __init imx6q_init_machine(void) { if (of_machine_is_compatible("fsl,imx6q-sabrelite")) - phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK, - ksz9021rn_phy_fixup); + imx6q_sabrelite_init();
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
From: Richard Zhao richard.zhao@linaro.org
Signed-off-by: Richard Zhao richard.zhao@linaro.org Signed-off-by: Richard Zhao richard.zhao@freescale.com --- arch/arm/boot/dts/imx6q-sabrelite.dts | 9 +++++++++ arch/arm/boot/dts/imx6q.dtsi | 18 +++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts index 4e13293..7bd8855 100644 --- a/arch/arm/boot/dts/imx6q-sabrelite.dts +++ b/arch/arm/boot/dts/imx6q-sabrelite.dts @@ -22,6 +22,15 @@ };
soc { + aips-bus@02000000 { /* AIPS1 */ + spba-bus@02000000 { + ssi1: ssi@02028000 { + fsl,mode = "i2s-slave"; + status = "okay"; + }; + }; + }; + aips-bus@02100000 { /* AIPS2 */ enet@02188000 { phy-mode = "rgmii"; diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index fe8c80d..da42fc0 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -177,19 +177,31 @@ interrupts = <0 51 0x04>; };
- ssi@02028000 { /* SSI1 */ + ssi1: ssi@02028000 { + compatible = "fsl,imx6q-ssi","fsl,imx21-ssi"; reg = <0x02028000 0x4000>; interrupts = <0 46 0x04>; + fsl,fifo-depth = <15>; + fsl,ssi-dma-events = <38 37>; + status = "disabled"; };
- ssi@0202c000 { /* SSI2 */ + ssi2: ssi@0202c000 { + compatible = "fsl,imx6q-ssi","fsl,imx21-ssi"; reg = <0x0202c000 0x4000>; interrupts = <0 47 0x04>; + fsl,fifo-depth = <15>; + fsl,ssi-dma-events = <42 41>; + status = "disabled"; };
- ssi@02030000 { /* SSI3 */ + ssi3: ssi@02030000 { + compatible = "fsl,imx6q-ssi","fsl,imx21-ssi"; reg = <0x02030000 0x4000>; interrupts = <0 48 0x04>; + fsl,fifo-depth = <15>; + fsl,ssi-dma-events = <46 45>; + status = "disabled"; };
asrc@02034000 {
From: Richard Zhao richard.zhao@linaro.org
Signed-off-by: Richard Zhao richard.zhao@linaro.org Signed-off-by: Richard Zhao richard.zhao@freescale.com --- arch/arm/boot/dts/imx6q-sabrelite.dts | 3 +++ arch/arm/boot/dts/imx6q.dtsi | 2 ++ 2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts index 7bd8855..02f93bc 100644 --- a/arch/arm/boot/dts/imx6q-sabrelite.dts +++ b/arch/arm/boot/dts/imx6q-sabrelite.dts @@ -52,6 +52,9 @@ status = "okay"; };
+ audmux@021d8000 { + status = "okay"; + }; uart2: uart@021e8000 { status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index da42fc0..7bf402e 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -596,7 +596,9 @@ };
audmux@021d8000 { + compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux"; reg = <0x021d8000 0x4000>; + status = "disabled"; };
mipi@021dc000 { /* MIPI-CSI */
Signed-off-by: Richard Zhao richard.zhao@freescale.com --- arch/arm/boot/dts/imx6q-sabrelite.dts | 3 +++ arch/arm/boot/dts/imx6q.dtsi | 10 ++++++++++ sound/soc/fsl/imx-audmux.c | 8 ++++++++ 3 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts index 02f93bc..cdae2dd 100644 --- a/arch/arm/boot/dts/imx6q-sabrelite.dts +++ b/arch/arm/boot/dts/imx6q-sabrelite.dts @@ -54,7 +54,10 @@
audmux@021d8000 { status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audmux_1>; }; + uart2: uart@021e8000 { status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index 7bf402e..3c3004d 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -402,6 +402,16 @@ reg = <0x020e0000 0x4000>;
/* shared pinctrl settings */ + audmux { + pinctrl_audmux_1: audmux-1 { + fsl,pins = "MX6Q_PAD_SD2_DAT0", + "MX6Q_PAD_SD2_DAT3", + "MX6Q_PAD_SD2_DAT2", + "MX6Q_PAD_SD2_DAT1"; + fsl,mux = <3 3 3 3>; + }; + }; + i2c1 { pinctrl_i2c1_1: i2c1grp-1 { fsl,pins = "MX6Q_PAD_EIM_D21", diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index f237003..6c7dfc0 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -26,6 +26,7 @@ #include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/pinctrl/consumer.h>
#include "imx-audmux.h"
@@ -249,6 +250,7 @@ EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port); static int __devinit imx_audmux_probe(struct platform_device *pdev) { struct resource *res; + struct pinctrl *pct; const struct of_device_id *of_id = of_match_device(imx_audmux_dt_ids, &pdev->dev);
@@ -257,6 +259,12 @@ static int __devinit imx_audmux_probe(struct platform_device *pdev) if (!audmux_base) return -EADDRNOTAVAIL;
+ pct = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pct)) { + dev_err(&pdev->dev, "setup pinctrl failed!"); + return PTR_ERR(pct); + } + audmux_clk = clk_get(&pdev->dev, "audmux"); if (IS_ERR(audmux_clk)) { dev_dbg(&pdev->dev, "cannot get clock: %ld\n",
It's used by audio drivers.
Signed-off-by: Richard Zhao richard.zhao@freescale.com --- arch/arm/mach-imx/clk-imx6q.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index f40a35d..9a03dcc 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -418,6 +418,7 @@ int __init mx6q_clocks_init(void) clk_register_clkdev(clk[sdma], NULL, "20ec000.sdma"); clk_register_clkdev(clk[dummy], NULL, "20bc000.wdog"); clk_register_clkdev(clk[dummy], NULL, "20c0000.wdog"); + clk_register_clkdev(clk[ssi1], NULL, "2028000.ssi");
for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) { c = clk_get_sys(clks_init_on[i], NULL);
Signed-off-by: Richard Zhao richard.zhao@freescale.com --- arch/arm/mach-imx/clk-imx6q.c | 3 +++ arch/arm/mach-imx/mach-imx6q.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index 9a03dcc..4ea0de0 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -419,6 +419,9 @@ int __init mx6q_clocks_init(void) clk_register_clkdev(clk[dummy], NULL, "20bc000.wdog"); clk_register_clkdev(clk[dummy], NULL, "20c0000.wdog"); clk_register_clkdev(clk[ssi1], NULL, "2028000.ssi"); + clk_register_clkdev(clk[cko1_sel], "cko1_sel", NULL); + clk_register_clkdev(clk[ahb], "ahb", NULL); + clk_register_clkdev(clk[cko1], "cko1", NULL);
for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) { c = clk_get_sys(clks_init_on[i], NULL); diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index d25c5d8..e9b2522 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -10,6 +10,8 @@ * http://www.gnu.org/copyleft/gpl.html */
+#include <linux/clkdev.h> +#include <linux/clk.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/io.h> @@ -75,10 +77,36 @@ static int ksz9021rn_phy_fixup(struct phy_device *phydev) return 0; }
+static void __init imx6q_cko1_setup(void) +{ + struct clk *cko1_sel, *ahb, *cko1; + unsigned long rate; + + cko1_sel = clk_get_sys(NULL, "cko1_sel"); + ahb = clk_get_sys(NULL, "ahb"); + cko1 = clk_get_sys(NULL, "cko1"); + if (IS_ERR(cko1_sel) || IS_ERR(ahb) || IS_ERR(cko1)) { + printk(KERN_ERR "cko1 setup failed!\n"); + goto put_clk; + } + clk_set_parent(cko1_sel, ahb); + rate = clk_round_rate(cko1, 16000000); + clk_set_rate(cko1, rate); + clk_register_clkdev(cko1, NULL, "0-000a"); +put_clk: + if (!IS_ERR(cko1_sel)) + clk_put(cko1_sel); + if (!IS_ERR(ahb)) + clk_put(ahb); + if (!IS_ERR(cko1)) + clk_put(cko1); +} + static void __init imx6q_sabrelite_init(void) { phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK, ksz9021rn_phy_fixup); + imx6q_cko1_setup(); }
static void __init imx6q_init_machine(void)
From: Richard Zhao richard.zhao@linaro.org
Signed-off-by: Richard Zhao richard.zhao@linaro.org Signed-off-by: Richard Zhao richard.zhao@freescale.com --- arch/arm/boot/dts/imx6q-sabrelite.dts | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts index cdae2dd..20aa767 100644 --- a/arch/arm/boot/dts/imx6q-sabrelite.dts +++ b/arch/arm/boot/dts/imx6q-sabrelite.dts @@ -97,4 +97,17 @@ regulator-always-on; }; }; + + sound { + compatible = "fsl,imx6q-sabrelite-sgtl5000", + "fsl,imx-audio-sgtl5000"; + model = "imx6q-sabrelite-sgtl5000"; + ssi-controller = <&ssi1>; + audio-codec = <&codec>; + audio-routing = + "MIC_IN", "Mic Jack", + "Headphone Jack", "HP_OUT"; + mux-int-port = <1>; + mux-ext-port = <4>; + }; };
participants (1)
-
Richard Zhao