From 03d5170904ddfe5784b5b3b1bde90c6c9c7ea704 Mon Sep 17 00:00:00 2001 From: liaoxl Date: Tue, 2 Jul 2019 17:22:56 +0800 Subject: [PATCH] Initial bringup for FM elan module & use fm_ctrl.ko As request from RF team, for fmradio signal lose issue in new HW design, need to add elna module for ensure fmradio performance. Change-Id: I9c21f63788fbef4c28785e9d985631f1ef248105 Reviewed-on: https://gerrit.mot.com/1376704 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Qiu Feng Reviewed-by: Tao Sun Submit-Approved: Jira Key --- drivers/fm/Android.mk | 10 +++ drivers/fm/Kbuild | 4 + drivers/fm/Makefile | 11 +++ drivers/fm/fm_ctrl.c | 199 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 224 insertions(+) create mode 100644 drivers/fm/Android.mk create mode 100644 drivers/fm/Kbuild create mode 100644 drivers/fm/Makefile create mode 100644 drivers/fm/fm_ctrl.c diff --git a/drivers/fm/Android.mk b/drivers/fm/Android.mk new file mode 100644 index 000000000000..a2c74915881a --- /dev/null +++ b/drivers/fm/Android.mk @@ -0,0 +1,10 @@ +ifeq ($(BOARD_HAS_FM_ELNA), true) +DLKM_DIR := motorola/kernel/modules +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := fm_ctrl.ko +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) +include $(DLKM_DIR)/AndroidKernelModule.mk +endif diff --git a/drivers/fm/Kbuild b/drivers/fm/Kbuild new file mode 100644 index 000000000000..3140ec437078 --- /dev/null +++ b/drivers/fm/Kbuild @@ -0,0 +1,4 @@ +# add -Wall to try to catch everything we can. +EXTRA_CFLAGS += -Wall + +obj-m += fm_ctrl.o diff --git a/drivers/fm/Makefile b/drivers/fm/Makefile new file mode 100644 index 000000000000..62a13fd28500 --- /dev/null +++ b/drivers/fm/Makefile @@ -0,0 +1,11 @@ +KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build + +all: + $(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS) + +modules_install: + $(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install + +clean: + $(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean + diff --git a/drivers/fm/fm_ctrl.c b/drivers/fm/fm_ctrl.c new file mode 100644 index 000000000000..d389a567d15a --- /dev/null +++ b/drivers/fm/fm_ctrl.c @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2019 Motorola Mobility LLC + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_VERSION "0.0.1" + +struct fm_ctrl_drvdata { + struct device *dev; + struct pinctrl *pinctrl; + struct pinctrl_state *pstate_default; + struct pinctrl_state *pstate_active; + struct pinctrl_state *pstate_suspend; +}; + +static ssize_t device_name_read(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct fm_ctrl_drvdata *data = dev_get_drvdata(dev); + + if (!data) { + pr_err("fm_ctrl drvdata is NULL\n"); + return -EINVAL; + } + + return snprintf(buf, PAGE_SIZE, "moto fm control intf\n"); +} + + +static ssize_t elna_en_read(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct fm_ctrl_drvdata *data = dev_get_drvdata(dev); + + if (!data) { + pr_err("fm_ctrl drvdata is NULL\n"); + return -EINVAL; + } + + return snprintf(buf, PAGE_SIZE, "fm_ctrl: not support!\n"); +} + +static ssize_t elna_en_write(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct fm_ctrl_drvdata *data = dev_get_drvdata(dev); + int ret = 0; + unsigned int res = 0; + + if (!data) { + pr_err("fm_ctrl drvdata is NULL\n"); + return -EINVAL; + } + + ret = kstrtouint(buf, 0, &res); + if(ret) { + pr_err("fm_ctrl failed to get data, set as default!\n"); + } + if(1 == res) { + ret = pinctrl_select_state(data->pinctrl, data->pstate_active); + } + else { + ret = pinctrl_select_state(data->pinctrl, data->pstate_suspend); + } + if(ret) { + pr_err("fm_ctrl failed to set pinctrl!\n"); + } + else { + pr_info("fm_ctrl set elan=%u\n", res); + } + + return count; +} + + +static DEVICE_ATTR(device_name, 0444, device_name_read, NULL); +static DEVICE_ATTR(elna_en, 0644, elna_en_read, elna_en_write); + +static struct attribute *fm_ctrl_sysfs_attrs[] = { + &dev_attr_device_name.attr, + &dev_attr_elna_en.attr, + NULL, +}; + +static struct attribute_group fm_ctrl_sysfs_attr_grp = { + .attrs = fm_ctrl_sysfs_attrs, +}; + + +static int fm_ctrl_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct fm_ctrl_drvdata *drvdata; + int ret = 0; + + dev_dbg(&pdev->dev, "%s begin\n", __func__); + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + drvdata->dev = &pdev->dev; + platform_set_drvdata(pdev, drvdata); + + /* Get pinctrl if target uses pinctrl */ + drvdata->pinctrl = devm_pinctrl_get(dev); + if (IS_ERR_OR_NULL(drvdata->pinctrl)) { + ret = PTR_ERR(drvdata->pinctrl); + pr_err("%s: Pincontrol DT property returned %X\n", __func__, ret); + return ret; + } + + drvdata->pstate_default = pinctrl_lookup_state(drvdata->pinctrl, + "default"); + if (IS_ERR_OR_NULL(drvdata->pstate_default)) { + ret = PTR_ERR(drvdata->pstate_default); + pr_err("Can not lookup default pinstate %d\n", ret); + return -ENOENT; + } + drvdata->pstate_active = pinctrl_lookup_state(drvdata->pinctrl, + "elna_active"); + if (IS_ERR_OR_NULL(drvdata->pstate_active)) { + ret = PTR_ERR(drvdata->pstate_active); + pr_err("Can not lookup active pinstate %d\n", ret); + return ret; + } + drvdata->pstate_suspend = pinctrl_lookup_state(drvdata->pinctrl, + "elna_suspend"); + if (IS_ERR_OR_NULL(drvdata->pstate_suspend)) { + ret = PTR_ERR(drvdata->pstate_suspend); + pr_err("Can not lookup suspend pinstate %d\n", ret); + return ret; + } + + ret = sysfs_create_group(&dev->kobj, &fm_ctrl_sysfs_attr_grp); + if (ret) { + pr_err("%s: sysfs group creation failed %d\n", __func__, ret); + return ret; + } + + device_init_wakeup(&pdev->dev, 1); + dev_info(&pdev->dev, "probe: All success !\n"); + + return ret; +} + +static int fm_ctrl_remove(struct platform_device *pdev) +{ + device_init_wakeup(&pdev->dev, 0); + return 0; +} + + +static const struct of_device_id fm_ctrl_match[] = { + { .compatible = "moto,fmctrl" }, + {} +}; + +static struct platform_driver fm_ctrl_plat_driver = { + .probe = fm_ctrl_probe, + .remove = fm_ctrl_remove, + .driver = { + .name = "fm_ctrl", + .owner = THIS_MODULE, + .of_match_table = fm_ctrl_match, + }, +}; + +module_platform_driver(fm_ctrl_plat_driver); + + +MODULE_AUTHOR("Motorola Mobiity"); +MODULE_DESCRIPTION("FMRadio control interface driver"); +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL");