|
@@ -60,6 +60,8 @@ struct img_i2s_in {
|
|
void __iomem *channel_base;
|
|
void __iomem *channel_base;
|
|
unsigned int active_channels;
|
|
unsigned int active_channels;
|
|
struct snd_soc_dai_driver dai_driver;
|
|
struct snd_soc_dai_driver dai_driver;
|
|
|
|
+ u32 suspend_ctl;
|
|
|
|
+ u32 *suspend_ch_ctl;
|
|
};
|
|
};
|
|
|
|
|
|
static inline void img_i2s_in_writel(struct img_i2s_in *i2s, u32 val, u32 reg)
|
|
static inline void img_i2s_in_writel(struct img_i2s_in *i2s, u32 val, u32 reg)
|
|
@@ -469,6 +471,13 @@ static int img_i2s_in_probe(struct platform_device *pdev)
|
|
IMG_I2S_IN_CH_CTL_JUST_MASK |
|
|
IMG_I2S_IN_CH_CTL_JUST_MASK |
|
|
IMG_I2S_IN_CH_CTL_FW_MASK, IMG_I2S_IN_CH_CTL);
|
|
IMG_I2S_IN_CH_CTL_FW_MASK, IMG_I2S_IN_CH_CTL);
|
|
|
|
|
|
|
|
+ i2s->suspend_ch_ctl = devm_kzalloc(dev,
|
|
|
|
+ sizeof(*i2s->suspend_ch_ctl) * i2s->max_i2s_chan, GFP_KERNEL);
|
|
|
|
+ if (!i2s->suspend_ch_ctl) {
|
|
|
|
+ ret = -ENOMEM;
|
|
|
|
+ goto err_clk_disable;
|
|
|
|
+ }
|
|
|
|
+
|
|
ret = devm_snd_soc_register_component(dev, &img_i2s_in_component,
|
|
ret = devm_snd_soc_register_component(dev, &img_i2s_in_component,
|
|
&i2s->dai_driver, 1);
|
|
&i2s->dai_driver, 1);
|
|
if (ret)
|
|
if (ret)
|
|
@@ -495,16 +504,59 @@ static int img_i2s_in_dev_remove(struct platform_device *pdev)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifdef CONFIG_PM_SLEEP
|
|
|
|
+static int img_i2s_in_suspend(struct device *dev)
|
|
|
|
+{
|
|
|
|
+ struct img_i2s_in *i2s = dev_get_drvdata(dev);
|
|
|
|
+ int i;
|
|
|
|
+ u32 reg;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < i2s->max_i2s_chan; i++) {
|
|
|
|
+ reg = img_i2s_in_ch_readl(i2s, i, IMG_I2S_IN_CH_CTL);
|
|
|
|
+ i2s->suspend_ch_ctl[i] = reg;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ i2s->suspend_ctl = img_i2s_in_readl(i2s, IMG_I2S_IN_CTL);
|
|
|
|
+
|
|
|
|
+ clk_disable_unprepare(i2s->clk_sys);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int img_i2s_in_resume(struct device *dev)
|
|
|
|
+{
|
|
|
|
+ struct img_i2s_in *i2s = dev_get_drvdata(dev);
|
|
|
|
+ int i;
|
|
|
|
+ u32 reg;
|
|
|
|
+
|
|
|
|
+ clk_prepare_enable(i2s->clk_sys);
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < i2s->max_i2s_chan; i++) {
|
|
|
|
+ reg = i2s->suspend_ch_ctl[i];
|
|
|
|
+ img_i2s_in_ch_writel(i2s, i, reg, IMG_I2S_IN_CH_CTL);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ img_i2s_in_writel(i2s, i2s->suspend_ctl, IMG_I2S_IN_CTL);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+#endif
|
|
|
|
+
|
|
static const struct of_device_id img_i2s_in_of_match[] = {
|
|
static const struct of_device_id img_i2s_in_of_match[] = {
|
|
{ .compatible = "img,i2s-in" },
|
|
{ .compatible = "img,i2s-in" },
|
|
{}
|
|
{}
|
|
};
|
|
};
|
|
MODULE_DEVICE_TABLE(of, img_i2s_in_of_match);
|
|
MODULE_DEVICE_TABLE(of, img_i2s_in_of_match);
|
|
|
|
|
|
|
|
+static const struct dev_pm_ops img_i2s_in_pm_ops = {
|
|
|
|
+ SET_SYSTEM_SLEEP_PM_OPS(img_i2s_in_suspend, img_i2s_in_resume)
|
|
|
|
+};
|
|
|
|
+
|
|
static struct platform_driver img_i2s_in_driver = {
|
|
static struct platform_driver img_i2s_in_driver = {
|
|
.driver = {
|
|
.driver = {
|
|
.name = "img-i2s-in",
|
|
.name = "img-i2s-in",
|
|
- .of_match_table = img_i2s_in_of_match
|
|
|
|
|
|
+ .of_match_table = img_i2s_in_of_match,
|
|
|
|
+ .pm = &img_i2s_in_pm_ops
|
|
},
|
|
},
|
|
.probe = img_i2s_in_probe,
|
|
.probe = img_i2s_in_probe,
|
|
.remove = img_i2s_in_dev_remove
|
|
.remove = img_i2s_in_dev_remove
|