diff options
author | Shangbing Hu <shangbing.hu@mediatek.com> | 2016-07-13 06:40:20 +0800 |
---|---|---|
committer | Shangbing Hu <shangbing.hu@mediatek.com> | 2016-07-14 11:25:39 +0800 |
commit | f36ed554c3fea0bedf6b183944396fde22edeaf3 (patch) | |
tree | e8929e3e488f7eafbbea3b7d83922b27a74357ef | |
parent | c858d97915320ffb5067801096d87edb0c9c2a60 (diff) |
[ALPS02768792] HDMI: add openpackage 8193 support
[Detail]
1.modify .dts&.dtsi file according to amt6797_64 project
2.modify .dws file that reuse ext_disp i2c node from 0x39 to 0x1d
3.add open package related code to ext_disp
which is switch by HDMI_OPEN_PACKAGE_SUPPORT macro
4.add MT8193 multibridge code
5.open HDMI & MT8193 in config file
[Solution]
HDMI_OPEN_PACKAGE_SUPPORT is default DISABLE
when build for open package, we should enable this macro
in src code
MTK-Commit-Id: 7ce45ca43a300ee6f173bfd123d75bb7539f16de
Change-Id: I4f37dba556356c0b48d155aba393b4ff0413e699
Signed-off-by: Shangbing Hu <shangbing.hu@mediatek.com>
CR-Id: ALPS02768792
Feature: Driver
22 files changed, 3719 insertions, 12 deletions
diff --git a/arch/arm64/boot/dts/amt6797_64_open.dts b/arch/arm64/boot/dts/amt6797_64_open.dts index 246f4a6dab84..44dd09c24f3a 100644 --- a/arch/arm64/boot/dts/amt6797_64_open.dts +++ b/arch/arm64/boot/dts/amt6797_64_open.dts @@ -1488,3 +1488,55 @@ }; /* SCP DVFS GPIO end */ + +/* USB XHCI GPIO start */ +&pio { + iddig_default: iddig_default { + }; + + gpio181_mode1_iddig: iddig_init { + pins_cmd_dat { + pins = <PINMUX_GPIO181__FUNC_IDDIG>; + slew-rate = <0>; + bias-pull-up = <00>; + }; + }; +}; + +&pio { + drvvbus_default: drvvbus_default { + }; + + gpio94_mode1_drvvbus_low: drvvbus_low { + pins_cmd_dat { + pins = <PINMUX_GPIO94__FUNC_USB_DRVVBUS>; + slew-rate = <1>; + output-low; + }; + }; + + gpio94_mode1_drvvbus_high: drvvbus_high { + pins_cmd_dat { + pins = <PINMUX_GPIO94__FUNC_USB_DRVVBUS>; + slew-rate = <1>; + output-high; + }; + }; +}; + +&usb0 { + pinctrl-names = "iddig_default", "iddig_init"; + pinctrl-0 = <&iddig_default>; + pinctrl-1 = <&gpio181_mode1_iddig>; + status = "okay"; +}; + +&xhci0 { + pinctrl-names = "drvvbus_default", "drvvbus_low", "drvvbus_high"; + pinctrl-0 = <&drvvbus_default>; + pinctrl-1 = <&gpio94_mode1_drvvbus_low>; + pinctrl-2 = <&gpio94_mode1_drvvbus_high>; + status = "okay"; +}; + +/* USB XHCI GPIO start */ diff --git a/arch/arm64/boot/dts/mt6797.dtsi b/arch/arm64/boot/dts/mt6797.dtsi index fdb6e9ed249e..d78b8ae1a172 100644 --- a/arch/arm64/boot/dts/mt6797.dtsi +++ b/arch/arm64/boot/dts/mt6797.dtsi @@ -774,6 +774,7 @@ vcn33_bt-supply = <&mt_pmic_vcn33_bt_ldo_reg>; vcn33_wifi-supply = <&mt_pmic_vcn33_wifi_ldo_reg>; mhl_12v-supply = <&mt_pmic_vgp3_ldo_reg>; + vldo28-supply = <&mt_pmic_vldo28_ldo_reg>; }; /* End of regulators_supply */ }; diff --git a/arch/arm64/configs/amt6797_64_open_debug_defconfig b/arch/arm64/configs/amt6797_64_open_debug_defconfig index 4881d8adf79d..b242b7fb63fa 100644 --- a/arch/arm64/configs/amt6797_64_open_debug_defconfig +++ b/arch/arm64/configs/amt6797_64_open_debug_defconfig @@ -176,6 +176,7 @@ CONFIG_ARCH_MTK_PROJECT="amt6797_64_open" CONFIG_MT_ENG_BUILD=y CONFIG_MTK_SHARED_SDCARD=y CONFIG_MTK_GPT_SCHEME_SUPPORT=y +CONFIG_MTK_DISABLE_PICACHU=y CONFIG_MTK_FREQ_HOPPING=y CONFIG_MTK_BQ25896_SUPPORT=y CONFIG_CUSTOM_KERNEL_IMGSENSOR="ov23850_mipi_raw s5k3m2_mipi_raw s5k5e2ya_mipi_raw imx258_mipi_raw imx377_mipi_raw s5k2x8_mipi_raw" @@ -237,6 +238,8 @@ CONFIG_MTK_SMI_EXT=y # CONFIG_USB_MTK_HDRC is not set CONFIG_MTK_MUSB_QMU_SUPPORT=y CONFIG_MTK_VIBRATOR=y +CONFIG_USB_XHCI_MTK=y +CONFIG_USB_MTK_DUALMODE=y CONFIG_MTK_MEMCFG=y CONFIG_MTK_AEE_FEATURE=y CONFIG_MTK_AEE_MRDUMP=y @@ -385,6 +388,7 @@ CONFIG_HID_TOPSEED=y CONFIG_HID_THRUSTMASTER=y CONFIG_HID_ZEROPLUS=y CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y CONFIG_USB_STORAGE=y CONFIG_USB_STORAGE_DEBUG=y CONFIG_USB_STORAGE_DATAFAB=y diff --git a/arch/arm64/configs/amt6797_64_open_defconfig b/arch/arm64/configs/amt6797_64_open_defconfig index eb0508d86f7b..19a712127f84 100644 --- a/arch/arm64/configs/amt6797_64_open_defconfig +++ b/arch/arm64/configs/amt6797_64_open_defconfig @@ -171,6 +171,7 @@ CONFIG_MTK_PLATFORM="mt6797" CONFIG_ARCH_MTK_PROJECT="amt6797_64_open" CONFIG_MTK_SHARED_SDCARD=y CONFIG_MTK_GPT_SCHEME_SUPPORT=y +CONFIG_MTK_DISABLE_PICACHU=y CONFIG_MTK_FREQ_HOPPING=y CONFIG_MTK_BQ25896_SUPPORT=y CONFIG_CUSTOM_KERNEL_IMGSENSOR="ov23850_mipi_raw s5k3m2_mipi_raw s5k5e2ya_mipi_raw imx258_mipi_raw imx377_mipi_raw s5k2x8_mipi_raw" @@ -232,6 +233,8 @@ CONFIG_MTK_SMI_EXT=y # CONFIG_USB_MTK_HDRC is not set CONFIG_MTK_MUSB_QMU_SUPPORT=y CONFIG_MTK_VIBRATOR=y +CONFIG_USB_XHCI_MTK=y +CONFIG_USB_MTK_DUALMODE=y CONFIG_MTK_AEE_FEATURE=y CONFIG_MTK_CHIP=y CONFIG_GATOR_DRIVER=y @@ -376,6 +379,7 @@ CONFIG_HID_TOPSEED=y CONFIG_HID_THRUSTMASTER=y CONFIG_HID_ZEROPLUS=y CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y CONFIG_USB_STORAGE=y CONFIG_USB_STORAGE_DATAFAB=y CONFIG_USB_STORAGE_FREECOM=y diff --git a/drivers/misc/mediatek/ext_disp/extd_hdmi.c b/drivers/misc/mediatek/ext_disp/extd_hdmi.c index d8543399bb17..c90d1b4aaeb2 100644 --- a/drivers/misc/mediatek/ext_disp/extd_hdmi.c +++ b/drivers/misc/mediatek/ext_disp/extd_hdmi.c @@ -137,6 +137,15 @@ struct task_struct *hdmi_fence_release_task = NULL; wait_queue_head_t hdmi_fence_release_wq; atomic_t hdmi_fence_release_event = ATOMIC_INIT(0); +/*#define HDMI_OPEN_PACAKAGE_SUPPORT*/ + +#ifdef HDMI_OPEN_PACAKAGE_SUPPORT +struct task_struct *hdmi_para_config_task = NULL; +wait_queue_head_t hdmi_para_config_wq; +atomic_t hdmi_para_config_event = ATOMIC_INIT(0); +#endif + + struct task_struct *hdmi_wait_vsync_task = NULL; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -397,7 +406,10 @@ int hdmi_get_support_info(void) #endif #ifdef MTK_AUDIO_MULTI_CHANNEL_SUPPORT - temp = hdmi_drv->get_external_device_capablity(); + if (hdmi_drv->get_external_device_capablity != NULL) + temp = hdmi_drv->get_external_device_capablity(); + else + temp = 0x2 << 3; #else temp = 0x2 << 3; #endif @@ -516,6 +528,28 @@ static void _hdmi_rdma_irq_handler(DISP_MODULE_ENUM module, unsigned int param) first_frame_done = 1; } +#ifdef HDMI_OPEN_PACAKAGE_SUPPORT +static int hdmi_para_config_kthread(void *data) +{ + + struct sched_param param = {.sched_priority = 94 }; /*RTPM_PRIO_SCRN_UPDATE*/ + + sched_setscheduler(current, SCHED_RR, ¶m); + for (;;) { + + wait_event_interruptible(hdmi_para_config_wq, atomic_read(&hdmi_para_config_event)); + atomic_set(&hdmi_para_config_event, 0); + + hdmi_set_resolution(HDMI_VIDEO_1280x720p_60Hz); + + if (kthread_should_stop()) + break; + } + + return 0; +} +#endif + static int hdmi_fence_release_kthread(void *data) { int layid = 0; @@ -667,6 +701,14 @@ static enum HDMI_STATUS hdmi_drv_init(void) wake_up_process(hdmi_fence_release_task); } +#ifdef HDMI_OPEN_PACAKAGE_SUPPORT + if (!hdmi_para_config_task) { + hdmi_para_config_task = kthread_create(hdmi_para_config_kthread, + NULL, "hdmi_fence_release_kthread"); + wake_up_process(hdmi_para_config_task); + } +#endif + if (!hdmi_3d_config_task) { hdmi_3d_config_task = kthread_create(hdmi_3d_config_kthread, NULL, "hdmi_3d_config_kthread"); wake_up_process(hdmi_3d_config_task); @@ -732,6 +774,7 @@ static void hdmi_state_reset(void) rdmafpscnt = 0; up(&hdmi_update_mutex); + hdmi_reschange = HDMI_VIDEO_RESOLUTION_NUM; MMProfileLogEx(ddp_mmp_get_events()->Extd_State, MMProfileFlagEnd, Plugout, 0); } @@ -789,6 +832,14 @@ static void hdmi_state_reset(void) hdmi_state_reset(); } } + +#ifdef HDMI_OPEN_PACAKAGE_SUPPORT + if (hdmi_drv->get_state() == HDMI_STATE_ACTIVE) { + atomic_set(&hdmi_para_config_event, 1); + wake_up_interruptible(&hdmi_para_config_wq); + } +#endif + } /*static*/ void hdmi_power_off(void) @@ -1002,6 +1053,11 @@ void hdmi_state_callback(enum HDMI_STATE state) ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_MHL_EVENT, true); #endif HDMI_LOG("[hdmi]%s, state = %d out!\n", __func__, state); + +#ifdef HDMI_OPEN_PACAKAGE_SUPPORT + atomic_set(&hdmi_para_config_event, 1); + wake_up_interruptible(&hdmi_para_config_wq); +#endif break; } default: @@ -1035,6 +1091,9 @@ int hdmi_enable(int enable) hdmi_drv->enter(); hdmi_drv_init(); +#ifdef HDMI_OPEN_PACAKAGE_SUPPORT + p->is_enabled = true; +#endif hdmi_power_on(); p->is_enabled = true; } else { @@ -1059,6 +1118,10 @@ int hdmi_power_enable(int enable) { HDMI_FUNC(); if (!p->is_enabled) { + +#ifdef HDMI_OPEN_PACAKAGE_SUPPORT + hdmi_enable(true); +#endif HDMI_LOG("return in %d\n", __LINE__); return 0; } @@ -1487,12 +1550,15 @@ int hdmi_post_init(void) return -1; } - hdmi_drv->set_util_funcs(&hdmi_utils); + if (hdmi_drv->set_util_funcs != NULL) + hdmi_drv->set_util_funcs(&hdmi_utils); hdmi_params->init_config.vformat = HDMI_VIDEO_1280x720p_60Hz; - hdmi_drv->get_params(hdmi_params); + if (hdmi_drv->get_params != NULL) + hdmi_drv->get_params(hdmi_params); - hdmi_drv->init(); /* need to remove to power on function Donglei */ + if (hdmi_drv->init != NULL) + hdmi_drv->init(); /* need to remove to power on function Donglei */ if (hdmi_drv->register_callback != NULL) { boot_mode = (int)get_boot_mode(); if (boot_mode == FACTORY_BOOT || boot_mode == ATE_FACTORY_BOOT) { @@ -1516,6 +1582,9 @@ int hdmi_post_init(void) init_waitqueue_head(&hdmi_3d_config_wq); +#ifdef HDMI_OPEN_PACAKAGE_SUPPORT + init_waitqueue_head(&hdmi_para_config_wq); +#endif Extd_DBG_Init(); return 0; } diff --git a/drivers/misc/mediatek/ext_disp/extd_hdmi.h b/drivers/misc/mediatek/ext_disp/extd_hdmi.h index eea61b1ba495..2a9ab81676d8 100644 --- a/drivers/misc/mediatek/ext_disp/extd_hdmi.h +++ b/drivers/misc/mediatek/ext_disp/extd_hdmi.h @@ -218,6 +218,7 @@ void hdmi_power_off(void); int hdmi_wait_vsync_debug(int enable); int hdmi_dump_vendor_chip_register(void); +int hdmi_set_resolution(int res); extern void Extd_DBG_Init(void); #endif diff --git a/drivers/misc/mediatek/hdmi/inc/hdmi_drv.h b/drivers/misc/mediatek/hdmi/inc/hdmi_drv.h index fc1bd1d31b59..e1689030038a 100644 --- a/drivers/misc/mediatek/hdmi/inc/hdmi_drv.h +++ b/drivers/misc/mediatek/hdmi/inc/hdmi_drv.h @@ -345,4 +345,5 @@ const struct HDMI_DRIVER *HDMI_GetDriver(void); void Notify_AP_MHL_TX_Event(unsigned int event, unsigned int event_param, void *param); extern int chip_device_id; extern bool need_reset_usb_switch; +extern struct device *ext_dev_context; #endif /* __HDMI_DRV_H__ */ diff --git a/drivers/misc/mediatek/hdmi/mt8193/hdmi_drv.c b/drivers/misc/mediatek/hdmi/mt8193/hdmi_drv.c index 29fde3469812..366972bfc5c9 100644 --- a/drivers/misc/mediatek/hdmi/mt8193/hdmi_drv.c +++ b/drivers/misc/mediatek/hdmi/mt8193/hdmi_drv.c @@ -19,7 +19,7 @@ #include <linux/slab.h> #include <linux/irq.h> #include <linux/miscdevice.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/delay.h> #include <linux/input.h> #include <linux/workqueue.h> @@ -28,7 +28,7 @@ #include <linux/earlysuspend.h> #endif #include <linux/platform_device.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #include <linux/init.h> #include <linux/module.h> #include <linux/sched.h> @@ -72,7 +72,11 @@ /*----------------------------------------------------------------------------*/ /* Debug message defination */ /*----------------------------------------------------------------------------*/ - +/*#define HDMI_OPEN_PACAKAGE_SUPPORT*/ +#ifdef HDMI_OPEN_PACAKAGE_SUPPORT +#include <linux/pinctrl/consumer.h> +char *power_pin_name[2] = {"power_default", "power_up"}; +#endif /*----------------------------------------------------------------------------*/ /* HDMI Timer */ /*----------------------------------------------------------------------------*/ @@ -294,7 +298,7 @@ static void mt8193_resume(void) /*----------------------------------------------------------------------------*/ static int mt8193_video_config(enum HDMI_VIDEO_RESOLUTION vformat, enum HDMI_VIDEO_INPUT_FORMAT vin, - enum HDMI_VIDEO_OUTPUT_FORMAT vout) + int vout) { HDMI_DEF_LOG("[hdmi]mt8193_video_config:%d\n", vformat); @@ -378,9 +382,14 @@ void mt8193_set_mode(unsigned char ucMode) int mt8193_power_on(void) { +#ifdef HDMI_OPEN_PACAKAGE_SUPPORT + int ret = 0; + struct pinctrl *power_pinctrl; + struct pinctrl_state *pin_state; +#else struct device_node *dn; int bus_switch_pin; - +#endif HDMI_DEF_LOG("[hdmi]mt8193_power_on_\n"); if (hdmi_powerenable == 1) { @@ -402,10 +411,29 @@ int mt8193_power_on(void) mt_set_gpio_out(GPIO_HDMI_POWER_CONTROL, GPIO_OUT_ONE); HDMI_DEF_LOG("[hdmi]hdmi_5v_on\n"); #endif - +#ifdef HDMI_OPEN_PACAKAGE_SUPPORT + if (ext_dev_context == NULL) { + pr_err("Cannot find ext_dev_context!\n"); + return 0; + } + power_pinctrl = devm_pinctrl_get(ext_dev_context); + if (IS_ERR(power_pinctrl)) { + ret = PTR_ERR(power_pinctrl); + pr_err("Cannot find mt8193 power pinctrl!\n"); + return 0; + } + pin_state = pinctrl_lookup_state(power_pinctrl, power_pin_name[1]); + if (IS_ERR(pin_state)) { + ret = PTR_ERR(pin_state); + pr_err("Cannot find mt8193 power pin state!\n"); + return 0; + } + pinctrl_select_state(power_pinctrl, pin_state); +#else dn = of_find_compatible_node(NULL, NULL, "mediatek,mt8193-hdmi"); bus_switch_pin = of_get_named_gpio(dn, "hdmi_power_gpios", 0); gpio_direction_output(bus_switch_pin, 1); +#endif vWriteHdmiSYSMsk(HDMI_PWR_CTRL, hdmi_power_turnon, hdmi_power_turnon); vWriteHdmiSYSMsk(HDMI_SYS_PWR_RST_B, hdmi_pwr_sys_sw_unreset, hdmi_pwr_sys_sw_unreset); @@ -430,9 +458,14 @@ int mt8193_power_on(void) void mt8193_power_off(void) { +#ifdef HDMI_OPEN_PACAKAGE_SUPPORT + int ret = 0; + struct pinctrl *power_pinctrl; + struct pinctrl_state *pin_state; +#else struct device_node *dn; int bus_switch_pin; - +#endif HDMI_DEF_LOG("[hdmi]mt8193_power_off\n"); if (hdmi_powerenable == 0) { HDMI_DEF_LOG("[hdmi]already power off, return\n"); @@ -459,10 +492,29 @@ void mt8193_power_off(void) mt_set_gpio_out(GPIO_HDMI_POWER_CONTROL, GPIO_OUT_ZERO); HDMI_DEF_LOG("[hdmi]hdmi_5v_off\n"); #endif - +#ifdef HDMI_OPEN_PACAKAGE_SUPPORT + if (ext_dev_context == NULL) { + pr_err("Cannot find ext_dev_context!\n"); + return; + } + power_pinctrl = devm_pinctrl_get(ext_dev_context); + if (IS_ERR(power_pinctrl)) { + ret = PTR_ERR(power_pinctrl); + pr_err("Cannot find mt8193 power pinctrl! ret = %d\n", ret); + return; + } + pin_state = pinctrl_lookup_state(power_pinctrl, power_pin_name[0]); + if (IS_ERR(pin_state)) { + ret = PTR_ERR(pin_state); + pr_err("Cannot find mt8193 power pin state! ret = %d\n", ret); + return; + } + pinctrl_select_state(power_pinctrl, pin_state); +#else dn = of_find_compatible_node(NULL, NULL, "mediatek,mt8193-hdmi"); bus_switch_pin = of_get_named_gpio(dn, "hdmi_power_gpios", 0); gpio_direction_output(bus_switch_pin, 0); +#endif vWriteHdmiSYSMsk(HDMI_PWR_CTRL, hdmi_clock_off, hdmi_clock_off); vWriteHdmiSYSMsk(HDMI_PWR_CTRL, hdmi_iso_en, hdmi_iso_en); diff --git a/drivers/misc/mediatek/hdmi/mt8193/mt8193table.h b/drivers/misc/mediatek/hdmi/mt8193/mt8193table.h index cd631462ca75..925ef6dd96e0 100644 --- a/drivers/misc/mediatek/hdmi/mt8193/mt8193table.h +++ b/drivers/misc/mediatek/hdmi/mt8193/mt8193table.h @@ -30,6 +30,8 @@ enum HDMI_VIDEO_RESOLUTION { HDMI_VIDEO_1920x1080p_29Hz, /* a */ HDMI_VIDEO_1920x1080p_60Hz, /* b */ HDMI_VIDEO_1920x1080p_50Hz, /* c */ + HDMI_VIDEO_2160p_DSC_30Hz = 0x13, + HDMI_VIDEO_2160p_DSC_24Hz = 0x14, HDMI_VIDEO_RESOLUTION_NUM }; diff --git a/drivers/misc/mediatek/multibridge/mt6797/Makefile b/drivers/misc/mediatek/multibridge/mt6797/Makefile new file mode 100644 index 000000000000..44f1c19c2723 --- /dev/null +++ b/drivers/misc/mediatek/multibridge/mt6797/Makefile @@ -0,0 +1,15 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms 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. +# + + +obj-$(CONFIG_MTK_MULTIBRIDGE_SUPPORT) += mt8193/ diff --git a/drivers/misc/mediatek/multibridge/mt6797/mt8193/Makefile b/drivers/misc/mediatek/multibridge/mt6797/mt8193/Makefile new file mode 100644 index 000000000000..767279b19ced --- /dev/null +++ b/drivers/misc/mediatek/multibridge/mt6797/mt8193/Makefile @@ -0,0 +1,24 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms 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. +# + + +ifeq ($(CONFIG_MTK_MULTIBRIDGE_SUPPORT),y) + +ccflags-y += -I$(srctree)/drivers/misc/mediatek/multibridge/$(CONFIG_MTK_PLATFORM)/mt8193/inc + +obj-y += mt8193_ckgen.o +obj-y += mt8193_ckgen_vfy.o +obj-y += mt8193_gpio.o +obj-y += mt8193_iic.o +obj-y += mt8193_pinmux.o +endif
\ No newline at end of file diff --git a/drivers/misc/mediatek/multibridge/mt6797/mt8193/inc/mt8193.h b/drivers/misc/mediatek/multibridge/mt6797/mt8193/inc/mt8193.h new file mode 100644 index 000000000000..d70d6cababd9 --- /dev/null +++ b/drivers/misc/mediatek/multibridge/mt6797/mt8193/inc/mt8193.h @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms 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. + */ + +#ifndef MT8193_H +#define MT8193_H + + +#include <generated/autoconf.h> +#include <linux/mm.h> +#include <linux/init.h> +#include <linux/fb.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/kthread.h> +#include <linux/vmalloc.h> +#include <linux/uaccess.h> +#include <linux/atomic.h> +#include <asm/cacheflush.h> +#include <linux/io.h> + +#include <mach/irqs.h> + +#include <linux/miscdevice.h> +#include <linux/fs.h> +#include <linux/file.h> +#include <linux/cdev.h> +#include <asm/tlbflush.h> +#include <asm/page.h> +#include <linux/slab.h> +#include <linux/module.h> + + +#include "mt8193_iic.h" + +#define CKGEN_BASE 0x1000 + + +#define REG_RW_BUS_CKCFG 0x000 +#define CLK_BUS_SEL_XTAL 0 +#define CLK_BUS_SEL_NFIPLL_D2 1 +#define CLK_BUS_SEL_NFIPLL_D3 2 +#define CLK_BUS_SEL_XTAL_D2 3 +#define CLK_BUS_SEL_32K 4 +#define CLK_BUS_SEL_PAD_DPI0 5 +#define CLK_BUS_SEL_PAD_DPI1 6 +#define CLK_BUS_SEL_ROSC 7 + + +#define REG_RW_NFI_CKCFG 0x008 +#define CLK_NFI_SEL_NFIPLL 0 +#define CLK_NFI_SEL_NFIPLL_D2 1 +#define CLK_NFI_SEL_NFIPLL_D3 2 +#define CLK_NFI_SEL_XTAL_D1 3 +#define CLK_PDN_NFI (1U<<7) + + +#define REG_RW_HDMI_PLL_CKCFG 0x00c +#define CLK_HDMI_PLL_SEL_HDMIPLL 0 +#define CLK_HDMI_PLL_SEL_32K 1 +#define CLK_HDMI_PLL_SEL_XTAL_D1 2 +#define CLK_HDMI_PLL_SEL_NFIPLL 3 +#define CLK_PDN_HDMI_PLL (1U<<7) + + + +#define REG_RW_HDMI_DISP_CKCFG 0x010 +#define CLK_HDMI_DISP_SEL_DISP 0 +#define CLK_HDMI_DISP_SEL_32K 1 +#define CLK_HDMI_DISP_SEL_XTAL_D1 2 +#define CLK_HDMI_DISP_SEL_NFIPLL 3 +#define CLK_PDN_HDMI_DISP (1U<<7) + + +#define REG_RW_LVDS_DISP_CKCFG 0x014 +#define CLK_LVDS_DISP_SEL_AD_VPLL_DPIX 0 +#define CLK_LVDS_DISP_SEL_32K 1 +#define CLK_LVDS_DISP_SEL_XTAL_D1 2 +#define CLK_LVDS_DISP_SEL_NFIPLL 3 +#define CLK_PDN_LVDS_DISP (1U<<7) + + +#define REG_RW_LVDS_CTS_CKCFG 0x018 +#define CLK_LVDS_CTS_SEL_AD_VPLL_DPIX 0 +#define CLK_LVDS_CTS_SEL_32K 1 +#define CLK_LVDS_CTS_SEL_XTAL_D1 2 +#define CLK_LVDS_CTS_SEL_NFIPLL 3 +#define CLK_PDN_LVDS_CTS (1U<<7) + + +#define REG_RW_PMUX0 0x200 +#define REG_RW_PMUX1 0x204 +#define REG_RW_PMUX2 0x208 +#define REG_RW_PMUX3 0x20c +#define REG_RW_PMUX4 0x210 +#define REG_RW_PMUX5 0x214 +#define REG_RW_PMUX6 0x218 +#define REG_RW_PMUX7 0x21c +#define REG_RW_PMUX8 0x220 +#define REG_RW_PMUX9 0x224 + + + +#define REG_RW_GPIO_EN_1 0x128 +#define REG_RW_GPIO_OUT_1 0x11c +#define REG_RW_GPIO_IN_1 0x138 + + +#define REG_RW_GPIO_EN_0 0x124 /* need get register addr */ +/* #define REG_RW_GPIO_OUT_0 0x11c // need get register addr */ +#define REG_RW_GPIO_IN_0 0x134 /* need get register addr */ + +/* #define REG_RW_GPIO_EN_2 0x128 // need get register addr */ +/* #define REG_RW_GPIO_OUT_2 0x11c // need get register addr */ +/* #define REG_RW_GPIO_IN_2 0x138 // need get register addr */ + + +#define REG_RW_PLL_GPANACFG0 0x34c +#define PLL_GPANACFG0_NFIPLL_EN (1U<<1) + + +#define REG_RW_PAD_PD0 0x258 +#define REG_RW_PAD_PD1 0x25c +#define REG_RW_PAD_PD2 0x260 + +#define REG_RW_PAD_PU0 0x264 +#define REG_RW_PAD_PU1 0x268 +#define REG_RW_PAD_PU2 0x26c + + +extern int mt8193_ckgen_i2c_write(u16 addr, u32 data); +extern u32 mt8193_ckgen_i2c_read(u16 addr); + + +#define IO_READ8(base, offset) mt8193_ckgen_i2c_read((base) + (offset)) +#define IO_READ16(base, offset) mt8193_ckgen_i2c_read((base) + (offset)) +#define IO_READ32(base, offset) mt8193_ckgen_i2c_read((base) + (offset)) + +/*===========================================================================*/ +/* Macros for register write */ +/*===========================================================================*/ +#define IO_WRITE8(base, offset, value) mt8193_ckgen_i2c_write((base) + (offset), (value)) +#define IO_WRITE16(base, offset, value) mt8193_ckgen_i2c_write((base) + (offset), (value)) +#define IO_WRITE32(base, offset, value) mt8193_ckgen_i2c_write((base) + (offset), (value)) + + +#define CKGEN_READ8(offset) IO_READ8(CKGEN_BASE, (offset)) +#define CKGEN_READ16(offset) IO_READ16(CKGEN_BASE, (offset)) +#define CKGEN_READ32(offset) IO_READ32(CKGEN_BASE, (offset)) + +#define CKGEN_WRITE8(offset, value) IO_WRITE8(CKGEN_BASE, (offset), (value)) +#define CKGEN_WRITE16(offset, value) IO_WRITE16(CKGEN_BASE, (offset), (value)) +#define CKGEN_WRITE32(offset, value) IO_WRITE32(CKGEN_BASE, (offset), (value)) + + +/*=======================================================================*/ +/* Constant Definitions */ +/*=======================================================================*/ + +enum SRC_CK_T { + SRC_CK_APLL, + SRC_CK_ARMPLL, + SRC_CK_VDPLL, + SRC_CK_DMPLL, + SRC_CK_SYSPLL1, + SRC_CK_SYSPLL2, + SRC_CK_USBCK, + SRC_CK_MEMPLL, + SRC_CK_MCK +}; + +enum e_CLK_T { + e_CLK_NFI, /*0 0x70.3 */ + e_CLK_HDMIPLL, /* 1 0x70.7 */ + e_CLK_HDMIDISP, + e_CLK_LVDSDISP, + e_CLK_LVDSCTS, + e_CLK_MAX /* 2 */ +}; + +enum e_CKGEN_T { + e_CKEN_NFI, /* 0 0x300.31 */ + e_CKEN_HDMI, /* 1 0x300.29 */ + e_CKEN_MAX /* 2 */ +}; + +#define MT8193_I2C_ID 1 +#define USING_MT8193_DPI1 1 + +#endif /* MT8193_H */ diff --git a/drivers/misc/mediatek/multibridge/mt6797/mt8193/inc/mt8193_ckgen.h b/drivers/misc/mediatek/multibridge/mt6797/mt8193/inc/mt8193_ckgen.h new file mode 100644 index 000000000000..35d27099eaee --- /dev/null +++ b/drivers/misc/mediatek/multibridge/mt6797/mt8193/inc/mt8193_ckgen.h @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms 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. + */ + +#ifndef MT8193_CKGEN_H +#define MT8193_CKGEN_H + +#define MT8193_CKGEN_VFY 1 + +#define MT8193_DISABLE_DCXO 0 + + +#define CKGEN_IOW(num, dtype) _IOW('H', num, dtype) +#define CKGEN_IOR(num, dtype) _IOR('H', num, dtype) +#define CKGEN_IOWR(num, dtype) _IOWR('H', num, dtype) +#define CKGEN_IO(num) _IO('H', num) + +#define MTK_MT8193_CKGEN_1 CKGEN_IO(1) +#define MTK_MT8193_CKGEN_2 CKGEN_IO(2) +#define MTK_MT8193_CKGEN_LS_TEST CKGEN_IO(3) /* level shift test */ +#define MTK_MT8193_CKGEN_SPM_CTRL CKGEN_IO(4) /* spm ctrl test */ +#define MTK_MT8193_CKGEN_FREQ_METER CKGEN_IO(5) /* FREQ METER TEST*/ +#define MTK_MT8193_GPIO_CTRL CKGEN_IO(6) /* GPIO CTRL*/ +#define MTK_MT8193_EARLY_SUSPEND CKGEN_IO(7) /* early suspend*/ +#define MTK_MT8193_LATE_RESUME CKGEN_IO(8) /* late resume*/ + +#define REG_RW_FMETER 0x04c /* freq meter register */ +#define CKGEN_FMETER_RESET 1 +#define CKGEN_FMETER_START (1U<<1) +#define CKGEN_FMETER_DONE (1U<<2) + +/* HDMI POWER OFF/ON CONTROL*/ + +#define REG_RW_HDMI_PWR_RST_B 0x100 +#define CKGEN_HDMI_PWR_RST_EN 1 + +#define REG_RW_HDMI_PWR_CTRL 0x104 +#define CKGEN_HDMI_PWR_ISO_EN 1 +#define CKGEN_HDMI_PWR_PWR_ON (1U<<1) +#define CKGEN_HDMI_PWR_CLK_OFF (1U<<2) + +/* LVDS POWER OFF/ON CONTROL*/ + +#define REG_RW_LVDS_PWR_RST_B 0x108 +#define CKGEN_LVDS_PWR_RST_EN 1 + +#define REG_RW_LVDS_PWR_CTRL 0x10c +#define CKGEN_LVDS_PWR_ISO_EN 1 +#define CKGEN_LVDS_PWR_PWR_ON (1U<<1) +#define CKGEN_LVDS_PWR_CLK_OFF (1U<<2) + +/* NFI POWER OFF/ON CONTROL*/ + +#define REG_RW_NFI_PWR_RST_B 0x110 +#define CKGEN_NFI_PWR_RST_EN 1 + +#define REG_RW_NFI_PWR_CTRL 0x114 +#define CKGEN_NFI_PWR_ISO_EN 1 +#define CKGEN_NFI_PWR_PWR_ON (1U<<1) +#define CKGEN_NFI_PWR_CLK_OFF (1U<<2) + +#define REG_RO_PWR_ACT 0x118 +#define CKGEN_NFI_PWR_ON_ACT 1 +#define CKGEN_LVDS_PWR_ON_ACT (1U<<1) +#define CKGEN_HDMI_PWR_ON_ACT (1U<<2) + +#define REG_RW_LS_CTRL 0x012c /* level shift control */ +#define LS_CTRL_GROUP0_SHIFT_HIGH 1 /* 0: 3.3 -> 1.8; 1: 1.8->3.3 */ +#define LS_CTRL_GROUP1_SHIFT_HIGH (1U<<1) /* 0: 3.3 -> 1.8; 1: 1.8->3.3 */ +#define LS_CTRL_GROUP2_SHIFT_HIGH (1U<<2) /* 0: 3.3 -> 1.8; 1: 1.8->3.3 */ +#define LS_CTRL_GROUP3_SHIFT_HIGH (1U<<3) /* 0: 3.3 -> 1.8; 1: 1.8->3.3 */ +#define LS_CTRL_GROUP4_SHIFT_HIGH (1U<<4) /* 0: 3.3 -> 1.8; 1: 1.8->3.3 */ +#define LS_CTRL_GROUP5_SHIFT_HIGH (1U<<5) /* 0: 3.3 -> 1.8; 1: 1.8->3.3 */ +#define LS_CTRL_GROUP6_SHIFT_HIGH (1U<<6) /* 0: 3.3 -> 1.8; 1: 1.8->3.3 */ +#define LS_CTRL_SHIFT_HIGH_EN (1U<<30) /* 1.8>3.3 enable */ +#define LS_CTRL_SHIFT_LOW_EN (1U<<31) /* 3.3>1.8 enable */ + +#define REG_RW_LVDS_ANACFG4 0x320 +#define LVDS_ANACFG4_VPlLL_PD (1U<<10) + +#define REG_RW_HDMITX_ANACFG3 0x334 +#define HDMITX_ANACFG3_BIT20 (1U<<20) +#define HDMITX_ANACFG3_BIT21 (1U<<21) + +#define REG_RW_PLLGP_ANACFG0 0x34c +#define PLLGP_ANACFG0_PLL1_RESERVED 1 +#define PLLGP_ANACFG0_PLL1_NFIPLL_EN (1U<<1) +#define PLLGP_ANACFG0_PLL1_EN (1U<<31) + +#define REG_RW_PLLGP_ANACFG2 0x354 +#define PLLGP_ANACFG2_PLLGP_BIAS_EN (1U<<20) + +#define REG_RW_DCXO_ANACFG9 0x388 +#define DCXO_ANACFG9_BUS_CK_SOURCE_SEL_SHIFT 9 +#define DCXO_ANACFG9_BUS_CK_SOURCE_SEL_MASK 0x7 +#define DCX0_ANACFG9_BUS_CK_CTRL_SEL (1U<<7) +#define DCX0_ANACFG9_BUS_CK_AUTO_SWITCH_EN (1U<<5) + +/* DCXO */ + +#define REG_RW_DCXO_ANACFG2 0x308 +#define DCXO_ANACFG2_LDO4_EN (1U<<2) +#define DCXO_ANACFG2_LDO4_MAN_EN (1U<<3) +#define DCXO_ANACFG2_LDO3_EN (1U<<4) +#define DCXO_ANACFG2_LDO3_MAN_EN (1U<<5) +#define DCXO_ANACFG2_LDO2_EN (1U<<6) +#define DCXO_ANACFG2_LDO2_MAN_EN (1U<<7) +#define DCXO_ANACFG2_LDO1_EN (1U<<8) +#define DCXO_ANACFG2_LDO1_MAN_EN (1U<<9) +#define DCXO_ANACFG2_PO_MAN (1U<<29) + +#define REG_RW_DCXO_ANACFG4 0x370 +#define DCXO_ANACFG4_BT_MAN (1U<<18) +#define DCXO_ANACFG4_EXT2_MAN (1U<<19) +#define DCXO_ANACFG4_EXT1_MAN (1U<<20) + +#if MT8193_CKGEN_VFY +/* level shift test parameter */ +struct mt8193_ckgen_ls_info_t { + int i4GroupNum; + int i4TurnLow; +}; + +/* freq meter parameter */ +struct mt8193_ckgen_freq_meter_t { + int u4Func; +}; + +/* GPIO CTRL parameter */ +struct mt8193_gpio_ctrl_t { + int u4GpioNum; + int u4Mode; /* 0 is input. 1 is output */ + int u4Value; /* 1 is high. 0 is low. only valid in output mode */ +}; + +#if 0 + +/* config gpio */ +int mt8193_ckgen_gpio_config(int i4GpioNum, int i4Output, int i4High); + +/* print gpio input value */ +int mt8193_ckgen_gpio_input(int i4GpioNum); + + +/* test pad level shift */ +int mt8193_ckgen_config_pad_level_shift(int i4GroupNum, int i4TurnLow); + +/* read and print chip id */ +void mt8193_ckgen_chipid(void); + + +/* measure clock with freq meter */ +u32 mt8193_ckgen_measure_clk(u32 u4Func); + +u32 mt8193_ckgen_reg_rw_test(u16 addr); +#endif + +extern int multibridge_exit; + +void mt8193_lvds_sys_spm_control(bool power_on); +void mt8193_hdmi_sys_spm_control(bool power_on); +void mt8193_nfi_sys_spm_control(bool power_on); +void mt8193_lvds_ana_pwr_control(bool power_on); +void mt8193_pllgp_ana_pwr_control(bool power_on); +void mt8193_bus_clk_switch(bool bus_26m_to_32k); +void mt8193_hdmi_ana_pwr_control(bool power_on); +void mt8193_nfi_ana_pwr_control(bool power_on); +int mt8193_ckgen_config_pad_level_shift(int i4GroupNum, int i4TurnLow); +void mt8193_spm_control_test(int u4Func); +u32 mt8193_ckgen_measure_clk(u32 u4Func); +void mt8193_ckgen_early_suspend(void); +void mt8193_ckgen_late_resume(void); + +#endif + +#endif /* MT8193_CKGEN_H */ diff --git a/drivers/misc/mediatek/multibridge/mt6797/mt8193/inc/mt8193_gpio.h b/drivers/misc/mediatek/multibridge/mt6797/mt8193/inc/mt8193_gpio.h new file mode 100644 index 000000000000..e8408ce7807a --- /dev/null +++ b/drivers/misc/mediatek/multibridge/mt6797/mt8193/inc/mt8193_gpio.h @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms 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. + */ + +#ifndef MT8193_GPIO_H +#define MT8193_GPIO_H + +#include <generated/autoconf.h> +#include <linux/mm.h> +#include <linux/init.h> +#include <linux/fb.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/kthread.h> +#include <linux/vmalloc.h> + +#include <linux/uaccess.h> +#include <linux/atomic.h> +#include <asm/cacheflush.h> +#include <linux/io.h> + +#include <mach/irqs.h> + +#include <linux/miscdevice.h> +#include <linux/fs.h> +#include <linux/file.h> +#include <linux/cdev.h> +#include <asm/tlbflush.h> +#include <asm/page.h> +#include <linux/slab.h> + +#include <linux/module.h> +#include "mt8193_pinmux.h" + + +#define MT8193_GPIO_OUTPUT 1 +#define MT8193_GPIO_INPUT 0 +#define MT8193_GPIO_HIGH 1 +#define MT8193_GPIO_LOW 0 + +enum MT8193_GPIO_PIN { + GPIO_PIN_UNSUPPORTED = -1, + + GPIO_PIN_GPIO0, + GPIO_PIN_GPIO1, + GPIO_PIN_GPIO2, + GPIO_PIN_GPIO3, + GPIO_PIN_GPIO4, + GPIO_PIN_GPIO5, + GPIO_PIN_GPIO6, + GPIO_PIN_GPIO7, + GPIO_PIN_GPIO8, + GPIO_PIN_GPIO9, + GPIO_PIN_GPIO10, + GPIO_PIN_GPIO11, + GPIO_PIN_GPIO12, + GPIO_PIN_GPIO13, + GPIO_PIN_GPIO14, + GPIO_PIN_GPIO15, + GPIO_PIN_GPIO16, + GPIO_PIN_GPIO17, + GPIO_PIN_GPIO18, + GPIO_PIN_GPIO19, + GPIO_PIN_GPIO20, + GPIO_PIN_GPIO21, + GPIO_PIN_GPIO22, + GPIO_PIN_GPIO23, + GPIO_PIN_GPIO24, + GPIO_PIN_GPIO25, + GPIO_PIN_GPIO26, + GPIO_PIN_GPIO27, + GPIO_PIN_GPIO28, + GPIO_PIN_GPIO29, + GPIO_PIN_GPIO30, + GPIO_PIN_GPIO31, + GPIO_PIN_GPIO32, + GPIO_PIN_GPIO33, + GPIO_PIN_GPIO34, + GPIO_PIN_GPIO35, + GPIO_PIN_GPIO36, + GPIO_PIN_GPIO37, + GPIO_PIN_GPIO38, + GPIO_PIN_GPIO39, + GPIO_PIN_GPIO40, + GPIO_PIN_GPIO41, + GPIO_PIN_GPIO42, + GPIO_PIN_GPIO43, + GPIO_PIN_GPIO44, + GPIO_PIN_GPIO45, + GPIO_PIN_GPIO46, + GPIO_PIN_GPIO47, + GPIO_PIN_GPIO48, + GPIO_PIN_GPIO49, + GPIO_PIN_GPIO50, + GPIO_PIN_GPIO51, + GPIO_PIN_GPIO52, + GPIO_PIN_GPIO53, + GPIO_PIN_GPIO54, + GPIO_PIN_GPIO55, + GPIO_PIN_GPIO56, + GPIO_PIN_GPIO57, + GPIO_PIN_GPIO58, + GPIO_PIN_GPIO59, + GPIO_PIN_GPIO60, + GPIO_PIN_GPIO61, + GPIO_PIN_GPIO62, + GPIO_PIN_GPIO63, + GPIO_PIN_GPIO64, + GPIO_PIN_GPIO65, + GPIO_PIN_GPIO66, + GPIO_PIN_GPIO67, + GPIO_PIN_GPIO68, + GPIO_PIN_GPIO69, + GPIO_PIN_GPIO70, + GPIO_PIN_GPIO71, + + GPIO_PIN_MAX +}; + + +/* _au4GpioTbl[gpio num] is pad num */ +static const u32 _au4GpioTbl[GPIO_PIN_MAX] = { + PIN_NFD6, /* gpio0 */ + PIN_NFD5, + PIN_NFD4, + PIN_NFD3, + PIN_NFD2, + PIN_NFD1, + PIN_NFD0, /* gpio6 */ + PIN_G0, /* gpio 7 */ + PIN_B5, + PIN_B4, + PIN_B3, + PIN_B2, + PIN_B1, + PIN_B0, + PIN_DE, + PIN_VCLK, + PIN_HSYNC, + PIN_VSYNC, + PIN_CEC, + PIN_HDMISCK, + PIN_HDMISD, + PIN_HTPLG, + PIN_I2S_DATA, + PIN_I2S_LRCK, + PIN_I2S_BCK, + PIN_DPI1CK, + PIN_DPI1D7, + PIN_DPI1D6, + PIN_DPI1D5, + PIN_DPI1D4, + PIN_DPI1D3, + PIN_DPI1D2, + PIN_DPI1D1, + PIN_DPI1D0, + PIN_DPI0CK, + PIN_DPI0HSYNC, + PIN_DPI0VSYNC, + PIN_DPI0D11, + PIN_DPI0D10, + PIN_DPI0D9, + PIN_DPI0D8, + PIN_DPI0D7, + PIN_DPI0D6, + PIN_DPI0D5, + PIN_DPI0D4, + PIN_DPI0D3, + PIN_DPI0D2, + PIN_DPI0D1, + PIN_DPI0D0, + PIN_SDA, + PIN_SCL, + PIN_NRNB, + PIN_NCLE, + PIN_NALE, + PIN_NWEB, + PIN_NREB, + PIN_NLD7, + PIN_NLD6, + PIN_NLD5, + PIN_NLD4, + PIN_NLD3, + PIN_NLD2, + PIN_NLD1, + PIN_NLD0, /* gpio 63 */ + PIN_INT, /* gpio 64*/ + PIN_NFRBN, /* gpio 65*/ + PIN_NFCLE, + PIN_NFALE, + PIN_NFWEN, + PIN_NFREN, + PIN_NFCEN, + PIN_NFD7, /* gpio 71 */ +}; + +extern int GPIO_Config(u32 u4GpioNum, u8 u1Mode, u8 u1Value); +extern u8 GPIO_Input(u32 i4GpioNum); +extern int GPIO_Output(u32 u4GpioNum, u32 u4High); + +#endif /* MT8193_H */ diff --git a/drivers/misc/mediatek/multibridge/mt6797/mt8193/inc/mt8193_iic.h b/drivers/misc/mediatek/multibridge/mt6797/mt8193/inc/mt8193_iic.h new file mode 100644 index 000000000000..4deb6524082e --- /dev/null +++ b/drivers/misc/mediatek/multibridge/mt6797/mt8193/inc/mt8193_iic.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms 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. + */ + +#ifndef MT8193_IIC_H +#define MT8193_IIC_H + +/*----------------------------------------------------------------------------*/ +/* IIC APIs */ +/*----------------------------------------------------------------------------*/ +int mt8193_i2c_read(u16 addr, u32 *data); +int mt8193_i2c_write(u16 addr, u32 data); + +#endif /* MT8193_IIC_H */ + diff --git a/drivers/misc/mediatek/multibridge/mt6797/mt8193/inc/mt8193_pinmux.h b/drivers/misc/mediatek/multibridge/mt6797/mt8193/inc/mt8193_pinmux.h new file mode 100644 index 000000000000..897fd347c4ec --- /dev/null +++ b/drivers/misc/mediatek/multibridge/mt6797/mt8193/inc/mt8193_pinmux.h @@ -0,0 +1,371 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms 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. + */ + +#ifndef MT8193_PINMUX_H +#define MT8193_PINMUX_H + + +#include <generated/autoconf.h> +#include <linux/mm.h> +#include <linux/init.h> +#include <linux/fb.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/kthread.h> +#include <linux/vmalloc.h> + +#include <linux/uaccess.h> +#include <linux/atomic.h> +#include <asm/cacheflush.h> +#include <linux/io.h> + +#include <mach/irqs.h> + +#include <linux/miscdevice.h> +#include <linux/fs.h> +#include <linux/file.h> +#include <linux/cdev.h> +#include <asm/tlbflush.h> +#include <asm/page.h> +#include <linux/slab.h> + +#include <linux/module.h> + +#include "mt8193.h" + + +/* ret code */ + +#define PINMUX_RET_OK 0 +#define PINMUX_RET_INVALID_ARG (-1) +#define PINMUX_RET_FAIL (-2) + + + +#define PINMUX_FUNCTION0 0 +#define PINMUX_FUNCTION1 1 +#define PINMUX_FUNCTION2 2 +#define PINMUX_FUNCTION3 3 +#define PINMUX_FUNCTION4 4 +#define PINMUX_FUNCTION5 5 +#define PINMUX_FUNCTION6 6 +#define PINMUX_FUNCTION7 7 +#define PINMUX_FUNCTION_MAX 8 + +enum MT8193_APD_PIN { + PIN_UNSUPPORTED = -1, + + PIN_NFD6, + PIN_NFD5, + PIN_NFD4, + PIN_NFD3, + PIN_NFD2, + PIN_NFD1, + PIN_NFD0, + PIN_TP_VPLL, + PIN_AO0N, + PIN_AO0P, + PIN_AO1N, + PIN_AO1P, + PIN_AO2N, + PIN_AO2P, + PIN_AOCK0N, + PIN_AOCK0P, + PIN_AO3N, + PIN_AO3P, + PIN_G0, + PIN_B5, + PIN_B4, + PIN_B3, + PIN_B2, + PIN_B1, + PIN_B0, + PIN_DE, + PIN_VCLK, + PIN_HSYNC, + PIN_VSYNC, + PIN_CEC, + PIN_HDMISCK, + PIN_HDMISD, + PIN_HTPLG, + PIN_I2S_DATA, + PIN_I2S_LRCK, + PIN_I2S_BCK, + PIN_DPI1CK, + PIN_DPI1D7, + PIN_DPI1D6, + PIN_DPI1D5, + PIN_DPI1D4, + PIN_DPI1D3, + PIN_DPI1D2, + PIN_DPI1D1, + PIN_DPI1D0, + PIN_DPI0CK, + PIN_DPI0HSYNC, + PIN_DPI0VSYNC, + PIN_DPI0D11, + PIN_DPI0D10, + PIN_DPI0D9, + PIN_DPI0D8, + PIN_DPI0D7, + PIN_DPI0D6, + PIN_DPI0D5, + PIN_DPI0D4, + PIN_DPI0D3, + PIN_DPI0D2, + PIN_DPI0D1, + PIN_DPI0D0, + PIN_SDA, + PIN_SCL, + PIN_NRNB, + PIN_NCLE, + PIN_NALE, + PIN_NWEB, + PIN_NREB, + PIN_NLD7, + PIN_NLD6, + PIN_NLD5, + PIN_NLD4, + PIN_NLD3, + PIN_NLD2, + PIN_NLD1, + PIN_NLD0, + PIN_RTC_32K_CK, + PIN_INT, + PIN_RESET, + PIN_EN_BB, + PIN_CK_SEL, + PIN_NFRBN, + PIN_NFCLE, + PIN_NFALE, + PIN_NFWEN, + PIN_NFREN, + PIN_NFCEN, + PIN_NFD7, + PIN_PROT0, + PIN_PROT1, + PIN_PROT2, + PIN_PROT3, + PIN_PROT4, + PIN_PROT5, + + PIN_MAX +}; + + +/* +function table + +[pin][2 * function] + +pin0: func_pmux, func_sel (<<), func_mask +pin1: func_pmux, func_sel, func_mask +pin2: func_pmux, func_sel, func_mask +*/ +static const u32 _au4PinmuxFuncTbl[PIN_MAX][3] = { + /* PIN_NFD6, */ {REG_RW_PMUX1, 0, 0x7}, + /* PIN_NFD5, */ {REG_RW_PMUX1, 3, 0x38}, + /* PIN_NFD4, */ {REG_RW_PMUX1, 6, 0x1C0}, + /* PIN_NFD3, */ {REG_RW_PMUX1, 9, 0xE00}, + /* PIN_NFD2, */ {REG_RW_PMUX1, 12, 0x7000}, + /* PIN_NFD1, */ {REG_RW_PMUX1, 15, 0x38000}, + /* PIN_NFD0, */ {REG_RW_PMUX1, 18, 0x1C0000}, + /* PIN_TP_VPLL, */ {REG_RW_PMUX8, 18, 0x1C0000}, + /* PIN_AO0N, */ {REG_RW_PMUX8, 21, 0xE00000}, + /* PIN_AO0P, */ {REG_RW_PMUX8, 24, 0x7000000}, + /* PIN_AO1N, */ {REG_RW_PMUX8, 27, 0x38000000}, + /* PIN_AO1P, */ {REG_RW_PMUX9, 0, 0x7}, + /* PIN_AO2N, */ {REG_RW_PMUX9, 3, 0x38}, + /* PIN_AO2P, */ {REG_RW_PMUX9, 6, 0x1C0}, + /* PIN_AOCK0N, */ {REG_RW_PMUX9, 9, 0xE00}, + /* PIN_AOCK0P, */ {REG_RW_PMUX9, 12, 0x7000}, + /* PIN_AO3N, */ {REG_RW_PMUX9, 15, 0x38000}, + /* PIN_AO3P, */ {REG_RW_PMUX9, 18, 0x1C0000}, + /* PIN_G0, */ {REG_RW_PMUX1, 21, 0xE00000}, + /* PIN_B5, */ {REG_RW_PMUX1, 24, 0x7000000}, + /* PIN_B4, */ {REG_RW_PMUX1, 27, 0x38000000}, + /* PIN_B3, */ {REG_RW_PMUX2, 0, 0x7}, + /* PIN_B2, */ {REG_RW_PMUX2, 3, 0x38}, + /* PIN_B1, */ {REG_RW_PMUX2, 6, 0x1C0}, + /* PIN_B0, */ {REG_RW_PMUX2, 9, 0xE00}, + /* PIN_DE, */ {REG_RW_PMUX2, 12, 0x7000}, + /* PIN_VCLK, */ {REG_RW_PMUX2, 15, 0x38000}, + /* PIN_HSYNC, */ {REG_RW_PMUX2, 18, 0x1C0000}, + /* PIN_VSYNC, */ {REG_RW_PMUX2, 21, 0xE00000}, + /* PIN_CEC, */ {REG_RW_PMUX2, 24, 0x7000000}, + /* PIN_HDMISCK, */ {REG_RW_PMUX2, 27, 0x38000000}, + /* PIN_HDMISD, */ {REG_RW_PMUX3, 0, 0x7}, + /* PIN_HTPLG, */ {REG_RW_PMUX3, 3, 0x38}, + /* PIN_I2S_DATA, */ {REG_RW_PMUX3, 6, 0x1C0}, + /* PIN_I2S_LRCK, */ {REG_RW_PMUX3, 9, 0xE00}, + /* PIN_I2S_BCK, */ {REG_RW_PMUX3, 12, 0x7000}, + /* PIN_DPI1CK, */ {REG_RW_PMUX3, 15, 0x38000}, + /* PIN_DPI1D7, */ {REG_RW_PMUX3, 18, 0x1C0000}, + /* PIN_DPI1D6, */ {REG_RW_PMUX3, 21, 0xE00000}, + /* PIN_DPI1D5, */ {REG_RW_PMUX3, 24, 0x7000000}, + /* PIN_DPI1D4, */ {REG_RW_PMUX3, 27, 0x38000000}, + /* PIN_DPI1D3, */ {REG_RW_PMUX4, 0, 0x7}, + /* PIN_DPI1D2, */ {REG_RW_PMUX4, 3, 0x38}, + /* PIN_DPI1D1, */ {REG_RW_PMUX4, 6, 0x1C0}, + /* PIN_DPI1D0, */ {REG_RW_PMUX4, 9, 0xE00}, + /* PIN_DPI0CK, */ {REG_RW_PMUX4, 12, 0x7000}, + /* PIN_DPI0HSYNC, */ {REG_RW_PMUX4, 15, 0x38000}, + /* PIN_DPI0VSYNC, */ {REG_RW_PMUX4, 18, 0x1C0000}, + /* PIN_DPI0D11, */ {REG_RW_PMUX4, 21, 0xE00000}, + /* PIN_DPI0D10, */ {REG_RW_PMUX4, 24, 0x7000000}, + /* PIN_DPI0D9, */ {REG_RW_PMUX4, 27, 0x38000000}, + /* PIN_DPI0D8, */ {REG_RW_PMUX5, 0, 0x7}, + /* PIN_DPI0D7, */ {REG_RW_PMUX5, 3, 0x38}, + /* PIN_DPI0D6, */ {REG_RW_PMUX5, 6, 0x1C0}, + /* PIN_DPI0D5, */ {REG_RW_PMUX5, 9, 0xE00}, + /* PIN_DPI0D4, */ {REG_RW_PMUX5, 12, 0x7000}, + /* PIN_DPI0D3, */ {REG_RW_PMUX5, 15, 0x38000}, + /* PIN_DPI0D2, */ {REG_RW_PMUX5, 18, 0x1C0000}, + /* PIN_DPI0D1, */ {REG_RW_PMUX5, 21, 0xE00000}, + /* PIN_DPI0D0, */ {REG_RW_PMUX5, 24, 0x7000000}, + /* PIN_SDA, */ {REG_RW_PMUX5, 27, 0x38000000}, + /* PIN_SCL, */ {REG_RW_PMUX6, 0, 0x7}, + /* PIN_NRNB, */ {REG_RW_PMUX6, 3, 0x38}, + /* PIN_NCLE, */ {REG_RW_PMUX6, 6, 0x1C0}, + /* PIN_NALE, */ {REG_RW_PMUX6, 9, 0xE00}, + /* PIN_NWEB, */ {REG_RW_PMUX6, 12, 0x7000}, + /* PIN_NREB, */ {REG_RW_PMUX6, 15, 0x38000}, + /* PIN_NLD7, */ {REG_RW_PMUX6, 18, 0x1C0000}, + /* PIN_NLD6, */ {REG_RW_PMUX6, 21, 0xE00000}, + /* PIN_NLD5, */ {REG_RW_PMUX6, 24, 0x7000000}, + /* PIN_NLD4, */ {REG_RW_PMUX6, 27, 0x38000000}, + /* PIN_NLD3, */ {REG_RW_PMUX7, 0, 0x7}, + /* PIN_NLD2, */ {REG_RW_PMUX7, 3, 0x38}, + /* PIN_NLD1, */ {REG_RW_PMUX7, 6, 0x1C0}, + /* PIN_NLD0, */ {REG_RW_PMUX7, 9, 0xE00}, + /* PIN_RTC_32K_CK, */ {REG_RW_PMUX7, 12, 0x7000}, + /* PIN_INT, */ {REG_RW_PMUX7, 15, 0x38000}, + /* PIN_RESET, */ {REG_RW_PMUX7, 18, 0x1C0000}, + /* PIN_EN_BB, */ {REG_RW_PMUX7, 21, 0xE00000}, + /* PIN_CK_SEL, */ {REG_RW_PMUX7, 24, 0x7000000}, + /* PIN_NFRBN, */ {REG_RW_PMUX7, 27, 0x38000000}, + /* PIN_NFCLE, */ {REG_RW_PMUX8, 0, 0x7}, + /* PIN_NFALE, */ {REG_RW_PMUX8, 3, 0x38}, + /* PIN_NFWEN, */ {REG_RW_PMUX8, 6, 0x1C0}, + /* PIN_NFREN, */ {REG_RW_PMUX8, 9, 0xE00}, + /* PIN_NFCEN, */ {REG_RW_PMUX8, 12, 0x7000}, + /* PIN_NFD7, */ {REG_RW_PMUX8, 15, 0x38000}, + /* PIN_PROT0, */ {REG_RW_PMUX9, 21, 0x100000}, + /* PIN_PROT1, */ {REG_RW_PMUX9, 22, 0x200000}, + /* PIN_PROT2, */ {REG_RW_PMUX9, 23, 0x400000}, + /* PIN_PROT3, */ {REG_RW_PMUX9, 24, 0x800000}, + /* PIN_PROT4, */ {REG_RW_PMUX9, 25, 0x1000000}, + /* PIN_PROT5, */ {REG_RW_PMUX9, 26, 0x2000000}, +}; + +/* pu shift, pd shift*/ +static const u32 _au4PinmuxPadPuPdTbl[PIN_MAX][2] = { + /* PIN_NFD6, */ {0, 0}, + /* PIN_NFD5, */ {1, 1}, + /* PIN_NFD4, */ {2, 2}, + /* PIN_NFD3, */ {3, 3}, + /* PIN_NFD2, */ {4, 4}, + /* PIN_NFD1, */ {5, 5}, + /* PIN_NFD0, */ {6, 6}, + /* PIN_TP_VPLL, */ {0, 0}, + /* PIN_AO0N, */ {0, 0}, + /* PIN_AO0P, */ {0, 0}, + /* PIN_AO1N, */ {0, 0}, + /* PIN_AO1P, */ {0, 0}, + /* PIN_AO2N, */ {0, 0}, + /* PIN_AO2P, */ {0, 0}, + /* PIN_AOCK0N, */ {0, 0}, + /* PIN_AOCK0P, */ {0, 0}, + /* PIN_AO3N, */ {0, 0}, + /* PIN_AO3P, */ {0, 0}, + /* PIN_G0, */ {7, 7}, + /* PIN_B5, */ {8, 8}, + /* PIN_B4, */ {9, 9}, + /* PIN_B3, */ {10, 10}, + /* PIN_B2, */ {11, 11}, + /* PIN_B1, */ {12, 12}, + /* PIN_B0, */ {13, 13}, + /* PIN_DE, */ {14, 14}, + /* PIN_VCLK, */ {17, 17}, + /* PIN_HSYNC, */ {16, 16}, + /* PIN_VSYNC, */ {15, 15}, + /* PIN_CEC, */ {0, 0}, + /* PIN_HDMISCK, */ {19, 19}, + /* PIN_HDMISD, */ {20, 20}, + /* PIN_HTPLG, */ {21, 21}, + /* PIN_I2S_DATA, */ {22, 22}, + /* PIN_I2S_LRCK, */ {23, 23}, + /* PIN_I2S_BCK, */ {24, 24}, + /* PIN_DPI1CK, */ {25, 25}, + /* PIN_DPI1D7, */ {26, 26}, + /* PIN_DPI1D6, */ {27, 27}, + /* PIN_DPI1D5, */ {28, 28}, + /* PIN_DPI1D4, */ {29, 29}, + /* PIN_DPI1D3, */ {30, 30}, + /* PIN_DPI1D2, */ {31, 31}, + /* PIN_DPI1D1, */ {32, 32}, + /* PIN_DPI1D0, */ {33, 33}, + /* PIN_DPI0CK, */ {34, 34}, + /* PIN_DPI0HSYNC, */ {35, 35}, + /* PIN_DPI0VSYNC, */ {36, 36}, + /* PIN_DPI0D11, */ {37, 37}, + /* PIN_DPI0D10, */ {38, 38}, + /* PIN_DPI0D9, */ {39, 39}, + /* PIN_DPI0D8, */ {40, 40}, + /* PIN_DPI0D7, */ {41, 41}, + /* PIN_DPI0D6, */ {42, 42}, + /* PIN_DPI0D5, */ {43, 43}, + /* PIN_DPI0D4, */ {44, 44}, + /* PIN_DPI0D3, */ {45, 45}, + /* PIN_DPI0D2, */ {46, 46}, + /* PIN_DPI0D1, */ {47, 47}, + /* PIN_DPI0D0, */ {48, 48}, + /* PIN_SDA, */ {49, 49}, + /* PIN_SCL, */ {50, 50}, + /* PIN_NRNB, */ {51, 51}, + /* PIN_NCLE, */ {52, 52}, + /* PIN_NALE, */ {53, 53}, + /* PIN_NWEB, */ {54, 54}, + /* PIN_NREB, */ {55, 55}, + /* PIN_NLD7, */ {56, 56}, + /* PIN_NLD6, */ {57, 57}, + /* PIN_NLD5, */ {58, 58}, + /* PIN_NLD4, */ {59, 59}, + /* PIN_NLD3, */ {60, 60}, + /* PIN_NLD2, */ {61, 16}, + /* PIN_NLD1, */ {62, 62}, + /* PIN_NLD0, */ {63, 63}, + /* PIN_RTC_32K_CK, */ {0, 0}, + /* PIN_INT, */ {64, 64}, + /* PIN_RESET, */ {0, 0}, + /* PIN_EN_BB, */ {0, 0}, + /* PIN_CK_SEL, */ {0, 0}, + /* PIN_NFRBN, */ {0, 0}, + /* PIN_NFCLE, */ {0, 0}, + /* PIN_NFALE, */ {0, 0}, + /* PIN_NFWEN, */ {0, 0}, + /* PIN_NFREN, */ {0, 0}, + /* PIN_NFCEN, */ {0, 0}, + /* PIN_NFD7, */ {0, 0}, + /* PIN_PROT0, */ {0, 0}, + /* PIN_PROT1, */ {0, 0}, + /* PIN_PROT2, */ {0, 0}, + /* PIN_PROT3, */ {0, 0}, + /* PIN_PROT4, */ {0, 0}, + /* PIN_PROT5, */ {0, 0}, +}; + +extern int mt8193_pinset(u32 pin_num, u32 function); + +#endif /* MT8193_H */ diff --git a/drivers/misc/mediatek/multibridge/mt6797/mt8193/mt8193_ckgen.c b/drivers/misc/mediatek/multibridge/mt6797/mt8193/mt8193_ckgen.c new file mode 100644 index 000000000000..abadd3f1a476 --- /dev/null +++ b/drivers/misc/mediatek/multibridge/mt6797/mt8193/mt8193_ckgen.c @@ -0,0 +1,1097 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms 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. + */ + +#define pr_fmt(fmt) "mt8193-ckgen: " fmt +#define DEBUG 1 + +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/wait.h> +#include <linux/spinlock.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/cdev.h> +#include <linux/uaccess.h> +#include <linux/delay.h> +#include <linux/pinctrl/consumer.h> +#include <linux/of_gpio.h> +#ifdef CONFIG_HAS_EARLYSUSPEND +#include <linux/earlysuspend.h> +#endif +#ifdef CONFIG_PM_AUTOSLEEP +#include <linux/fb.h> +#include <linux/notifier.h> +#endif +#include "mt8193.h" +#include "mt8193_ckgen.h" +#include "mt8193_gpio.h" + + +#define MT8193_MLC 0 +#define MT8193_CKGEN_VFY 1 +#define MT8193_CKGEN_DEVNAME "mt8193-ckgen" + +static int mt8193_ckgen_probe(struct platform_device *pdev); +static int mt8193_ckgen_suspend(struct platform_device *pdev, pm_message_t state); +static int mt8193_ckgen_resume(struct platform_device *pdev); +static int mt8193_ckgen_remove(struct platform_device *pdev); +static void mt8193_ckgen_shutdown(struct platform_device *pdev); + +/****************************************************************************** +Device driver structure +******************************************************************************/ +#ifdef CONFIG_OF +static const struct of_device_id mt8193ckgen_of_ids[] = { + {.compatible = "mediatek,mt8193-ckgen",}, + {} +}; +#endif + +static struct platform_driver mt8193_ckgen_driver = { + .probe = mt8193_ckgen_probe, + .remove = mt8193_ckgen_remove, + .shutdown = mt8193_ckgen_shutdown, + .suspend = mt8193_ckgen_suspend, + .resume = mt8193_ckgen_resume, + .driver = { + .name = "mt8193-ckgen", + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = mt8193ckgen_of_ids, +#endif + }, +}; + +static struct class *ckgen_class; +static struct cdev *ckgen_cdev; + +static struct pinctrl *pinctrl; +static struct pinctrl_state *pins_gpio; +static struct pinctrl_state *pins_dpi; + +int multibridge_exit = 0; + +#if MT8193_CKGEN_VFY + +static int mt8193_ckgen_release(struct inode *inode, struct file *file); +static int mt8193_ckgen_open(struct inode *inode, struct file *file); +static long mt8193_ckgen_ioctl(struct file *file, unsigned int cmd, unsigned long arg); + +static const struct file_operations mt8193_ckgen_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = mt8193_ckgen_ioctl, + .open = mt8193_ckgen_open, + .release = mt8193_ckgen_release, +}; +#endif + +void mt8193_ckgen_early_suspend(void) +{ + pr_err("[CKGEN] mt8193_ckgen_early_suspend() enter\n"); + +#if !MT8193_MLC + + /* If we use 8193 NFI, we should turn off pllgp in suspend because early suspend state may still use NFI. + Otherwise, we can turn off pllgp in early suspend. */ + + mt8193_pllgp_ana_pwr_control(false); + msleep(20); + + mt8193_nfi_ana_pwr_control(false); + + /* bus clk switch to 32K */ + mt8193_bus_clk_switch(true); + msleep(50); + +#if MT8193_DISABLE_DCXO + mt8193_disable_dcxo_core(); +#endif + +#endif + + pr_debug("[CKGEN] mt8193_ckgen_early_suspend() exit\n"); +} + +void mt8193_ckgen_late_resume(void) +{ + pr_err("[CKGEN] mt8193_ckgen_late_resume() enter\n"); + +#if !MT8193_MLC + + /* If we use 8193 NFI, we should turn off pllgp in suspend because early suspend state may still use NFI. + Otherwise, we can turn off pllgp in early suspend. */ + +#if MT8193_DISABLE_DCXO + mt8193_enable_dcxo_core(); + msleep(20); +#endif + + mt8193_bus_clk_switch(false); + msleep(20); + + mt8193_nfi_ana_pwr_control(true); + + /* turn on pllgp analog */ + mt8193_pllgp_ana_pwr_control(true); + msleep(20); +#endif + + pr_debug("[CKGEN] mt8193_ckgen_late_resume() exit\n"); +} + +#if defined(CONFIG_HAS_EARLYSUSPEND) +static struct early_suspend mt8193_ckgen_early_suspend_desc = { + .level = 0xFF, + .suspend = mt8193_ckgen_early_suspend, + .resume = mt8193_ckgen_late_resume, +}; +#endif +#if 0 +#ifdef CONFIG_PM_AUTOSLEEP +static int mt8193_ckgen_fb_notifier_callback(struct notifier_block *self, unsigned long event, void *fb_evdata) +{ + struct fb_event *evdata = fb_evdata; + int blank; + + if (event != FB_EVENT_BLANK) + return 0; + + blank = *(int *)evdata->data; + + switch (blank) { + case FB_BLANK_UNBLANK: + case FB_BLANK_NORMAL: + mt8193_ckgen_late_resume(); + break; + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + break; + case FB_BLANK_POWERDOWN: + mt8193_ckgen_early_suspend(); + break; + default: + return -EINVAL; + } + + return 0; +} + +static struct notifier_block mt8193ckgen_fb_notif = { + .notifier_call = mt8193_ckgen_fb_notifier_callback, +}; +#endif +#endif + +#if MT8193_CKGEN_VFY +static int mt8193_ckgen_release(struct inode *inode, struct file *file) +{ + return 0; +} + +static int mt8193_ckgen_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static char *_mt8193_ckgen_ioctl_spy(unsigned int cmd) +{ + switch (cmd) { + case MTK_MT8193_CKGEN_1: + return "MTK_MT8193_CKGEN_1"; + case MTK_MT8193_CKGEN_2: + return "MTK_MT8193_CKGEN_2"; + case MTK_MT8193_CKGEN_SPM_CTRL: + return "MTK_MT8193_CKGEN_SPM_CTRL"; + case MTK_MT8193_CKGEN_LS_TEST: + return "MTK_MT8193_CKGEN_LS_TEST"; + case MTK_MT8193_CKGEN_FREQ_METER: + return "MTK_MT8193_CKGEN_FREQ_METER"; + default: + return "unknown ioctl command"; + } +} + +static long mt8193_ckgen_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int r = 0; + + pr_debug("[CKGEN] cmd=%s, arg=0x%08lx\n", _mt8193_ckgen_ioctl_spy(cmd), arg); + + switch (cmd) { + case MTK_MT8193_CKGEN_1: + break; + case MTK_MT8193_CKGEN_2: + break; + case MTK_MT8193_CKGEN_LS_TEST: + { + struct mt8193_ckgen_ls_info_t tLsInfo; + + if (copy_from_user(&tLsInfo, (void __user *)arg, sizeof(tLsInfo))) { + pr_err("[CKGEN] copy_from_user fails!!\n"); + return -1; + } + + r = mt8193_ckgen_config_pad_level_shift(tLsInfo.i4GroupNum, tLsInfo.i4TurnLow); + + break; + } + case MTK_MT8193_CKGEN_SPM_CTRL: + { + int u4Func = 0; + + u4Func = arg; + mt8193_spm_control_test(u4Func); + break; + } + + case MTK_MT8193_CKGEN_FREQ_METER: + { + struct mt8193_ckgen_freq_meter_t t_freq; + u32 u4Clk = 0; + + if (copy_from_user(&t_freq, (void __user *)arg, sizeof(t_freq))) { + pr_err("[CKGEN] copy_from_user fails!!\n"); + return -1; + } + + u4Clk = mt8193_ckgen_measure_clk(t_freq.u4Func); + break; + } + case MTK_MT8193_GPIO_CTRL: + { + struct mt8193_gpio_ctrl_t t_gpio; + u32 u4Val = 0; + + if (copy_from_user(&t_gpio, (void __user *)arg, sizeof(t_gpio))) { + pr_err("[CKGEN] copy_from_user fails!!\n"); + return -1; + } + + if (t_gpio.u4Mode == MT8193_GPIO_OUTPUT) { + GPIO_Output(t_gpio.u4GpioNum, t_gpio.u4Value); + } else { + GPIO_Config(t_gpio.u4GpioNum, MT8193_GPIO_INPUT, 0); + u4Val = GPIO_Input(t_gpio.u4GpioNum); + pr_debug("[CKGEN] GPIO INPUT VALUE IS %d\n", u4Val); + } + + break; + } + case MTK_MT8193_EARLY_SUSPEND: + break; + case MTK_MT8193_LATE_RESUME: + break; + default: + pr_err("[CKGEN] arguments error\n"); + break; + } + + return r; +} + +#endif + +/****************************************************************************** + * mt8193_ckgen_init + * + * DESCRIPTION: + * Init the device driver ! + * + * PARAMETERS: + * None + * + * RETURNS: + * None + * + * NOTES: + * None + * + ******************************************************************************/ +static int __init mt8193_ckgen_init(void) +{ + int ret = 0; + + + pr_debug("[CKGEN] mt8193_ckgen_init() enter\n"); + ret = platform_driver_register(&mt8193_ckgen_driver); + if (ret) { + pr_err("fail to register 8193ckgen driver, ret=%d\n", ret); + return ret; + } + +#if defined(CONFIG_HAS_EARLYSUSPEND) + register_early_suspend(&mt8193_ckgen_early_suspend_desc); +#endif + +#if 0 +#ifdef CONFIG_PM_AUTOSLEEP + ret = fb_register_client(&mt8193ckgen_fb_notif); + if (ret) { + pr_err("fail to register fb notifier, ret=%d\n", ret); + return ret; + } +#endif +#endif + pr_debug("[CKGEN] mt8193_ckgen_init() exit\n"); + + return 0; +} + +/****************************************************************************** + * mt8193_ckgen_exit + * + * DESCRIPTION: + * Free the device driver ! + * + * PARAMETERS: + * None + * + * RETURNS: + * None + * + * NOTES: + * None + * + ******************************************************************************/ +static void __exit mt8193_ckgen_exit(void) +{ + devm_pinctrl_put(pinctrl); + platform_driver_unregister(&mt8193_ckgen_driver); +#if defined(CONFIG_HAS_EARLYSUSPEND) + unregister_early_suspend(&mt8193_ckgen_early_suspend_desc); +#endif +} + +static dev_t mt8193_ckgen_devno; +static struct cdev *mt8193_ckgen_cdev; + +/****************************************************************************** + * mt8193_ckgen_probe + * + * DESCRIPTION: + * register the nand device file operations ! + * + * PARAMETERS: + * struct platform_device *pdev : device structure + * + * RETURNS: + * 0 : Success + * + * NOTES: + * None + * + ******************************************************************************/ +static int mt8193_ckgen_probe(struct platform_device *pdev) +{ +#if MT8193_CKGEN_VFY + int ret = 0; + + pr_err("[CKGEN] %s\n", __func__); + /* Allocate device number for hdmi driver */ + ret = alloc_chrdev_region(&mt8193_ckgen_devno, 0, 1, MT8193_CKGEN_DEVNAME); + if (ret) { + pr_err("[CKGEN] alloc_chrdev_region fail\n"); + return -1; + } + + /* For character driver register to system, device number binded to file operations */ + mt8193_ckgen_cdev = cdev_alloc(); + mt8193_ckgen_cdev->owner = THIS_MODULE; + mt8193_ckgen_cdev->ops = &mt8193_ckgen_fops; + ret = cdev_add(mt8193_ckgen_cdev, mt8193_ckgen_devno, 1); + + /* For device number binded to device name(hdmitx), one class is corresponeded to one node */ + ckgen_class = class_create(THIS_MODULE, MT8193_CKGEN_DEVNAME); + /* mknod /dev/hdmitx */ + ckgen_cdev = (struct cdev *)device_create(ckgen_class, NULL, mt8193_ckgen_devno, NULL, MT8193_CKGEN_DEVNAME); + + pinctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(pinctrl)) { + ret = PTR_ERR(pinctrl); + pr_err("Cannot find pinctrl, ret=%d!\n", ret); + return ret; + } + + pins_gpio = pinctrl_lookup_state(pinctrl, "bus_switch_gpio"); + if (IS_ERR(pins_gpio)) { + ret = PTR_ERR(pins_gpio); + pr_err("Cannot find bus_switch_gpio, ret=%d!\n", ret); + return ret; + } + + pins_dpi = pinctrl_lookup_state(pinctrl, "bus_switch_dpi"); + if (IS_ERR(pins_dpi)) { + ret = PTR_ERR(pins_dpi); + pr_err("Cannot find bus_switch_dpi, ret=%d!\n", ret); + return ret; + } +#endif + return 0; +} + +/****************************************************************************** + * mt8193_ckgen_remove + * + * DESCRIPTION: + * unregister the nand device file operations ! + * + * PARAMETERS: + * struct platform_device *pdev : device structure + * + * RETURNS: + * 0 : Success + * + * NOTES: + * None + * + ******************************************************************************/ + +static int mt8193_ckgen_remove(struct platform_device *pdev) +{ + return 0; +} + +static void mt8193_ckgen_shutdown(struct platform_device *pdev) +{ + if (!multibridge_exit) { + multibridge_exit = 1; + mt8193_bus_clk_switch(false); + } +} + +module_init(mt8193_ckgen_init); +module_exit(mt8193_ckgen_exit); + +int mt8193_CKGEN_AgtOnClk(enum e_CLK_T eAgt) +{ + u32 u4Tmp; + + pr_debug("mt8193_CKGEN_AgtOnClk() %d\n", eAgt); + + switch (eAgt) { + case e_CLK_NFI: + u4Tmp = CKGEN_READ32(REG_RW_NFI_CKCFG); + CKGEN_WRITE32(REG_RW_NFI_CKCFG, u4Tmp & (~CLK_PDN_NFI)); + break; + case e_CLK_HDMIPLL: + u4Tmp = CKGEN_READ32(REG_RW_HDMI_PLL_CKCFG); + CKGEN_WRITE32(REG_RW_HDMI_PLL_CKCFG, u4Tmp & (~CLK_PDN_HDMI_PLL)); + break; + case e_CLK_HDMIDISP: + u4Tmp = CKGEN_READ32(REG_RW_HDMI_DISP_CKCFG); + CKGEN_WRITE32(REG_RW_HDMI_DISP_CKCFG, u4Tmp & (~CLK_PDN_HDMI_DISP)); + break; + case e_CLK_LVDSDISP: + u4Tmp = CKGEN_READ32(REG_RW_LVDS_DISP_CKCFG); + CKGEN_WRITE32(REG_RW_LVDS_DISP_CKCFG, u4Tmp & (~CLK_PDN_LVDS_DISP)); + break; + case e_CLK_LVDSCTS: + u4Tmp = CKGEN_READ32(REG_RW_LVDS_CTS_CKCFG); + CKGEN_WRITE32(REG_RW_LVDS_DISP_CKCFG, u4Tmp & (~CLK_PDN_LVDS_CTS)); + break; + default: + return -1; + } + + return 0; +} + +int mt8193_CKGEN_AgtOffClk(enum e_CLK_T eAgt) +{ + u32 u4Tmp; + + pr_debug("mt8193_CKGEN_AgtOffClk() %d\n", eAgt); + + switch (eAgt) { + case e_CLK_NFI: + u4Tmp = CKGEN_READ32(REG_RW_NFI_CKCFG); + CKGEN_WRITE32(REG_RW_NFI_CKCFG, u4Tmp | CLK_PDN_NFI); + break; + case e_CLK_HDMIPLL: + u4Tmp = CKGEN_READ32(REG_RW_HDMI_PLL_CKCFG); + CKGEN_WRITE32(REG_RW_HDMI_PLL_CKCFG, u4Tmp | CLK_PDN_HDMI_PLL); + break; + case e_CLK_HDMIDISP: + u4Tmp = CKGEN_READ32(REG_RW_HDMI_DISP_CKCFG); + CKGEN_WRITE32(REG_RW_HDMI_DISP_CKCFG, u4Tmp | CLK_PDN_HDMI_DISP); + break; + case e_CLK_LVDSDISP: + u4Tmp = CKGEN_READ32(REG_RW_LVDS_DISP_CKCFG); + CKGEN_WRITE32(REG_RW_LVDS_DISP_CKCFG, u4Tmp | CLK_PDN_LVDS_DISP); + break; + case e_CLK_LVDSCTS: + u4Tmp = CKGEN_READ32(REG_RW_LVDS_CTS_CKCFG); + CKGEN_WRITE32(REG_RW_LVDS_DISP_CKCFG, u4Tmp | CLK_PDN_LVDS_CTS); + break; + default: + return -1; + } + + return 0; +} + +int mt8193_CKGEN_AgtSelClk(enum e_CLK_T eAgt, u32 u4Sel) +{ + u32 u4Tmp; + + pr_debug("mt8193_CKGEN_AgtSelClk() %d\n", eAgt); + + switch (eAgt) { + case e_CLK_NFI: + u4Tmp = CKGEN_READ32(REG_RW_NFI_CKCFG); + CKGEN_WRITE32(REG_RW_NFI_CKCFG, u4Tmp | u4Sel); + break; + case e_CLK_HDMIPLL: + u4Tmp = CKGEN_READ32(REG_RW_HDMI_PLL_CKCFG); + CKGEN_WRITE32(REG_RW_HDMI_PLL_CKCFG, u4Tmp | u4Sel); + break; + case e_CLK_HDMIDISP: + u4Tmp = CKGEN_READ32(REG_RW_HDMI_DISP_CKCFG); + CKGEN_WRITE32(REG_RW_HDMI_DISP_CKCFG, u4Tmp | u4Sel); + break; + case e_CLK_LVDSDISP: + u4Tmp = CKGEN_READ32(REG_RW_LVDS_DISP_CKCFG); + CKGEN_WRITE32(REG_RW_LVDS_DISP_CKCFG, u4Tmp | u4Sel); + break; + case e_CLK_LVDSCTS: + u4Tmp = CKGEN_READ32(REG_RW_LVDS_CTS_CKCFG); + CKGEN_WRITE32(REG_RW_LVDS_DISP_CKCFG, u4Tmp | u4Sel); + break; + default: + return -1; + } + + return 0; +} + +u32 mt8193_CKGEN_AgtGetClk(enum e_CLK_T eAgt) +{ + return 0; +} + +int mt8193_ckgen_i2c_write(u16 addr, u32 data) +{ + u32 u4_ret = 0; + + pr_debug("mt8193_ckgen_i2c_write() 0x%x; 0x%x\n", addr, data); + u4_ret = mt8193_i2c_write(addr, data); + if (u4_ret != 0) + pr_err("mt8193_i2c_read() fails!!!!!!\n"); + + return 0; +} + +u32 mt8193_ckgen_i2c_read(u16 addr) +{ + u32 u4_val = 0; + u32 u4_ret = 0; + + u4_ret = mt8193_i2c_read(addr, &u4_val); + if (u4_ret != 0) + pr_err("mt8193_i2c_read() fails!!!!!!\n"); + + pr_debug("mt8193_ckgen_i2c_read() 0x%x; value is 0x%x\n", addr, u4_val); + return u4_val; +} + +/* freq meter measure clock */ +u32 mt8193_ckgen_measure_clk(u32 u4Func) +{ + u32 ui4_delay_cnt = 0x400; + u32 ui4_result = 0; + + pr_debug("[CKGEN] mt8193_ckgen_measure_clk() %d\n", u4Func); + + /* select source */ + CKGEN_WRITE32(REG_RW_FMETER, (CKGEN_READ32(REG_RW_FMETER)&(~(0xFF<<3)))|(u4Func<<3)); + /* start fmeter */ + CKGEN_WRITE32(REG_RW_FMETER, (CKGEN_READ32(REG_RW_FMETER)|CKGEN_FMETER_RESET)); + /* wait until fmeter done */ + do { + ui4_delay_cnt--; + } while ((!(CKGEN_READ32(REG_RW_FMETER)&CKGEN_FMETER_DONE)) && ui4_delay_cnt); + + ui4_result = CKGEN_READ32(REG_RW_FMETER)>>16; + + pr_debug("[CKGEN] Measure Done CLK [0X%X] for func [%d] delay count [0x%X]\n", + ui4_result, u4Func, ui4_delay_cnt); + + return ui4_result; +} + +void mt8193_lvds_ana_pwr_control(bool power_on) +{ + u32 u4Tmp = 0; + + if (power_on) { + u4Tmp = CKGEN_READ32(REG_RW_LVDS_ANACFG4); + u4Tmp &= (~LVDS_ANACFG4_VPlLL_PD); + CKGEN_WRITE32(REG_RW_LVDS_ANACFG4, u4Tmp); + } else { + u4Tmp = CKGEN_READ32(REG_RW_LVDS_ANACFG4); + u4Tmp |= (LVDS_ANACFG4_VPlLL_PD); + CKGEN_WRITE32(REG_RW_LVDS_ANACFG4, u4Tmp); + } +} + +void mt8193_hdmi_ana_pwr_control(bool power_on) +{ + u32 u4Tmp = 0; + + if (power_on) { + u4Tmp = CKGEN_READ32(REG_RW_HDMITX_ANACFG3); + u4Tmp |= (HDMITX_ANACFG3_BIT20); + u4Tmp |= (HDMITX_ANACFG3_BIT21); + CKGEN_WRITE32(REG_RW_HDMITX_ANACFG3, u4Tmp); + } else { + u4Tmp = CKGEN_READ32(REG_RW_HDMITX_ANACFG3); + u4Tmp &= (~HDMITX_ANACFG3_BIT20); + u4Tmp &= (~HDMITX_ANACFG3_BIT21); + CKGEN_WRITE32(REG_RW_HDMITX_ANACFG3, u4Tmp); + } +} + +void mt8193_pllgp_ana_pwr_control(bool power_on) +{ + u32 u4Tmp = 0; + + if (power_on) { + u4Tmp = CKGEN_READ32(REG_RW_PLLGP_ANACFG0); + u4Tmp |= (PLLGP_ANACFG0_PLL1_EN); + CKGEN_WRITE32(REG_RW_PLLGP_ANACFG0, u4Tmp); + } else { + u4Tmp = CKGEN_READ32(REG_RW_PLLGP_ANACFG0); + u4Tmp &= (~PLLGP_ANACFG0_PLL1_EN); + CKGEN_WRITE32(REG_RW_PLLGP_ANACFG0, u4Tmp); + } +} + +void mt8193_nfi_ana_pwr_control(bool power_on) +{ + u32 u4Tmp = 0; + + pr_debug("[CKGEN] mt8193_nfi_ana_pwr_control() %d\n", power_on); + if (power_on) { + u4Tmp = CKGEN_READ32(REG_RW_PLLGP_ANACFG2); + u4Tmp |= (PLLGP_ANACFG2_PLLGP_BIAS_EN); + CKGEN_WRITE32(REG_RW_PLLGP_ANACFG2, u4Tmp); + + u4Tmp = CKGEN_READ32(REG_RW_PLLGP_ANACFG0); + u4Tmp |= (PLLGP_ANACFG0_PLL1_NFIPLL_EN); + CKGEN_WRITE32(REG_RW_PLLGP_ANACFG0, u4Tmp); + } else { + u4Tmp = CKGEN_READ32(REG_RW_PLLGP_ANACFG0); + u4Tmp &= (~PLLGP_ANACFG0_PLL1_NFIPLL_EN); + CKGEN_WRITE32(REG_RW_PLLGP_ANACFG0, u4Tmp); + msleep(20); + u4Tmp = CKGEN_READ32(REG_RW_PLLGP_ANACFG2); + u4Tmp &= (~PLLGP_ANACFG2_PLLGP_BIAS_EN); + CKGEN_WRITE32(REG_RW_PLLGP_ANACFG2, u4Tmp); + msleep(20); + } +} + +void mt8193_lvds_sys_spm_control(bool power_on) +{ + u32 u4Tmp = 0; + u32 u4Tmp2 = 0; + u32 ui4_delay_cnt = 0x40000; + + if (power_on) { + /* turn on power */ + u4Tmp = CKGEN_READ32(REG_RW_LVDS_PWR_CTRL); + u4Tmp |= CKGEN_LVDS_PWR_PWR_ON; + CKGEN_WRITE32(REG_RW_LVDS_PWR_CTRL, u4Tmp); + + /* disable reset */ + u4Tmp2 = CKGEN_READ32(REG_RW_LVDS_PWR_RST_B); + u4Tmp2 |= CKGEN_LVDS_PWR_RST_EN; + CKGEN_WRITE32(REG_RW_LVDS_PWR_RST_B, u4Tmp2); + + /* disable iso */ + u4Tmp &= (~CKGEN_LVDS_PWR_ISO_EN); + CKGEN_WRITE32(REG_RW_LVDS_PWR_CTRL, u4Tmp); + + /* enable clock */ + u4Tmp &= (~CKGEN_LVDS_PWR_CLK_OFF); + CKGEN_WRITE32(REG_RW_LVDS_PWR_CTRL, u4Tmp); + + /* wait until pwr act */ + do { + ui4_delay_cnt--; + } while ((!(CKGEN_READ32(REG_RO_PWR_ACT)&CKGEN_LVDS_PWR_ON_ACT)) && ui4_delay_cnt); + + if (ui4_delay_cnt == 0) + pr_err("[CKGEN] Did not get power act for LVDS!!!!\n"); + } else { + /* disable clock */ + u4Tmp = CKGEN_READ32(REG_RW_LVDS_PWR_CTRL); + u4Tmp |= CKGEN_LVDS_PWR_CLK_OFF; + CKGEN_WRITE32(REG_RW_LVDS_PWR_CTRL, u4Tmp); + + /* enable iso */ + u4Tmp |= CKGEN_LVDS_PWR_ISO_EN; + CKGEN_WRITE32(REG_RW_LVDS_PWR_CTRL, u4Tmp); + + /* enable reset */ + u4Tmp2 = CKGEN_READ32(REG_RW_LVDS_PWR_RST_B); + u4Tmp2 &= (~CKGEN_LVDS_PWR_RST_EN); + CKGEN_WRITE32(REG_RW_LVDS_PWR_RST_B, u4Tmp2); + + /* turn off power */ + u4Tmp &= (~CKGEN_LVDS_PWR_PWR_ON); + CKGEN_WRITE32(REG_RW_LVDS_PWR_CTRL, u4Tmp); + } +} + +void mt8193_hdmi_sys_spm_control(bool power_on) +{ + u32 u4Tmp = 0; + u32 u4Tmp2 = 0; + u32 ui4_delay_cnt = 0x40000; + + if (power_on) { + /* turn on power */ + u4Tmp = CKGEN_READ32(REG_RW_HDMI_PWR_CTRL); + u4Tmp |= CKGEN_HDMI_PWR_PWR_ON; + CKGEN_WRITE32(REG_RW_HDMI_PWR_CTRL, u4Tmp); + + /* disable reset */ + u4Tmp2 = CKGEN_READ32(REG_RW_HDMI_PWR_RST_B); + u4Tmp2 |= CKGEN_HDMI_PWR_RST_EN; + CKGEN_WRITE32(REG_RW_HDMI_PWR_RST_B, u4Tmp2); + + /* disable iso */ + u4Tmp &= (~CKGEN_HDMI_PWR_ISO_EN); + CKGEN_WRITE32(REG_RW_HDMI_PWR_CTRL, u4Tmp); + + /* enable clock */ + u4Tmp &= (~CKGEN_HDMI_PWR_CLK_OFF); + CKGEN_WRITE32(REG_RW_HDMI_PWR_CTRL, u4Tmp); + + /* wait until pwr act */ + do { + ui4_delay_cnt--; + } while ((!(CKGEN_READ32(REG_RO_PWR_ACT)&CKGEN_HDMI_PWR_ON_ACT)) && ui4_delay_cnt); + + if (ui4_delay_cnt == 0) + pr_err("[CKGEN] Did not get power act for HDMI!!!!\n"); + } else { + /* disable clock */ + u4Tmp = CKGEN_READ32(REG_RW_HDMI_PWR_CTRL); + u4Tmp |= CKGEN_HDMI_PWR_CLK_OFF; + CKGEN_WRITE32(REG_RW_HDMI_PWR_CTRL, u4Tmp); + + /* enable iso */ + u4Tmp |= CKGEN_HDMI_PWR_ISO_EN; + CKGEN_WRITE32(REG_RW_HDMI_PWR_CTRL, u4Tmp); + + /* enable reset */ + u4Tmp2 = CKGEN_READ32(REG_RW_HDMI_PWR_RST_B); + u4Tmp2 &= (~CKGEN_HDMI_PWR_RST_EN); + CKGEN_WRITE32(REG_RW_HDMI_PWR_RST_B, u4Tmp2); + + /* turn off power */ + u4Tmp &= (~CKGEN_HDMI_PWR_PWR_ON); + CKGEN_WRITE32(REG_RW_HDMI_PWR_CTRL, u4Tmp); + } +} + +void mt8193_nfi_sys_spm_control(bool power_on) +{ + u32 u4Tmp = 0; + u32 u4Tmp2 = 0; + u32 ui4_delay_cnt = 0x40000; + + if (power_on) { + /* turn on power */ + u4Tmp = CKGEN_READ32(REG_RW_NFI_PWR_CTRL); + u4Tmp |= CKGEN_NFI_PWR_PWR_ON; + CKGEN_WRITE32(REG_RW_NFI_PWR_CTRL, u4Tmp); + + /* disable reset */ + u4Tmp2 = CKGEN_READ32(REG_RW_NFI_PWR_RST_B); + u4Tmp2 |= CKGEN_NFI_PWR_RST_EN; + CKGEN_WRITE32(REG_RW_NFI_PWR_RST_B, u4Tmp2); + + /* disable iso */ + u4Tmp &= (~CKGEN_NFI_PWR_ISO_EN); + CKGEN_WRITE32(REG_RW_NFI_PWR_CTRL, u4Tmp); + + /* enable clock */ + u4Tmp &= (~CKGEN_NFI_PWR_CLK_OFF); + CKGEN_WRITE32(REG_RW_NFI_PWR_CTRL, u4Tmp); + + /* wait until pwr act */ + do { + ui4_delay_cnt--; + } while ((!(CKGEN_READ32(REG_RO_PWR_ACT)&CKGEN_NFI_PWR_ON_ACT)) && ui4_delay_cnt); + + if (ui4_delay_cnt == 0) + pr_err("[CKGEN] Did not get power act for NFI!!!!\n"); + } else { + /* disable clock */ + u4Tmp = CKGEN_READ32(REG_RW_NFI_PWR_CTRL); + u4Tmp |= CKGEN_NFI_PWR_CLK_OFF; + CKGEN_WRITE32(REG_RW_NFI_PWR_CTRL, u4Tmp); + + /* enable iso */ + u4Tmp |= CKGEN_NFI_PWR_ISO_EN; + CKGEN_WRITE32(REG_RW_NFI_PWR_CTRL, u4Tmp); + + /* enable reset */ + u4Tmp2 = CKGEN_READ32(REG_RW_NFI_PWR_RST_B); + u4Tmp2 &= (~CKGEN_NFI_PWR_RST_EN); + CKGEN_WRITE32(REG_RW_NFI_PWR_RST_B, u4Tmp2); + + /* turn off power */ + u4Tmp &= (~CKGEN_NFI_PWR_PWR_ON); + CKGEN_WRITE32(REG_RW_NFI_PWR_CTRL, u4Tmp); + } +} + +void mt8193_bus_clk_switch(bool bus_26m_to_32k) +{ + u32 u4Tmp = 0; + struct device_node *dn; + int bus_switch_pin; + int ret; + + dn = of_find_compatible_node(NULL, NULL, "mediatek,mt8193-ckgen"); + bus_switch_pin = of_get_named_gpio(dn, "bus_switch_pin", 0); + ret = gpio_request(bus_switch_pin, "8193 bus switch pin"); + if (ret) { + pr_err("request gpio fail, ret=%d\n", ret); + return; + } + + if (bus_26m_to_32k) { + /* bus clock switch from 26M to 32K */ + /* sequence: out -> dir -> select -> enable -> mode */ +#if 0 + mt_set_gpio_out(GPIO_MT8193_BUS_SWITCH_PIN, GPIO_OUT_ONE); + mt_set_gpio_dir(GPIO_MT8193_BUS_SWITCH_PIN, GPIO_DIR_OUT); + mt_set_gpio_pull_select(GPIO_MT8193_BUS_SWITCH_PIN, GPIO_PULL_UP); + mt_set_gpio_pull_enable(GPIO_MT8193_BUS_SWITCH_PIN, GPIO_PULL_ENABLE); + mt_set_gpio_mode(GPIO_MT8193_BUS_SWITCH_PIN, MT8193_BUS_SWITCH_PIN_GPIO_MODE); +#else + pinctrl_select_state(pinctrl, pins_gpio); +#endif + + u4Tmp = CKGEN_READ32(REG_RW_DCXO_ANACFG9); + u4Tmp &= (~(DCXO_ANACFG9_BUS_CK_SOURCE_SEL_MASK << DCXO_ANACFG9_BUS_CK_SOURCE_SEL_SHIFT)); +#if defined(USING_MT8193_DPI1) && USING_MT8193_DPI1 + u4Tmp |= (6 << DCXO_ANACFG9_BUS_CK_SOURCE_SEL_SHIFT); +#else + u4Tmp |= (3 << DCXO_ANACFG9_BUS_CK_SOURCE_SEL_SHIFT); +#endif + /* using a GPIO as auto switch source */ + u4Tmp &= (~DCX0_ANACFG9_BUS_CK_CTRL_SEL); + /* enable bus_ck auto switch function */ + u4Tmp |= (DCX0_ANACFG9_BUS_CK_AUTO_SWITCH_EN); + pr_debug("[early_suspend] u4Tmp=0x%x\n", u4Tmp); + CKGEN_WRITE32(REG_RW_DCXO_ANACFG9, u4Tmp); +#if 0 + mt_set_gpio_out(GPIO_MT8193_BUS_SWITCH_PIN, GPIO_OUT_ZERO); +#else + gpio_set_value(bus_switch_pin, 0); +#endif + msleep(20); + /* verify: reading register must fail if switch clock success */ + u4Tmp = CKGEN_READ32(REG_RW_DCXO_ANACFG9); + } else { + /* bus clock switch from 32K to 26M */ +#if 0 + mt_set_gpio_out(GPIO_MT8193_BUS_SWITCH_PIN, GPIO_OUT_ONE); +#else + gpio_set_value(bus_switch_pin, 1); +#endif + msleep(20); + u4Tmp = CKGEN_READ32(REG_RW_DCXO_ANACFG9); + u4Tmp &= (~(DCXO_ANACFG9_BUS_CK_SOURCE_SEL_MASK << DCXO_ANACFG9_BUS_CK_SOURCE_SEL_SHIFT)); + pr_debug("[late_resume] u4Tmp=0x%x\n", u4Tmp); + CKGEN_WRITE32(REG_RW_DCXO_ANACFG9, u4Tmp); +#if 0 + mt_set_gpio_mode(GPIO_MT8193_BUS_SWITCH_PIN, MT8193_BUS_SWITCH_PIN_DPI_MODE); +#else + pinctrl_select_state(pinctrl, pins_dpi); +#endif + } + + gpio_free(bus_switch_pin); +} + +#if 0 +void mt8193_bus_clk_switch_to_26m(void) +{ + u32 u4Tmp = 0; + + pr_debug(" mt8193_bus_clk_switch_to_26m()\n"); + + /* bus clock switch from 32K to 26M */ + + mt_set_gpio_out(GPIO_MT8193_BUS_SWITCH_PIN, GPIO_OUT_ONE); + + mdelay(20); + + u4Tmp = CKGEN_READ32(REG_RW_DCXO_ANACFG9); + u4Tmp &= (~(DCXO_ANACFG9_BUS_CK_SOURCE_SEL_MASK << DCXO_ANACFG9_BUS_CK_SOURCE_SEL_SHIFT)); + CKGEN_WRITE32(REG_RW_DCXO_ANACFG9, u4Tmp); + + mt_set_gpio_mode(GPIO_MT8193_BUS_SWITCH_PIN, MT8193_BUS_SWITCH_PIN_DPI_MODE); +} +#endif + +#if MT8193_DISABLE_DCXO + +/* disable dcxo ldo1, 8193 core clock buffer */ +void mt8193_disable_dcxo_core(void) +{ + u32 u4Tmp = 0; + + pr_debug("mt8193_disable_dcxo_core()\n"); + + /* set bt clock buffer manual mode */ + u4Tmp = CKGEN_READ32(REG_RW_DCXO_ANACFG2); + u4Tmp &= (~DCXO_ANACFG2_PO_MAN); + CKGEN_WRITE32(REG_RW_DCXO_ANACFG2, u4Tmp); + + /* disable dcxo ldo2 at manual mode */ + u4Tmp &= (~DCXO_ANACFG2_LDO1_MAN_EN); + CKGEN_WRITE32(REG_RW_DCXO_ANACFG2, u4Tmp); + + /* disable dcxo ldo2*/ + u4Tmp &= (~DCXO_ANACFG2_LDO1_EN); + CKGEN_WRITE32(REG_RW_DCXO_ANACFG2, u4Tmp); +} + +/* enable dcxo ldo1, 8193 core clock buffer */ +void mt8193_enable_dcxo_core(void) +{ + u32 u4Tmp = 0; + + pr_debug("mt8193_enable_dcxo_core()\n"); + + /* disable dcxo ldo2*/ + u4Tmp = CKGEN_READ32(REG_RW_DCXO_ANACFG2); + u4Tmp |= DCXO_ANACFG2_LDO1_EN; + CKGEN_WRITE32(REG_RW_DCXO_ANACFG2, u4Tmp); + + /* disable dcxo ldo2 at manual mode */ + u4Tmp |= DCXO_ANACFG2_LDO1_MAN_EN; + CKGEN_WRITE32(REG_RW_DCXO_ANACFG2, u4Tmp); + + /* set bt clock buffer manual mode */ + + u4Tmp |= DCXO_ANACFG2_PO_MAN; + CKGEN_WRITE32(REG_RW_DCXO_ANACFG2, u4Tmp); +} + +#endif + +#if 0 +void mt8193_en_bb_ctrl(bool pd) +{ + /* GPIO60 is EN_BB */ + /* GPIO59 is CK_SEL */ + if (pd) { + /* pull low */ + mt_set_gpio_out(GPIO60, 0); + mt_set_gpio_out(GPIO59, 0); + } else { + /* pull high */ + mt_set_gpio_out(GPIO59, 1); + mt_set_gpio_out(GPIO60, 1); + } +} +#endif + +/****************************************************************************** + * mt8193_ckgen_suspend + * + * DESCRIPTION: + * Suspend the nand device! + * + * PARAMETERS: + * struct platform_device *pdev : device structure + * + * RETURNS: + * 0 : Success + * + * NOTES: + * None + * + ******************************************************************************/ +static int mt8193_ckgen_suspend(struct platform_device *pdev, pm_message_t state) +{ + pr_debug("[CKGEN] mt8193_ckgen_suspend() enter\n"); + +#if MT8193_MLC + + /* If we use 8193 NFI, we should turn off pllgp in suspend because early suspend state may still use NFI. + Otherwise, we can turn off pllgp in early suspend. */ + + /* add 8193 suspend function here */ + + mt8193_pllgp_ana_pwr_control(false); + msleep(20); + + /* bus clk switch to 32K */ + mt8193_bus_clk_switch(true); + msleep(50); +#endif + pr_debug("[CKGEN] mt8193_ckgen_suspend() exit\n"); + + return 0; +} +/****************************************************************************** + * mt8193_ckgen_resume + * + * DESCRIPTION: + * Resume the nand device! + * + * PARAMETERS: + * struct platform_device *pdev : device structure + * + * RETURNS: + * 0 : Success + * + * NOTES: + * None + * + ******************************************************************************/ +static int mt8193_ckgen_resume(struct platform_device *pdev) +{ + pr_debug("[CKGEN] mt8193_ckgen_resume() enter\n"); + + /* If we use 8193 NFI, we should turn off pllgp in suspend because early suspend state may still use NFI. + Otherwise, we can turn off pllgp in early suspend. */ + +#if MT8193_MLC + /* add 8193 resume function here */ + /* bus clk switch to 26M */ + mt8193_bus_clk_switch(false); + msleep(20); + /* turn on pllgp analog */ + mt8193_pllgp_ana_pwr_control(true); + msleep(20); +#endif + pr_debug("[CKGEN] mt8193_ckgen_resume() exit\n"); + + return 0; +} diff --git a/drivers/misc/mediatek/multibridge/mt6797/mt8193/mt8193_ckgen_vfy.c b/drivers/misc/mediatek/multibridge/mt6797/mt8193/mt8193_ckgen_vfy.c new file mode 100644 index 000000000000..8c8969fc877d --- /dev/null +++ b/drivers/misc/mediatek/multibridge/mt6797/mt8193/mt8193_ckgen_vfy.c @@ -0,0 +1,501 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms 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. + */ + +#if defined(CONFIG_MTK_MULTIBRIDGE_SUPPORT) + +#define MT8193_CKGEN_VFY 1 + +#if MT8193_CKGEN_VFY + +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/wait.h> +#include <linux/spinlock.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/cdev.h> +#include "mt8193.h" +#include "mt8193_ckgen.h" + + +int mt8193_ckgen_config_pad_level_shift(int i4GroupNum, int i4TurnLow) +{ + u32 u4Tmp; + + pr_debug("[CKGEN] mt8193_ckgen_config_pad_level_shift() %d, %d\n", i4GroupNum, i4TurnLow); + + if (i4TurnLow == 0) { + /* 3.3V->1.8V */ + u4Tmp = CKGEN_READ32(REG_RW_LS_CTRL); + u4Tmp |= LS_CTRL_SHIFT_LOW_EN; + CKGEN_WRITE32(REG_RW_LS_CTRL, u4Tmp); + u4Tmp &= (~(1U<<i4GroupNum)); + CKGEN_WRITE32(REG_RW_LS_CTRL, u4Tmp); + } else { + /* 1.8V -> 3.3V */ + u4Tmp = CKGEN_READ32(REG_RW_LS_CTRL); + u4Tmp |= LS_CTRL_SHIFT_HIGH_EN; + CKGEN_WRITE32(REG_RW_LS_CTRL, u4Tmp); + u4Tmp |= (1U<<i4GroupNum); + CKGEN_WRITE32(REG_RW_LS_CTRL, u4Tmp); + } + + pr_debug("[CKGEN] LS_CTRL: 0x%x\n", u4Tmp); + + return 0; +} + +u32 mt8193_ckgen_reg_rw_test(u16 addr) +{ + u32 u4Loop = 0; + + pr_debug("[CKGEN] mt8193_ckgen_reg_rw_test() 0x%x\n", addr); + + for (; u4Loop < 0xFFFF; u4Loop += 0x10) { + CKGEN_WRITE32(addr, u4Loop); + if (CKGEN_READ32(addr) != u4Loop) { + pr_err("[CKGEN] reg rw test fail at loop 0x%x\n", u4Loop); + return -1; + } + } + + pr_debug("[CKGEN] mt8193_ckgen_reg_rw_test() success at 0x%x\n", addr); + + return 0; +} + + +u32 mt8193_ckgen_bus_clk_switch_xtal_test(u16 addr) +{ + /* switch bus clock to 32k. pdwn dcxo. rw register */ + u32 u4Tmp = 0; + + /* swicth bus clock to 32k */ + u4Tmp = CKGEN_READ32(REG_RW_BUS_CKCFG); + CKGEN_WRITE32(REG_RW_BUS_CKCFG, (u4Tmp & (~(0xF))) | CLK_BUS_SEL_32K); + return 0; +} + +u32 mt8193_io_agent_test(void) +{ + u32 u4Tmp = 0; + + pr_debug("[CKGEN] IO AGENT TEST ------------------------------------------\n"); + + IO_WRITE32(0x1000, 0x500, 0x55555555); + u4Tmp = IO_READ32(0x1000, 0x500); + if (u4Tmp == 0x55555555) + pr_debug("[CKGEN] TEST PASS at 0x1500\n"); + else + pr_err("[CKGEN] TEST FAIL at 0x1500. [0x%x] !!!!!!!!!!\n", u4Tmp); + + IO_WRITE32(0x0, 0x18, 0x55555555); + u4Tmp = IO_READ32(0x0, 0x18); + if (u4Tmp == 0x55555555) + pr_debug("[CKGEN] TEST PASS at 0x18\n"); + else + pr_err("[CKGEN] TEST FAIL at 0x18. [0x%x] !!!!!!!!!!\n", u4Tmp); + + IO_WRITE32(0x0, 0x0408, 0x55555555); + u4Tmp = IO_READ32(0x0, 0x408); + if (u4Tmp == 0x55555555) + pr_debug("[CKGEN] TEST PASS at 0x408\n"); + else + pr_err("[CKGEN] TEST FAIL at 0x408. [0x%x] !!!!!!!!!!\n", u4Tmp); + + IO_WRITE32(0x0, 0x0608, 0x55555555); + u4Tmp = IO_READ32(0x0, 0x608); + if (u4Tmp == 0x55555555) + pr_debug("[CKGEN] TEST PASS at 0x608\n"); + else + pr_err("[CKGEN] TEST FAIL at 0x608. [0x%x] !!!!!!!!!!\n", u4Tmp); + + IO_WRITE32(0x0, 0x0a10, 0x55555555); + u4Tmp = IO_READ32(0x0, 0xa10); + if (u4Tmp == 0x00055555) + pr_debug("[CKGEN] TEST PASS at 0xa10\n"); + else + pr_err("[CKGEN] TEST FAIL at 0xa10. [0x%x] !!!!!!!!!!\n", u4Tmp); + + IO_WRITE32(0x1000, 0x200, 0xaaaaffff); + u4Tmp = IO_READ32(0x1000, 0x200); + if (u4Tmp == 0xaaaaffff) + pr_debug("[CKGEN] TEST PASS at 0x1200\n"); + else + pr_err("[CKGEN] TEST FAIL at 0x1200. [0x%x] !!!!!!!!!!\n", u4Tmp); + + IO_WRITE32(0x1000, 0x608, 0x05550555); + u4Tmp = IO_READ32(0x1000, 0x608); + if (u4Tmp == 0x05550555) + pr_debug("[CKGEN] TEST PASS at 0x1608\n"); + else + pr_err("[CKGEN] TEST FAIL at 0x1608. [0x%x] !!!!!!!!!!\n", u4Tmp); + + IO_WRITE32(0x1000, 0x708, 0x55555555); + u4Tmp = IO_READ32(0x1000, 0x708); + if (u4Tmp == 0x55555555) + pr_debug("[CKGEN] TEST PASS at 0x1708\n"); + else + pr_err("[CKGEN] TEST FAIL at 0x1708. [0x%x] !!!!!!!!!!\n", u4Tmp); + + IO_WRITE32(0x1000, 0xd00, 0x55555555); + u4Tmp = IO_READ32(0x1000, 0xd00); + if (u4Tmp == 0x55555555) + pr_debug("[CKGEN] TEST PASS at 0x1d00\n"); + else + pr_err("[CKGEN] TEST FAIL at 0x1d00. [0x%x] !!!!!!!!!!\n", u4Tmp); + + IO_WRITE32(0x1000, 0xd00, 0xaaaaaaaa); + u4Tmp = IO_READ32(0x1000, 0xd00); + if (u4Tmp == 0xaaaaaaaa) + pr_debug("[CKGEN] TEST PASS at 0x1d00\n"); + else + pr_err("[CKGEN] TEST FAIL at 0x1d00. [0x%x] !!!!!!!!!!\n", u4Tmp); + + pr_debug("[CKGEN] IO AGENT TEST FINISH ------------------------------------------\n"); + + return 0; +} + +void mt8193_hdmi_on_test(void) +{ + int i = 0; + u32 u4Crc = 0; + + mt8193_i2c_write(0x1254, 0x00000323); + msleep(100); + mt8193_i2c_write(0x101c, 0x00000004); + msleep(100); + mt8193_i2c_write(0x1328, 0x00009999); + msleep(100); + mt8193_i2c_write(0x1334, 0x0020008f); + msleep(100); + mt8193_i2c_write(0x1338, 0xd4a88f00); + msleep(100); + mt8193_i2c_write(0x1344, 0x00008012); + msleep(100); + mt8193_i2c_write(0x1348, 0x11ff0000); + msleep(100); + mt8193_i2c_write(0x1334, 0x0030008f); + msleep(100); + mt8193_i2c_write(0x02d4, 0x02); + msleep(100); + mt8193_i2c_write(0x02d8, 0x80); + msleep(100); + mt8193_i2c_write(0x0448, 0x00000); + msleep(100); + mt8193_i2c_write(0x0450, 0x2); + msleep(100); + mt8193_i2c_write(0x0608, 0x80000005); + msleep(100); + mt8193_i2c_write(0x065c, 0x0000000f); + msleep(100); + mt8193_i2c_write(0x0604, 0x00000040); + msleep(100); + mt8193_i2c_write(0x061c, 0x00104000); + msleep(100); + mt8193_i2c_write(0x0624, 0x02ee07bc); + msleep(100); + mt8193_i2c_write(0x0628, 0x00030005); + msleep(100); + mt8193_i2c_write(0x0630, 0x0080057f); + msleep(100); + mt8193_i2c_write(0x0634, 0x001002df); + msleep(100); + mt8193_i2c_write(0x0638, 0x001002df); + msleep(100); + mt8193_i2c_write(0x0620, 0x000207ba); + msleep(100); + mt8193_i2c_write(0x0600, 0x00000001); + msleep(100); + mt8193_i2c_write(0x060c, 0x00000002); + msleep(100); + mt8193_i2c_write(0x0700, 0x02ee07bc); + msleep(100); + mt8193_i2c_write(0x0704, 0x00030005); + msleep(100); + mt8193_i2c_write(0x0708, 0x01000080); + msleep(100); + mt8193_i2c_write(0x070c, 0x02d00500); + msleep(100); + mt8193_i2c_write(0x0710, 0x00000203); + msleep(100); + mt8193_i2c_write(0x0714, 0x00ff8844); + msleep(100); + mt8193_i2c_write(0x0718, 0x000000ff); + msleep(100); + + for (; i < 100; i++) { + u32 u4Crc_2 = 0; + + mt8193_i2c_write(0x071c, 2); + msleep(50); + mt8193_i2c_write(0x071c, 1); + msleep(50); + mt8193_i2c_read(0x0720, &u4Crc_2); + msleep(50); + + if (i > 1 && u4Crc_2 != u4Crc) { + pr_err("[HDMI] CHECK CRC ERROR! 0x%x, 0x%x, %d\n", u4Crc, u4Crc_2, i); + break; + } else { + pr_debug("[HDMI] CHECK CRC OK %d\n", i); + } + + u4Crc = u4Crc_2; + } +} + +void mt8193_spm_control_test(int u4Func) +{ + pr_debug("[CKGEN] mt8193_spm_control_test()enters. %d\n", u4Func); + + /* mt8193_io_agent_test(); */ + + if (u4Func == 0) { + /* loop 1 */ + mt8193_lvds_sys_spm_control(false); + msleep(1000); + mt8193_hdmi_sys_spm_control(false); + msleep(1000); + mt8193_nfi_sys_spm_control(false); + msleep(1000); + + mt8193_lvds_sys_spm_control(true); + msleep(1000); + mt8193_hdmi_sys_spm_control(true); + msleep(1000); + mt8193_nfi_sys_spm_control(true); + msleep(1000); + + mt8193_io_agent_test(); + + /* loop 2 */ + mt8193_hdmi_sys_spm_control(false); + msleep(1000); + mt8193_lvds_sys_spm_control(false); + msleep(1000); + mt8193_nfi_sys_spm_control(false); + msleep(1000); + + mt8193_lvds_sys_spm_control(true); + msleep(1000); + mt8193_hdmi_sys_spm_control(true); + msleep(1000); + mt8193_nfi_sys_spm_control(true); + msleep(1000); + + mt8193_io_agent_test(); + + /* loop 3 */ + mt8193_nfi_sys_spm_control(false); + msleep(1000); + mt8193_lvds_sys_spm_control(false); + msleep(1000); + mt8193_hdmi_sys_spm_control(false); + msleep(1000); + + mt8193_lvds_sys_spm_control(true); + msleep(1000); + mt8193_hdmi_sys_spm_control(true); + msleep(1000); + mt8193_nfi_sys_spm_control(true); + msleep(1000); + + mt8193_io_agent_test(); + + /* loop 4 */ + mt8193_lvds_sys_spm_control(false); + msleep(1000); + mt8193_nfi_sys_spm_control(false); + msleep(1000); + mt8193_hdmi_sys_spm_control(false); + msleep(1000); + + mt8193_lvds_sys_spm_control(true); + msleep(1000); + mt8193_hdmi_sys_spm_control(true); + msleep(1000); + mt8193_nfi_sys_spm_control(true); + msleep(1000); + + mt8193_io_agent_test(); + + /* loop 5 */ + + mt8193_hdmi_sys_spm_control(false); + msleep(1000); + mt8193_lvds_sys_spm_control(false); + msleep(1000); + mt8193_nfi_sys_spm_control(false); + msleep(1000); + + mt8193_lvds_sys_spm_control(true); + msleep(1000); + mt8193_hdmi_sys_spm_control(true); + msleep(1000); + mt8193_nfi_sys_spm_control(true); + msleep(1000); + + mt8193_io_agent_test(); + } else if (u4Func == 1) { + /* + step 1: turn off digital + step 2: turn off analog + step3: BUS CLK SWITCH TO 32K + step4: PULL LOW EN_BB & CK_SEL + Step5: PULL UP EN_BB & CK_SEL + step6: BUS CLK SWITCH to 26M + step7: turn on analog + step8: turn on digital + step9: test function + */ + /* lvds spm ctrl test */ + mt8193_lvds_sys_spm_control(false); + msleep(100); + /*mt8193_hdmi_sys_spm_control(false);*/ + msleep(100); + /*mt8193_nfi_sys_spm_control(false);*/ + msleep(100); + + mt8193_lvds_ana_pwr_control(false); + msleep(100); + /*mt8193_hdmi_ana_pwr_control(false);*/ + msleep(100); + mt8193_pllgp_ana_pwr_control(false); + msleep(100); + /*mt8193_nfi_ana_pwr_control(false);*/ + msleep(1000); + + /* bus clk switch to 32K*/ + mt8193_bus_clk_switch(true); + + msleep(20); + /* pull low en_bb */ + /* mt8193_en_bb_ctrl(true); */ + + msleep(100); + + /* pull up en_bb */ + /* mt8193_en_bb_ctrl(false); */ + + /* msleep(20); */ + + /* bus clk switch to 26M */ + mt8193_bus_clk_switch(false); + + /*mt8193_nfi_ana_pwr_control(true);*/ + msleep(100); + mt8193_pllgp_ana_pwr_control(true); + msleep(100); + /*mt8193_hdmi_ana_pwr_control(true);*/ + msleep(100); + mt8193_lvds_ana_pwr_control(true); + msleep(100); + mt8193_lvds_sys_spm_control(true); + msleep(100); + /*mt8193_hdmi_sys_spm_control(true);*/ + msleep(100); + /*mt8193_nfi_sys_spm_control(true);*/ + msleep(100); + + /* lcm_mt8193_lvds_on_test();*/ + } else if (u4Func == 2) { + /*int i = 0;*/ + + /*for (; i<=1000; i++) { */ + /*pr_debug("[CKGEN] LOOP %d START-------------------------------------\n", i);*/ + /* hdmi spm ctrl test */ + msleep(1000); + mt8193_lvds_ana_pwr_control(false); + msleep(20); + mt8193_hdmi_ana_pwr_control(false); + msleep(20); + mt8193_pllgp_ana_pwr_control(false); + msleep(20); + mt8193_nfi_ana_pwr_control(false); + msleep(20); + mt8193_lvds_sys_spm_control(false); + msleep(20); + mt8193_hdmi_sys_spm_control(false); + msleep(20); + mt8193_nfi_sys_spm_control(false); + msleep(20); + + /* bus clk switch to 32K */ + mt8193_bus_clk_switch(true); + + msleep(1000); + /* pull low en_bb */ + /*mt8193_en_bb_ctrl(true);*/ + + /*msleep(100);*/ + + /* pull up en_bb*/ + /*mt8193_en_bb_ctrl(false);*/ + + /*msleep(1);*/ + + /* bus clk switch to 26M */ + mt8193_bus_clk_switch(false); + msleep(20); + mt8193_lvds_sys_spm_control(true); + msleep(20); + mt8193_hdmi_sys_spm_control(true); + msleep(20); + mt8193_nfi_sys_spm_control(true); + msleep(20); + mt8193_nfi_ana_pwr_control(true); + msleep(20); + mt8193_pllgp_ana_pwr_control(true); + msleep(20); + mt8193_hdmi_ana_pwr_control(true); + msleep(20); + mt8193_lvds_ana_pwr_control(true); + msleep(1000); + + /*pr_debug("[CKGEN] LOOP %d END-------------------------------------\n", i); */ + /*}*/ + + /*mt8193_hdmi_on_test();*/ + } else if (u4Func == 3) { + /* nfi spm ctrl test */ + mt8193_nfi_sys_spm_control(false); + msleep(1000); + mt8193_nfi_sys_spm_control(true); + msleep(1000); + + mt8193_io_agent_test(); + } else if (u4Func == 4) { + /* bus clk switch to 32K */ + mt8193_bus_clk_switch(true); + msleep(20); + /* pull low en_bb */ + /* mt8193_en_bb_ctrl(true); */ + } else if (u4Func == 5) { + /* pull up en_bb */ + /* mt8193_en_bb_ctrl(false); */ + /* bus clk switch to 32K */ + mt8193_bus_clk_switch(false); + } + + pr_debug("[CKGEN] mt8193_spm_control() exit\n"); +} + +#endif +#endif diff --git a/drivers/misc/mediatek/multibridge/mt6797/mt8193/mt8193_gpio.c b/drivers/misc/mediatek/multibridge/mt6797/mt8193/mt8193_gpio.c new file mode 100644 index 000000000000..b1d1c7c46d4d --- /dev/null +++ b/drivers/misc/mediatek/multibridge/mt6797/mt8193/mt8193_gpio.c @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms 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. + */ + +#define pr_fmt(fmt) "mt8193-gpio: " fmt + +#include <generated/autoconf.h> +#include <linux/mm.h> +#include <linux/init.h> +#include <linux/fb.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/kthread.h> +#include <linux/vmalloc.h> + +#include <linux/uaccess.h> +#include <linux/atomic.h> +#include <asm/cacheflush.h> +#include <linux/io.h> + +#include <mach/irqs.h> + +#include <linux/miscdevice.h> +#include <linux/platform_device.h> +#include <linux/fs.h> +#include <linux/file.h> +#include <linux/mm.h> +#include <linux/cdev.h> +#include <asm/tlbflush.h> +#include <asm/page.h> +#include <linux/io.h> +#include <linux/uaccess.h> +#include <linux/slab.h> + +#include <generated/autoconf.h> +#include <linux/module.h> +#include <linux/mm.h> +#include <linux/init.h> +#include <linux/fb.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/kthread.h> + +#include <linux/uaccess.h> +#include <linux/atomic.h> +#include <asm/cacheflush.h> +#include <linux/io.h> + +#include <mach/irqs.h> +#include <linux/vmalloc.h> + +#include <linux/uaccess.h> + +#include "mt8193_pinmux.h" +#include "mt8193_gpio.h" +#include "mt8193.h" + + +/* config gpio input/output low/high */ +int GPIO_Config(u32 u4GpioNum, u8 u1Mode, u8 u1Value) +{ + int ret = 0; + u32 u4PadNum = 0; + u32 u4Tmp = 0; + + if (u4GpioNum > GPIO_PIN_MAX) { + pr_err("[PINMUX] Invalid GPIO NUM %d\n", u4GpioNum); + return PINMUX_RET_INVALID_ARG; + } + + u4PadNum = _au4GpioTbl[u4GpioNum]; + + pr_debug("[PINMUX] GPIO_Config() %d, %d, %d, %d\n", u4GpioNum, u4PadNum, u1Mode, u1Value); + + if (u4PadNum >= PIN_NFD6 && u4PadNum <= PIN_NFD0) { + /* NFI ND GROUP. function 1 is gpio*/ + ret = mt8193_pinset(u4PadNum, PINMUX_FUNCTION1); + } else if (u4PadNum >= PIN_G0 && u4PadNum <= PIN_VSYNC) { + /* GRB OUT GROUP. function 0 is gpio */ + ret = mt8193_pinset(u4PadNum, PINMUX_FUNCTION0); + } else if (u4PadNum >= PIN_CEC && u4PadNum <= PIN_HTPLG) { + /* HDMI GROUP. function 2 is gpio */ + ret = mt8193_pinset(u4PadNum, PINMUX_FUNCTION2); + } else if (u4PadNum >= PIN_I2S_DATA && u4PadNum <= PIN_I2S_BCK) { + /* audio GROUP. function 3 is gpio */ + ret = mt8193_pinset(u4PadNum, PINMUX_FUNCTION3); + } else if (u4PadNum == PIN_DPI1CK) { + /* RGB_IN2 group. function 2 is gpio*/ + ret = mt8193_pinset(u4PadNum, PINMUX_FUNCTION2); + } else if (u4PadNum >= PIN_DPI1D7 && u4PadNum <= PIN_DPI1D0) { + /* RGB_IN1 GROUP. function 3 is gpio */ + ret = mt8193_pinset(u4PadNum, PINMUX_FUNCTION3); + } else if (u4PadNum >= PIN_DPI0CK && u4PadNum <= PIN_DPI0D3) { + /* RGB_IN1 GROUP. function 2 is gpio */ + ret = mt8193_pinset(u4PadNum, PINMUX_FUNCTION2); + } else if (u4PadNum >= PIN_DPI0D2 && u4PadNum <= PIN_DPI0D0) { + /* RGB_IN1 GROUP. function 1 is gpio */ + ret = mt8193_pinset(u4PadNum, PINMUX_FUNCTION1); + } else if (u4PadNum >= PIN_SDA && u4PadNum <= PIN_SCL) { + /* I2C_SLAVE GROUP. function 1 is gpio */ + ret = mt8193_pinset(u4PadNum, PINMUX_FUNCTION1); + } else if (u4PadNum >= PIN_NRNB && u4PadNum <= PIN_NLD7) { + /* NFI_6583 GROUP. function 2 is gpio */ + ret = mt8193_pinset(u4PadNum, PINMUX_FUNCTION2); + } else if (u4PadNum >= PIN_NLD6 && u4PadNum <= PIN_NLD3) { + /* NFI_6583 GROUP. function 3 is gpio */ + ret = mt8193_pinset(u4PadNum, PINMUX_FUNCTION3); + } else if (u4PadNum >= PIN_NLD2 && u4PadNum <= PIN_NLD0) { + /* NFI_6583 GROUP. function 2 is gpio */ + ret = mt8193_pinset(u4PadNum, PINMUX_FUNCTION2); + } else if (u4PadNum == PIN_INT) { + /* INTERRUPT group. function 3 is gpio*/ + ret = mt8193_pinset(u4PadNum, PINMUX_FUNCTION3); + } else if (u4PadNum >= PIN_NLD2 && u4PadNum <= PIN_NLD0) { + /* NFI_6583 GROUP. function 2 is gpio */ + ret = mt8193_pinset(u4PadNum, PINMUX_FUNCTION2); + } else if (u4PadNum == PIN_NFRBN) { + /* NFI_ND group. function 1 is gpio*/ + ret = mt8193_pinset(u4PadNum, PINMUX_FUNCTION1); + } else if (u4PadNum >= PIN_NFCLE && u4PadNum <= PIN_NFALE) { + /* NFI ND GROUP. function 3 is gpio*/ + ret = mt8193_pinset(u4PadNum, PINMUX_FUNCTION3); + } else if (u4PadNum >= PIN_NFWEN && u4PadNum <= PIN_NFD7) { + /* NFI ND GROUP. function 2 is gpio*/ + ret = mt8193_pinset(u4PadNum, PINMUX_FUNCTION2); + } else { + pr_err("[PINMUX] GPIO CFG ERROR !\n"); + return PINMUX_RET_INVALID_ARG; + } + + if (u1Mode == MT8193_GPIO_OUTPUT) { + /* output*/ + if (u4GpioNum >= 32 && u4GpioNum <= 63) { + u4Tmp = CKGEN_READ32(REG_RW_GPIO_EN_1); + u4Tmp |= (1 << (u4GpioNum-32)); + CKGEN_WRITE32(REG_RW_GPIO_EN_1, u4Tmp); + + u4Tmp = CKGEN_READ32(REG_RW_GPIO_OUT_1); + + if (u1Value == MT8193_GPIO_HIGH) + u4Tmp |= (1 << (u4GpioNum-32)); + else + u4Tmp &= (~(1 << (u4GpioNum-32))); + + CKGEN_WRITE32(REG_RW_GPIO_OUT_1, u4Tmp); + } else if (u4GpioNum >= 0 && u4GpioNum <= 31) { + /* work around method for gpio0~gpio31 */ + u32 u4PdShift = 0; + u32 u4PuShift = 0; + + u4PdShift = _au4PinmuxPadPuPdTbl[u4PadNum][0]; + u4PuShift = _au4PinmuxPadPuPdTbl[u4PadNum][1]; + + u4Tmp = CKGEN_READ32(REG_RW_GPIO_EN_0); + + if (u1Value == MT8193_GPIO_HIGH) { + /* for output high, set en as 0. set pad pd as 0, set pad pu as 1 */ + u4Tmp &= (~(1 << u4GpioNum)); + CKGEN_WRITE32(REG_RW_GPIO_EN_0, u4Tmp); + + if (u4PdShift <= 31) { + u4Tmp = CKGEN_READ32(REG_RW_PAD_PD0); + u4Tmp &= (~(1 << u4PdShift)); + CKGEN_WRITE32(REG_RW_PAD_PD0, u4Tmp); + + u4Tmp = CKGEN_READ32(REG_RW_PAD_PU0); + u4Tmp |= (1 << u4PdShift); + CKGEN_WRITE32(REG_RW_PAD_PU0, u4Tmp); + } else if (u4PdShift >= 32 && u4PdShift <= 63) { + u4Tmp = CKGEN_READ32(REG_RW_PAD_PD1); + u4Tmp &= (~(1 << (u4PdShift - 31))); + CKGEN_WRITE32(REG_RW_PAD_PD1, u4Tmp); + + u4Tmp = CKGEN_READ32(REG_RW_PAD_PU1); + u4Tmp |= (1 << (u4PdShift - 31)); + CKGEN_WRITE32(REG_RW_PAD_PU1, u4Tmp); + } + } else { + /* for output low, just set en as 1 */ + u4Tmp |= (1 << u4GpioNum); + CKGEN_WRITE32(REG_RW_GPIO_EN_0, u4Tmp); + } + + /* CKGEN_WRITE32(REG_RW_GPIO_OUT_0, u4Tmp); */ + } + } else { + /* input*/ + if (u4GpioNum >= 32 && u4GpioNum <= 63) { + u4Tmp = CKGEN_READ32(REG_RW_GPIO_EN_1); + u4Tmp &= (~(1 << (u4GpioNum-32))); + CKGEN_WRITE32(REG_RW_GPIO_EN_1, u4Tmp); + } else if (u4GpioNum >= 0 && u4GpioNum <= 31) { + u4Tmp = CKGEN_READ32(REG_RW_GPIO_EN_0); + u4Tmp &= (~(1 << u4GpioNum)); + CKGEN_WRITE32(REG_RW_GPIO_EN_0, u4Tmp); + } + } + + return PINMUX_RET_OK; +} + +/* return MT8193_GPIO_HIGH or MT8193_GPIO_LOW */ +u8 GPIO_Input(u32 u4GpioNum) +{ + u32 u4Tmp = 0; + u8 u1Val = MT8193_GPIO_LOW; + + if (u4GpioNum >= 32 && u4GpioNum <= 63) { + u4Tmp = CKGEN_READ32(REG_RW_GPIO_IN_1); + u1Val = (u4Tmp & (1 << (u4GpioNum-32))) ? MT8193_GPIO_HIGH : MT8193_GPIO_LOW; + } else if (u4GpioNum >= 0 && u4GpioNum <= 31) { + u4Tmp = CKGEN_READ32(REG_RW_GPIO_IN_0); + u1Val = (u4Tmp & (1 << u4GpioNum)) ? MT8193_GPIO_HIGH : MT8193_GPIO_LOW; + } + + return u1Val; +} + +int GPIO_Output(u32 u4GpioNum, u32 u4High) +{ + int ret = 0; + + ret = GPIO_Config(u4GpioNum, MT8193_GPIO_OUTPUT, u4High); + + return ret; +} diff --git a/drivers/misc/mediatek/multibridge/mt6797/mt8193/mt8193_iic.c b/drivers/misc/mediatek/multibridge/mt6797/mt8193/mt8193_iic.c new file mode 100644 index 000000000000..09c208200402 --- /dev/null +++ b/drivers/misc/mediatek/multibridge/mt6797/mt8193/mt8193_iic.c @@ -0,0 +1,479 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms 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. + */ + +#define pr_fmt(fmt) "mt8193-iic: " fmt +#define DEBUG 1 + +#include <generated/autoconf.h> +#include <linux/mm.h> +#include <linux/init.h> +#include <linux/fb.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/kthread.h> +#include <linux/vmalloc.h> + +#include <linux/uaccess.h> +#include <linux/atomic.h> +#include <asm/cacheflush.h> +#include <linux/io.h> + +#include <mach/irqs.h> + +#include <linux/miscdevice.h> +#include <linux/platform_device.h> +#include <linux/fs.h> +#include <linux/file.h> +#include <linux/mm.h> +#include <linux/cdev.h> +#include <asm/tlbflush.h> +#include <asm/page.h> +#include <linux/io.h> +#include <linux/uaccess.h> +#include <linux/slab.h> + +#include <generated/autoconf.h> +#include <linux/module.h> +#include <linux/mm.h> +#include <linux/init.h> +#include <linux/fb.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/kthread.h> + +#include <linux/uaccess.h> +#include <linux/atomic.h> +#include <asm/cacheflush.h> +#include <linux/io.h> + +#include <mach/irqs.h> +#include <linux/vmalloc.h> + +#include <linux/uaccess.h> + +#include "mt8193_iic.h" +#include "mt8193.h" +/*#define HDMI_OPEN_PACAKAGE_SUPPORT*/ +#ifdef HDMI_OPEN_PACAKAGE_SUPPORT +#include <linux/of_gpio.h> +#include <linux/gpio.h> +#include <mt-plat/mt_gpio.h> +#include <linux/regulator/consumer.h> +#include <linux/pinctrl/consumer.h> +#endif +/*----------------------------------------------------------------------------*/ +/* mt8193 device information */ +/*----------------------------------------------------------------------------*/ +#define MAX_TRANSACTION_LENGTH 8 +#define MT8193_DEVICE_NAME "mtk-multibridge" +#define MT8193_I2C_SLAVE_ADDR 0x3A +#define MT8193_I2C_DEVICE_ADDR_LEN 2 +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +static int mt8193_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id); +static int mt8193_i2c_remove(struct i2c_client *client); +static struct i2c_client *mt8193_i2c_client; +static const struct i2c_device_id mt8193_i2c_id[] = {{MT8193_DEVICE_NAME, 0}, {} }; +#ifdef HDMI_OPEN_PACAKAGE_SUPPORT +struct regulator *vldo28_pmu; +struct regulator *vrf12_pmu; +struct regulator *vibr_pmu; +struct regulator *vmipi_pmu; +struct device *mt8193_dev_context; +static const struct of_device_id mt8193_i2c_mhl_id[] = { + {.compatible = "mediatek,ext_disp"}, + {}, + }; +char *rst_pin_name[2] = {"rst_default", "rst_high"}; + +struct i2c_driver mt8193_i2c_driver = { + .probe = mt8193_i2c_probe, + .remove = mt8193_i2c_remove, + .driver = { .name = MT8193_DEVICE_NAME, + .of_match_table = mt8193_i2c_mhl_id, + }, + .id_table = mt8193_i2c_id, +}; +#else +static struct i2c_board_info i2c_mt8193 __initdata = {I2C_BOARD_INFO(MT8193_DEVICE_NAME, (MT8193_I2C_SLAVE_ADDR>>1))}; +/*----------------------------------------------------------------------------*/ +struct i2c_driver mt8193_i2c_driver = { + .probe = mt8193_i2c_probe, + .remove = mt8193_i2c_remove, + .driver = { .name = MT8193_DEVICE_NAME, }, + .id_table = mt8193_i2c_id, +}; +#endif + +struct mt8193_i2c_data { + struct i2c_client *client; + uint16_t addr; + int use_reset; /*use RESET flag*/ + int use_irq; /*use EINT flag*/ + int retry; +}; + +static struct mt8193_i2c_data *obj_i2c_data; + +/*----------------------------------------------------------------------------*/ +int mt8193_i2c_read(u16 addr, u32 *data) +{ +#if 0 + u8 rxBuf[8] = {0}; + int ret = 0; + struct i2c_client *client = mt8193_i2c_client; + u8 lens; + + if (((addr >> 8) & 0xFF) >= 0x80) { + /* 8 bit : fast mode */ + rxBuf[0] = (addr >> 8) & 0xFF; + lens = 1; + } else { + /* 16 bit : noraml mode */ + rxBuf[0] = (addr >> 8) & 0xFF; + rxBuf[1] = addr & 0xFF; + lens = 2; + } + + /*client->addr = (client->addr & I2C_MASK_FLAG); + client->ext_flag = I2C_WR_FLAG;*/ + client->addr = client->addr; + + ret = i2c_master_send(client, (const char *)&rxBuf, (4 << 8) | lens); + if (ret < 0) { + pr_err("%s: read error\n", __func__); + return -EFAULT; + } +#else + struct i2c_client *client = mt8193_i2c_client; + struct i2c_msg msg[2]; + u8 rxBuf[8] = {0}; + u8 lens = 0; + + if (((addr >> 8) & 0xFF) >= 0x80) { + /* 8 bit : fast mode */ + rxBuf[0] = (addr >> 8) & 0xFF; + lens = 1; + } else { + /* 16 bit : noraml mode */ + rxBuf[0] = (addr >> 8) & 0xFF; + rxBuf[1] = addr & 0xFF; + lens = 2; + } + + msg[0].flags = 0; + msg[0].addr = client->addr; + msg[0].buf = rxBuf; + msg[0].len = lens; + + msg[1].flags = I2C_M_RD; + msg[1].addr = client->addr; + msg[1].buf = rxBuf; + msg[1].len = 4; + + + i2c_transfer(client->adapter, msg, 2); +#endif + *data = (rxBuf[3] << 24) | (rxBuf[2] << 16) | (rxBuf[1] << 8) | (rxBuf[0]); /*LSB fisrt*/ + return 0; +} +/*----------------------------------------------------------------------------*/ +EXPORT_SYMBOL_GPL(mt8193_i2c_read); +/*----------------------------------------------------------------------------*/ + +int mt8193_i2c_write(u16 addr, u32 data) +{ + struct i2c_client *client = mt8193_i2c_client; + u8 buffer[8]; + int ret = 0; + struct i2c_msg msg = { + /*.addr = client->addr & I2C_MASK_FLAG,*/ + .addr = client->addr, + .flags = 0, + .len = (((addr >> 8) & 0xFF) >= 0x80)?5:6, + .buf = buffer, + }; + + if (((addr >> 8) & 0xFF) >= 0x80) { + /* 8 bit : fast mode */ + buffer[0] = (addr >> 8) & 0xFF; + buffer[1] = (data >> 24) & 0xFF; + buffer[2] = (data >> 16) & 0xFF; + buffer[3] = (data >> 8) & 0xFF; + buffer[4] = data & 0xFF; + } else { + /* 16 bit : noraml mode */ + buffer[0] = (addr >> 8) & 0xFF; + buffer[1] = addr & 0xFF; + buffer[2] = (data >> 24) & 0xFF; + buffer[3] = (data >> 16) & 0xFF; + buffer[4] = (data >> 8) & 0xFF; + buffer[5] = data & 0xFF; + } + + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret < 0) { + pr_err("%s: send command error\n", __func__); + return -EFAULT; + } + return 0; +} +/*----------------------------------------------------------------------------*/ +EXPORT_SYMBOL_GPL(mt8193_i2c_write); + +/*----------------------------------------------------------------------------*/ +/* IIC Probe */ +/*----------------------------------------------------------------------------*/ +static int mt8193_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int ret = -1; + struct mt8193_i2c_data *obj; + + pr_err("%s\n", __func__); + + obj = kzalloc(sizeof(*obj), GFP_KERNEL); + if (obj == NULL) { + ret = -ENOMEM; + pr_err("%s: Allocate ts memory fail\n", __func__); + return ret; + } + obj_i2c_data = obj; + obj->client = client; + mt8193_i2c_client = obj->client; + i2c_set_clientdata(client, obj); + + return 0; +} +/*----------------------------------------------------------------------------*/ + +static int mt8193_i2c_remove(struct i2c_client *client) +{ + pr_err("%s\n", __func__); + mt8193_i2c_client = NULL; + i2c_unregister_device(client); + kfree(i2c_get_clientdata(client)); + return 0; +} +/*----------------------------------------------------------------------------*/ +#ifdef HDMI_OPEN_PACAKAGE_SUPPORT +static int mt8193_power_init(struct platform_device *pdev) +{ + int ret = 0; + struct device_node *kd_node = NULL; + struct pinctrl *rst_pinctrl; + struct pinctrl_state *pin_state; + + mt8193_dev_context = (struct device *)&(pdev->dev); + kd_node = mt8193_dev_context->of_node; + /* get regulator supply node */ + mt8193_dev_context->of_node = of_find_compatible_node(NULL, NULL, "mediatek,mt_pmic_regulator_supply"); + + pr_err("mt8193_power_init get mt_pmic_regulator_supply!\n"); + + if (vmipi_pmu == NULL) + vmipi_pmu = regulator_get(mt8193_dev_context, "vmipi"); + + if (IS_ERR(vmipi_pmu)) { + pr_err("mt8193_power_init vmipi_pmu error %p!!!!!!!!!!!!!!\n", vmipi_pmu); + ret = -1; + goto exit; + } else { + pr_debug("mt8193_power_init vmipi_pmu init done %p\n", vmipi_pmu); + regulator_set_voltage(vmipi_pmu, 1800000, 1800000); + ret = regulator_enable(vmipi_pmu); + if (ret) + pr_err("regulator_enable vmipi failed!\n"); + else + pr_err("regulator_enable vmipi pass!\n"); + } + udelay(4); + + if (vrf12_pmu == NULL) + vrf12_pmu = regulator_get(mt8193_dev_context, "vrf12"); + + if (IS_ERR(vrf12_pmu)) { + pr_err("mt8193_power_init vrf12_pmu error %p!!!!!!!!!!!!!!\n", vrf12_pmu); + ret = -1; + goto vrf12_pmu_exit; + } else { + pr_debug("mt8193_power_init vrf12_pmu init done %p\n", vrf12_pmu); + regulator_set_voltage(vrf12_pmu, 1200000, 1200000); + ret = regulator_enable(vrf12_pmu); + if (ret) + pr_err("regulator_enable vrf12_pmu failed!\n"); + else + pr_err("regulator_enable vrf12_pmu pass!\n"); + } + udelay(8); + + if (vibr_pmu == NULL) + vibr_pmu = regulator_get(mt8193_dev_context, "vibr"); + + if (IS_ERR(vibr_pmu)) { + pr_err("mt8193_power_init vibr_pmu error %p!!!!!!!!!!!!!!\n", vibr_pmu); + ret = -1; + goto vibr_pmu_exit; + } else { + pr_debug("mt8193_power_init vibr_pmu init done %p\n", vibr_pmu); + regulator_set_voltage(vibr_pmu, 3300000, 3300000); + ret = regulator_enable(vibr_pmu); + if (ret) + pr_err("regulator_enable vibr_pmu failed!\n"); + else + pr_err("regulator_enable vibr_pmu pass!\n"); + } + udelay(4); + + if (vldo28_pmu == NULL) + vldo28_pmu = regulator_get(mt8193_dev_context, "vldo28"); + + if (IS_ERR(vldo28_pmu)) { + pr_err("mt8193_power_init vldo28_pmu error %p!!!!!!!!!!!!!!\n", vldo28_pmu); + ret = -1; + goto vldo28_pmu_exit; + } else { + pr_debug("mt8193_power_init vldo28_pmu init done %p\n", vldo28_pmu); + regulator_set_voltage(vldo28_pmu, 2800000, 2800000); + ret = regulator_enable(vldo28_pmu); + if (ret) + pr_err("regulator_enable vldo28_pmu failed!\n"); + else + pr_err("regulator_enable vldo28_pmu pass!\n"); + } + msleep(20); + + mt8193_dev_context->of_node = kd_node; + rst_pinctrl = devm_pinctrl_get(mt8193_dev_context); + if (IS_ERR(rst_pinctrl)) { + ret = PTR_ERR(rst_pinctrl); + pr_err("Cannot find mt8193 rst pinctrl!\n"); + goto rst_exit; + } + pin_state = pinctrl_lookup_state(rst_pinctrl, rst_pin_name[1]); + if (IS_ERR(pin_state)) { + ret = PTR_ERR(pin_state); + pr_err("Cannot find mt8193 rst pin state!\n"); + goto rst_exit; + } else { + pinctrl_select_state(rst_pinctrl, pin_state); + } +#if 0 + dn = of_find_compatible_node(NULL, NULL, "mediatek,mt8193-hdmi"); + bus_reset_pin = of_get_named_gpio(dn, "hdmi_reset_gpios", 0); + gpio_direction_output(bus_reset_pin, 1); +#endif + return ret; +rst_exit: + regulator_disable(vldo28_pmu); +vldo28_pmu_exit: + regulator_disable(vibr_pmu); +vibr_pmu_exit: + regulator_disable(vrf12_pmu); +vrf12_pmu_exit: + regulator_disable(vmipi_pmu); +exit: + mt8193_dev_context->of_node = kd_node; + return ret; +} +#endif +/*----------------------------------------------------------------------------*/ +/* device driver probe */ +/*----------------------------------------------------------------------------*/ +static int mt8193_probe(struct platform_device *pdev) +{ + pr_err("%s\n", __func__); +#ifdef HDMI_OPEN_PACAKAGE_SUPPORT + mt8193_power_init(pdev); +#else + if (i2c_add_driver(&mt8193_i2c_driver)) { + pr_err("%s: unable to add mt8193 i2c driver\n", __func__); + return -1; + } +#endif + return 0; +} +/*----------------------------------------------------------------------------*/ +static int mt8193_remove(struct platform_device *pdev) +{ + pr_err("%s\n", __func__); + i2c_del_driver(&mt8193_i2c_driver); + return 0; +} +/*----------------------------------------------------------------------------*/ +#ifdef CONFIG_OF +static const struct of_device_id multibridge_of_ids[] = { + {.compatible = "mediatek,multibridge",}, + {} +}; +#endif + +static struct platform_driver mt8193_mb_driver = { + .probe = mt8193_probe, + .remove = mt8193_remove, + .driver = { + .name = "multibridge", +#ifdef CONFIG_OF + .of_match_table = multibridge_of_ids, +#endif + } +}; + +/*----------------------------------------------------------------------------*/ +static int __init mt8193_mb_init(void) +{ + int ret = 0; + + pr_err("%s\n", __func__); +#ifdef HDMI_OPEN_PACAKAGE_SUPPORT + if (i2c_add_driver(&mt8193_i2c_driver)) { + pr_err("%s: unable to add mt8193 i2c driver\n", __func__); + return -1; + } +#endif + /*i2c_register_board_info(1, &i2c_mt8193, 1);*/ + ret = platform_driver_register(&mt8193_mb_driver); + if (ret) { + pr_err("failed to register mt8193_mb_driver, ret=%d\n", ret); + return ret; + } + + return 0; +} +/*----------------------------------------------------------------------------*/ +static void __exit mt8193_mb_exit(void) +{ + platform_driver_unregister(&mt8193_mb_driver); +} +/*----------------------------------------------------------------------------*/ +#ifndef HDMI_OPEN_PACAKAGE_SUPPORT +static int __init mt8193_i2c_board_init(void) +{ + int ret = 0; + + pr_err("%s\n", __func__); + ret = i2c_register_board_info(MT8193_I2C_ID, &i2c_mt8193, 1); + if (ret) + pr_err("failed to register mt8193 i2c_board_info, ret=%d\n", ret); + + return ret; +} +/*----------------------------------------------------------------------------*/ +core_initcall(mt8193_i2c_board_init); +#endif +module_init(mt8193_mb_init); +module_exit(mt8193_mb_exit); +MODULE_AUTHOR("SS, Wu <ss.wu@mediatek.com>"); +MODULE_DESCRIPTION("MT8193 Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/multibridge/mt6797/mt8193/mt8193_pinmux.c b/drivers/misc/mediatek/multibridge/mt6797/mt8193/mt8193_pinmux.c new file mode 100644 index 000000000000..2ff2c3781ae4 --- /dev/null +++ b/drivers/misc/mediatek/multibridge/mt6797/mt8193/mt8193_pinmux.c @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms 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. + */ + +#if defined(CONFIG_MTK_MULTIBRIDGE_SUPPORT) + +#define pr_fmt(fmt) "mt8193-pinmux: " fmt + +#include <generated/autoconf.h> +#include <linux/mm.h> +#include <linux/init.h> +#include <linux/fb.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/kthread.h> +#include <linux/vmalloc.h> + +#include <linux/uaccess.h> +#include <linux/atomic.h> +#include <asm/cacheflush.h> +#include <linux/io.h> + +#include <mach/irqs.h> + +#include <linux/miscdevice.h> +#include <linux/platform_device.h> +#include <linux/fs.h> +#include <linux/file.h> +#include <linux/mm.h> +#include <linux/cdev.h> +#include <asm/tlbflush.h> +#include <asm/page.h> +#include <linux/io.h> +#include <linux/uaccess.h> +#include <linux/slab.h> + +#include <generated/autoconf.h> +#include <linux/module.h> +#include <linux/mm.h> +#include <linux/init.h> +#include <linux/fb.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/kthread.h> + +#include <linux/uaccess.h> +#include <linux/atomic.h> +#include <asm/cacheflush.h> +#include <linux/io.h> + +#include <mach/irqs.h> +#include <linux/vmalloc.h> + +#include <linux/uaccess.h> + +#include "mt8193_pinmux.h" +#include "mt8193.h" + + +/* select function according to pinmux table */ +int mt8193_pinset(u32 pin_num, u32 function) +{ + u32 pin_mux_val = 0; + u32 pin_mux_reg = 0; + u32 pin_mux_mask = 0; + u32 pin_mux_shift = 0; + + if (pin_num >= PIN_MAX) { + pr_err("[PINMUX] INVALID PINMUX!! %d\n", pin_num); + return -1; + } + if (function >= PINMUX_FUNCTION_MAX) { + pr_err("[PINMUX] INVALID FUNCTION NUM!! %d\n", function); + return -1; + } + + pr_debug("[PINMUX] mt8193_pinset() %d, %d\n", pin_num, function); + + pin_mux_reg = _au4PinmuxFuncTbl[pin_num][0]; /* pinmux register */ + pin_mux_shift = _au4PinmuxFuncTbl[pin_num][1]; /*pinmux left shift */ + pin_mux_mask = _au4PinmuxFuncTbl[pin_num][2]; /* pinmux mask */ + + pin_mux_val = CKGEN_READ32(pin_mux_reg); + + /* clear function first*/ + pin_mux_val &= (~pin_mux_mask); + /* set function */ + pin_mux_val |= ((function << pin_mux_shift) & pin_mux_mask); + CKGEN_WRITE32(pin_mux_reg, pin_mux_val); + + return PINMUX_RET_OK; +} + +#endif + + + + + diff --git a/drivers/misc/mediatek/video/mt6797/dispsys/ddp_dpi.c b/drivers/misc/mediatek/video/mt6797/dispsys/ddp_dpi.c index 9b3cfead222f..4a7d8aa8252d 100644 --- a/drivers/misc/mediatek/video/mt6797/dispsys/ddp_dpi.c +++ b/drivers/misc/mediatek/video/mt6797/dispsys/ddp_dpi.c @@ -445,6 +445,70 @@ enum DPI_STATUS ddp_dpi_ConfigSize(cmdqRecHandle cmdq, unsigned width, unsigned return DPI_STATUS_OK; } +#ifdef HDMI_MT8193_SUPPORT +enum DPI_STATUS ddp_dpi_ConfigCCIR656(cmdqRecHandle cmdq, bool enable) +{ + struct DPI_REG_CNTL csc = DPI_REG->CNTL; + struct DPI_REG_OUTPUT_SETTING outputsetting = DPI_REG->OUTPUT_SETTING; + struct DPI_REG_Y_LIMIT ylimit = DPI_REG->Y_LIMIT; + struct DPI_REG_C_LIMIT climit = DPI_REG->C_LIMIT; + struct DPI_REG_YUV422_SETTING yuv422setting = DPI_REG->YUV422_SETTING; + struct DPI_REG_EMBSYNC_SETTING embsync = DPI_REG->EMBSYNC_SETTING; + struct DPI_REG_ESAV_VTIM_LOAD esavtimload = DPI_REG->ESAV_VTIM_LOAD; + + + if (enable == FALSE) + return DPI_STATUS_OK; + + csc.YUV422_EN = 1; + csc.RGB2YUV_EN = 1; + csc.EMBSYNC_EN = 1; + + DPI_OUTREGBIT(cmdq, struct DPI_REG_CNTL, DPI_REG->CNTL, YUV422_EN, csc.YUV422_EN); + DPI_OUTREGBIT(cmdq, struct DPI_REG_CNTL, DPI_REG->CNTL, RGB2YUV_EN, csc.RGB2YUV_EN); + DPI_OUTREGBIT(cmdq, struct DPI_REG_CNTL, DPI_REG->CNTL, EMBSYNC_EN, csc.EMBSYNC_EN); + + outputsetting.YC_MAP = 7; + outputsetting.CLK_POL = 1; + + DPI_OUTREGBIT(cmdq, struct DPI_REG_OUTPUT_SETTING, DPI_REG->OUTPUT_SETTING, YC_MAP, outputsetting.YC_MAP); + DPI_OUTREGBIT(cmdq, struct DPI_REG_OUTPUT_SETTING, DPI_REG->OUTPUT_SETTING, CLK_POL, outputsetting.CLK_POL); + + ylimit.Y_LIMIT_BOT = 0x100; + ylimit.Y_LIMIT_TOP = 0xF00; + climit.C_LIMIT_BOT = 0x100; + climit.C_LIMIT_TOP = 0xF00; + + DPI_OUTREGBIT(cmdq, struct DPI_REG_Y_LIMIT, DPI_REG->Y_LIMIT, Y_LIMIT_BOT, ylimit.Y_LIMIT_BOT); + DPI_OUTREGBIT(cmdq, struct DPI_REG_Y_LIMIT, DPI_REG->Y_LIMIT, Y_LIMIT_TOP, ylimit.Y_LIMIT_TOP); + DPI_OUTREGBIT(cmdq, struct DPI_REG_C_LIMIT, DPI_REG->C_LIMIT, C_LIMIT_BOT, climit.C_LIMIT_BOT); + DPI_OUTREGBIT(cmdq, struct DPI_REG_C_LIMIT, DPI_REG->C_LIMIT, C_LIMIT_TOP, climit.C_LIMIT_TOP); + + yuv422setting.UV_SWAP = 1; + + DPI_OUTREGBIT(cmdq, struct DPI_REG_YUV422_SETTING, DPI_REG->YUV422_SETTING, UV_SWAP, yuv422setting.UV_SWAP); + + embsync.EMBVSYNC_R_CR = 1; + embsync.EMBVSYNC_G_Y = 1; + embsync.EMBVSYNC_B_CB = 1; + + DPI_OUTREGBIT(cmdq, struct DPI_REG_EMBSYNC_SETTING, DPI_REG->EMBSYNC_SETTING, + EMBVSYNC_R_CR, embsync.EMBVSYNC_R_CR); + DPI_OUTREGBIT(cmdq, struct DPI_REG_EMBSYNC_SETTING, DPI_REG->EMBSYNC_SETTING, + EMBVSYNC_G_Y, embsync.EMBVSYNC_G_Y); + DPI_OUTREGBIT(cmdq, struct DPI_REG_EMBSYNC_SETTING, DPI_REG->EMBSYNC_SETTING, + EMBVSYNC_B_CB, embsync.EMBVSYNC_B_CB); + + esavtimload.ESAV_VWID_LODD = 0x1E; + + DPI_OUTREGBIT(cmdq, struct DPI_REG_ESAV_VTIM_LOAD, DPI_REG->ESAV_VTIM_LOAD, + ESAV_VWID_LODD, esavtimload.ESAV_VWID_LODD); + + + return DPI_STATUS_OK; +} +#endif + enum DPI_STATUS ddp_dpi_EnableColorBar(void) { /*enable internal pattern - color bar */ @@ -546,6 +610,9 @@ int ddp_dpi_config(DISP_MODULE_ENUM module, disp_ddp_path_config *config, void * ddp_dpi_ConfigDualEdge(cmdq_handle, dpi_config->i2x_en, dpi_config->i2x_edge); +#ifdef HDMI_MT8193_SUPPORT + ddp_dpi_ConfigCCIR656(cmdq_handle, TRUE); +#endif s_isDpiConfig = TRUE; pr_warn("DISP/DPI,ddp_dpi_config done\n"); } |