kernel-brax3-ubuntu-touch/drivers/misc/mediatek/prize/fm_ant/fm_ant.c
erascape f319b992b1 kernel-5.15: Initial import brax3 UT kernel
* halium configs enabled

Signed-off-by: erascape <erascape@proton.me>
2025-09-23 15:17:10 +00:00

349 lines
9.9 KiB
C
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/***********************************************************
* <20><>Ȩ<EFBFBD><C8A8><EFBFBD><EFBFBD> (C) 2015-2020, <20><><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD>Ǻ<EFBFBD><C7BA>Ƽ<EFBFBD><C6BC><EFBFBD><EFBFBD>޹<EFBFBD>˾
*
* <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>: hall_device.c
* <20><><EFBFBD><EFBFBD>ժҪ: hall driver for hall device
* <20><>ǰ<EFBFBD>汾: V1.0
* <20><> <20><>: <20><><EFBFBD><EFBFBD>
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: 2015-04-10
* <20>޸ļ<DEB8>¼:
* <20>޸<EFBFBD><DEB8><EFBFBD><EFBFBD><EFBFBD>:
* <20><EFBFBD><E6B1BE> :
* <20>޸<EFBFBD><DEB8><EFBFBD> :
***********************************************************/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/vmalloc.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/wait.h>
#include <linux/spinlock.h>
#include <linux/ctype.h>
#include <linux/semaphore.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <linux/kthread.h>
#include <linux/input.h>
#if defined(CONFIG_PM_WAKELOCKS)
#include <linux/pm_wakeup.h>
#else
#include <linux/wakelock.h>
#endif
#include <linux/time.h>
#include <linux/string.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
/*----------------------------------------------------------------------
static variable defination
----------------------------------------------------------------------*/
#define FM_ANT_DEVNAME "fm_ant_dev"
#define EN_DEBUG
#if defined(EN_DEBUG)
#define TRACE_FUNC printk("[fm_ant_dev] function: %s, line: %d \n", __func__, __LINE__);
#define FM_ANT_DEBUG printk
#else
#define TRACE_FUNC(x,...)
#define FM_ANT_DEBUG(x,...)
#endif
/*
&pio {
fm_ant_lna_default: fm_ant_lna_default {
};
fm_ant_lna_en_high: fm_ant_lna_en_high {
pins_cmd_dat {
pinmux = <PINMUX_GPIO153__FUNC_GPIO153>;
slew-rate = <1>;
output-high;
};
};
fm_ant_lna_en_low: fm_ant_lna_en_low {
pins_cmd_dat {
pinmux = <PINMUX_GPIO153__FUNC_GPIO153>;
slew-rate = <1>;
output-low;
};
};
fm_ant_switch_en_high: fm_ant_switch_en_high {
pins_cmd_dat {
pinmux = <PINMUX_GPIO165__FUNC_GPIO165>;
slew-rate = <1>;
output-high;
};
};
fm_ant_switch_en_low: fm_ant_switch_en_low {
pins_cmd_dat {
pinmux = <PINMUX_GPIO165__FUNC_GPIO165>;
slew-rate = <1>;
output-low;
};
};
fm_ant_switch_sel_high: fm_ant_switch_sel_high {
pins_cmd_dat {
pinmux = <PINMUX_GPIO150__FUNC_GPIO150>;
slew-rate = <1>;
output-high;
};
};
fm_ant_switch_sel_low: fm_ant_switch_sel_low {
pins_cmd_dat {
pinmux = <PINMUX_GPIO150__FUNC_GPIO150>;
slew-rate = <1>;
output-low;
};
};
};
&odm {
fm_ant: fm_ant {
compatible = "prize,fm_ant";
pinctrl-names = "default", "lna_en_high","lna_en_low","switch_en_high","switch_en_low","switch_sel_high","switch_sel_low";
pinctrl-0 = <&fm_ant_lna_default>;
pinctrl-1 = <&fm_ant_lna_en_high>;
pinctrl-2 = <&fm_ant_lna_en_low>;
pinctrl-3 = <&fm_ant_switch_en_high>;
pinctrl-4 = <&fm_ant_switch_en_low>;
pinctrl-5 = <&fm_ant_switch_sel_high>;
pinctrl-6 = <&fm_ant_switch_sel_low>;
};
};
*/
/****************************************************************/
/*******static function defination **/
/****************************************************************/
#define FM_CLOSE_SWITCH_CLOSE 0
#define FM_OPEN_SWITCH_D2 1
#define FM_OPEN_SWITCH_D1 2
//static struct kobject *fm_ant_sys_device;
static volatile int cur_fm_en_status = FM_CLOSE_SWITCH_CLOSE;
static struct pinctrl *fm_ant_pinctrl;
static struct pinctrl_state *fm_ant_default;
static struct pinctrl_state *fm_ant_lna_en_high;
static struct pinctrl_state *fm_ant_lna_en_low;
static struct pinctrl_state *fm_ant_switch_en_high;
static struct pinctrl_state *fm_ant_switch_en_low;
static struct pinctrl_state *fm_ant_switch_sel_high;
static struct pinctrl_state *fm_ant_switch_sel_low;
static ssize_t device_fm_ant_status_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
FM_ANT_DEBUG("[fm_ant_dev] cur_fm_en_status=%d\n", cur_fm_en_status);
return sprintf(buf, "%u\n", cur_fm_en_status);
}
static ssize_t device_fm_ant_status_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
FM_ANT_DEBUG("[fm_ant_dev] %s ON/OFF value = %d:\n ", __func__, cur_fm_en_status);
if(sscanf(buf, "%u", &cur_fm_en_status) != 1)
{
FM_ANT_DEBUG("[fm_ant_dev]: Invalid values\n");
return -EINVAL;
}
switch(cur_fm_en_status)
{
case 2:
//fm ant enable <20>л<EFBFBD><D0BB><EFBFBD>D1
pinctrl_select_state(fm_ant_pinctrl, fm_ant_lna_en_high);
pinctrl_select_state(fm_ant_pinctrl, fm_ant_switch_en_low);
pinctrl_select_state(fm_ant_pinctrl, fm_ant_switch_sel_low);
break;
case 1:
//fm ant enable <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD>D2
pinctrl_select_state(fm_ant_pinctrl, fm_ant_lna_en_low);
pinctrl_select_state(fm_ant_pinctrl, fm_ant_switch_en_low);
pinctrl_select_state(fm_ant_pinctrl, fm_ant_switch_sel_high);
break;
case 0:
//fm ant diable
pinctrl_select_state(fm_ant_pinctrl, fm_ant_lna_en_low);
pinctrl_select_state(fm_ant_pinctrl, fm_ant_switch_en_high);
pinctrl_select_state(fm_ant_pinctrl, fm_ant_switch_sel_low);
break;
default:
FM_ANT_DEBUG("[fm_ant_dev]: Invalid values_%d\n",cur_fm_en_status);
break;
}
return size;
}
static DEVICE_ATTR(fm_ant_status, S_IRUGO|S_IWUSR|S_IWGRP, device_fm_ant_status_show, device_fm_ant_status_store);
static int fm_ant_get_dts_fun(struct platform_device *pdev)
{
int ret = 0;
fm_ant_pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(fm_ant_pinctrl)) {
FM_ANT_DEBUG("Cannot find fm ant pinctrl!");
ret = PTR_ERR(fm_ant_pinctrl);
}
//fm ant eint pin initialization
fm_ant_default= pinctrl_lookup_state(fm_ant_pinctrl, "default");
if (IS_ERR(fm_ant_default)) {
ret = PTR_ERR(fm_ant_default);
FM_ANT_DEBUG("%s : init err, fm_ant_default\n", __func__);
}
fm_ant_lna_en_high = pinctrl_lookup_state(fm_ant_pinctrl, "lna_en_high");
if (IS_ERR(fm_ant_lna_en_high)) {
ret = PTR_ERR(fm_ant_lna_en_high);
FM_ANT_DEBUG("%s : init err, fm_ant_lna_en_high\n", __func__);
}
fm_ant_lna_en_low = pinctrl_lookup_state(fm_ant_pinctrl, "lna_en_low");
if (IS_ERR(fm_ant_lna_en_low)) {
ret = PTR_ERR(fm_ant_lna_en_low);
FM_ANT_DEBUG("%s : init err, fm_ant_lna_en_low\n", __func__);
}
fm_ant_switch_en_high = pinctrl_lookup_state(fm_ant_pinctrl, "switch_en_high");
if (IS_ERR(fm_ant_switch_en_high)) {
ret = PTR_ERR(fm_ant_switch_en_high);
FM_ANT_DEBUG("%s : init err, fm_ant_switch_en_high\n", __func__);
}
fm_ant_switch_en_low = pinctrl_lookup_state(fm_ant_pinctrl, "switch_en_low");
if (IS_ERR(fm_ant_switch_en_low)) {
ret = PTR_ERR(fm_ant_switch_en_low);
FM_ANT_DEBUG("%s : init err, fm_ant_switch_en_low\n", __func__);
}
fm_ant_switch_sel_high = pinctrl_lookup_state(fm_ant_pinctrl, "switch_sel_high");
if (IS_ERR(fm_ant_switch_sel_high)) {
ret = PTR_ERR(fm_ant_switch_sel_high);
FM_ANT_DEBUG("%s : init err, fm_ant_switch_sel_high\n", __func__);
}
fm_ant_switch_sel_low = pinctrl_lookup_state(fm_ant_pinctrl, "switch_sel_low");
if (IS_ERR(fm_ant_switch_sel_low)) {
ret = PTR_ERR(fm_ant_switch_sel_low);
FM_ANT_DEBUG("%s : init err, fm_ant_switch_sel_low\n", __func__);
}
//<2F><><EFBFBD><EFBFBD>״̬0
pinctrl_select_state(fm_ant_pinctrl, fm_ant_lna_en_low);
pinctrl_select_state(fm_ant_pinctrl, fm_ant_switch_en_high);
pinctrl_select_state(fm_ant_pinctrl, fm_ant_switch_sel_low);
return ret;
}
/****************************************************************/
/*******export function defination **/
/****************************************************************/
struct class *fm_ant_class;
static int fm_ant_probe(struct platform_device *pdev)
{
//int ret = 0;
struct device *fm_ant_dev;
TRACE_FUNC;
fm_ant_get_dts_fun(pdev);
fm_ant_class = class_create(THIS_MODULE, "fm_ant");
if (IS_ERR(fm_ant_class)) {
FM_ANT_DEBUG("Failed to create class(fm_ant_class)!");
return PTR_ERR(fm_ant_class);
}
fm_ant_dev = device_create(fm_ant_class, NULL, 0, NULL, "fm_ant_data");
if (IS_ERR(fm_ant_dev))
FM_ANT_DEBUG("Failed to create fm_ant_dev device");
if (device_create_file(fm_ant_dev, &dev_attr_fm_ant_status) < 0)
FM_ANT_DEBUG("Failed to create device file(%s)!",dev_attr_fm_ant_status.attr.name);
#if 0
fm_ant_sys_device = kobject_create_and_add("fm_ant_state", NULL);
if (fm_ant_sys_device == NULL)
{
FM_ANT_DEBUG("[fm_ant_dev]:%s: subsystem_register failed\n", __func__);
ret = -ENXIO;
return ret ;
}
ret = sysfs_create_file(fm_ant_sys_device, &dev_attr_fm_ant_status.attr);
if (ret)
{
FM_ANT_DEBUG("[fm_ant_dev]:%s: sysfs_create_file failed\n", __func__);
kobject_del(fm_ant_sys_device);
}
#endif
return 0;
}
static int fm_ant_remove(struct platform_device *dev)
{
FM_ANT_DEBUG("[fm_ant_dev]:fm_ant_remove begin!\n");
class_destroy(fm_ant_class);
FM_ANT_DEBUG("[fm_ant_dev]:fm_ant_remove Done!\n");
return 0;
}
static const struct of_device_id fm_ant_dt_match[] = {
{.compatible = "prize,fm_ant"},
{},
};
static struct platform_driver fm_ant_driver = {
.probe = fm_ant_probe,
.remove = fm_ant_remove,
.driver = {
.name = "Fm_Ant_Driver",
.of_match_table = of_match_ptr(fm_ant_dt_match),
},
};
static int __init fm_ant_init(void)
{
int retval = 0;
TRACE_FUNC;
// retval = platform_device_register(&hall_device);
printk("[%s]: fm_ant_driver, retval=%d \n!", __func__, retval);
if (retval != 0) {
return retval;
}
platform_driver_register(&fm_ant_driver);
return 0;
}
static void __exit fm_ant_exit(void)
{
TRACE_FUNC;
platform_driver_unregister(&fm_ant_driver);
}
module_init(fm_ant_init);
module_exit(fm_ant_exit);
MODULE_DESCRIPTION("FM ANT DEVICE driver");
MODULE_AUTHOR("huangjiwu <huangjiwu@boruizhiheng.com>");
MODULE_LICENSE("GPL");