1414#include <linux/clk.h>
1515#include <linux/dmaengine.h>
1616#include <linux/module.h>
17+ #include <linux/of_device.h>
1718#include <linux/platform_device.h>
1819#include <linux/pm_runtime.h>
1920#include <linux/regmap.h>
21+ #include <linux/reset.h>
2022
2123#include <sound/dmaengine_pcm.h>
2224#include <sound/pcm_params.h>
@@ -92,6 +94,7 @@ struct sun4i_i2s {
9294 struct clk * bus_clk ;
9395 struct clk * mod_clk ;
9496 struct regmap * regmap ;
97+ struct reset_control * rst ;
9598
9699 unsigned int mclk_freq ;
97100
@@ -651,9 +654,22 @@ static int sun4i_i2s_runtime_suspend(struct device *dev)
651654 return 0 ;
652655}
653656
657+ struct sun4i_i2s_quirks {
658+ bool has_reset ;
659+ };
660+
661+ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
662+ .has_reset = false,
663+ };
664+
665+ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
666+ .has_reset = true,
667+ };
668+
654669static int sun4i_i2s_probe (struct platform_device * pdev )
655670{
656671 struct sun4i_i2s * i2s ;
672+ const struct sun4i_i2s_quirks * quirks ;
657673 struct resource * res ;
658674 void __iomem * regs ;
659675 int irq , ret ;
@@ -674,6 +690,12 @@ static int sun4i_i2s_probe(struct platform_device *pdev)
674690 return irq ;
675691 }
676692
693+ quirks = of_device_get_match_data (& pdev -> dev );
694+ if (!quirks ) {
695+ dev_err (& pdev -> dev , "Failed to determine the quirks to use\n" );
696+ return - ENODEV ;
697+ }
698+
677699 i2s -> bus_clk = devm_clk_get (& pdev -> dev , "apb" );
678700 if (IS_ERR (i2s -> bus_clk )) {
679701 dev_err (& pdev -> dev , "Can't get our bus clock\n" );
@@ -692,7 +714,24 @@ static int sun4i_i2s_probe(struct platform_device *pdev)
692714 dev_err (& pdev -> dev , "Can't get our mod clock\n" );
693715 return PTR_ERR (i2s -> mod_clk );
694716 }
695-
717+
718+ if (quirks -> has_reset ) {
719+ i2s -> rst = devm_reset_control_get (& pdev -> dev , NULL );
720+ if (IS_ERR (i2s -> rst )) {
721+ dev_err (& pdev -> dev , "Failed to get reset control\n" );
722+ return PTR_ERR (i2s -> rst );
723+ }
724+ }
725+
726+ if (!IS_ERR (i2s -> rst )) {
727+ ret = reset_control_deassert (i2s -> rst );
728+ if (ret ) {
729+ dev_err (& pdev -> dev ,
730+ "Failed to deassert the reset control\n" );
731+ return - EINVAL ;
732+ }
733+ }
734+
696735 i2s -> playback_dma_data .addr = res -> start + SUN4I_I2S_FIFO_TX_REG ;
697736 i2s -> playback_dma_data .maxburst = 4 ;
698737
@@ -727,23 +766,37 @@ static int sun4i_i2s_probe(struct platform_device *pdev)
727766 sun4i_i2s_runtime_suspend (& pdev -> dev );
728767err_pm_disable :
729768 pm_runtime_disable (& pdev -> dev );
769+ if (!IS_ERR (i2s -> rst ))
770+ reset_control_assert (i2s -> rst );
730771
731772 return ret ;
732773}
733774
734775static int sun4i_i2s_remove (struct platform_device * pdev )
735776{
777+ struct sun4i_i2s * i2s = dev_get_drvdata (& pdev -> dev );
778+
736779 snd_dmaengine_pcm_unregister (& pdev -> dev );
737780
738781 pm_runtime_disable (& pdev -> dev );
739782 if (!pm_runtime_status_suspended (& pdev -> dev ))
740783 sun4i_i2s_runtime_suspend (& pdev -> dev );
741784
785+ if (!IS_ERR (i2s -> rst ))
786+ reset_control_assert (i2s -> rst );
787+
742788 return 0 ;
743789}
744790
745791static const struct of_device_id sun4i_i2s_match [] = {
746- { .compatible = "allwinner,sun4i-a10-i2s" , },
792+ {
793+ .compatible = "allwinner,sun4i-a10-i2s" ,
794+ .data = & sun4i_a10_i2s_quirks ,
795+ },
796+ {
797+ .compatible = "allwinner,sun6i-a31-i2s" ,
798+ .data = & sun6i_a31_i2s_quirks ,
799+ },
747800 {}
748801};
749802MODULE_DEVICE_TABLE (of , sun4i_i2s_match );
0 commit comments