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 ** File:
14 ** tas2557-misc.c
15 **
16 ** Description:
17 ** misc driver for Texas Instruments TAS2557 High Performance 4W Smart Amplifier
18 **
19 ** =============================================================================
20 */
22 #ifdef CONFIG_TAS2557_MISC
24 #define DEBUG
25 #include <linux/module.h>
26 #include <linux/moduleparam.h>
27 #include <linux/init.h>
28 #include <linux/delay.h>
29 #include <linux/pm.h>
30 #include <linux/i2c.h>
31 #include <linux/gpio.h>
32 #include <linux/regulator/consumer.h>
33 #include <linux/firmware.h>
34 #include <linux/regmap.h>
35 #include <linux/of.h>
36 #include <linux/of_gpio.h>
37 #include <linux/slab.h>
38 #include <linux/syscalls.h>
39 #include <linux/fcntl.h>
40 #include <linux/miscdevice.h>
41 #include <linux/uaccess.h>
43 #include "tas2557.h"
44 #include "tas2557-core.h"
45 #include "tas2557-misc.h"
46 #include <linux/dma-mapping.h>
48 static int g_logEnable = 1;
49 static struct tas2557_priv *g_tas2557;
51 static int tas2557_file_open(struct inode *inode, struct file *file)
52 {
53 struct tas2557_priv *pTAS2557 = g_tas2557;
55 if (!try_module_get(THIS_MODULE))
56 return -ENODEV;
58 file->private_data = (void *)pTAS2557;
59 if (g_logEnable)
60 dev_info(pTAS2557->dev, "%s\n", __func__);
61 return 0;
62 }
64 static int tas2557_file_release(struct inode *inode, struct file *file)
65 {
66 struct tas2557_priv *pTAS2557 = (struct tas2557_priv *)file->private_data;
68 if (g_logEnable)
69 dev_info(pTAS2557->dev, "%s\n", __func__);
70 file->private_data = (void *)NULL;
71 module_put(THIS_MODULE);
73 return 0;
74 }
76 static ssize_t tas2557_file_read(struct file *file, char *buf, size_t count, loff_t *ppos)
77 {
78 struct tas2557_priv *pTAS2557 = (struct tas2557_priv *)file->private_data;
79 int ret = 0;
80 unsigned int nValue = 0;
81 unsigned char value = 0;
82 unsigned char *p_kBuf = NULL;
84 mutex_lock(&pTAS2557->file_lock);
86 switch (pTAS2557->mnDBGCmd) {
87 case TIAUDIO_CMD_REG_READ: {
88 if (g_logEnable)
89 dev_info(pTAS2557->dev, "TIAUDIO_CMD_REG_READ: current_reg = 0x%x, count=%d\n",
90 pTAS2557->mnCurrentReg, (int)count);
91 if (count == 1) {
92 ret = pTAS2557->read(pTAS2557, pTAS2557->mnCurrentReg, &nValue);
93 if (ret < 0)
94 break;
96 value = (u8)nValue;
97 if (g_logEnable)
98 dev_info(pTAS2557->dev, "TIAUDIO_CMD_REG_READ: nValue=0x%x, value=0x%x\n", nValue, value);
99 ret = copy_to_user(buf, &value, 1);
100 if (ret != 0) {
101 /* Failed to copy all the data, exit */
102 dev_err(pTAS2557->dev, "copy to user fail %d\n", ret);
103 }
104 } else if (count > 1) {
105 p_kBuf = kzalloc(count, GFP_KERNEL);
106 if (p_kBuf != NULL) {
107 ret = pTAS2557->bulk_read(pTAS2557, pTAS2557->mnCurrentReg, p_kBuf, count);
108 if (ret < 0)
109 break;
110 ret = copy_to_user(buf, p_kBuf, count);
111 if (ret != 0) {
112 /* Failed to copy all the data, exit */
113 dev_err(pTAS2557->dev, "copy to user fail %d\n", ret);
114 }
115 kfree(p_kBuf);
116 } else
117 dev_err(pTAS2557->dev, "read no mem\n");
118 }
119 }
120 break;
122 case TIAUDIO_CMD_PROGRAM: {
123 if ((pTAS2557->mpFirmware->mnConfigurations > 0)
124 && (pTAS2557->mpFirmware->mnPrograms > 0)) {
125 if (g_logEnable)
126 dev_info(pTAS2557->dev, "TIAUDIO_CMD_PROGRAM: count = %d\n", (int)count);
128 if (count == PROGRAM_BUF_SIZE) {
129 p_kBuf = kzalloc(count, GFP_KERNEL);
130 if (p_kBuf != NULL) {
131 struct TProgram *pProgram =
132 &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]);
133 p_kBuf[0] = pTAS2557->mpFirmware->mnPrograms;
134 p_kBuf[1] = pTAS2557->mnCurrentProgram;
135 p_kBuf[2] = pProgram->mnAppMode;
136 p_kBuf[3] = (pProgram->mnBoost&0xff00)>>8;
137 p_kBuf[4] = (pProgram->mnBoost&0x00ff);
138 memcpy(&p_kBuf[5], pProgram->mpName, FW_NAME_SIZE);
139 strlcpy(&p_kBuf[5+FW_NAME_SIZE], pProgram->mpDescription, strlen(pProgram->mpDescription) + 1);
140 ret = copy_to_user(buf, p_kBuf, count);
141 if (ret != 0) {
142 /* Failed to copy all the data, exit */
143 dev_err(pTAS2557->dev, "copy to user fail %d\n", ret);
144 }
145 kfree(p_kBuf);
146 } else
147 dev_err(pTAS2557->dev, "read no mem\n");
148 } else
149 dev_err(pTAS2557->dev, "read buffer not sufficient\n");
150 } else
151 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
152 }
153 break;
155 case TIAUDIO_CMD_CONFIGURATION: {
156 if ((pTAS2557->mpFirmware->mnConfigurations > 0)
157 && (pTAS2557->mpFirmware->mnPrograms > 0)) {
158 if (g_logEnable)
159 dev_info(pTAS2557->dev, "TIAUDIO_CMD_CONFIGURATION: count = %d\n", (int)count);
160 if (count == CONFIGURATION_BUF_SIZE) {
161 p_kBuf = kzalloc(count, GFP_KERNEL);
162 if (p_kBuf != NULL) {
163 struct TConfiguration *pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
165 p_kBuf[0] = pTAS2557->mpFirmware->mnConfigurations;
166 p_kBuf[1] = pTAS2557->mnCurrentConfiguration;
167 memcpy(&p_kBuf[2], pConfiguration->mpName, FW_NAME_SIZE);
168 p_kBuf[2+FW_NAME_SIZE] = pConfiguration->mnProgram;
169 p_kBuf[3+FW_NAME_SIZE] = pConfiguration->mnPLL;
170 p_kBuf[4+FW_NAME_SIZE] = (pConfiguration->mnSamplingRate&0x000000ff);
171 p_kBuf[5+FW_NAME_SIZE] = ((pConfiguration->mnSamplingRate&0x0000ff00)>>8);
172 p_kBuf[6+FW_NAME_SIZE] = ((pConfiguration->mnSamplingRate&0x00ff0000)>>16);
173 p_kBuf[7+FW_NAME_SIZE] = ((pConfiguration->mnSamplingRate&0xff000000)>>24);
174 strlcpy(&p_kBuf[8+FW_NAME_SIZE], pConfiguration->mpDescription, strlen(pConfiguration->mpDescription)+1);
175 ret = copy_to_user(buf, p_kBuf, count);
176 if (ret != 0) {
177 /* Failed to copy all the data, exit */
178 dev_err(pTAS2557->dev, "copy to user fail %d\n", ret);
179 }
180 kfree(p_kBuf);
181 } else
182 dev_err(pTAS2557->dev, "read no mem\n");
183 } else
184 dev_err(pTAS2557->dev, "read buffer not sufficient\n");
185 } else
186 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
187 }
188 break;
190 case TIAUDIO_CMD_FW_TIMESTAMP: {
191 if (g_logEnable)
192 dev_info(pTAS2557->dev, "TIAUDIO_CMD_FW_TIMESTAMP: count = %d\n", (int)count);
194 if (count == 4) {
195 p_kBuf = kzalloc(count, GFP_KERNEL);
196 if (p_kBuf != NULL) {
197 p_kBuf[0] = (pTAS2557->mpFirmware->mnTimeStamp&0x000000ff);
198 p_kBuf[1] = ((pTAS2557->mpFirmware->mnTimeStamp&0x0000ff00)>>8);
199 p_kBuf[2] = ((pTAS2557->mpFirmware->mnTimeStamp&0x00ff0000)>>16);
200 p_kBuf[3] = ((pTAS2557->mpFirmware->mnTimeStamp&0xff000000)>>24);
201 ret = copy_to_user(buf, p_kBuf, count);
202 if (ret != 0) {
203 /* Failed to copy all the data, exit */
204 dev_err(pTAS2557->dev, "copy to user fail %d\n", ret);
205 }
206 kfree(p_kBuf);
207 } else
208 dev_err(pTAS2557->dev, "read no mem\n");
209 }
210 }
211 break;
213 case TIAUDIO_CMD_CALIBRATION: {
214 if (g_logEnable)
215 dev_info(pTAS2557->dev, "TIAUDIO_CMD_CALIBRATION: count = %d\n", (int)count);
217 if (count == 1) {
218 unsigned char curCal = pTAS2557->mnCurrentCalibration;
220 ret = copy_to_user(buf, &curCal, 1);
221 if (ret != 0) {
222 /* Failed to copy all the data, exit */
223 dev_err(pTAS2557->dev, "copy to user fail %d\n", ret);
224 }
225 }
226 }
227 break;
229 case TIAUDIO_CMD_SAMPLERATE: {
230 if (g_logEnable)
231 dev_info(pTAS2557->dev, "TIAUDIO_CMD_SAMPLERATE: count = %d\n", (int)count);
232 if (count == 4) {
233 p_kBuf = kzalloc(count, GFP_KERNEL);
234 if (p_kBuf != NULL) {
235 struct TConfiguration *pConfiguration =
236 &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]);
238 p_kBuf[0] = (pConfiguration->mnSamplingRate&0x000000ff);
239 p_kBuf[1] = ((pConfiguration->mnSamplingRate&0x0000ff00)>>8);
240 p_kBuf[2] = ((pConfiguration->mnSamplingRate&0x00ff0000)>>16);
241 p_kBuf[3] = ((pConfiguration->mnSamplingRate&0xff000000)>>24);
243 ret = copy_to_user(buf, p_kBuf, count);
244 if (ret != 0) {
245 /* Failed to copy all the data, exit */
246 dev_err(pTAS2557->dev, "copy to user fail %d\n", ret);
247 }
249 kfree(p_kBuf);
250 } else
251 dev_err(pTAS2557->dev, "read no mem\n");
252 }
253 }
254 break;
256 case TIAUDIO_CMD_BITRATE: {
257 if (g_logEnable)
258 dev_info(pTAS2557->dev,
259 "TIAUDIO_CMD_BITRATE: count = %d\n", (int)count);
261 if (count == 1) {
262 unsigned char bitRate = 0;
263 ret = tas2557_get_bit_rate(pTAS2557, &bitRate);
264 if (ret >= 0) {
265 ret = copy_to_user(buf, &bitRate, 1);
266 if (ret != 0) {
267 /* Failed to copy all the data, exit */
268 dev_err(pTAS2557->dev, "copy to user fail %d\n", ret);
269 }
270 }
271 }
272 }
273 break;
275 case TIAUDIO_CMD_DACVOLUME: {
276 if (g_logEnable)
277 dev_info(pTAS2557->dev, "TIAUDIO_CMD_DACVOLUME: count = %d\n", (int)count);
279 if (count == 1) {
280 unsigned char volume = 0;
282 ret = tas2557_get_DAC_gain(pTAS2557, &volume);
283 if (ret >= 0) {
284 ret = copy_to_user(buf, &volume, 1);
285 if (ret != 0) {
286 /* Failed to copy all the data, exit */
287 dev_err(pTAS2557->dev, "copy to user fail %d\n", ret);
288 }
289 }
290 }
291 }
292 break;
293 }
294 pTAS2557->mnDBGCmd = 0;
296 mutex_unlock(&pTAS2557->file_lock);
297 return count;
298 }
300 static ssize_t tas2557_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
301 {
302 struct tas2557_priv *pTAS2557 = (struct tas2557_priv *)file->private_data;
303 int ret = 0;
304 unsigned char *p_kBuf = NULL;
305 unsigned int reg = 0;
306 unsigned int len = 0;
308 mutex_lock(&pTAS2557->file_lock);
310 p_kBuf = kzalloc(count, GFP_KERNEL);
311 if (p_kBuf == NULL) {
312 dev_err(pTAS2557->dev, "write no mem\n");
313 goto err;
314 }
316 ret = copy_from_user(p_kBuf, buf, count);
317 if (ret != 0) {
318 dev_err(pTAS2557->dev, "copy_from_user failed.\n");
319 goto err;
320 }
322 pTAS2557->mnDBGCmd = p_kBuf[0];
323 switch (pTAS2557->mnDBGCmd) {
324 case TIAUDIO_CMD_REG_WITE:
325 if (count > 5) {
326 reg = ((unsigned int)p_kBuf[1] << 24)
327 + ((unsigned int)p_kBuf[2] << 16)
328 + ((unsigned int)p_kBuf[3] << 8)
329 + (unsigned int)p_kBuf[4];
330 len = count - 5;
331 if (len == 1) {
332 ret = pTAS2557->write(pTAS2557, reg, p_kBuf[5]);
333 if (g_logEnable)
334 dev_info(pTAS2557->dev, "TIAUDIO_CMD_REG_WITE, Reg=0x%x, Val=0x%x\n", reg, p_kBuf[5]);
335 } else
336 ret = pTAS2557->bulk_write(pTAS2557, reg, &p_kBuf[5], len);
337 } else
338 dev_err(pTAS2557->dev, "%s, write len fail, count=%d.\n", __func__, (int)count);
339 pTAS2557->mnDBGCmd = 0;
340 break;
342 case TIAUDIO_CMD_REG_READ:
343 if (count == 5) {
344 pTAS2557->mnCurrentReg = ((unsigned int)p_kBuf[1] << 24)
345 + ((unsigned int)p_kBuf[2] << 16)
346 + ((unsigned int)p_kBuf[3] << 8)
347 + (unsigned int)p_kBuf[4];
348 if (g_logEnable)
349 dev_info(pTAS2557->dev, "TIAUDIO_CMD_REG_READ whole=0x%x\n", pTAS2557->mnCurrentReg);
350 } else
351 dev_err(pTAS2557->dev, "read len fail.\n");
352 break;
354 case TIAUDIO_CMD_DEBUG_ON:
355 if (count == 2)
356 g_logEnable = p_kBuf[1];
358 pTAS2557->mnDBGCmd = 0;
359 break;
361 case TIAUDIO_CMD_PROGRAM:
362 {
363 if (count == 2) {
364 if ((pTAS2557->mpFirmware->mnConfigurations > 0)
365 && (pTAS2557->mpFirmware->mnPrograms > 0)) {
366 int config = -1;
368 if (p_kBuf[1] == pTAS2557->mnCurrentProgram)
369 config = pTAS2557->mnCurrentConfiguration;
370 if (g_logEnable)
371 dev_info(pTAS2557->dev, "TIAUDIO_CMD_PROGRAM, set to %d, cfg=%d\n", p_kBuf[1], config);
372 tas2557_set_program(pTAS2557, p_kBuf[1], config);
373 pTAS2557->mnDBGCmd = 0;
374 } else
375 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
376 }
377 }
378 break;
380 case TIAUDIO_CMD_CONFIGURATION:
381 {
382 if (count == 2) {
383 if ((pTAS2557->mpFirmware->mnConfigurations > 0)
384 && (pTAS2557->mpFirmware->mnPrograms > 0)) {
385 if (g_logEnable)
386 dev_info(pTAS2557->dev, "TIAUDIO_CMD_CONFIGURATION, set to %d\n", p_kBuf[1]);
387 tas2557_set_config(pTAS2557, p_kBuf[1]);
388 pTAS2557->mnDBGCmd = 0;
389 } else
390 dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
391 }
392 }
393 break;
395 case TIAUDIO_CMD_FW_TIMESTAMP:
396 /*let go*/
397 break;
399 case TIAUDIO_CMD_CALIBRATION:
400 {
401 if (count == 2) {
402 if ((pTAS2557->mpFirmware->mnConfigurations > 0)
403 && (pTAS2557->mpFirmware->mnPrograms > 0)) {
404 if (g_logEnable)
405 dev_info(pTAS2557->dev, "TIAUDIO_CMD_CALIBRATION, set to %d\n", p_kBuf[1]);
406 tas2557_set_calibration(pTAS2557, p_kBuf[1]);
407 pTAS2557->mnDBGCmd = 0;
408 }
409 }
410 }
411 break;
413 case TIAUDIO_CMD_SAMPLERATE:
414 if (count == 5) {
415 unsigned int nSampleRate = ((unsigned int)p_kBuf[1] << 24) +
416 ((unsigned int)p_kBuf[2] << 16) +
417 ((unsigned int)p_kBuf[3] << 8) +
418 (unsigned int)p_kBuf[4];
419 if (g_logEnable)
420 dev_info(pTAS2557->dev, "TIAUDIO_CMD_SAMPLERATE, set to %d\n", nSampleRate);
422 tas2557_set_sampling_rate(pTAS2557, nSampleRate);
423 }
424 break;
426 case TIAUDIO_CMD_BITRATE:
427 if (count == 2) {
428 if (g_logEnable)
429 dev_info(pTAS2557->dev, "TIAUDIO_CMD_BITRATE, set to %d\n", p_kBuf[1]);
431 tas2557_set_bit_rate(pTAS2557, p_kBuf[1]);
432 }
433 break;
435 case TIAUDIO_CMD_DACVOLUME:
436 if (count == 2) {
437 unsigned char volume;
439 volume = (p_kBuf[1] & 0x0f);
440 if (g_logEnable)
441 dev_info(pTAS2557->dev, "TIAUDIO_CMD_DACVOLUME, set to %d\n", volume);
443 ret = tas2557_set_DAC_gain(pTAS2557, volume);
444 if (ret < 0)
445 goto err;
446 }
447 break;
449 case TIAUDIO_CMD_SPEAKER:
450 if (count == 2) {
451 if (g_logEnable)
452 dev_info(pTAS2557->dev, "TIAUDIO_CMD_SPEAKER, set to %d\n", p_kBuf[1]);
453 tas2557_enable(pTAS2557, (p_kBuf[1] > 0));
454 }
455 break;
457 case TIAUDIO_CMD_FW_RELOAD:
458 if (count == 1) {
459 const char *pFWName;
460 if (pTAS2557->mnPGID == TAS2557_PG_VERSION_2P1)
461 pFWName = TAS2557_FW_NAME;
462 else if (pTAS2557->mnPGID == TAS2557_PG_VERSION_1P0)
463 pFWName = TAS2557_PG1P0_FW_NAME;
464 else
465 break;
467 ret = request_firmware_nowait(THIS_MODULE, 1, pFWName,
468 pTAS2557->dev, GFP_KERNEL, pTAS2557, tas2557_fw_ready);
470 if (g_logEnable)
471 dev_info(pTAS2557->dev, "TIAUDIO_CMD_FW_RELOAD: ret = %d\n", ret);
472 }
473 break;
475 default:
476 pTAS2557->mnDBGCmd = 0;
477 break;
478 }
480 err:
481 if (p_kBuf != NULL)
482 kfree(p_kBuf);
484 mutex_unlock(&pTAS2557->file_lock);
486 return count;
487 }
489 static long tas2557_file_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
490 {
491 struct tas2557_priv *pTAS2557 = file->private_data;
492 int ret = 0;
494 mutex_lock(&pTAS2557->file_lock);
496 switch (cmd) {
497 case SMARTPA_SPK_DAC_VOLUME:
498 {
499 }
500 break;
502 case SMARTPA_SPK_POWER_ON:
503 {
504 tas2557_enable(pTAS2557, true);
505 }
506 break;
508 case SMARTPA_SPK_POWER_OFF:
509 {
510 tas2557_enable(pTAS2557, false);
511 }
512 break;
514 case SMARTPA_SPK_SWITCH_PROGRAM:
515 {
516 if ((pTAS2557->mpFirmware->mnConfigurations > 0)
517 && (pTAS2557->mpFirmware->mnPrograms > 0))
518 tas2557_set_program(pTAS2557, arg, -1);
519 }
520 break;
522 case SMARTPA_SPK_SWITCH_CONFIGURATION:
523 {
524 if ((pTAS2557->mpFirmware->mnConfigurations > 0)
525 && (pTAS2557->mpFirmware->mnPrograms > 0))
526 tas2557_set_config(pTAS2557, arg);
527 }
528 break;
530 case SMARTPA_SPK_SWITCH_CALIBRATION:
531 {
532 if ((pTAS2557->mpFirmware->mnConfigurations > 0)
533 && (pTAS2557->mpFirmware->mnPrograms > 0))
534 tas2557_set_calibration(pTAS2557, arg);
535 }
536 break;
538 case SMARTPA_SPK_SET_SAMPLERATE:
539 {
540 tas2557_set_sampling_rate(pTAS2557, arg);
541 }
542 break;
544 case SMARTPA_SPK_SET_BITRATE:
545 {
546 tas2557_set_bit_rate(pTAS2557, arg);
547 }
548 break;
549 }
551 mutex_unlock(&pTAS2557->file_lock);
552 return ret;
553 }
555 static const struct file_operations fops = {
556 .owner = THIS_MODULE,
557 .read = tas2557_file_read,
558 .write = tas2557_file_write,
559 .unlocked_ioctl = tas2557_file_unlocked_ioctl,
560 .open = tas2557_file_open,
561 .release = tas2557_file_release,
562 };
564 #define MODULE_NAME "tas2557"
565 static struct miscdevice tas2557_misc = {
566 .minor = MISC_DYNAMIC_MINOR,
567 .name = MODULE_NAME,
568 .fops = &fops,
569 };
571 int tas2557_register_misc(struct tas2557_priv *pTAS2557)
572 {
573 int ret = 0;
575 g_tas2557 = pTAS2557;
577 ret = misc_register(&tas2557_misc);
578 if (ret)
579 dev_err(pTAS2557->dev, "TAS2557 misc fail: %d\n", ret);
581 dev_info(pTAS2557->dev, "%s, leave\n", __func__);
583 return ret;
584 }
586 int tas2557_deregister_misc(struct tas2557_priv *pTAS2557)
587 {
588 misc_deregister(&tas2557_misc);
589 return 0;
590 }
592 MODULE_AUTHOR("Texas Instruments Inc.");
593 MODULE_DESCRIPTION("TAS2557 Misc Smart Amplifier driver");
594 MODULE_LICENSE("GPL v2");
595 #endif