| .. | .. |
|---|
| 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 | }; |
|---|
| .. | .. |
|---|
| 132 | 131 | { |
|---|
| 133 | 132 | struct rk_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai); |
|---|
| 134 | 133 | unsigned int val = SPDIF_CFGR_HALFWORD_ENABLE; |
|---|
| 135 | | - int srate, mclk; |
|---|
| 136 | | - int ret, i; |
|---|
| 134 | + unsigned int mclk_rate = clk_get_rate(spdif->mclk); |
|---|
| 135 | + int bmc, div, ret, i; |
|---|
| 137 | 136 | u8 cs[CS_BYTE]; |
|---|
| 138 | 137 | u16 *fc = (u16 *)cs; |
|---|
| 139 | 138 | |
|---|
| .. | .. |
|---|
| 147 | 146 | regmap_update_bits(spdif->regmap, SPDIF_CFGR, SPDIF_CFGR_CSE_MASK, |
|---|
| 148 | 147 | SPDIF_CFGR_CSE_EN); |
|---|
| 149 | 148 | |
|---|
| 150 | | - srate = params_rate(params); |
|---|
| 151 | | - mclk = srate * 128; |
|---|
| 149 | + /* bmc = 128fs */ |
|---|
| 150 | + bmc = 128 * params_rate(params); |
|---|
| 151 | + div = DIV_ROUND_CLOSEST(mclk_rate, bmc); |
|---|
| 152 | + val |= SPDIF_CFGR_CLK_DIV(div); |
|---|
| 152 | 153 | |
|---|
| 153 | 154 | switch (params_format(params)) { |
|---|
| 154 | 155 | case SNDRV_PCM_FORMAT_S16_LE: |
|---|
| .. | .. |
|---|
| 169 | 170 | return -EINVAL; |
|---|
| 170 | 171 | } |
|---|
| 171 | 172 | |
|---|
| 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 | 173 | regmap_update_bits(spdif->regmap, SPDIF_CFGR, SPDIF_CFGR_CLR_MASK, |
|---|
| 181 | 174 | SPDIF_CFGR_CLR_EN); |
|---|
| 175 | + |
|---|
| 182 | 176 | udelay(1); |
|---|
| 183 | 177 | ret = regmap_update_bits(spdif->regmap, SPDIF_CFGR, |
|---|
| 184 | 178 | SPDIF_CFGR_CLK_DIV_MASK | |
|---|
| .. | .. |
|---|
| 243 | 237 | return 0; |
|---|
| 244 | 238 | } |
|---|
| 245 | 239 | |
|---|
| 240 | +static int rk_spdif_set_sysclk(struct snd_soc_dai *dai, |
|---|
| 241 | + int clk_id, unsigned int freq, int dir) |
|---|
| 242 | +{ |
|---|
| 243 | + struct rk_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai); |
|---|
| 244 | + int ret = 0; |
|---|
| 245 | + |
|---|
| 246 | + if (!freq) |
|---|
| 247 | + return 0; |
|---|
| 248 | + |
|---|
| 249 | + ret = clk_set_rate(spdif->mclk, freq); |
|---|
| 250 | + if (ret) |
|---|
| 251 | + dev_err(spdif->dev, "Failed to set mclk: %d\n", ret); |
|---|
| 252 | + |
|---|
| 253 | + return ret; |
|---|
| 254 | +} |
|---|
| 255 | + |
|---|
| 246 | 256 | static const struct snd_soc_dai_ops rk_spdif_dai_ops = { |
|---|
| 257 | + .set_sysclk = rk_spdif_set_sysclk, |
|---|
| 247 | 258 | .hw_params = rk_spdif_hw_params, |
|---|
| 248 | 259 | .trigger = rk_spdif_trigger, |
|---|
| 249 | 260 | }; |
|---|
| .. | .. |
|---|
| 363 | 374 | if (IS_ERR(spdif->mclk)) |
|---|
| 364 | 375 | return PTR_ERR(spdif->mclk); |
|---|
| 365 | 376 | |
|---|
| 366 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 367 | | - regs = devm_ioremap_resource(&pdev->dev, res); |
|---|
| 377 | + regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); |
|---|
| 368 | 378 | if (IS_ERR(regs)) |
|---|
| 369 | 379 | return PTR_ERR(regs); |
|---|
| 370 | 380 | |
|---|