soc-ac97.c 10.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
// SPDX-License-Identifier: GPL-2.0+
//
// soc-ac97.c  --  ALSA SoC Audio Layer AC97 support
//
// Copyright 2005 Wolfson Microelectronics PLC.
// Copyright 2005 Openedhand Ltd.
// Copyright (C) 2010 Slimlogic Ltd.
// Copyright (C) 2010 Texas Instruments Inc.
//
// Author: Liam Girdwood <lrg@slimlogic.co.uk>
//         with code, comments and ideas from :-
//         Richard Purdie <richard@openedhand.com>
13 14 15 16 17

#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/gpio.h>
R
Robert Jarzmik 已提交
18
#include <linux/gpio/driver.h>
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
#include <linux/init.h>
#include <linux/of_gpio.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/slab.h>
#include <sound/ac97_codec.h>
#include <sound/soc.h>

struct snd_ac97_reset_cfg {
	struct pinctrl *pctl;
	struct pinctrl_state *pstate_reset;
	struct pinctrl_state *pstate_warm_reset;
	struct pinctrl_state *pstate_run;
	int gpio_sdata;
	int gpio_sync;
	int gpio_reset;
};

R
Robert Jarzmik 已提交
37 38 39 40 41
struct snd_ac97_gpio_priv {
#ifdef CONFIG_GPIOLIB
	struct gpio_chip gpio_chip;
#endif
	unsigned int gpios_set;
42
	struct snd_soc_component *component;
R
Robert Jarzmik 已提交
43 44
};

45 46 47 48
static struct snd_ac97_bus soc_ac97_bus = {
	.ops = NULL, /* Gets initialized in snd_soc_set_ac97_ops() */
};

49 50 51 52 53
static void soc_ac97_device_release(struct device *dev)
{
	kfree(to_ac97_t(dev));
}

R
Robert Jarzmik 已提交
54
#ifdef CONFIG_GPIOLIB
55
static inline struct snd_soc_component *gpio_to_component(struct gpio_chip *chip)
R
Robert Jarzmik 已提交
56
{
57
	struct snd_ac97_gpio_priv *gpio_priv = gpiochip_get_data(chip);
R
Robert Jarzmik 已提交
58

59
	return gpio_priv->component;
R
Robert Jarzmik 已提交
60 61 62 63 64 65 66 67 68 69 70 71 72
}

static int snd_soc_ac97_gpio_request(struct gpio_chip *chip, unsigned offset)
{
	if (offset >= AC97_NUM_GPIOS)
		return -EINVAL;

	return 0;
}

static int snd_soc_ac97_gpio_direction_in(struct gpio_chip *chip,
					  unsigned offset)
{
73
	struct snd_soc_component *component = gpio_to_component(chip);
R
Robert Jarzmik 已提交
74

75 76
	dev_dbg(component->dev, "set gpio %d to output\n", offset);
	return snd_soc_component_update_bits(component, AC97_GPIO_CFG,
R
Robert Jarzmik 已提交
77 78 79 80 81
				   1 << offset, 1 << offset);
}

static int snd_soc_ac97_gpio_get(struct gpio_chip *chip, unsigned offset)
{
82
	struct snd_soc_component *component = gpio_to_component(chip);
R
Robert Jarzmik 已提交
83 84
	int ret;

85 86 87 88
	if (snd_soc_component_read(component, AC97_GPIO_STATUS, &ret) < 0)
		ret = -1;

	dev_dbg(component->dev, "get gpio %d : %d\n", offset,
R
Robert Jarzmik 已提交
89 90
		ret < 0 ? ret : ret & (1 << offset));

91
	return ret < 0 ? ret : !!(ret & (1 << offset));
R
Robert Jarzmik 已提交
92 93 94 95 96
}

static void snd_soc_ac97_gpio_set(struct gpio_chip *chip, unsigned offset,
				  int value)
{
97
	struct snd_ac97_gpio_priv *gpio_priv = gpiochip_get_data(chip);
98
	struct snd_soc_component *component = gpio_to_component(chip);
R
Robert Jarzmik 已提交
99 100 101

	gpio_priv->gpios_set &= ~(1 << offset);
	gpio_priv->gpios_set |= (!!value) << offset;
102 103 104
	snd_soc_component_write(component, AC97_GPIO_STATUS,
				gpio_priv->gpios_set);
	dev_dbg(component->dev, "set gpio %d to %d\n", offset, !!value);
R
Robert Jarzmik 已提交
105 106 107 108 109
}

static int snd_soc_ac97_gpio_direction_out(struct gpio_chip *chip,
				     unsigned offset, int value)
{
110
	struct snd_soc_component *component = gpio_to_component(chip);
R
Robert Jarzmik 已提交
111

112
	dev_dbg(component->dev, "set gpio %d to output\n", offset);
R
Robert Jarzmik 已提交
113
	snd_soc_ac97_gpio_set(chip, offset, value);
114 115
	return snd_soc_component_update_bits(component, AC97_GPIO_CFG,
					     1 << offset, 0);
R
Robert Jarzmik 已提交
116 117
}

118
static const struct gpio_chip snd_soc_ac97_gpio_chip = {
R
Robert Jarzmik 已提交
119 120 121 122 123 124 125 126 127 128 129
	.label			= "snd_soc_ac97",
	.owner			= THIS_MODULE,
	.request		= snd_soc_ac97_gpio_request,
	.direction_input	= snd_soc_ac97_gpio_direction_in,
	.get			= snd_soc_ac97_gpio_get,
	.direction_output	= snd_soc_ac97_gpio_direction_out,
	.set			= snd_soc_ac97_gpio_set,
	.can_sleep		= 1,
};

static int snd_soc_ac97_init_gpio(struct snd_ac97 *ac97,
130
				  struct snd_soc_component *component)
R
Robert Jarzmik 已提交
131 132 133 134
{
	struct snd_ac97_gpio_priv *gpio_priv;
	int ret;

135
	gpio_priv = devm_kzalloc(component->dev, sizeof(*gpio_priv), GFP_KERNEL);
R
Robert Jarzmik 已提交
136 137 138
	if (!gpio_priv)
		return -ENOMEM;
	ac97->gpio_priv = gpio_priv;
139
	gpio_priv->component = component;
R
Robert Jarzmik 已提交
140 141
	gpio_priv->gpio_chip = snd_soc_ac97_gpio_chip;
	gpio_priv->gpio_chip.ngpio = AC97_NUM_GPIOS;
142
	gpio_priv->gpio_chip.parent = component->dev;
R
Robert Jarzmik 已提交
143 144
	gpio_priv->gpio_chip.base = -1;

145
	ret = gpiochip_add_data(&gpio_priv->gpio_chip, gpio_priv);
R
Robert Jarzmik 已提交
146
	if (ret != 0)
147
		dev_err(component->dev, "Failed to add GPIOs: %d\n", ret);
R
Robert Jarzmik 已提交
148 149 150 151 152 153 154 155 156
	return ret;
}

static void snd_soc_ac97_free_gpio(struct snd_ac97 *ac97)
{
	gpiochip_remove(&ac97->gpio_priv->gpio_chip);
}
#else
static int snd_soc_ac97_init_gpio(struct snd_ac97 *ac97,
157
				  struct snd_soc_component *component)
R
Robert Jarzmik 已提交
158 159 160 161 162 163 164 165 166
{
	return 0;
}

static void snd_soc_ac97_free_gpio(struct snd_ac97 *ac97)
{
}
#endif

167
/**
168 169
 * snd_soc_alloc_ac97_component() - Allocate new a AC'97 device
 * @component: The COMPONENT for which to create the AC'97 device
170
 *
171 172 173 174 175
 * Allocated a new snd_ac97 device and intializes it, but does not yet register
 * it. The caller is responsible to either call device_add(&ac97->dev) to
 * register the device, or to call put_device(&ac97->dev) to free the device.
 *
 * Returns: A snd_ac97 device or a PTR_ERR in case of an error.
176
 */
177
struct snd_ac97 *snd_soc_alloc_ac97_component(struct snd_soc_component *component)
178
{
179
	struct snd_ac97 *ac97;
180

181 182 183
	ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL);
	if (ac97 == NULL)
		return ERR_PTR(-ENOMEM);
184

185 186
	ac97->bus = &soc_ac97_bus;
	ac97->num = 0;
187

188
	ac97->dev.bus = &ac97_bus_type;
189
	ac97->dev.parent = component->card->dev;
190
	ac97->dev.release = soc_ac97_device_release;
191

192
	dev_set_name(&ac97->dev, "%d-%d:%s",
193 194
		     component->card->snd_card->number, 0,
		     component->name);
195

196 197 198 199
	device_initialize(&ac97->dev);

	return ac97;
}
200
EXPORT_SYMBOL(snd_soc_alloc_ac97_component);
201 202

/**
203 204
 * snd_soc_new_ac97_component - initailise AC97 device
 * @component: audio component
205 206
 * @id: The expected device ID
 * @id_mask: Mask that is applied to the device ID before comparing with @id
207
 *
208
 * Initialises AC97 component resources for use by ad-hoc devices only.
209 210 211 212 213 214
 *
 * If @id is not 0 this function will reset the device, then read the ID from
 * the device and check if it matches the expected ID. If it doesn't match an
 * error will be returned and device will not be registered.
 *
 * Returns: A PTR_ERR() on failure or a valid snd_ac97 struct on success.
215
 */
216
struct snd_ac97 *snd_soc_new_ac97_component(struct snd_soc_component *component,
217
	unsigned int id, unsigned int id_mask)
218 219 220 221
{
	struct snd_ac97 *ac97;
	int ret;

222
	ac97 = snd_soc_alloc_ac97_component(component);
223 224 225
	if (IS_ERR(ac97))
		return ac97;

226 227 228
	if (id) {
		ret = snd_ac97_reset(ac97, false, id, id_mask);
		if (ret < 0) {
229
			dev_err(component->dev, "Failed to reset AC97 device: %d\n",
230 231 232
				ret);
			goto err_put_device;
		}
233
	}
234

235 236 237 238
	ret = device_add(&ac97->dev);
	if (ret)
		goto err_put_device;

239
	ret = snd_soc_ac97_init_gpio(ac97, component);
R
Robert Jarzmik 已提交
240 241 242
	if (ret)
		goto err_put_device;

243
	return ac97;
244 245 246 247

err_put_device:
	put_device(&ac97->dev);
	return ERR_PTR(ret);
248
}
249
EXPORT_SYMBOL_GPL(snd_soc_new_ac97_component);
250 251

/**
252
 * snd_soc_free_ac97_component - free AC97 component device
253
 * @ac97: snd_ac97 device to be freed
254
 *
255
 * Frees AC97 component device resources.
256
 */
257
void snd_soc_free_ac97_component(struct snd_ac97 *ac97)
258
{
R
Robert Jarzmik 已提交
259
	snd_soc_ac97_free_gpio(ac97);
260 261 262
	device_del(&ac97->dev);
	ac97->bus = NULL;
	put_device(&ac97->dev);
263
}
264
EXPORT_SYMBOL_GPL(snd_soc_free_ac97_component);
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388

static struct snd_ac97_reset_cfg snd_ac97_rst_cfg;

static void snd_soc_ac97_warm_reset(struct snd_ac97 *ac97)
{
	struct pinctrl *pctl = snd_ac97_rst_cfg.pctl;

	pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_warm_reset);

	gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 1);

	udelay(10);

	gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0);

	pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run);
	msleep(2);
}

static void snd_soc_ac97_reset(struct snd_ac97 *ac97)
{
	struct pinctrl *pctl = snd_ac97_rst_cfg.pctl;

	pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_reset);

	gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0);
	gpio_direction_output(snd_ac97_rst_cfg.gpio_sdata, 0);
	gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 0);

	udelay(10);

	gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 1);

	pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run);
	msleep(2);
}

static int snd_soc_ac97_parse_pinctl(struct device *dev,
		struct snd_ac97_reset_cfg *cfg)
{
	struct pinctrl *p;
	struct pinctrl_state *state;
	int gpio;
	int ret;

	p = devm_pinctrl_get(dev);
	if (IS_ERR(p)) {
		dev_err(dev, "Failed to get pinctrl\n");
		return PTR_ERR(p);
	}
	cfg->pctl = p;

	state = pinctrl_lookup_state(p, "ac97-reset");
	if (IS_ERR(state)) {
		dev_err(dev, "Can't find pinctrl state ac97-reset\n");
		return PTR_ERR(state);
	}
	cfg->pstate_reset = state;

	state = pinctrl_lookup_state(p, "ac97-warm-reset");
	if (IS_ERR(state)) {
		dev_err(dev, "Can't find pinctrl state ac97-warm-reset\n");
		return PTR_ERR(state);
	}
	cfg->pstate_warm_reset = state;

	state = pinctrl_lookup_state(p, "ac97-running");
	if (IS_ERR(state)) {
		dev_err(dev, "Can't find pinctrl state ac97-running\n");
		return PTR_ERR(state);
	}
	cfg->pstate_run = state;

	gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 0);
	if (gpio < 0) {
		dev_err(dev, "Can't find ac97-sync gpio\n");
		return gpio;
	}
	ret = devm_gpio_request(dev, gpio, "AC97 link sync");
	if (ret) {
		dev_err(dev, "Failed requesting ac97-sync gpio\n");
		return ret;
	}
	cfg->gpio_sync = gpio;

	gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 1);
	if (gpio < 0) {
		dev_err(dev, "Can't find ac97-sdata gpio %d\n", gpio);
		return gpio;
	}
	ret = devm_gpio_request(dev, gpio, "AC97 link sdata");
	if (ret) {
		dev_err(dev, "Failed requesting ac97-sdata gpio\n");
		return ret;
	}
	cfg->gpio_sdata = gpio;

	gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 2);
	if (gpio < 0) {
		dev_err(dev, "Can't find ac97-reset gpio\n");
		return gpio;
	}
	ret = devm_gpio_request(dev, gpio, "AC97 link reset");
	if (ret) {
		dev_err(dev, "Failed requesting ac97-reset gpio\n");
		return ret;
	}
	cfg->gpio_reset = gpio;

	return 0;
}

struct snd_ac97_bus_ops *soc_ac97_ops;
EXPORT_SYMBOL_GPL(soc_ac97_ops);

int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops)
{
	if (ops == soc_ac97_ops)
		return 0;

	if (soc_ac97_ops && ops)
		return -EBUSY;

	soc_ac97_ops = ops;
389
	soc_ac97_bus.ops = ops;
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422

	return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops);

/**
 * snd_soc_set_ac97_ops_of_reset - Set ac97 ops with generic ac97 reset functions
 *
 * This function sets the reset and warm_reset properties of ops and parses
 * the device node of pdev to get pinctrl states and gpio numbers to use.
 */
int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops,
		struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct snd_ac97_reset_cfg cfg;
	int ret;

	ret = snd_soc_ac97_parse_pinctl(dev, &cfg);
	if (ret)
		return ret;

	ret = snd_soc_set_ac97_ops(ops);
	if (ret)
		return ret;

	ops->warm_reset = snd_soc_ac97_warm_reset;
	ops->reset = snd_soc_ac97_reset;

	snd_ac97_rst_cfg = cfg;
	return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops_of_reset);