diff options
-rw-r--r-- | sound/soc/sh/fsi.c | 86 |
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 | ||
158 | struct fsi_core { | 165 | struct 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 | ||
1294 | static 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 | |||
1308 | static 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 | |||
1322 | static 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 | |||
1343 | static 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 | |||
1280 | static int fsi_runtime_nop(struct device *dev) | 1364 | static 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 | ||
1292 | static struct dev_pm_ops fsi_pm_ops = { | 1376 | static 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 | }; |