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
	ret = snd_soc_component_read(component, AC97_GPIO_STATUS);
86 87

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

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

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

	gpio_priv->gpios_set &= ~(1 << offset);
	gpio_priv->gpios_set |= (!!value) << offset;
101 102 103
	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 已提交
104 105 106 107 108
}

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

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

117
static const struct gpio_chip snd_soc_ac97_gpio_chip = {
R
Robert Jarzmik 已提交
118 119 120 121 122 123 124 125 126 127 128
	.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,
129
				  struct snd_soc_component *component)
R
Robert Jarzmik 已提交
130 131 132 133
{
	struct snd_ac97_gpio_priv *gpio_priv;
	int ret;

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

144
	ret = gpiochip_add_data(&gpio_priv->gpio_chip, gpio_priv);
R
Robert Jarzmik 已提交
145
	if (ret != 0)
146
		dev_err(component->dev, "Failed to add GPIOs: %d\n", ret);
R
Robert Jarzmik 已提交
147 148 149 150 151 152 153 154 155
	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,
156
				  struct snd_soc_component *component)
R
Robert Jarzmik 已提交
157 158 159 160 161 162 163 164 165
{
	return 0;
}

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

166
/**
167 168
 * snd_soc_alloc_ac97_component() - Allocate new a AC'97 device
 * @component: The COMPONENT for which to create the AC'97 device
169
 *
170 171 172 173 174
 * 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.
175
 */
176
struct snd_ac97 *snd_soc_alloc_ac97_component(struct snd_soc_component *component)
177
{
178
	struct snd_ac97 *ac97;
179

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

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

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

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

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

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

/**
202 203
 * snd_soc_new_ac97_component - initailise AC97 device
 * @component: audio component
204 205
 * @id: The expected device ID
 * @id_mask: Mask that is applied to the device ID before comparing with @id
206
 *
207
 * Initialises AC97 component resources for use by ad-hoc devices only.
208 209 210 211 212 213
 *
 * 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.
214
 */
215
struct snd_ac97 *snd_soc_new_ac97_component(struct snd_soc_component *component,
216
	unsigned int id, unsigned int id_mask)
217 218 219 220
{
	struct snd_ac97 *ac97;
	int ret;

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

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

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

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

242
	return ac97;
243 244 245 246

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

/**
251
 * snd_soc_free_ac97_component - free AC97 component device
252
 * @ac97: snd_ac97 device to be freed
253
 *
254
 * Frees AC97 component device resources.
255
 */
256
void snd_soc_free_ac97_component(struct snd_ac97 *ac97)
257
{
R
Robert Jarzmik 已提交
258
	snd_soc_ac97_free_gpio(ac97);
259 260 261
	device_del(&ac97->dev);
	ac97->bus = NULL;
	put_device(&ac97->dev);
262
}
263
EXPORT_SYMBOL_GPL(snd_soc_free_ac97_component);
264 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

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;
388
	soc_ac97_bus.ops = ops;
389 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

	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);