update boot/page/register to be unsigned char
[tas2557sw-android/tas2557-android-driver.git] / tas2557-regmap.c
1 /*
2 ** =============================================================================
3 ** Copyright (c) 2016  Texas Instruments Inc.
4 **
5 ** This program is free software; you can redistribute it and/or modify it under
6 ** the terms of the GNU General Public License as published by the Free Software 
7 ** Foundation; version 2.
8 **
9 ** This program is distributed in the hope that it will be useful, but WITHOUT
10 ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 ** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 **
13 ** You should have received a copy of the GNU General Public License along with
14 ** this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15 ** Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 **
17 ** File:
18 **     tas2557-regmap.c
19 **
20 ** Description:
21 **     I2C driver with regmap for Texas Instruments TAS2557 High Performance 4W Smart Amplifier
22 **
23 ** =============================================================================
24 */
26 #ifdef CONFIG_TAS2557_REGMAP
28 #define DEBUG
29 #include <linux/module.h>
30 #include <linux/moduleparam.h>
31 #include <linux/init.h>
32 #include <linux/delay.h>
33 #include <linux/pm.h>
34 #include <linux/i2c.h>
35 #include <linux/gpio.h>
36 #include <linux/regulator/consumer.h>
37 #include <linux/firmware.h>
38 #include <linux/regmap.h>
39 #include <linux/of.h>
40 #include <linux/of_gpio.h>
41 #include <linux/slab.h>
42 #include <linux/syscalls.h>
43 #include <linux/fcntl.h>
44 #include <asm/uaccess.h>
45 #include "tas2557.h"
46 #include "tas2557-core.h"
48 #ifdef CONFIG_TAS2557_CODEC
49 #include "tas2557-codec.h"
50 #endif
52 #ifdef CONFIG_TAS2557_MISC
53 #include "tas2557-misc.h"
54 #endif
56 #define ENABLE_TILOAD                   //only enable this for in-system tuning or debug, not for production systems
57 #ifdef ENABLE_TILOAD
58 #include "tiload.h"
59 #endif
61 static void tas2557_change_book_page(struct tas2557_priv *pTAS2557, unsigned char nBook,
62         unsigned char nPage)
63 {
64         if ((pTAS2557->mnCurrentBook == nBook) 
65                 && pTAS2557->mnCurrentPage == nPage){
66                 return;
67         }
69         if (pTAS2557->mnCurrentBook != nBook) {
70                 regmap_write(pTAS2557->mpRegmap, TAS2557_BOOKCTL_PAGE, 0);
71                 pTAS2557->mnCurrentPage = 0;
72                 regmap_write(pTAS2557->mpRegmap, TAS2557_BOOKCTL_REG, nBook);
73                 pTAS2557->mnCurrentBook = nBook;
74                 if (nPage != 0) {
75                         regmap_write(pTAS2557->mpRegmap, TAS2557_BOOKCTL_PAGE, nPage);
76                         pTAS2557->mnCurrentPage = nPage;
77                 }
78         } else if (pTAS2557->mnCurrentPage != nPage) {
79                 regmap_write(pTAS2557->mpRegmap, TAS2557_BOOKCTL_PAGE, nPage);
80                 pTAS2557->mnCurrentPage = nPage;
81         }
82 }
84 static int tas2557_dev_read(struct tas2557_priv *pTAS2557,
85         unsigned int nRegister, unsigned int *pValue)
86 {
87         int ret = 0;
89         mutex_lock(&pTAS2557->dev_lock);        
90         
91         if (pTAS2557->mbTILoadActive) {
92                 if (!(nRegister & 0x80000000)){
93                         mutex_unlock(&pTAS2557->dev_lock);
94                         return 0;                       // let only reads from TILoad pass.
95                 }
96                 nRegister &= ~0x80000000;
97         }
99 /*      
100         dev_dbg(pTAS2557->dev, "%s: BOOK:PAGE:REG %u:%u:%u\n", __func__,
101                 TAS2557_BOOK_ID(nRegister), TAS2557_PAGE_ID(nRegister),
102                 TAS2557_PAGE_REG(nRegister));
103 */
104         tas2557_change_book_page(pTAS2557, TAS2557_BOOK_ID(nRegister),
105                 TAS2557_PAGE_ID(nRegister));
106         ret = regmap_read(pTAS2557->mpRegmap, TAS2557_PAGE_REG(nRegister), pValue);
108         mutex_unlock(&pTAS2557->dev_lock);
109         return ret;
112 static int tas2557_dev_write(struct tas2557_priv *pTAS2557,
113         unsigned int nRegister, unsigned int nValue)
115         int ret = 0;
116         
117         mutex_lock(&pTAS2557->dev_lock);
118         if ((nRegister == 0xAFFEAFFE) && (nValue == 0xBABEBABE)) {
119                 pTAS2557->mbTILoadActive = true;
120                 mutex_unlock(&pTAS2557->dev_lock);
121                 return 0;
122         }
124         if ((nRegister == 0xBABEBABE) && (nValue == 0xAFFEAFFE)) {
125                 pTAS2557->mbTILoadActive = false;
126                 mutex_unlock(&pTAS2557->dev_lock);
127                 return 0;
128         }
130         if (pTAS2557->mbTILoadActive) {
131                 if (!(nRegister & 0x80000000)){
132                         mutex_unlock(&pTAS2557->dev_lock);
133                         return 0;                       // let only writes from TILoad pass.
134                 }
135                 nRegister &= ~0x80000000;
136         }
138         tas2557_change_book_page(pTAS2557, TAS2557_BOOK_ID(nRegister),
139                 TAS2557_PAGE_ID(nRegister));
140 //  dev_err(codec->dev, "%s: BOOK:PAGE:REG %u:%u:%u, VAL: 0x%02x\n",
141 //      __func__, TAS2557_BOOK_ID(nRegister), TAS2557_PAGE_ID(nRegister),
142 //      TAS2557_PAGE_REG(nRegister), value);
143         ret = regmap_write(pTAS2557->mpRegmap, TAS2557_PAGE_REG(nRegister),
144                 nValue);
145         mutex_unlock(&pTAS2557->dev_lock);              
146         
147         return ret;
150 static int tas2557_dev_bulk_read(struct tas2557_priv *pTAS2557,
151         unsigned int nRegister, u8 * pData, unsigned int nLength)
153         int ret = 0;
154         
155         mutex_lock(&pTAS2557->dev_lock);
156         if (pTAS2557->mbTILoadActive) {
157                 if (!(nRegister & 0x80000000)){
158                         mutex_unlock(&pTAS2557->dev_lock);
159                         return 0;                       // let only writes from TILoad pass.
160                 }
161                 nRegister &= ~0x80000000;
162         }
164         tas2557_change_book_page(pTAS2557, TAS2557_BOOK_ID(nRegister),
165                 TAS2557_PAGE_ID(nRegister));
166         ret = regmap_bulk_read(pTAS2557->mpRegmap, TAS2557_PAGE_REG(nRegister),
167                 pData, nLength);
168         mutex_unlock(&pTAS2557->dev_lock);      
170         return ret;
173 static int tas2557_dev_bulk_write(struct tas2557_priv *pTAS2557,
174         unsigned int nRegister, u8 * pData, unsigned int nLength)
176         int ret = 0;
177         mutex_lock(&pTAS2557->dev_lock);
178         if (pTAS2557->mbTILoadActive) {
179                 if (!(nRegister & 0x80000000)){
180                         mutex_unlock(&pTAS2557->dev_lock);
181                         return 0;                       // let only writes from TILoad pass.
182                 }
183                 nRegister &= ~0x80000000;
184         }
186         tas2557_change_book_page(pTAS2557, TAS2557_BOOK_ID(nRegister),
187                 TAS2557_PAGE_ID(nRegister));
188         ret = regmap_bulk_write(pTAS2557->mpRegmap, TAS2557_PAGE_REG(nRegister),
189                 pData, nLength);
190         mutex_unlock(&pTAS2557->dev_lock);              
191         
192         return ret;
195 static int tas2557_dev_update_bits(struct tas2557_priv *pTAS2557,
196         unsigned int nRegister, unsigned int nMask, unsigned int nValue)
198         int ret = 0;
199         
200         mutex_lock(&pTAS2557->dev_lock);
201         
202         if (pTAS2557->mbTILoadActive) {
203                 if (!(nRegister & 0x80000000)){
204                         mutex_unlock(&pTAS2557->dev_lock);
205                         return 0;                       // let only writes from TILoad pass.
206                 }
207                 nRegister &= ~0x80000000;
208         }
209         
210         tas2557_change_book_page(pTAS2557, TAS2557_BOOK_ID(nRegister),
211                 TAS2557_PAGE_ID(nRegister));
212         
213         ret = regmap_update_bits(pTAS2557->mpRegmap, TAS2557_PAGE_REG(nRegister), nMask, nValue);
214                 
215         mutex_unlock(&pTAS2557->dev_lock);              
216         return ret;
219 static bool tas2557_volatile(struct device *pDev, unsigned int nRegister)
221         return true;
224 static bool tas2557_writeable(struct device *pDev, unsigned int nRegister)
226         return true;
229 static const struct regmap_config tas2557_i2c_regmap = {
230         .reg_bits = 8,
231         .val_bits = 8,
232         .writeable_reg = tas2557_writeable,
233         .volatile_reg = tas2557_volatile,
234         .cache_type = REGCACHE_NONE,
235         .max_register = 128,
236 };
238 static int tas2557_i2c_probe(struct i2c_client *pClient,
239         const struct i2c_device_id *pID)
241         struct tas2557_priv *pTAS2557;
242         int nResult;
244         dev_info(&pClient->dev, "%s enter\n", __FUNCTION__);
245         
246         pTAS2557 = devm_kzalloc(&pClient->dev, sizeof(struct tas2557_priv), GFP_KERNEL);
247         if (!pTAS2557)
248                 return -ENOMEM;
250         pTAS2557->dev = &pClient->dev;
251         i2c_set_clientdata(pClient, pTAS2557);
252         dev_set_drvdata(&pClient->dev, pTAS2557);
254         if (pClient->dev.of_node){
255                 tas2557_parse_dt(&pClient->dev, pTAS2557);
256         }
258         if (gpio_is_valid(pTAS2557->mnResetGPIO)) {
259 #ifdef HW_RESET //mandatory             
260                 devm_gpio_request_one(&pClient->dev, pTAS2557->mnResetGPIO,
261                         GPIOF_OUT_INIT_LOW, "TAS2557_RST");
262                 msleep(5);
263                 gpio_set_value_cansleep(pTAS2557->mnResetGPIO, 1);
264                 mdelay(1);
265 #endif          
266         }
268         pTAS2557->mpRegmap = devm_regmap_init_i2c(pClient, &tas2557_i2c_regmap);
269         if (IS_ERR(pTAS2557->mpRegmap)) {
270                 nResult = PTR_ERR(pTAS2557->mpRegmap);
271                 dev_err(&pClient->dev, "Failed to allocate register map: %d\n",
272                         nResult);
273                 return nResult;
274         }
276         pTAS2557->read = tas2557_dev_read;
277         pTAS2557->write = tas2557_dev_write;
278         pTAS2557->bulk_read = tas2557_dev_bulk_read;
279         pTAS2557->bulk_write = tas2557_dev_bulk_write;
280         pTAS2557->update_bits = tas2557_dev_update_bits;
281         pTAS2557->set_config = tas2557_set_config;
282         pTAS2557->set_calibration = tas2557_set_calibration;
283                 
284         mutex_init(&pTAS2557->dev_lock);
285         
286         /* Reset the chip */
287         nResult = tas2557_dev_write(pTAS2557, TAS2557_SW_RESET_REG, 0x01);
288         if(nResult < 0){
289                 dev_err(&pClient->dev, "I2C communication ERROR: %d\n",
290                         nResult);
291                 return nResult;
292         }
293         
294         udelay(1000);
296         pTAS2557->mpFirmware =
297                 devm_kzalloc(&pClient->dev, sizeof(TFirmware),
298                 GFP_KERNEL);
299         if (!pTAS2557->mpFirmware)
300                 return -ENOMEM;
302         pTAS2557->mpCalFirmware =
303                 devm_kzalloc(&pClient->dev, sizeof(TFirmware),
304                 GFP_KERNEL);
305         if (!pTAS2557->mpCalFirmware)
306                 return -ENOMEM;
308         pTAS2557->mnCurrentPage = 0;
309         pTAS2557->mnCurrentBook = 0;
311         nResult = tas2557_dev_read(pTAS2557, TAS2557_REV_PGID_REG, &pTAS2557->mnPGID);
312         dev_info(&pClient->dev, "TAS2557 PGID: 0x%02x\n", pTAS2557->mnPGID);
314         pTAS2557->mbTILoadActive = false;
316 #ifdef CONFIG_TAS2557_CODEC     
317         mutex_init(&pTAS2557->codec_lock);
318         tas2557_register_codec(pTAS2557);
319 #endif
321 #ifdef CONFIG_TAS2557_MISC      
322         mutex_init(&pTAS2557->file_lock);
323         tas2557_register_misc(pTAS2557);
324 #endif
326 #ifdef ENABLE_TILOAD
327         tiload_driver_init(pTAS2557);
328 #endif
330         nResult = request_firmware_nowait(THIS_MODULE, 1, TAS2557_FW_NAME,
331                 pTAS2557->dev, GFP_KERNEL, pTAS2557, tas2557_fw_ready);
332                 
333         return nResult;
336 static int tas2557_i2c_remove(struct i2c_client *pClient)
338         struct tas2557_priv *pTAS2557 = i2c_get_clientdata(pClient);
339         
340         dev_info(pTAS2557->dev, "%s\n", __FUNCTION__);
341         
342 #ifdef CONFIG_TAS2557_CODEC             
343         tas2557_deregister_codec(pTAS2557);
344         mutex_destroy(&pTAS2557->codec_lock);
345 #endif
347 #ifdef CONFIG_TAS2557_MISC              
348         tas2557_deregister_misc(pTAS2557);
349         mutex_destroy(&pTAS2557->file_lock);
350 #endif
351         
352         return 0;
355 static const struct i2c_device_id tas2557_i2c_id[] = {
356         {"tas2557", 0},
357         {}
358 };
360 MODULE_DEVICE_TABLE(i2c, tas2557_i2c_id);
362 #if defined(CONFIG_OF)
363 static const struct of_device_id tas2557_of_match[] = {
364         {.compatible = "ti,tas2557"},
365         {},
366 };
368 MODULE_DEVICE_TABLE(of, tas2557_of_match);
369 #endif
371 static struct i2c_driver tas2557_i2c_driver = {
372         .driver = {
373                         .name = "tas2557",
374                         .owner = THIS_MODULE,
375 #if defined(CONFIG_OF)
376                         .of_match_table = of_match_ptr(tas2557_of_match),
377 #endif
378                 },
379         .probe = tas2557_i2c_probe,
380         .remove = tas2557_i2c_remove,
381         .id_table = tas2557_i2c_id,
382 };
384 module_i2c_driver(tas2557_i2c_driver);
386 MODULE_AUTHOR("Texas Instruments Inc.");
387 MODULE_DESCRIPTION("TAS2557 I2C Smart Amplifier driver");
388 MODULE_LICENSE("GPLv2");
389 #endif