Commit | Line | Data |
---|---|---|
af48f1d0 OC |
1 | /* |
2 | * rt5677-spi.c -- RT5677 ALSA SoC audio codec driver | |
3 | * | |
4 | * Copyright 2013 Realtek Semiconductor Corp. | |
5 | * Author: Oder Chiou <oder_chiou@realtek.com> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License version 2 as | |
9 | * published by the Free Software Foundation. | |
10 | */ | |
11 | ||
12 | #include <linux/module.h> | |
13 | #include <linux/input.h> | |
14 | #include <linux/spi/spi.h> | |
15 | #include <linux/device.h> | |
16 | #include <linux/init.h> | |
17 | #include <linux/delay.h> | |
18 | #include <linux/interrupt.h> | |
19 | #include <linux/irq.h> | |
20 | #include <linux/slab.h> | |
21 | #include <linux/gpio.h> | |
22 | #include <linux/sched.h> | |
23 | #include <linux/kthread.h> | |
24 | #include <linux/uaccess.h> | |
25 | #include <linux/miscdevice.h> | |
26 | #include <linux/regulator/consumer.h> | |
27 | #include <linux/pm_qos.h> | |
28 | #include <linux/sysfs.h> | |
29 | #include <linux/clk.h> | |
30 | #include <linux/firmware.h> | |
31 | ||
32 | #include "rt5677-spi.h" | |
33 | ||
34 | static struct spi_device *g_spi; | |
35 | ||
36 | /** | |
37 | * rt5677_spi_write - Write data to SPI. | |
38 | * @txbuf: Data Buffer for writing. | |
39 | * @len: Data length. | |
40 | * | |
41 | * | |
42 | * Returns true for success. | |
43 | */ | |
44 | int rt5677_spi_write(u8 *txbuf, size_t len) | |
45 | { | |
46 | int status; | |
47 | ||
48 | status = spi_write(g_spi, txbuf, len); | |
49 | ||
50 | if (status) | |
51 | dev_err(&g_spi->dev, "rt5677_spi_write error %d\n", status); | |
52 | ||
53 | return status; | |
54 | } | |
e29bee09 | 55 | EXPORT_SYMBOL_GPL(rt5677_spi_write); |
af48f1d0 OC |
56 | |
57 | /** | |
58 | * rt5677_spi_burst_write - Write data to SPI by rt5677 dsp memory address. | |
59 | * @addr: Start address. | |
60 | * @txbuf: Data Buffer for writng. | |
61 | * @len: Data length, it must be a multiple of 8. | |
62 | * | |
63 | * | |
64 | * Returns true for success. | |
65 | */ | |
66 | int rt5677_spi_burst_write(u32 addr, const struct firmware *fw) | |
67 | { | |
68 | u8 spi_cmd = RT5677_SPI_CMD_BURST_WRITE; | |
69 | u8 *write_buf; | |
70 | unsigned int i, end, offset = 0; | |
71 | ||
72 | write_buf = kmalloc(RT5677_SPI_BUF_LEN + 6, GFP_KERNEL); | |
73 | ||
74 | if (write_buf == NULL) | |
75 | return -ENOMEM; | |
76 | ||
77 | while (offset < fw->size) { | |
78 | if (offset + RT5677_SPI_BUF_LEN <= fw->size) | |
79 | end = RT5677_SPI_BUF_LEN; | |
80 | else | |
81 | end = fw->size % RT5677_SPI_BUF_LEN; | |
82 | ||
83 | write_buf[0] = spi_cmd; | |
84 | write_buf[1] = ((addr + offset) & 0xff000000) >> 24; | |
85 | write_buf[2] = ((addr + offset) & 0x00ff0000) >> 16; | |
86 | write_buf[3] = ((addr + offset) & 0x0000ff00) >> 8; | |
87 | write_buf[4] = ((addr + offset) & 0x000000ff) >> 0; | |
88 | ||
89 | for (i = 0; i < end; i += 8) { | |
90 | write_buf[i + 12] = fw->data[offset + i + 0]; | |
91 | write_buf[i + 11] = fw->data[offset + i + 1]; | |
92 | write_buf[i + 10] = fw->data[offset + i + 2]; | |
93 | write_buf[i + 9] = fw->data[offset + i + 3]; | |
94 | write_buf[i + 8] = fw->data[offset + i + 4]; | |
95 | write_buf[i + 7] = fw->data[offset + i + 5]; | |
96 | write_buf[i + 6] = fw->data[offset + i + 6]; | |
97 | write_buf[i + 5] = fw->data[offset + i + 7]; | |
98 | } | |
99 | ||
100 | write_buf[end + 5] = spi_cmd; | |
101 | ||
102 | rt5677_spi_write(write_buf, end + 6); | |
103 | ||
104 | offset += RT5677_SPI_BUF_LEN; | |
105 | } | |
106 | ||
107 | kfree(write_buf); | |
108 | ||
109 | return 0; | |
110 | } | |
e29bee09 | 111 | EXPORT_SYMBOL_GPL(rt5677_spi_burst_write); |
af48f1d0 OC |
112 | |
113 | static int rt5677_spi_probe(struct spi_device *spi) | |
114 | { | |
115 | g_spi = spi; | |
116 | return 0; | |
117 | } | |
118 | ||
119 | static struct spi_driver rt5677_spi_driver = { | |
120 | .driver = { | |
121 | .name = "rt5677", | |
122 | .owner = THIS_MODULE, | |
123 | }, | |
124 | .probe = rt5677_spi_probe, | |
125 | }; | |
126 | module_spi_driver(rt5677_spi_driver); | |
127 | ||
128 | MODULE_DESCRIPTION("ASoC RT5677 SPI driver"); | |
129 | MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>"); | |
130 | MODULE_LICENSE("GPL v2"); |