aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/sh/fsi.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 5a2fdf3b84b9..1029a03c618e 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -153,6 +153,13 @@ struct fsi_priv {
153 int clk_master:1; 153 int clk_master:1;
154 154
155 long rate; 155 long rate;
156
157 /* for suspend/resume */
158 u32 saved_do_fmt;
159 u32 saved_di_fmt;
160 u32 saved_ckg1;
161 u32 saved_ckg2;
162 u32 saved_out_sel;
156}; 163};
157 164
158struct fsi_core { 165struct fsi_core {
@@ -173,6 +180,13 @@ struct fsi_master {
173 struct fsi_core *core; 180 struct fsi_core *core;
174 struct sh_fsi_platform_info *info; 181 struct sh_fsi_platform_info *info;
175 spinlock_t lock; 182 spinlock_t lock;
183
184 /* for suspend/resume */
185 u32 saved_a_mclk;
186 u32 saved_b_mclk;
187 u32 saved_iemsk;
188 u32 saved_imsk;
189 u32 saved_clk_rst;
176}; 190};
177 191
178/* 192/*
@@ -1277,6 +1291,76 @@ static int fsi_remove(struct platform_device *pdev)
1277 return 0; 1291 return 0;
1278} 1292}
1279 1293
1294static void __fsi_suspend(struct fsi_priv *fsi,
1295 struct device *dev,
1296 set_rate_func set_rate)
1297{
1298 fsi->saved_do_fmt = fsi_reg_read(fsi, DO_FMT);
1299 fsi->saved_di_fmt = fsi_reg_read(fsi, DI_FMT);
1300 fsi->saved_ckg1 = fsi_reg_read(fsi, CKG1);
1301 fsi->saved_ckg2 = fsi_reg_read(fsi, CKG2);
1302 fsi->saved_out_sel = fsi_reg_read(fsi, OUT_SEL);
1303
1304 if (fsi_is_clk_master(fsi))
1305 set_rate(dev, fsi_is_port_a(fsi), fsi->rate, 0);
1306}
1307
1308static void __fsi_resume(struct fsi_priv *fsi,
1309 struct device *dev,
1310 set_rate_func set_rate)
1311{
1312 fsi_reg_write(fsi, DO_FMT, fsi->saved_do_fmt);
1313 fsi_reg_write(fsi, DI_FMT, fsi->saved_di_fmt);
1314 fsi_reg_write(fsi, CKG1, fsi->saved_ckg1);
1315 fsi_reg_write(fsi, CKG2, fsi->saved_ckg2);
1316 fsi_reg_write(fsi, OUT_SEL, fsi->saved_out_sel);
1317
1318 if (fsi_is_clk_master(fsi))
1319 set_rate(dev, fsi_is_port_a(fsi), fsi->rate, 1);
1320}
1321
1322static int fsi_suspend(struct device *dev)
1323{
1324 struct fsi_master *master = dev_get_drvdata(dev);
1325 set_rate_func set_rate = fsi_get_info_set_rate(master);
1326
1327 pm_runtime_get_sync(dev);
1328
1329 __fsi_suspend(&master->fsia, dev, set_rate);
1330 __fsi_suspend(&master->fsib, dev, set_rate);
1331
1332 master->saved_a_mclk = fsi_core_read(master, a_mclk);
1333 master->saved_b_mclk = fsi_core_read(master, b_mclk);
1334 master->saved_iemsk = fsi_core_read(master, iemsk);
1335 master->saved_imsk = fsi_core_read(master, imsk);
1336 master->saved_clk_rst = fsi_master_read(master, CLK_RST);
1337
1338 pm_runtime_put_sync(dev);
1339
1340 return 0;
1341}
1342
1343static int fsi_resume(struct device *dev)
1344{
1345 struct fsi_master *master = dev_get_drvdata(dev);
1346 set_rate_func set_rate = fsi_get_info_set_rate(master);
1347
1348 pm_runtime_get_sync(dev);
1349
1350 __fsi_resume(&master->fsia, dev, set_rate);
1351 __fsi_resume(&master->fsib, dev, set_rate);
1352
1353 fsi_core_mask_set(master, a_mclk, 0xffff, master->saved_a_mclk);
1354 fsi_core_mask_set(master, b_mclk, 0xffff, master->saved_b_mclk);
1355 fsi_core_mask_set(master, iemsk, 0xffff, master->saved_iemsk);
1356 fsi_core_mask_set(master, imsk, 0xffff, master->saved_imsk);
1357 fsi_master_mask_set(master, CLK_RST, 0xffff, master->saved_clk_rst);
1358
1359 pm_runtime_put_sync(dev);
1360
1361 return 0;
1362}
1363
1280static int fsi_runtime_nop(struct device *dev) 1364static int fsi_runtime_nop(struct device *dev)
1281{ 1365{
1282 /* Runtime PM callback shared between ->runtime_suspend() 1366 /* Runtime PM callback shared between ->runtime_suspend()
@@ -1290,6 +1374,8 @@ static int fsi_runtime_nop(struct device *dev)
1290} 1374}
1291 1375
1292static struct dev_pm_ops fsi_pm_ops = { 1376static struct dev_pm_ops fsi_pm_ops = {
1377 .suspend = fsi_suspend,
1378 .resume = fsi_resume,
1293 .runtime_suspend = fsi_runtime_nop, 1379 .runtime_suspend = fsi_runtime_nop,
1294 .runtime_resume = fsi_runtime_nop, 1380 .runtime_resume = fsi_runtime_nop,
1295}; 1381};