7f9354e6f1f98c89f61f6d5d86c5569280774410
[tas2770sw-android/tas2770sw-android.git] / tas2770-regmap.c
1 /*
2  * ALSA SoC Texas Instruments TAS2770 High Performance 4W Smart Amplifier
3  *
4  * Copyright (C) 2016 Texas Instruments, Inc.
5  *
6  * Author: saiprasad
7  *
8  * This package is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15  *
16  */
17 #ifdef CONFIG_TAS2770_REGMAP
19 #define DEBUG
20 #include <linux/module.h>
21 #include <linux/moduleparam.h>
22 #include <linux/err.h>
23 #include <linux/init.h>
24 #include <linux/delay.h>
25 #include <linux/pm.h>
26 #include <linux/i2c.h>
27 #include <linux/gpio.h>
28 #include <linux/regulator/consumer.h>
29 #include <linux/firmware.h>
30 #include <linux/regmap.h>
31 #include <linux/of.h>
32 #include <linux/of_gpio.h>
33 #include <linux/slab.h>
34 #include <sound/soc.h>
36 #include "tas2770.h"
37 #include "tas2770-codec.h"
39 static const struct reg_default tas2770_reg_defaults[] = {
40         { TAS2770_Page, 0x00 },
41         { TAS2770_SoftwareReset, 0x00 },
42         { TAS2770_PowerControl, 0x0e },
43         { TAS2770_PlaybackConfigurationReg0, 0x10 },
44         { TAS2770_PlaybackConfigurationReg1, 0x01 },
45         { TAS2770_PlaybackConfigurationReg2, 0x00 },
46         { TAS2770_MiscConfigurationReg0, 0x07 },
47         { TAS2770_TDMConfigurationReg1, 0x02 },
48         { TAS2770_TDMConfigurationReg2, 0x0a },
49         { TAS2770_TDMConfigurationReg3, 0x10 },
50         { TAS2770_InterruptMaskReg0, 0xfc },
51         { TAS2770_InterruptMaskReg1, 0xb1 },
52         { TAS2770_InterruptConfiguration, 0x05 },
53         { TAS2770_MiscIRQ, 0x81 },
54         { TAS2770_ClockConfiguration, 0x0c },
56 };
58 static bool tas2770_volatile(struct device *dev, unsigned int reg)
59 {
60         switch (reg) {
61         case TAS2770_Page: /* regmap implementation requires this */
62         case TAS2770_SoftwareReset: /* always clears after write */
63         case TAS2770_BrownOutPreventionReg0:/* has a self clearing bit */
64         case TAS2770_LiveInterruptReg0:
65         case TAS2770_LiveInterruptReg1:
66         case TAS2770_LatchedInterruptReg0:/* Sticky interrupt flags */
67         case TAS2770_LatchedInterruptReg1:/* Sticky interrupt flags */
68         case TAS2770_VBATMSB:
69         case TAS2770_VBATLSB:
70         case TAS2770_TEMPMSB:
71         case TAS2770_TEMPLSB:
72                 return true;
73         }
74         return false;
75 }
77 static bool tas2770_writeable(struct device *dev, unsigned int reg)
78 {
79         switch (reg) {
80         case TAS2770_LiveInterruptReg0:
81         case TAS2770_LiveInterruptReg1:
82         case TAS2770_LatchedInterruptReg0:
83         case TAS2770_LatchedInterruptReg1:
84         case TAS2770_VBATMSB:
85         case TAS2770_VBATLSB:
86         case TAS2770_TEMPMSB:
87         case TAS2770_TEMPLSB:
88         case TAS2770_TDMClockdetectionmonitor:
89         case TAS2770_RevisionandPGID:
90                 return false;
91         }
92         return true;
93 }
94 static const struct regmap_config tas2770_i2c_regmap = {
95         .reg_bits = 8,
96         .val_bits = 8,
97         .writeable_reg = tas2770_writeable,
98         .volatile_reg = tas2770_volatile,
99         .reg_defaults = tas2770_reg_defaults,
100         .num_reg_defaults = ARRAY_SIZE(tas2770_reg_defaults),
101         .cache_type = REGCACHE_RBTREE,
102         .max_register = 1 * 128,
103 };
106 static void tas2770_hw_reset(struct tas2770_priv *pTAS2770)
108         if (gpio_is_valid(pTAS2770->mnResetGPIO)) {
109                 gpio_direction_output(pTAS2770->mnResetGPIO, 0);
110                 msleep(5);
111                 gpio_direction_output(pTAS2770->mnResetGPIO, 1);
112                 msleep(2);
113         }
115         pTAS2770->mnCurrentBook = -1;
116         pTAS2770->mnCurrentPage = -1;
119 void tas2770_enableIRQ(struct tas2770_priv *pTAS2770, bool enable)
121         if (enable) {
122                 if (pTAS2770->mbIRQEnable)
123                         return;
125                 if (gpio_is_valid(pTAS2770->mnIRQGPIO))
126                         enable_irq(pTAS2770->mnIRQ);
128                 schedule_delayed_work(&pTAS2770->irq_work, msecs_to_jiffies(10));
129                 pTAS2770->mbIRQEnable = true;
130         } else {
131                 if (!pTAS2770->mbIRQEnable)
132                         return;
134                 if (gpio_is_valid(pTAS2770->mnIRQGPIO))
135                         disable_irq_nosync(pTAS2770->mnIRQ);
136                 pTAS2770->mbIRQEnable = false;
137         }
140 static void irq_work_routine(struct work_struct *work)
142         struct tas2770_priv *pTAS2770 =
143                 container_of(work, struct tas2770_priv, irq_work.work);
145 #ifdef CONFIG_TAS2770_CODEC
146         mutex_lock(&pTAS2770->codec_lock);
147 #endif
149         if (pTAS2770->mbRuntimeSuspend) {
150                 dev_info(pTAS2770->dev, "%s, Runtime Suspended\n", __func__);
151                 goto end;
152         }
154         if (!pTAS2770->mbPowerUp) {
155                 dev_info(pTAS2770->dev, "%s, device not powered\n", __func__);
156                 goto end;
157         }
159 end:
160 #ifdef CONFIG_TAS2770_CODEC
161         mutex_unlock(&pTAS2770->codec_lock);
162 #endif
165 static enum hrtimer_restart timer_func(struct hrtimer *timer)
167         struct tas2770_priv *pTAS2770 = container_of(timer,
168                 struct tas2770_priv, mtimer);
170         if (pTAS2770->mbPowerUp) {
171                 if (!delayed_work_pending(&pTAS2770->irq_work))
172                         schedule_delayed_work(&pTAS2770->irq_work,
173                                 msecs_to_jiffies(20));
174         }
176         return HRTIMER_NORESTART;
179 static irqreturn_t tas2770_irq_handler(int irq, void *dev_id)
181         struct tas2770_priv *pTAS2770 = (struct tas2770_priv *)dev_id;
183         tas2770_enableIRQ(pTAS2770, false);
185         /* get IRQ status after 100 ms */
186         if (!delayed_work_pending(&pTAS2770->irq_work))
187                 schedule_delayed_work(&pTAS2770->irq_work,
188                         msecs_to_jiffies(100));
190         return IRQ_HANDLED;
193 static int tas2770_runtime_suspend(struct tas2770_priv *pTAS2770)
195         dev_dbg(pTAS2770->dev, "%s\n", __func__);
197         pTAS2770->mbRuntimeSuspend = true;
199         if (hrtimer_active(&pTAS2770->mtimer)) {
200                 dev_dbg(pTAS2770->dev, "cancel die temp timer\n");
201                 hrtimer_cancel(&pTAS2770->mtimer);
202         }
204         if (delayed_work_pending(&pTAS2770->irq_work)) {
205                 dev_dbg(pTAS2770->dev, "cancel IRQ work\n");
206                 cancel_delayed_work_sync(&pTAS2770->irq_work);
207         }
209         return 0;
212 #define CHECK_PERIOD    5000    /* 5 second */
213 static int tas2770_runtime_resume(struct tas2770_priv *pTAS2770)
215         dev_dbg(pTAS2770->dev, "%s\n", __func__);
217         if (pTAS2770->mbPowerUp) {
218                 if (!hrtimer_active(&pTAS2770->mtimer)) {
219                         hrtimer_start(&pTAS2770->mtimer,
220                                 ns_to_ktime((u64)CHECK_PERIOD * NSEC_PER_MSEC),
221                                 HRTIMER_MODE_REL);
222                 }
224         }
226         pTAS2770->mbRuntimeSuspend = false;
228         return 0;
231 static int tas2770_parse_dt(struct device *dev, struct tas2770_priv *pTAS2770)
233         struct device_node *np = dev->of_node;
234         int rc = 0, ret = 0;
236         rc = of_property_read_u32(np, "ti,asi-format", &pTAS2770->mnASIFormat);
237         if (rc) {
238                 dev_err(pTAS2770->dev, "Looking up %s property in node %s failed %d\n",
239                         "ti,asi-format", np->full_name, rc);
240         } else {
241                 dev_dbg(pTAS2770->dev, "ti,asi-format=%d",
242                         pTAS2770->mnASIFormat);
243         }
245         pTAS2770->mnResetGPIO = of_get_named_gpio(np, "ti,reset-gpio", 0);
246         if (!gpio_is_valid(pTAS2770->mnResetGPIO)) {
247                 dev_err(pTAS2770->dev, "Looking up %s property in node %s failed %d\n",
248                         "ti,reset-gpio", np->full_name, pTAS2770->mnResetGPIO);
249         } else {
250                 dev_dbg(pTAS2770->dev, "ti,reset-gpio=%d",
251                         pTAS2770->mnResetGPIO);
252         }
254         pTAS2770->mnIRQGPIO = of_get_named_gpio(np, "ti,irq-gpio", 0);
255         if (!gpio_is_valid(pTAS2770->mnIRQGPIO)) {
256                 dev_err(pTAS2770->dev, "Looking up %s property in node %s failed %d\n",
257                         "ti,irq-gpio", np->full_name, pTAS2770->mnIRQGPIO);
258         } else {
259                 dev_dbg(pTAS2770->dev, "ti,irq-gpio=%d", pTAS2770->mnIRQGPIO);
260         }
262         return ret;
265 static int tas2770_i2c_probe(struct i2c_client *client,
266                         const struct i2c_device_id *id)
268         struct tas2770_priv *pTAS2770;
269         int nResult;
271         dev_info(&client->dev, "%s enter\n", __func__);
273         pTAS2770 = devm_kzalloc(&client->dev,
274                 sizeof(struct tas2770_priv), GFP_KERNEL);
275         if (pTAS2770 == NULL) {
276                 nResult = -ENOMEM;
277                 goto end;
278         }
280         pTAS2770->dev = &client->dev;
281         i2c_set_clientdata(client, pTAS2770);
282         dev_set_drvdata(&client->dev, pTAS2770);
284         pTAS2770->regmap = devm_regmap_init_i2c(client, &tas2770_i2c_regmap);
285         if (IS_ERR(pTAS2770->regmap)) {
286                 nResult = PTR_ERR(pTAS2770->regmap);
287                 dev_err(&client->dev, "Failed to allocate register map: %d\n",
288                                         nResult);
289                 goto end;
290         }
292         if (client->dev.of_node)
293                 tas2770_parse_dt(&client->dev, pTAS2770);
295         if (gpio_is_valid(pTAS2770->mnResetGPIO)) {
296                 nResult = gpio_request(pTAS2770->mnResetGPIO, "TAS2770_RESET");
297                 if (nResult) {
298                         dev_err(pTAS2770->dev, "%s: Failed to request gpio %d\n",
299                                 __func__, pTAS2770->mnResetGPIO);
300                         nResult = -EINVAL;
301                         goto free_gpio;
302                 }
303         }
305         if (gpio_is_valid(pTAS2770->mnIRQGPIO)) {
306                 nResult = gpio_request(pTAS2770->mnIRQGPIO, "TAS2770-IRQ");
307                 if (nResult < 0) {
308                         dev_err(pTAS2770->dev, "%s: GPIO %d request error\n",
309                                 __func__, pTAS2770->mnIRQGPIO);
310                         goto free_gpio;
311                 }
312                 gpio_direction_input(pTAS2770->mnIRQGPIO);
313                 pTAS2770->mnIRQ = gpio_to_irq(pTAS2770->mnIRQGPIO);
314                 dev_dbg(pTAS2770->dev, "irq = %d\n", pTAS2770->mnIRQ);
315                 nResult = request_threaded_irq(pTAS2770->mnIRQ,
316                                         tas2770_irq_handler, NULL,
317                                         IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
318                                         client->name, pTAS2770);
319                 if (nResult < 0) {
320                         dev_err(pTAS2770->dev,
321                                 "request_irq failed, %d\n", nResult);
322                         goto free_gpio;
323                 }
324                 disable_irq_nosync(pTAS2770->mnIRQ);
325                 INIT_DELAYED_WORK(&pTAS2770->irq_work, irq_work_routine);
326         }
328         pTAS2770->hw_reset = tas2770_hw_reset;
329         pTAS2770->enableIRQ = tas2770_enableIRQ;
330         pTAS2770->runtime_suspend = tas2770_runtime_suspend;
331         pTAS2770->runtime_resume = tas2770_runtime_resume;
332         mutex_init(&pTAS2770->dev_lock);
333         if (nResult < 0)
334                 goto destroy_mutex;
336 #ifdef CONFIG_TAS2770_CODEC
337         mutex_init(&pTAS2770->codec_lock);
338         tas2770_register_codec(pTAS2770);
339 #endif
341         hrtimer_init(&pTAS2770->mtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
342         pTAS2770->mtimer.function = timer_func;
344 destroy_mutex:
345         if (nResult < 0)
346                 mutex_destroy(&pTAS2770->dev_lock);
348 free_gpio:
349         if (nResult < 0) {
350                 if (gpio_is_valid(pTAS2770->mnResetGPIO))
351                         gpio_free(pTAS2770->mnResetGPIO);
352                 if (gpio_is_valid(pTAS2770->mnIRQGPIO))
353                         gpio_free(pTAS2770->mnIRQGPIO);
354         }
356 end:
357         return nResult;
360 static int tas2770_i2c_remove(struct i2c_client *client)
362         struct tas2770_priv *pTAS2770 = i2c_get_clientdata(client);
364         dev_info(pTAS2770->dev, "%s\n", __func__);
366 #ifdef CONFIG_TAS2770_CODEC
367         tas2770_deregister_codec(pTAS2770);
368         mutex_destroy(&pTAS2770->codec_lock);
369 #endif
371         if (gpio_is_valid(pTAS2770->mnResetGPIO))
372                 gpio_free(pTAS2770->mnResetGPIO);
373         if (gpio_is_valid(pTAS2770->mnIRQGPIO))
374                 gpio_free(pTAS2770->mnIRQGPIO);
376         return 0;
380 static const struct i2c_device_id tas2770_i2c_id[] = {
381         { "tas2770", 0},
382         { }
383 };
384 MODULE_DEVICE_TABLE(i2c, tas2770_i2c_id);
386 #if defined(CONFIG_OF)
387 static const struct of_device_id tas2770_of_match[] = {
388         { .compatible = "ti,tas2770" },
389         {},
390 };
391 MODULE_DEVICE_TABLE(of, tas2770_of_match);
392 #endif
395 static struct i2c_driver tas2770_i2c_driver = {
396         .driver = {
397                 .name   = "tas2770",
398                 .owner  = THIS_MODULE,
399 #if defined(CONFIG_OF)
400                 .of_match_table = of_match_ptr(tas2770_of_match),
401 #endif
402         },
403         .probe      = tas2770_i2c_probe,
404         .remove     = tas2770_i2c_remove,
405         .id_table   = tas2770_i2c_id,
406 };
408 module_i2c_driver(tas2770_i2c_driver);
410 MODULE_AUTHOR("Texas Instruments Inc.");
411 MODULE_DESCRIPTION("TAS2770 I2C Smart Amplifier driver");
412 MODULE_LICENSE("GPL v2");
413 #endif