| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * linux/sound/pxa2xx-ac97.c -- AC97 support for the Intel PXA2xx chip. |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Author: Nicolas Pitre |
|---|
| 5 | 6 | * Created: Dec 02, 2004 |
|---|
| 6 | 7 | * Copyright: MontaVista Software Inc. |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 10 | | - * published by the Free Software Foundation. |
|---|
| 11 | 8 | */ |
|---|
| 12 | 9 | |
|---|
| 13 | 10 | #include <linux/init.h> |
|---|
| .. | .. |
|---|
| 17 | 14 | #include <linux/dmaengine.h> |
|---|
| 18 | 15 | #include <linux/dma/pxa-dma.h> |
|---|
| 19 | 16 | |
|---|
| 17 | +#include <sound/ac97/controller.h> |
|---|
| 20 | 18 | #include <sound/core.h> |
|---|
| 21 | 19 | #include <sound/ac97_codec.h> |
|---|
| 22 | 20 | #include <sound/soc.h> |
|---|
| .. | .. |
|---|
| 27 | 25 | #include <mach/regs-ac97.h> |
|---|
| 28 | 26 | #include <mach/audio.h> |
|---|
| 29 | 27 | |
|---|
| 30 | | -static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97) |
|---|
| 28 | +static void pxa2xx_ac97_warm_reset(struct ac97_controller *adrv) |
|---|
| 31 | 29 | { |
|---|
| 32 | 30 | pxa2xx_ac97_try_warm_reset(); |
|---|
| 33 | 31 | |
|---|
| 34 | 32 | pxa2xx_ac97_finish_reset(); |
|---|
| 35 | 33 | } |
|---|
| 36 | 34 | |
|---|
| 37 | | -static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97) |
|---|
| 35 | +static void pxa2xx_ac97_cold_reset(struct ac97_controller *adrv) |
|---|
| 38 | 36 | { |
|---|
| 39 | 37 | pxa2xx_ac97_try_cold_reset(); |
|---|
| 40 | 38 | |
|---|
| 41 | 39 | pxa2xx_ac97_finish_reset(); |
|---|
| 42 | 40 | } |
|---|
| 43 | 41 | |
|---|
| 44 | | -static unsigned short pxa2xx_ac97_legacy_read(struct snd_ac97 *ac97, |
|---|
| 45 | | - unsigned short reg) |
|---|
| 42 | +static int pxa2xx_ac97_read_actrl(struct ac97_controller *adrv, int slot, |
|---|
| 43 | + unsigned short reg) |
|---|
| 46 | 44 | { |
|---|
| 47 | | - int ret; |
|---|
| 48 | | - |
|---|
| 49 | | - ret = pxa2xx_ac97_read(ac97->num, reg); |
|---|
| 50 | | - if (ret < 0) |
|---|
| 51 | | - return 0; |
|---|
| 52 | | - else |
|---|
| 53 | | - return (unsigned short)(ret & 0xffff); |
|---|
| 45 | + return pxa2xx_ac97_read(slot, reg); |
|---|
| 54 | 46 | } |
|---|
| 55 | 47 | |
|---|
| 56 | | -static void pxa2xx_ac97_legacy_write(struct snd_ac97 *ac97, |
|---|
| 57 | | - unsigned short reg, unsigned short val) |
|---|
| 48 | +static int pxa2xx_ac97_write_actrl(struct ac97_controller *adrv, int slot, |
|---|
| 49 | + unsigned short reg, unsigned short val) |
|---|
| 58 | 50 | { |
|---|
| 59 | | - int ret; |
|---|
| 60 | | - |
|---|
| 61 | | - ret = pxa2xx_ac97_write(ac97->num, reg, val); |
|---|
| 51 | + return pxa2xx_ac97_write(slot, reg, val); |
|---|
| 62 | 52 | } |
|---|
| 63 | 53 | |
|---|
| 64 | | -static struct snd_ac97_bus_ops pxa2xx_ac97_ops = { |
|---|
| 65 | | - .read = pxa2xx_ac97_legacy_read, |
|---|
| 66 | | - .write = pxa2xx_ac97_legacy_write, |
|---|
| 54 | +static struct ac97_controller_ops pxa2xx_ac97_ops = { |
|---|
| 55 | + .read = pxa2xx_ac97_read_actrl, |
|---|
| 56 | + .write = pxa2xx_ac97_write_actrl, |
|---|
| 67 | 57 | .warm_reset = pxa2xx_ac97_warm_reset, |
|---|
| 68 | 58 | .reset = pxa2xx_ac97_cold_reset, |
|---|
| 69 | 59 | }; |
|---|
| .. | .. |
|---|
| 167 | 157 | static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = { |
|---|
| 168 | 158 | { |
|---|
| 169 | 159 | .name = "pxa2xx-ac97", |
|---|
| 170 | | - .bus_control = true, |
|---|
| 171 | 160 | .playback = { |
|---|
| 172 | 161 | .stream_name = "AC97 Playback", |
|---|
| 173 | 162 | .channels_min = 2, |
|---|
| .. | .. |
|---|
| 184 | 173 | }, |
|---|
| 185 | 174 | { |
|---|
| 186 | 175 | .name = "pxa2xx-ac97-aux", |
|---|
| 187 | | - .bus_control = true, |
|---|
| 188 | 176 | .playback = { |
|---|
| 189 | 177 | .stream_name = "AC97 Aux Playback", |
|---|
| 190 | 178 | .channels_min = 1, |
|---|
| .. | .. |
|---|
| 201 | 189 | }, |
|---|
| 202 | 190 | { |
|---|
| 203 | 191 | .name = "pxa2xx-ac97-mic", |
|---|
| 204 | | - .bus_control = true, |
|---|
| 205 | 192 | .capture = { |
|---|
| 206 | 193 | .stream_name = "AC97 Mic Capture", |
|---|
| 207 | 194 | .channels_min = 1, |
|---|
| .. | .. |
|---|
| 214 | 201 | |
|---|
| 215 | 202 | static const struct snd_soc_component_driver pxa_ac97_component = { |
|---|
| 216 | 203 | .name = "pxa-ac97", |
|---|
| 217 | | - .ops = &pxa2xx_pcm_ops, |
|---|
| 218 | | - .pcm_new = pxa2xx_soc_pcm_new, |
|---|
| 219 | | - .pcm_free = pxa2xx_pcm_free_dma_buffers, |
|---|
| 204 | + .pcm_construct = pxa2xx_soc_pcm_new, |
|---|
| 205 | + .pcm_destruct = pxa2xx_soc_pcm_free, |
|---|
| 206 | + .open = pxa2xx_soc_pcm_open, |
|---|
| 207 | + .close = pxa2xx_soc_pcm_close, |
|---|
| 208 | + .hw_params = pxa2xx_soc_pcm_hw_params, |
|---|
| 209 | + .hw_free = pxa2xx_soc_pcm_hw_free, |
|---|
| 210 | + .prepare = pxa2xx_soc_pcm_prepare, |
|---|
| 211 | + .trigger = pxa2xx_soc_pcm_trigger, |
|---|
| 212 | + .pointer = pxa2xx_soc_pcm_pointer, |
|---|
| 213 | + .mmap = pxa2xx_soc_pcm_mmap, |
|---|
| 220 | 214 | }; |
|---|
| 221 | 215 | |
|---|
| 222 | 216 | #ifdef CONFIG_OF |
|---|
| .. | .. |
|---|
| 233 | 227 | static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) |
|---|
| 234 | 228 | { |
|---|
| 235 | 229 | int ret; |
|---|
| 230 | + struct ac97_controller *ctrl; |
|---|
| 231 | + pxa2xx_audio_ops_t *pdata = pdev->dev.platform_data; |
|---|
| 232 | + void **codecs_pdata; |
|---|
| 236 | 233 | |
|---|
| 237 | 234 | if (pdev->id != -1) { |
|---|
| 238 | 235 | dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n"); |
|---|
| .. | .. |
|---|
| 245 | 242 | return ret; |
|---|
| 246 | 243 | } |
|---|
| 247 | 244 | |
|---|
| 248 | | - ret = snd_soc_set_ac97_ops(&pxa2xx_ac97_ops); |
|---|
| 249 | | - if (ret != 0) |
|---|
| 250 | | - return ret; |
|---|
| 245 | + codecs_pdata = pdata ? pdata->codec_pdata : NULL; |
|---|
| 246 | + ctrl = snd_ac97_controller_register(&pxa2xx_ac97_ops, &pdev->dev, |
|---|
| 247 | + AC97_SLOTS_AVAILABLE_ALL, |
|---|
| 248 | + codecs_pdata); |
|---|
| 249 | + if (IS_ERR(ctrl)) |
|---|
| 250 | + return PTR_ERR(ctrl); |
|---|
| 251 | 251 | |
|---|
| 252 | + platform_set_drvdata(pdev, ctrl); |
|---|
| 252 | 253 | /* Punt most of the init to the SoC probe; we may need the machine |
|---|
| 253 | 254 | * driver to do interesting things with the clocking to get us up |
|---|
| 254 | 255 | * and running. |
|---|
| 255 | 256 | */ |
|---|
| 256 | | - return snd_soc_register_component(&pdev->dev, &pxa_ac97_component, |
|---|
| 257 | + return devm_snd_soc_register_component(&pdev->dev, &pxa_ac97_component, |
|---|
| 257 | 258 | pxa_ac97_dai_driver, ARRAY_SIZE(pxa_ac97_dai_driver)); |
|---|
| 258 | 259 | } |
|---|
| 259 | 260 | |
|---|
| 260 | 261 | static int pxa2xx_ac97_dev_remove(struct platform_device *pdev) |
|---|
| 261 | 262 | { |
|---|
| 262 | | - snd_soc_unregister_component(&pdev->dev); |
|---|
| 263 | | - snd_soc_set_ac97_ops(NULL); |
|---|
| 263 | + struct ac97_controller *ctrl = platform_get_drvdata(pdev); |
|---|
| 264 | + |
|---|
| 265 | + snd_ac97_controller_unregister(ctrl); |
|---|
| 264 | 266 | pxa2xx_ac97_hw_remove(pdev); |
|---|
| 265 | 267 | return 0; |
|---|
| 266 | 268 | } |
|---|