Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * L3 code
  4 *
  5 *  Copyright (C) 2008, Christian Pellegrin <chripell@evolware.org>
  6 *
  7 * based on:
  8 *
  9 * L3 bus algorithm module.
 10 *
 11 *  Copyright (C) 2001 Russell King, All Rights Reserved.
 12 */
 13
 14#include <linux/module.h>
 15#include <linux/kernel.h>
 16#include <linux/delay.h>
 17#include <linux/device.h>
 18#include <linux/gpio.h>
 19
 20#include <sound/l3.h>
 21
 22/*
 23 * Send one byte of data to the chip.  Data is latched into the chip on
 24 * the rising edge of the clock.
 25 */
 26static void sendbyte(struct l3_pins *adap, unsigned int byte)
 27{
 28	int i;
 29
 30	for (i = 0; i < 8; i++) {
 31		adap->setclk(adap, 0);
 32		udelay(adap->data_hold);
 33		adap->setdat(adap, byte & 1);
 34		udelay(adap->data_setup);
 35		adap->setclk(adap, 1);
 36		udelay(adap->clock_high);
 37		byte >>= 1;
 38	}
 39}
 40
 41/*
 42 * Send a set of bytes to the chip.  We need to pulse the MODE line
 43 * between each byte, but never at the start nor at the end of the
 44 * transfer.
 45 */
 46static void sendbytes(struct l3_pins *adap, const u8 *buf,
 47		      int len)
 48{
 49	int i;
 50
 51	for (i = 0; i < len; i++) {
 52		if (i) {
 53			udelay(adap->mode_hold);
 54			adap->setmode(adap, 0);
 55			udelay(adap->mode);
 56		}
 57		adap->setmode(adap, 1);
 58		udelay(adap->mode_setup);
 59		sendbyte(adap, buf[i]);
 60	}
 61}
 62
 63int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len)
 64{
 65	adap->setclk(adap, 1);
 66	adap->setdat(adap, 1);
 67	adap->setmode(adap, 1);
 68	udelay(adap->mode);
 69
 70	adap->setmode(adap, 0);
 71	udelay(adap->mode_setup);
 72	sendbyte(adap, addr);
 73	udelay(adap->mode_hold);
 74
 75	sendbytes(adap, data, len);
 76
 77	adap->setclk(adap, 1);
 78	adap->setdat(adap, 1);
 79	adap->setmode(adap, 0);
 80
 81	return len;
 82}
 83EXPORT_SYMBOL_GPL(l3_write);
 84
 85
 86static void l3_set_clk(struct l3_pins *adap, int val)
 87{
 88	gpio_set_value(adap->gpio_clk, val);
 89}
 90
 91static void l3_set_data(struct l3_pins *adap, int val)
 92{
 93	gpio_set_value(adap->gpio_data, val);
 94}
 95
 96static void l3_set_mode(struct l3_pins *adap, int val)
 97{
 98	gpio_set_value(adap->gpio_mode, val);
 99}
100
101int l3_set_gpio_ops(struct device *dev, struct l3_pins *adap)
102{
103	int ret;
104
105	if (!adap->use_gpios)
106		return -EINVAL;
107
108	ret = devm_gpio_request_one(dev, adap->gpio_data,
109				GPIOF_OUT_INIT_LOW, "l3_data");
110	if (ret < 0)
111		return ret;
112	adap->setdat = l3_set_data;
113
114	ret = devm_gpio_request_one(dev, adap->gpio_clk,
115				GPIOF_OUT_INIT_LOW, "l3_clk");
116	if (ret < 0)
117		return ret;
118	adap->setclk = l3_set_clk;
119
120	ret = devm_gpio_request_one(dev, adap->gpio_mode,
121				GPIOF_OUT_INIT_LOW, "l3_mode");
122	if (ret < 0)
123		return ret;
124	adap->setmode = l3_set_mode;
125
126	return 0;
127}
128EXPORT_SYMBOL_GPL(l3_set_gpio_ops);
129
130MODULE_DESCRIPTION("L3 bit-banging driver");
131MODULE_AUTHOR("Christian Pellegrin <chripell@evolware.org>");
132MODULE_LICENSE("GPL");