.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* sound/soc/rockchip/rk_spdif.c |
---|
2 | 3 | * |
---|
3 | 4 | * ALSA SoC Audio Layer - Rockchip I2S Controller driver |
---|
.. | .. |
---|
6 | 7 | * Author: Jianqun <jay.xu@rock-chips.com> |
---|
7 | 8 | * Copyright (c) 2015 Collabora Ltd. |
---|
8 | 9 | * Author: Sjoerd Simons <sjoerd.simons@collabora.co.uk> |
---|
9 | | - * |
---|
10 | | - * This program is free software; you can redistribute it and/or modify |
---|
11 | | - * it under the terms of the GNU General Public License version 2 as |
---|
12 | | - * published by the Free Software Foundation. |
---|
13 | 10 | */ |
---|
14 | 11 | |
---|
15 | 12 | #include <linux/module.h> |
---|
.. | .. |
---|
63 | 60 | struct regmap *regmap; |
---|
64 | 61 | }; |
---|
65 | 62 | |
---|
66 | | -static const struct of_device_id rk_spdif_match[] = { |
---|
| 63 | +static const struct of_device_id rk_spdif_match[] __maybe_unused = { |
---|
67 | 64 | { .compatible = "rockchip,rk3066-spdif", |
---|
68 | 65 | .data = (void *)RK_SPDIF_RK3066 }, |
---|
69 | 66 | { .compatible = "rockchip,rk3188-spdif", |
---|
.. | .. |
---|
81 | 78 | { .compatible = "rockchip,rk3399-spdif", |
---|
82 | 79 | .data = (void *)RK_SPDIF_RK3366 }, |
---|
83 | 80 | { .compatible = "rockchip,rk3568-spdif", |
---|
| 81 | + .data = (void *)RK_SPDIF_RK3366 }, |
---|
| 82 | + { .compatible = "rockchip,rk3588-spdif", |
---|
84 | 83 | .data = (void *)RK_SPDIF_RK3366 }, |
---|
85 | 84 | {}, |
---|
86 | 85 | }; |
---|
.. | .. |
---|
110 | 109 | |
---|
111 | 110 | ret = clk_prepare_enable(spdif->hclk); |
---|
112 | 111 | if (ret) { |
---|
| 112 | + clk_disable_unprepare(spdif->mclk); |
---|
113 | 113 | dev_err(spdif->dev, "hclk clock enable failed %d\n", ret); |
---|
114 | 114 | return ret; |
---|
115 | 115 | } |
---|
.. | .. |
---|
132 | 132 | { |
---|
133 | 133 | struct rk_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai); |
---|
134 | 134 | unsigned int val = SPDIF_CFGR_HALFWORD_ENABLE; |
---|
135 | | - int srate, mclk; |
---|
136 | | - int ret, i; |
---|
| 135 | + unsigned int mclk_rate = clk_get_rate(spdif->mclk); |
---|
| 136 | + int bmc, div, ret, i; |
---|
137 | 137 | u8 cs[CS_BYTE]; |
---|
138 | 138 | u16 *fc = (u16 *)cs; |
---|
139 | 139 | |
---|
.. | .. |
---|
147 | 147 | regmap_update_bits(spdif->regmap, SPDIF_CFGR, SPDIF_CFGR_CSE_MASK, |
---|
148 | 148 | SPDIF_CFGR_CSE_EN); |
---|
149 | 149 | |
---|
150 | | - srate = params_rate(params); |
---|
151 | | - mclk = srate * 128; |
---|
| 150 | + /* bmc = 128fs */ |
---|
| 151 | + bmc = 128 * params_rate(params); |
---|
| 152 | + div = DIV_ROUND_CLOSEST(mclk_rate, bmc); |
---|
| 153 | + val |= SPDIF_CFGR_CLK_DIV(div); |
---|
152 | 154 | |
---|
153 | 155 | switch (params_format(params)) { |
---|
154 | 156 | case SNDRV_PCM_FORMAT_S16_LE: |
---|
.. | .. |
---|
169 | 171 | return -EINVAL; |
---|
170 | 172 | } |
---|
171 | 173 | |
---|
172 | | - /* Set clock and calculate divider */ |
---|
173 | | - ret = clk_set_rate(spdif->mclk, mclk); |
---|
174 | | - if (ret != 0) { |
---|
175 | | - dev_err(spdif->dev, "Failed to set module clock rate: %d\n", |
---|
176 | | - ret); |
---|
177 | | - return ret; |
---|
178 | | - } |
---|
179 | | - |
---|
180 | 174 | regmap_update_bits(spdif->regmap, SPDIF_CFGR, SPDIF_CFGR_CLR_MASK, |
---|
181 | 175 | SPDIF_CFGR_CLR_EN); |
---|
| 176 | + |
---|
182 | 177 | udelay(1); |
---|
183 | 178 | ret = regmap_update_bits(spdif->regmap, SPDIF_CFGR, |
---|
184 | 179 | SPDIF_CFGR_CLK_DIV_MASK | |
---|
.. | .. |
---|
243 | 238 | return 0; |
---|
244 | 239 | } |
---|
245 | 240 | |
---|
| 241 | +static int rk_spdif_set_sysclk(struct snd_soc_dai *dai, |
---|
| 242 | + int clk_id, unsigned int freq, int dir) |
---|
| 243 | +{ |
---|
| 244 | + struct rk_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai); |
---|
| 245 | + int ret = 0; |
---|
| 246 | + |
---|
| 247 | + if (!freq) |
---|
| 248 | + return 0; |
---|
| 249 | + |
---|
| 250 | + ret = clk_set_rate(spdif->mclk, freq); |
---|
| 251 | + if (ret) |
---|
| 252 | + dev_err(spdif->dev, "Failed to set mclk: %d\n", ret); |
---|
| 253 | + |
---|
| 254 | + return ret; |
---|
| 255 | +} |
---|
| 256 | + |
---|
246 | 257 | static const struct snd_soc_dai_ops rk_spdif_dai_ops = { |
---|
| 258 | + .set_sysclk = rk_spdif_set_sysclk, |
---|
247 | 259 | .hw_params = rk_spdif_hw_params, |
---|
248 | 260 | .trigger = rk_spdif_trigger, |
---|
249 | 261 | }; |
---|
.. | .. |
---|
363 | 375 | if (IS_ERR(spdif->mclk)) |
---|
364 | 376 | return PTR_ERR(spdif->mclk); |
---|
365 | 377 | |
---|
366 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
367 | | - regs = devm_ioremap_resource(&pdev->dev, res); |
---|
| 378 | + regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); |
---|
368 | 379 | if (IS_ERR(regs)) |
---|
369 | 380 | return PTR_ERR(regs); |
---|
370 | 381 | |
---|