Commit 9e13f345 authored by Fabio Estevam's avatar Fabio Estevam Committed by Mark Brown

ASoC: sgtl5000: Let the codec acquire its clock

On a mx6qsabrelite board the following error happens on probe:

sgtl5000: probe of 0-000a failed with error -5
imx-sgtl5000 sound.13: ASoC: CODEC (null) not registered
imx-sgtl5000 sound.13: snd_soc_register_card failed (-517)
platform sound.13: Driver imx-sgtl5000 requests probe defer

Prior to reading the codec ID we need to turn the SYS_MCLK clock, so let's
enable the codec clock inside sgtl5000_i2c_probe().

Also remove the codec clock enable/disable functions from the machine driver.
Signed-off-by: default avatarFabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: default avatarMark Brown <broonie@linaro.org>
parent 915b2c75
...@@ -114,6 +114,7 @@ struct sgtl5000_priv { ...@@ -114,6 +114,7 @@ struct sgtl5000_priv {
struct regulator_bulk_data supplies[SGTL5000_SUPPLY_NUM]; struct regulator_bulk_data supplies[SGTL5000_SUPPLY_NUM];
struct ldo_regulator *ldo; struct ldo_regulator *ldo;
struct regmap *regmap; struct regmap *regmap;
struct clk *mclk;
}; };
/* /*
...@@ -1522,16 +1523,28 @@ static int sgtl5000_i2c_probe(struct i2c_client *client, ...@@ -1522,16 +1523,28 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
return ret; return ret;
} }
sgtl5000->mclk = devm_clk_get(&client->dev, NULL);
if (IS_ERR(sgtl5000->mclk)) {
ret = PTR_ERR(sgtl5000->mclk);
dev_err(&client->dev, "Failed to get mclock: %d\n", ret);
return ret;
}
ret = clk_prepare_enable(sgtl5000->mclk);
if (ret)
return ret;
/* read chip information */ /* read chip information */
ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ID, &reg); ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ID, &reg);
if (ret) if (ret)
return ret; goto disable_clk;
if (((reg & SGTL5000_PARTID_MASK) >> SGTL5000_PARTID_SHIFT) != if (((reg & SGTL5000_PARTID_MASK) >> SGTL5000_PARTID_SHIFT) !=
SGTL5000_PARTID_PART_ID) { SGTL5000_PARTID_PART_ID) {
dev_err(&client->dev, dev_err(&client->dev,
"Device with ID register %x is not a sgtl5000\n", reg); "Device with ID register %x is not a sgtl5000\n", reg);
return -ENODEV; ret = -ENODEV;
goto disable_clk;
} }
rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT; rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT;
...@@ -1542,17 +1555,30 @@ static int sgtl5000_i2c_probe(struct i2c_client *client, ...@@ -1542,17 +1555,30 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
/* Ensure sgtl5000 will start with sane register values */ /* Ensure sgtl5000 will start with sane register values */
ret = sgtl5000_fill_defaults(sgtl5000); ret = sgtl5000_fill_defaults(sgtl5000);
if (ret) if (ret)
return ret; goto disable_clk;
ret = snd_soc_register_codec(&client->dev, ret = snd_soc_register_codec(&client->dev,
&sgtl5000_driver, &sgtl5000_dai, 1); &sgtl5000_driver, &sgtl5000_dai, 1);
if (ret)
goto disable_clk;
return 0;
disable_clk:
clk_disable_unprepare(sgtl5000->mclk);
return ret; return ret;
} }
static int sgtl5000_i2c_remove(struct i2c_client *client) static int sgtl5000_i2c_remove(struct i2c_client *client)
{ {
snd_soc_unregister_codec(&client->dev); struct sgtl5000_priv *sgtl5000;
sgtl5000 = devm_kzalloc(&client->dev, sizeof(struct sgtl5000_priv),
GFP_KERNEL);
if (!sgtl5000)
return -ENOMEM;
snd_soc_unregister_codec(&client->dev);
clk_disable_unprepare(sgtl5000->mclk);
return 0; return 0;
} }
......
...@@ -129,20 +129,10 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) ...@@ -129,20 +129,10 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
} }
data->codec_clk = clk_get(&codec_dev->dev, NULL); data->codec_clk = clk_get(&codec_dev->dev, NULL);
if (IS_ERR(data->codec_clk)) { if (IS_ERR(data->codec_clk))
/* assuming clock enabled by default */ goto fail;
data->codec_clk = NULL;
ret = of_property_read_u32(codec_np, "clock-frequency", data->clk_frequency = clk_get_rate(data->codec_clk);
&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"; data->dai.name = "HiFi";
data->dai.stream_name = "HiFi"; data->dai.stream_name = "HiFi";
...@@ -157,10 +147,10 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) ...@@ -157,10 +147,10 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
data->card.dev = &pdev->dev; data->card.dev = &pdev->dev;
ret = snd_soc_of_parse_card_name(&data->card, "model"); ret = snd_soc_of_parse_card_name(&data->card, "model");
if (ret) if (ret)
goto clk_fail; goto fail;
ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing"); ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing");
if (ret) if (ret)
goto clk_fail; goto fail;
data->card.num_links = 1; data->card.num_links = 1;
data->card.owner = THIS_MODULE; data->card.owner = THIS_MODULE;
data->card.dai_link = &data->dai; data->card.dai_link = &data->dai;
...@@ -170,7 +160,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) ...@@ -170,7 +160,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
ret = snd_soc_register_card(&data->card); ret = snd_soc_register_card(&data->card);
if (ret) { if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
goto clk_fail; goto fail;
} }
platform_set_drvdata(pdev, data); platform_set_drvdata(pdev, data);
...@@ -179,8 +169,6 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) ...@@ -179,8 +169,6 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
return 0; return 0;
clk_fail:
clk_put(data->codec_clk);
fail: fail:
if (ssi_np) if (ssi_np)
of_node_put(ssi_np); of_node_put(ssi_np);
...@@ -194,10 +182,6 @@ static int imx_sgtl5000_remove(struct platform_device *pdev) ...@@ -194,10 +182,6 @@ static int imx_sgtl5000_remove(struct platform_device *pdev)
{ {
struct imx_sgtl5000_data *data = platform_get_drvdata(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); snd_soc_unregister_card(&data->card);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment