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 | } | |
55 | ||
56 | /** | |
57 | * rt5677_spi_burst_write - Write data to SPI by rt5677 dsp memory address. | |
58 | * @addr: Start address. | |
59 | * @txbuf: Data Buffer for writng. | |
60 | * @len: Data length, it must be a multiple of 8. | |
61 | * | |
62 | * | |
63 | * Returns true for success. | |
64 | */ | |
65 | int rt5677_spi_burst_write(u32 addr, const struct firmware *fw) | |
66 | { | |
67 | u8 spi_cmd = RT5677_SPI_CMD_BURST_WRITE; | |
68 | u8 *write_buf; | |
69 | unsigned int i, end, offset = 0; | |
70 | ||
71 | write_buf = kmalloc(RT5677_SPI_BUF_LEN + 6, GFP_KERNEL); | |
72 | ||
73 | if (write_buf == NULL) | |
74 | return -ENOMEM; | |
75 | ||
76 | while (offset < fw->size) { | |
77 | if (offset + RT5677_SPI_BUF_LEN <= fw->size) | |
78 | end = RT5677_SPI_BUF_LEN; | |
79 | else | |
80 | end = fw->size % RT5677_SPI_BUF_LEN; | |
81 | ||
82 | write_buf[0] = spi_cmd; | |
83 | write_buf[1] = ((addr + offset) & 0xff000000) >> 24; | |
84 | write_buf[2] = ((addr + offset) & 0x00ff0000) >> 16; | |
85 | write_buf[3] = ((addr + offset) & 0x0000ff00) >> 8; | |
86 | write_buf[4] = ((addr + offset) & 0x000000ff) >> 0; | |
87 | ||
88 | for (i = 0; i < end; i += 8) { | |
89 | write_buf[i + 12] = fw->data[offset + i + 0]; | |
90 | write_buf[i + 11] = fw->data[offset + i + 1]; | |
91 | write_buf[i + 10] = fw->data[offset + i + 2]; | |
92 | write_buf[i + 9] = fw->data[offset + i + 3]; | |
93 | write_buf[i + 8] = fw->data[offset + i + 4]; | |
94 | write_buf[i + 7] = fw->data[offset + i + 5]; | |
95 | write_buf[i + 6] = fw->data[offset + i + 6]; | |
96 | write_buf[i + 5] = fw->data[offset + i + 7]; | |
97 | } | |
98 | ||
99 | write_buf[end + 5] = spi_cmd; | |
100 | ||
101 | rt5677_spi_write(write_buf, end + 6); | |
102 | ||
103 | offset += RT5677_SPI_BUF_LEN; | |
104 | } | |
105 | ||
106 | kfree(write_buf); | |
107 | ||
108 | return 0; | |
109 | } | |
110 | ||
111 | static int rt5677_spi_probe(struct spi_device *spi) | |
112 | { | |
113 | g_spi = spi; | |
114 | return 0; | |
115 | } | |
116 | ||
117 | static struct spi_driver rt5677_spi_driver = { | |
118 | .driver = { | |
119 | .name = "rt5677", | |
120 | .owner = THIS_MODULE, | |
121 | }, | |
122 | .probe = rt5677_spi_probe, | |
123 | }; | |
124 | module_spi_driver(rt5677_spi_driver); | |
125 | ||
126 | MODULE_DESCRIPTION("ASoC RT5677 SPI driver"); | |
127 | MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>"); | |
128 | MODULE_LICENSE("GPL v2"); |