123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815 |
- /* SPDX-License-Identifier: GPL-2.0-only */
- /*
- * Copyright (c) 2020, The Linux Foundation. All rights reserved.
- */
- /*
- * sec_audio_sysfs.c
- *
- * Copyright (c) 2017 Samsung Electronics
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
- #include <linux/err.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/of.h>
- #include <linux/platform_device.h>
- #include <linux/slab.h>
- #include <linux/time.h>
- #include <linux/uaccess.h>
- #include <linux/wait.h>
- #include <sound/samsung/sec_audio_sysfs.h>
- #include <sound/samsung/snd_debug_proc.h>
- #define EARJACK_DEV_ID 0
- #define CODEC_DEV_ID 1
- #define AMP_DEV_ID 2
- #define ADSP_DEV_ID 3
- #define ADSP_SRCNT_MAX 1000
- #define ADSP_SRCNT_SUM_MAX 10000
- /* bigdata add */
- #define DECLARE_AMP_BIGDATA_SYSFS(id) \
- static ssize_t audio_amp_##id##_temperature_max_show(struct device *dev, \
- struct device_attribute *attr, char *buf) \
- { \
- int report = 0; \
- if (audio_data->get_amp_temperature_max) \
- report = audio_data->get_amp_temperature_max((id)); \
- else \
- dev_info(dev, "%s: No callback registered\n", __func__); \
- return snprintf(buf, PAGE_SIZE, "%d\n", report); \
- } \
- static DEVICE_ATTR(temperature_max_##id, S_IRUGO | S_IWUSR | S_IWGRP, \
- audio_amp_##id##_temperature_max_show, NULL); \
- static ssize_t audio_amp_##id##_temperature_keep_max_show(struct device *dev, \
- struct device_attribute *attr, char *buf) \
- { \
- int report = 0; \
- if (audio_data->get_amp_temperature_keep_max) \
- report = audio_data->get_amp_temperature_keep_max((id)); \
- else \
- dev_info(dev, "%s: No callback registered\n", __func__); \
- return snprintf(buf, PAGE_SIZE, "%d\n", report); \
- } \
- static DEVICE_ATTR(temperature_keep_max_##id, S_IRUGO | S_IWUSR | S_IWGRP, \
- audio_amp_##id##_temperature_keep_max_show, NULL); \
- static ssize_t audio_amp_##id##_temperature_overcount_show(struct device *dev, \
- struct device_attribute *attr, char *buf) \
- { \
- int report = 0; \
- if (audio_data->get_amp_temperature_overcount) \
- report = audio_data->get_amp_temperature_overcount((id)); \
- else \
- dev_info(dev, "%s: No callback registered\n", __func__); \
- return snprintf(buf, PAGE_SIZE, "%d\n", report); \
- } \
- static DEVICE_ATTR(temperature_overcount_##id, S_IRUGO | S_IWUSR | S_IWGRP, \
- audio_amp_##id##_temperature_overcount_show, NULL); \
- static ssize_t audio_amp_##id##_excursion_max_show(struct device *dev, \
- struct device_attribute *attr, char *buf) \
- { \
- int report = 0; \
- if (audio_data->get_amp_excursion_max) \
- report = audio_data->get_amp_excursion_max((id)); \
- else \
- dev_info(dev, "%s: No callback registered\n", __func__); \
- return snprintf(buf, PAGE_SIZE, "%04d\n", report); \
- } \
- static DEVICE_ATTR(excursion_max_##id, S_IRUGO | S_IWUSR | S_IWGRP, \
- audio_amp_##id##_excursion_max_show, NULL); \
- static ssize_t audio_amp_##id##_excursion_overcount_show(struct device *dev, \
- struct device_attribute *attr, char *buf) \
- { \
- int report = 0; \
- if (audio_data->get_amp_excursion_overcount) \
- report = audio_data->get_amp_excursion_overcount(id); \
- else \
- dev_info(dev, "%s: No callback registered\n", __func__); \
- return snprintf(buf, PAGE_SIZE, "%d\n", report); \
- } \
- static DEVICE_ATTR(excursion_overcount_##id, S_IRUGO | S_IWUSR | S_IWGRP, \
- audio_amp_##id##_excursion_overcount_show, NULL); \
- static ssize_t audio_amp_##id##_curr_temperature_show(struct device *dev, \
- struct device_attribute *attr, char *buf) \
- { \
- int report = 0; \
- if (audio_data->get_amp_curr_temperature) \
- report = audio_data->get_amp_curr_temperature((id)); \
- else \
- dev_info(dev, "%s: No callback registered\n", __func__); \
- return snprintf(buf, PAGE_SIZE, "%d\n", report); \
- } \
- static DEVICE_ATTR(curr_temperature_##id, S_IRUGO | S_IWUSR | S_IWGRP, \
- audio_amp_##id##_curr_temperature_show, NULL); \
- static ssize_t audio_amp_##id##_surface_temperature_store(struct device *dev, \
- struct device_attribute *attr, const char *buf, size_t size) \
- { \
- int ret, temp = 0; \
- ret = kstrtos32(buf, 10, &temp); \
- if (audio_data->set_amp_surface_temperature) \
- ret = audio_data->set_amp_surface_temperature((id), temp); \
- else \
- dev_info(dev, "%s: No callback registered\n", __func__); \
- return size; \
- } \
- static DEVICE_ATTR(surface_temperature_##id, S_IRUGO | S_IWUSR | S_IWGRP, \
- NULL, audio_amp_##id##_surface_temperature_store); \
- static ssize_t audio_amp_##id##_ready_show(struct device *dev, \
- struct device_attribute *attr, char *buf) \
- { \
- int report = 0; \
- if (audio_data->get_amp_ready) \
- report = audio_data->get_amp_ready((id)); \
- else {\
- dev_info(dev, "%s: No callback registered\n", __func__); \
- report = -EACCES; \
- } \
- return snprintf(buf, PAGE_SIZE, "%d\n", report); \
- } \
- static DEVICE_ATTR(ready_##id, S_IRUGO | S_IWUSR | S_IWGRP, \
- audio_amp_##id##_ready_show, NULL); \
- static struct attribute *audio_amp_##id##_attr[] = { \
- &dev_attr_temperature_max_##id.attr, \
- &dev_attr_temperature_keep_max_##id.attr, \
- &dev_attr_temperature_overcount_##id.attr, \
- &dev_attr_excursion_max_##id.attr, \
- &dev_attr_excursion_overcount_##id.attr, \
- &dev_attr_curr_temperature_##id.attr, \
- &dev_attr_surface_temperature_##id.attr, \
- &dev_attr_ready_##id.attr, \
- NULL, \
- }
- static struct sec_audio_sysfs_data *audio_data;
- static int adsp_silent_reset_count;
- static int adsp_silent_reset_count_sum;
- int audio_register_jack_select_cb(int (*set_jack) (int))
- {
- if (audio_data->set_jack_state) {
- dev_err(audio_data->jack_dev,
- "%s: Already registered\n", __func__);
- return -EEXIST;
- }
- audio_data->set_jack_state = set_jack;
- return 0;
- }
- EXPORT_SYMBOL_GPL(audio_register_jack_select_cb);
- static ssize_t audio_jack_select_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- if (audio_data->set_jack_state) {
- if ((!size) || (buf[0] != '1')) {
- dev_info(dev, "%s: Forced remove jack\n", __func__);
- audio_data->set_jack_state(0);
- } else {
- dev_info(dev, "%s: Forced detect jack\n", __func__);
- audio_data->set_jack_state(1);
- }
- } else {
- dev_info(dev, "%s: No callback registered\n", __func__);
- }
- return size;
- }
- static DEVICE_ATTR(select_jack, S_IRUGO | S_IWUSR | S_IWGRP,
- NULL, audio_jack_select_store);
- int audio_register_jack_state_cb(int (*jack_state) (void))
- {
- if (audio_data->get_jack_state) {
- dev_err(audio_data->jack_dev,
- "%s: Already registered\n", __func__);
- return -EEXIST;
- }
- audio_data->get_jack_state = jack_state;
- return 0;
- }
- EXPORT_SYMBOL_GPL(audio_register_jack_state_cb);
- static ssize_t audio_jack_state_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- int report = 0;
- if (audio_data->get_jack_state)
- report = audio_data->get_jack_state();
- else
- dev_info(dev, "%s: No callback registered\n", __func__);
- return snprintf(buf, 4, "%d\n", report);
- }
- static DEVICE_ATTR(state, S_IRUGO | S_IWUSR | S_IWGRP,
- audio_jack_state_show, NULL);
- int audio_register_key_state_cb(int (*key_state) (void))
- {
- if (audio_data->get_key_state) {
- dev_err(audio_data->jack_dev,
- "%s: Already registered\n", __func__);
- return -EEXIST;
- }
- audio_data->get_key_state = key_state;
- return 0;
- }
- EXPORT_SYMBOL_GPL(audio_register_key_state_cb);
- static ssize_t audio_key_state_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- int report = 0;
- if (audio_data->get_key_state)
- report = audio_data->get_key_state();
- else
- dev_info(dev, "%s: No callback registered\n", __func__);
- return snprintf(buf, 4, "%d\n", report);
- }
- static DEVICE_ATTR(key_state, S_IRUGO | S_IWUSR | S_IWGRP,
- audio_key_state_show, NULL);
- int audio_register_mic_adc_cb(int (*mic_adc) (void))
- {
- if (audio_data->get_mic_adc) {
- dev_err(audio_data->jack_dev,
- "%s: Already registered\n", __func__);
- return -EEXIST;
- }
- audio_data->get_mic_adc = mic_adc;
- return 0;
- }
- EXPORT_SYMBOL_GPL(audio_register_mic_adc_cb);
- static ssize_t audio_mic_adc_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- int report = 0;
- if (audio_data->get_mic_adc)
- report = audio_data->get_mic_adc();
- else
- dev_info(dev, "%s: No callback registered\n", __func__);
- return snprintf(buf, 16, "%d\n", report);
- }
- static DEVICE_ATTR(mic_adc, S_IRUGO | S_IWUSR | S_IWGRP,
- audio_mic_adc_show, NULL);
- int audio_register_force_enable_antenna_cb(int (*force_enable_antenna) (int))
- {
- if (audio_data->set_force_enable_antenna) {
- dev_err(audio_data->jack_dev,
- "%s: Already registered\n", __func__);
- return -EEXIST;
- }
- audio_data->set_force_enable_antenna = force_enable_antenna;
- return 0;
- }
- EXPORT_SYMBOL_GPL(audio_register_force_enable_antenna_cb);
- static ssize_t force_enable_antenna_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- if (audio_data->set_force_enable_antenna) {
- if ((!size) || (buf[0] != '1')) {
- dev_info(dev, "%s: antenna disable\n", __func__);
- audio_data->set_force_enable_antenna(0);
- } else {
- dev_info(dev, "%s: update antenna enable\n", __func__);
- audio_data->set_force_enable_antenna(1);
- }
- } else {
- dev_info(dev, "%s: No callback registered\n", __func__);
- }
- return size;
- }
- static DEVICE_ATTR(force_enable_antenna, S_IRUGO | S_IWUSR | S_IWGRP,
- NULL, force_enable_antenna_store);
- int audio_register_antenna_state_cb(int (*antenna_state) (void))
- {
- if (audio_data->get_antenna_state) {
- dev_err(audio_data->jack_dev,
- "%s: Already registered\n", __func__);
- return -EEXIST;
- }
- audio_data->get_antenna_state = antenna_state;
- return 0;
- }
- EXPORT_SYMBOL_GPL(audio_register_antenna_state_cb);
- static ssize_t audio_antenna_state_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- int report = 0;
- if (audio_data->get_antenna_state)
- report = audio_data->get_antenna_state();
- else
- dev_info(dev, "%s: No callback registered\n", __func__);
- return snprintf(buf, 4, "%d\n", report);
- }
- static DEVICE_ATTR(antenna_state, S_IRUGO | S_IWUSR | S_IWGRP,
- audio_antenna_state_show, NULL);
- static struct attribute *sec_audio_jack_attr[] = {
- &dev_attr_select_jack.attr,
- &dev_attr_state.attr,
- &dev_attr_key_state.attr,
- &dev_attr_mic_adc.attr,
- &dev_attr_force_enable_antenna.attr,
- &dev_attr_antenna_state.attr,
- NULL,
- };
- static struct attribute_group sec_audio_jack_attr_group = {
- .attrs = sec_audio_jack_attr,
- };
- int audio_register_codec_id_state_cb(int (*codec_id_state) (void))
- {
- if (audio_data->get_codec_id_state) {
- dev_err(audio_data->codec_dev,
- "%s: Already registered\n", __func__);
- return -EEXIST;
- }
- audio_data->get_codec_id_state = codec_id_state;
- return 0;
- }
- EXPORT_SYMBOL_GPL(audio_register_codec_id_state_cb);
- static ssize_t audio_check_codec_id_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- int report = 0;
- if (audio_data->get_codec_id_state)
- report = audio_data->get_codec_id_state();
- else
- dev_info(dev, "%s: No callback registered\n", __func__);
- return snprintf(buf, 4, "%d\n", report);
- }
- static DEVICE_ATTR(check_codec_id, S_IRUGO | S_IWUSR | S_IWGRP,
- audio_check_codec_id_show, NULL);
- static struct attribute *sec_audio_codec_attr[] = {
- &dev_attr_check_codec_id.attr,
- NULL,
- };
- static struct attribute_group sec_audio_codec_attr_group = {
- .attrs = sec_audio_codec_attr,
- };
- /* bigdata */
- int audio_register_temperature_max_cb(int (*temperature_max) (enum amp_id))
- {
- if (audio_data->get_amp_temperature_max) {
- dev_err(audio_data->amp_dev,
- "%s: Already registered\n", __func__);
- return -EEXIST;
- }
- audio_data->get_amp_temperature_max = temperature_max;
- return 0;
- }
- EXPORT_SYMBOL_GPL(audio_register_temperature_max_cb);
- int audio_register_temperature_keep_max_cb(int (*temperature_keep_max) (enum amp_id))
- {
- if (audio_data->get_amp_temperature_keep_max) {
- dev_err(audio_data->amp_dev,
- "%s: Already registered\n", __func__);
- return -EEXIST;
- }
- audio_data->get_amp_temperature_keep_max = temperature_keep_max;
- return 0;
- }
- EXPORT_SYMBOL_GPL(audio_register_temperature_keep_max_cb);
- int audio_register_temperature_overcount_cb(int (*temperature_overcount) (enum amp_id))
- {
- if (audio_data->get_amp_temperature_overcount) {
- dev_err(audio_data->amp_dev,
- "%s: Already registered\n", __func__);
- return -EEXIST;
- }
- audio_data->get_amp_temperature_overcount = temperature_overcount;
- return 0;
- }
- EXPORT_SYMBOL_GPL(audio_register_temperature_overcount_cb);
- int audio_register_excursion_max_cb(int (*excursion_max) (enum amp_id))
- {
- if (audio_data->get_amp_excursion_max) {
- dev_err(audio_data->amp_dev,
- "%s: Already registered\n", __func__);
- return -EEXIST;
- }
- audio_data->get_amp_excursion_max = excursion_max;
- return 0;
- }
- EXPORT_SYMBOL_GPL(audio_register_excursion_max_cb);
- int audio_register_excursion_overcount_cb(int (*excursion_overcount) (enum amp_id))
- {
- if (audio_data->get_amp_excursion_overcount) {
- dev_err(audio_data->amp_dev,
- "%s: Already registered\n", __func__);
- return -EEXIST;
- }
- audio_data->get_amp_excursion_overcount = excursion_overcount;
- return 0;
- }
- EXPORT_SYMBOL_GPL(audio_register_excursion_overcount_cb);
- int audio_register_curr_temperature_cb(int (*curr_temperature) (enum amp_id))
- {
- if (audio_data->get_amp_curr_temperature) {
- dev_err(audio_data->amp_dev,
- "%s: Already registered\n", __func__);
- return -EEXIST;
- }
- audio_data->get_amp_curr_temperature = curr_temperature;
- return 0;
- }
- EXPORT_SYMBOL_GPL(audio_register_curr_temperature_cb);
- int audio_register_surface_temperature_cb(int (*surface_temperature) (enum amp_id, int temperature))
- {
- if (audio_data->set_amp_surface_temperature) {
- dev_err(audio_data->amp_dev,
- "%s: Already registered\n", __func__);
- return -EEXIST;
- }
- audio_data->set_amp_surface_temperature = surface_temperature;
- return 0;
- }
- EXPORT_SYMBOL_GPL(audio_register_surface_temperature_cb);
- int audio_register_ready_cb(int (*ready) (enum amp_id))
- {
- if (audio_data->get_amp_ready) {
- dev_err(audio_data->amp_dev,
- "%s: Already registered\n", __func__);
- return -EEXIST;
- }
- audio_data->get_amp_ready = ready;
- return 0;
- }
- EXPORT_SYMBOL_GPL(audio_register_ready_cb);
- DECLARE_AMP_BIGDATA_SYSFS(0);
- DECLARE_AMP_BIGDATA_SYSFS(1);
- DECLARE_AMP_BIGDATA_SYSFS(2);
- DECLARE_AMP_BIGDATA_SYSFS(3);
- static struct attribute_group sec_audio_amp_big_data_attr_group[AMP_ID_MAX] = {
- [AMP_0] = {.attrs = audio_amp_0_attr, },
- [AMP_1] = {.attrs = audio_amp_1_attr, },
- [AMP_2] = {.attrs = audio_amp_2_attr, },
- [AMP_3] = {.attrs = audio_amp_3_attr, },
- };
- void send_adsp_silent_reset_ev(void)
- {
- if (adsp_silent_reset_count < ADSP_SRCNT_MAX)
- adsp_silent_reset_count++;
- if (adsp_silent_reset_count_sum < ADSP_SRCNT_SUM_MAX)
- adsp_silent_reset_count_sum++;
- pr_info("%s: count %d\n", __func__,
- (adsp_silent_reset_count + adsp_silent_reset_count_sum));
- sdp_info_print("%s: count %d\n", __func__,
- (adsp_silent_reset_count + adsp_silent_reset_count_sum));
- }
- EXPORT_SYMBOL_GPL(send_adsp_silent_reset_ev);
- static ssize_t srcnt_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- int report = adsp_silent_reset_count;
- adsp_silent_reset_count = 0;
- if (adsp_silent_reset_count_sum < ADSP_SRCNT_SUM_MAX)
- adsp_silent_reset_count_sum += report;
- if (adsp_silent_reset_count_sum > ADSP_SRCNT_SUM_MAX)
- adsp_silent_reset_count_sum = ADSP_SRCNT_SUM_MAX;
- dev_info(dev, "%s: %d\n", __func__, report);
- return snprintf(buf, 8, "%d\n", report);
- }
- static DEVICE_ATTR_RO(srcnt);
- static ssize_t srcnt_keep_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- int report = adsp_silent_reset_count_sum;
- dev_info(dev, "%s: %d\n", __func__, report);
- return snprintf(buf, 8, "%d\n", report);
- }
- static DEVICE_ATTR_RO(srcnt_keep);
- static struct attribute *sec_audio_adsp_attrs[] = {
- &dev_attr_srcnt.attr,
- &dev_attr_srcnt_keep.attr,
- NULL,
- };
- static struct attribute_group sec_audio_adsp_attr_group = {
- .attrs = sec_audio_adsp_attrs,
- };
- static int sec_audio_sysfs_probe(struct platform_device *pdev)
- {
- struct device_node *np = pdev->dev.of_node;
- int i;
- if (audio_data == NULL) {
- dev_err(&pdev->dev, "%s: no audio_data\n", __func__);
- return -ENOMEM;
- }
- audio_data->no_earjack = of_property_read_bool(np, "audio,no-earjack");
- if (audio_data->no_earjack) {
- dev_info(&pdev->dev, "%s: remove earjack sysfs dev\n", __func__);
- if (audio_data->jack_dev) {
- sysfs_remove_group(&audio_data->jack_dev->kobj,
- &sec_audio_jack_attr_group);
- device_destroy(audio_data->audio_class, EARJACK_DEV_ID);
- }
- }
- of_property_read_u32(np, "audio,num-amp", &audio_data->num_amp);
- if (audio_data->num_amp > 0) {
- for (i = audio_data->num_amp; i < AMP_ID_MAX; i++) {
- sysfs_remove_group(&audio_data->amp_dev->kobj,
- &sec_audio_amp_big_data_attr_group[i]);
- }
- }
- return 0;
- }
- static int sec_audio_sysfs_remove(struct platform_device *pdev)
- {
- int i;
- if (audio_data->num_amp == 0)
- audio_data->num_amp = AMP_ID_MAX;
- for (i = 0; i < audio_data->num_amp; i++) {
- sysfs_remove_group(&audio_data->amp_dev->kobj,
- &sec_audio_amp_big_data_attr_group[i]);
- }
- return 0;
- }
- #if IS_ENABLED(CONFIG_OF)
- static const struct of_device_id sec_audio_sysfs_of_match[] = {
- { .compatible = "samsung,audio-sysfs", },
- {},
- };
- MODULE_DEVICE_TABLE(of, sec_audio_sysfs_of_match);
- #endif /* CONFIG_OF */
- static struct platform_driver sec_audio_sysfs_driver = {
- .driver = {
- .name = "sec-audio-sysfs",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(sec_audio_sysfs_of_match),
- },
- .probe = sec_audio_sysfs_probe,
- .remove = sec_audio_sysfs_remove,
- };
- static int __init sec_audio_sysfs_init(void)
- {
- int ret = 0;
- int i = 0;
- audio_data = kzalloc(sizeof(struct sec_audio_sysfs_data), GFP_KERNEL);
- if (audio_data == NULL)
- return -ENOMEM;
- audio_data->audio_class = class_create(THIS_MODULE, "audio");
- if (IS_ERR(audio_data->audio_class)) {
- pr_err("%s: Failed to create audio class\n", __func__);
- ret = PTR_ERR(audio_data->audio_class);
- goto err_alloc;
- }
- audio_data->jack_dev =
- device_create(audio_data->audio_class,
- NULL, EARJACK_DEV_ID, NULL, "earjack");
- if (IS_ERR(audio_data->jack_dev)) {
- pr_err("%s: Failed to create earjack device\n", __func__);
- ret = PTR_ERR(audio_data->jack_dev);
- goto err_class;
- }
- ret = sysfs_create_group(&audio_data->jack_dev->kobj,
- &sec_audio_jack_attr_group);
- if (ret) {
- pr_err("%s: Failed to create earjack sysfs\n", __func__);
- goto err_jack_device;
- }
- audio_data->codec_dev =
- device_create(audio_data->audio_class,
- NULL, CODEC_DEV_ID, NULL, "codec");
- if (IS_ERR(audio_data->codec_dev)) {
- pr_err("%s: Failed to create codec device\n", __func__);
- ret = PTR_ERR(audio_data->codec_dev);
- goto err_jack_attr;
- }
- ret = sysfs_create_group(&audio_data->codec_dev->kobj,
- &sec_audio_codec_attr_group);
- if (ret) {
- pr_err("%s: Failed to create codec sysfs\n", __func__);
- goto err_codec_device;
- }
- audio_data->amp_dev =
- device_create(audio_data->audio_class,
- NULL, AMP_DEV_ID, NULL, "amp");
- if (IS_ERR(audio_data->amp_dev)) {
- pr_err("%s: Failed to create amp device\n", __func__);
- ret = PTR_ERR(audio_data->amp_dev);
- goto err_codec_attr;
- }
- audio_data->num_amp = 0;
- for (i = 0; i < AMP_ID_MAX; i++) {
- ret = sysfs_create_group(&audio_data->amp_dev->kobj,
- &sec_audio_amp_big_data_attr_group[i]);
- if (ret) {
- pr_err("%s: Failed to create amp sysfs\n", __func__);
- goto err_amp_attr;
- }
- }
- pr_err("%s: DSP DEVICE CREATE\n", __func__);
- audio_data->adsp_dev =
- device_create(audio_data->audio_class,
- NULL, ADSP_DEV_ID, NULL, "dsp");
- if (IS_ERR(audio_data->adsp_dev)) {
- pr_err("%s: Failed to create adsp device\n", __func__);
- ret = PTR_ERR(audio_data->adsp_dev);
- goto err_amp_attr;
- }
- ret = sysfs_create_group(&audio_data->adsp_dev->kobj,
- &sec_audio_adsp_attr_group);
- if (ret) {
- pr_err("%s: Failed to create adsp sysfs\n", __func__);
- goto err_adsp_device;
- }
- ret = platform_driver_register(&sec_audio_sysfs_driver);
- if (ret) {
- pr_err("%s: fail to register sysfs driver\n", __func__);
- goto err_adsp_attr;
- }
- adsp_silent_reset_count = 0;
- adsp_silent_reset_count_sum = 0;
- return ret;
- err_adsp_attr:
- sysfs_remove_group(&audio_data->adsp_dev->kobj,
- &sec_audio_adsp_attr_group);
- err_adsp_device:
- device_destroy(audio_data->audio_class, ADSP_DEV_ID);
- audio_data->adsp_dev = NULL;
- err_amp_attr:
- while (--i >= 0)
- sysfs_remove_group(&audio_data->amp_dev->kobj,
- &sec_audio_amp_big_data_attr_group[i]);
- device_destroy(audio_data->audio_class, AMP_DEV_ID);
- audio_data->amp_dev = NULL;
- err_codec_attr:
- sysfs_remove_group(&audio_data->codec_dev->kobj,
- &sec_audio_codec_attr_group);
- err_codec_device:
- device_destroy(audio_data->audio_class, CODEC_DEV_ID);
- audio_data->codec_dev = NULL;
- err_jack_attr:
- sysfs_remove_group(&audio_data->jack_dev->kobj,
- &sec_audio_jack_attr_group);
- err_jack_device:
- device_destroy(audio_data->audio_class, EARJACK_DEV_ID);
- audio_data->jack_dev = NULL;
- err_class:
- class_destroy(audio_data->audio_class);
- audio_data->audio_class = NULL;
- err_alloc:
- kfree(audio_data);
- audio_data = NULL;
- return ret;
- }
- module_init(sec_audio_sysfs_init);
- static void __exit sec_audio_sysfs_exit(void)
- {
- platform_driver_unregister(&sec_audio_sysfs_driver);
- if (audio_data->amp_dev)
- device_destroy(audio_data->audio_class, AMP_DEV_ID);
- if (audio_data->codec_dev) {
- sysfs_remove_group(&audio_data->codec_dev->kobj,
- &sec_audio_codec_attr_group);
- device_destroy(audio_data->audio_class, CODEC_DEV_ID);
- }
- if (audio_data->jack_dev) {
- sysfs_remove_group(&audio_data->jack_dev->kobj,
- &sec_audio_jack_attr_group);
- device_destroy(audio_data->audio_class, EARJACK_DEV_ID);
- }
- if (audio_data->audio_class)
- class_destroy(audio_data->audio_class);
- kfree(audio_data);
- }
- module_exit(sec_audio_sysfs_exit);
- MODULE_DESCRIPTION("Samsung Electronics Audio SYSFS driver");
- MODULE_LICENSE("GPL");
|