kernel_samsung_a34x-permissive/drivers/misc/mediatek/lcm/lcm_gpio.c
2024-04-28 15:51:13 +02:00

327 lines
7.2 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#if defined(MTK_LCM_DEVICE_TREE_SUPPORT)
#include <linux/string.h>
#include <linux/wait.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/pinctrl/consumer.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/module.h>
#ifdef BUILD_LK
#include <platform/upmu_common.h>
#include <platform/upmu_hw.h>
#include <platform/mt_gpio.h>
#include <platform/mt_i2c.h>
#include <platform/mt_pmic.h>
#include <string.h>
#else
#ifdef CONFIG_MTK_LEGACY
#include <mach/mt_pm_ldo.h> /* hwPowerOn */
#include <mt-plat/upmu_common.h>
#include <mach/upmu_sw.h>
#include <mach/upmu_hw.h>
#else
#include <mt-plat/upmu_common.h>
#include <mach/upmu_sw.h>
#include <mach/upmu_hw.h>
#endif
#endif
#ifdef CONFIG_MTK_LEGACY
#include <mach/mt_gpio.h>
#include <cust_gpio_usage.h>
#include <cust_i2c.h>
#else
#include <mt-plat/mt_gpio.h>
#endif
#include "lcm_define.h"
#include "lcm_drv.h"
#include "lcm_gpio.h"
#ifdef CONFIG_MTK_LEGACY
#if defined(GPIO_LCD_BIAS_ENP_PIN)
#define GPIO_65132_EN GPIO_LCD_BIAS_ENP_PIN
#else
#define GPIO_65132_EN 0
#endif
#else
#ifdef CONFIG_PINCTRL
static struct pinctrl *_lcm_gpio;
static struct pinctrl_state *_lcm_gpio_mode_default;
static struct pinctrl_state *_lcm_gpio_mode[MAX_LCM_GPIO_MODE];
static unsigned char _lcm_gpio_mode_list[MAX_LCM_GPIO_MODE][128] = {
"lcm_mode_00",
"lcm_mode_01",
"lcm_mode_02",
"lcm_mode_03",
"lcm_mode_04",
"lcm_mode_05",
"lcm_mode_06",
"lcm_mode_07"
};
static unsigned int GPIO_LCD_PWR_EN;
static unsigned int GPIO_LCD_BL_EN;
#endif
/* function definitions */
static int __init _lcm_gpio_init(void);
static void __exit _lcm_gpio_exit(void);
static int _lcm_gpio_probe(struct platform_device *pdev);
static int _lcm_gpio_remove(struct platform_device *pdev);
#ifdef CONFIG_OF
static const struct of_device_id _lcm_gpio_of_ids[] = {
{.compatible = "mediatek,lcm_mode",},
{},
};
MODULE_DEVICE_TABLE(of, _lcm_gpio_of_ids);
#endif
static struct platform_driver _lcm_gpio_driver = {
.driver = {
.name = LCM_GPIO_DEVICE,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(_lcm_gpio_of_ids),
},
.probe = _lcm_gpio_probe,
.remove = _lcm_gpio_remove,
};
module_platform_driver(_lcm_gpio_driver);
#endif
#ifdef CONFIG_MTK_LEGACY
#else
/* LCM GPIO probe */
static int _lcm_gpio_probe(struct platform_device *pdev)
{
#ifdef CONFIG_PINCTRL
int ret;
unsigned int mode;
const struct of_device_id *match;
struct device *dev = &pdev->dev;
pr_debug("[LCM][GPIO] enter %s, %d\n", __func__, __LINE__);
_lcm_gpio = devm_pinctrl_get(dev);
if (IS_ERR(_lcm_gpio)) {
ret = PTR_ERR(_lcm_gpio);
pr_info("[LCM][ERROR] Cannot find _lcm_gpio!\n");
return ret;
}
_lcm_gpio_mode_default = pinctrl_lookup_state(_lcm_gpio, "default");
if (IS_ERR(_lcm_gpio_mode_default)) {
ret = PTR_ERR(_lcm_gpio_mode_default);
pr_info("[LCM][ERROR] Cannot find lcm_mode_default %d!\n",
ret);
}
for (mode = LCM_GPIO_MODE_00; mode < MAX_LCM_GPIO_MODE; mode++) {
_lcm_gpio_mode[mode] =
pinctrl_lookup_state(_lcm_gpio,
_lcm_gpio_mode_list[mode]);
if (IS_ERR(_lcm_gpio_mode[mode]))
pr_info("[LCM][ERROR] Cannot find lcm_mode:%d! skip it.\n",
mode);
}
if (dev->of_node) {
match = of_match_device(of_match_ptr(_lcm_gpio_of_ids), dev);
if (!match) {
pr_info("[LCM][ERROR] No device match found\n");
return -ENODEV;
}
}
GPIO_LCD_PWR_EN =
of_get_named_gpio(dev->of_node, "lcm_power_gpio", 0);
GPIO_LCD_BL_EN =
of_get_named_gpio(dev->of_node, "lcm_bl_gpio", 0);
ret = gpio_request(GPIO_LCD_PWR_EN, "lcm_power_gpio");
if (ret < 0)
pr_info("[LCM][ERROR] Unable to request GPIO_LCD_PWR_EN\n");
ret = gpio_request(GPIO_LCD_BL_EN, "lcm_bl_gpio");
if (ret < 0)
pr_info("[LCM][ERROR] Unable to request GPIO_LCD_BL_EN\n");
pr_debug("[LCM][GPIO] _lcm_gpio_get_info end!\n");
#endif
return 0;
}
static int _lcm_gpio_remove(struct platform_device *pdev)
{
#ifdef CONFIG_PINCTRL
gpio_free(GPIO_LCD_BL_EN);
gpio_free(GPIO_LCD_PWR_EN);
#endif
return 0;
}
/* called when loaded into kernel */
static int __init _lcm_gpio_init(void)
{
pr_debug("MediaTek LCM GPIO driver init\n");
if (platform_driver_register(&_lcm_gpio_driver) != 0) {
pr_info("unable to register LCM GPIO driver.\n");
return -1;
}
return 0;
}
/* should never be called */
static void __exit _lcm_gpio_exit(void)
{
pr_debug("MediaTek LCM GPIO driver exit\n");
platform_driver_unregister(&_lcm_gpio_driver);
}
#endif
static enum LCM_STATUS _lcm_gpio_check_data(char type,
const struct LCM_DATA_T1 *t1)
{
switch (type) {
case LCM_GPIO_MODE:
switch (t1->data) {
case LCM_GPIO_MODE_00:
case LCM_GPIO_MODE_01:
case LCM_GPIO_MODE_02:
case LCM_GPIO_MODE_03:
case LCM_GPIO_MODE_04:
case LCM_GPIO_MODE_05:
case LCM_GPIO_MODE_06:
case LCM_GPIO_MODE_07:
break;
default:
pr_info("[LCM][ERROR] %s/%d: %d, %d\n",
__func__, __LINE__, type, t1->data);
return LCM_STATUS_ERROR;
}
break;
case LCM_GPIO_DIR:
switch (t1->data) {
case LCM_GPIO_DIR_IN:
case LCM_GPIO_DIR_OUT:
break;
default:
pr_info("[LCM][ERROR] %s/%d: %d, %d\n",
__func__, __LINE__, type, t1->data);
return LCM_STATUS_ERROR;
}
break;
case LCM_GPIO_OUT:
switch (t1->data) {
case LCM_GPIO_OUT_ZERO:
case LCM_GPIO_OUT_ONE:
break;
default:
pr_info("[LCM][ERROR] %s/%d: %d, %d\n",
__func__, __LINE__, type, t1->data);
return LCM_STATUS_ERROR;
}
break;
default:
pr_info("[LCM][ERROR] %s/%d: %d\n",
__func__, __LINE__, type);
return LCM_STATUS_ERROR;
}
return LCM_STATUS_OK;
}
enum LCM_STATUS lcm_gpio_set_data(char type, const struct LCM_DATA_T1 *t1)
{
/* check parameter is valid */
if (_lcm_gpio_check_data(type, t1) == LCM_STATUS_OK) {
switch (type) {
#ifdef CONFIG_MTK_LEGACY
case LCM_GPIO_MODE:
mt_set_gpio_mode(GPIO_65132_EN, (unsigned int)t1->data);
break;
case LCM_GPIO_DIR:
mt_set_gpio_dir(GPIO_65132_EN, (unsigned int)t1->data);
break;
case LCM_GPIO_OUT:
mt_set_gpio_out(GPIO_65132_EN, (unsigned int)t1->data);
break;
#else
#ifdef CONFIG_PINCTRL
case LCM_GPIO_MODE:
pr_debug("[LCM][GPIO] %s/%d: set mode: %d\n",
__func__, __LINE__, (unsigned int)t1->data);
pinctrl_select_state(_lcm_gpio,
_lcm_gpio_mode[(unsigned int)t1->data]);
break;
case LCM_GPIO_DIR:
pr_debug("[LCM][GPIO] %s/%d: set dir: %d, %d\n",
__func__, __LINE__, GPIO_LCD_PWR_EN,
(unsigned int)t1->data);
gpio_direction_output(GPIO_LCD_PWR_EN, (int)t1->data);
break;
case LCM_GPIO_OUT:
pr_debug("[LCM][GPIO] %s/%d: set out: %d, %d\n",
__func__, __LINE__, GPIO_LCD_PWR_EN,
(unsigned int)t1->data);
gpio_set_value(GPIO_LCD_PWR_EN, (int)t1->data);
break;
#else
case LCM_GPIO_MODE:
case LCM_GPIO_DIR:
case LCM_GPIO_OUT:
break;
#endif
#endif
default:
pr_info("[LCM][ERROR] %s/%d: %d\n",
__func__, __LINE__, type);
return LCM_STATUS_ERROR;
}
} else {
pr_info("[LCM][ERROR] %s: 0x%x, 0x%x\n",
__func__, type, t1->data);
return LCM_STATUS_ERROR;
}
return LCM_STATUS_OK;
}
#ifdef CONFIG_MTK_LEGACY
#else
module_init(_lcm_gpio_init);
module_exit(_lcm_gpio_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MediaTek LCM GPIO driver");
MODULE_AUTHOR("Joey Pan<joey.pan@mediatek.com>");
#endif
#endif