458 lines
12 KiB
C
458 lines
12 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* core.h -- core define for mfd display arch
|
|
*
|
|
* Copyright (c) 2023-2028 Rockchip Electronics Co., Ltd.
|
|
*
|
|
* Author: luowei <lw@rock-chips.com>
|
|
*
|
|
*/
|
|
|
|
#ifndef __MFD_SERDES_CORE_H__
|
|
#define __MFD_SERDES_CORE_H__
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/export.h>
|
|
#include <linux/init.h>
|
|
#include <linux/i2c.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/mfd/core.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/err.h>
|
|
#include <linux/of_device.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/seq_file.h>
|
|
#include <linux/regulator/consumer.h>
|
|
#include <linux/backlight.h>
|
|
#include <linux/module.h>
|
|
#include <linux/irq.h>
|
|
#include <linux/irqdomain.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/random.h>
|
|
|
|
#include <linux/completion.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/list.h>
|
|
#include <linux/regmap.h>
|
|
#include <linux/of.h>
|
|
#include <linux/gpio/driver.h>
|
|
#include <linux/gpio/consumer.h>
|
|
#include <linux/extcon-provider.h>
|
|
#include <linux/bitfield.h>
|
|
#include <linux/version.h>
|
|
#include <drm/drm_atomic_helper.h>
|
|
#include <drm/drm_bridge.h>
|
|
#include <drm/drm_panel.h>
|
|
#include <drm/drm_print.h>
|
|
#include <drm/drm_of.h>
|
|
#include <drm/drm_connector.h>
|
|
#include <drm/drm_probe_helper.h>
|
|
#if (KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE)
|
|
#include <drm/display/drm_dp_helper.h>
|
|
#else
|
|
#include <drm/drm_dp_helper.h>
|
|
#endif
|
|
#include <drm/drm_device.h>
|
|
#include <drm/drm_modes.h>
|
|
#include <drm/drm_atomic_state_helper.h>
|
|
#include <drm/drm_mipi_dsi.h>
|
|
#include <drm/drm_modeset_helper_vtables.h>
|
|
|
|
#include <video/videomode.h>
|
|
#include <video/of_display_timing.h>
|
|
#include <video/display_timing.h>
|
|
#include <uapi/linux/media-bus-format.h>
|
|
|
|
#include <linux/pinctrl/pinctrl.h>
|
|
#include <linux/pinctrl/pinconf-generic.h>
|
|
#include <linux/pinctrl/pinconf.h>
|
|
#include <linux/pinctrl/pinmux.h>
|
|
|
|
#include <asm/unaligned.h>
|
|
#include "gpio.h"
|
|
|
|
#include "../../../../drivers/pinctrl/core.h"
|
|
#include "../../../../drivers/pinctrl/pinconf.h"
|
|
#include "../../../../drivers/pinctrl/pinmux.h"
|
|
#include "../../../../drivers/gpio/gpiolib.h"
|
|
#include "../../../../drivers/extcon/extcon.h"
|
|
#include "../../../../drivers/base/regmap/internal.h"
|
|
|
|
/*
|
|
* if enable all the debug information,
|
|
* there will be much log.
|
|
*
|
|
* so suggest set CONFIG_LOG_BUF_SHIFT to 18
|
|
*/
|
|
//#define SERDES_DEBUG_MFD
|
|
//#define SERDES_DEBUG_I2C
|
|
//#define SERDES_DEBUG_CHIP
|
|
|
|
#ifdef SERDES_DEBUG_MFD
|
|
#define SERDES_DBG_MFD(x...) pr_info(x)
|
|
#else
|
|
#define SERDES_DBG_MFD(x...) no_printk(x)
|
|
#endif
|
|
|
|
#ifdef SERDES_DEBUG_I2C
|
|
#define SERDES_DBG_I2C(x...) pr_info(x)
|
|
#else
|
|
#define SERDES_DBG_I2C(x...) no_printk(x)
|
|
#endif
|
|
|
|
#ifdef SERDES_DEBUG_CHIP
|
|
#define SERDES_DBG_CHIP(x...) pr_info(x)
|
|
#else
|
|
#define SERDES_DBG_CHIP(x...) no_printk(x)
|
|
#endif
|
|
|
|
#define MFD_SERDES_DISPLAY_VERSION "serdes-mfd-displaly-v11-241025"
|
|
#define MAX_NUM_SERDES_SPLIT 8
|
|
struct serdes;
|
|
enum ser_link_mode {
|
|
SER_DUAL_LINK,
|
|
SER_LINKA,
|
|
SER_LINKB,
|
|
SER_SPLITTER_MODE,
|
|
};
|
|
|
|
struct check_reg_data {
|
|
char name[30];
|
|
struct reg_sequence seq;
|
|
};
|
|
|
|
struct serdes_chip_pinctrl_info {
|
|
struct pinctrl_pin_desc *pins;
|
|
unsigned int num_pins;
|
|
struct group_desc *groups;
|
|
unsigned int num_groups;
|
|
struct function_desc *functions;
|
|
unsigned int num_functions;
|
|
};
|
|
|
|
struct serdes_chip_bridge_ops {
|
|
/* serdes chip function for bridge */
|
|
int (*power_on)(struct serdes *serdes);
|
|
int (*init)(struct serdes *serdes);
|
|
int (*attach)(struct serdes *serdes);
|
|
enum drm_connector_status (*detect)(struct serdes *serdes);
|
|
int (*get_modes)(struct serdes *serdes);
|
|
int (*pre_enable)(struct serdes *serdes);
|
|
int (*enable)(struct serdes *serdes);
|
|
int (*disable)(struct serdes *serdes);
|
|
int (*post_disable)(struct serdes *serdes);
|
|
};
|
|
|
|
struct serdes_chip_panel_ops {
|
|
/*serdes chip function for bridge*/
|
|
int (*power_on)(struct serdes *serdes);
|
|
int (*init)(struct serdes *serdes);
|
|
int (*disable)(struct serdes *serdes);
|
|
int (*unprepare)(struct serdes *serdes);
|
|
int (*prepare)(struct serdes *serdes);
|
|
int (*enable)(struct serdes *serdes);
|
|
int (*get_modes)(struct serdes *serdes);
|
|
int (*backlight_enable)(struct serdes *serdes);
|
|
int (*backlight_disable)(struct serdes *serdes);
|
|
};
|
|
|
|
struct serdes_chip_pinctrl_ops {
|
|
/* serdes chip pinctrl function */
|
|
int (*pin_config_get)(struct serdes *serdes,
|
|
unsigned int pin,
|
|
unsigned long *config);
|
|
int (*pin_config_set)(struct serdes *serdes,
|
|
unsigned int pin,
|
|
unsigned long *configs,
|
|
unsigned int num_configs);
|
|
|
|
int (*set_mux)(struct serdes *serdes, unsigned int func_selector,
|
|
unsigned int group_selector);
|
|
};
|
|
|
|
struct serdes_chip_gpio_ops {
|
|
/* serdes chip gpio function */
|
|
int (*direction_input)(struct serdes *serdes, int gpio);
|
|
int (*direction_output)(struct serdes *serdes, int gpio, int value);
|
|
int (*get_level)(struct serdes *serdes, int gpio);
|
|
int (*set_level)(struct serdes *serdes, int gpio, int value);
|
|
int (*set_config)(struct serdes *serdes, int gpio, unsigned long config);
|
|
int (*to_irq)(struct serdes *serdes, int gpio);
|
|
};
|
|
|
|
struct serdes_chip_split_ops {
|
|
int (*select)(struct serdes *serdes, int chan);
|
|
int (*deselect)(struct serdes *serdes, int chan);
|
|
int (*set_i2c_addr)(struct serdes *serdes, int address, int link);
|
|
};
|
|
|
|
struct serdes_check_reg_ops {
|
|
int (*check_reg)(struct serdes *serdes);
|
|
};
|
|
|
|
struct serdes_chip_pm_ops {
|
|
/* serdes chip function for suspend and resume */
|
|
int (*suspend)(struct serdes *serdes);
|
|
int (*resume)(struct serdes *serdes);
|
|
};
|
|
|
|
struct serdes_chip_irq_ops {
|
|
/* serdes chip function for lock and err irq */
|
|
int (*lock_handle)(struct serdes *serdes);
|
|
int (*err_handle)(struct serdes *serdes);
|
|
};
|
|
|
|
struct serdes_chip_data {
|
|
const char *name;
|
|
enum serdes_type serdes_type;
|
|
enum serdes_id serdes_id;
|
|
enum serdes_bridge_type bridge_type;
|
|
int sequence_init;
|
|
int connector_type;
|
|
int reg_id;
|
|
int id_data;
|
|
int int_status_reg;
|
|
int int_trig;
|
|
int num_gpio;
|
|
int gpio_base;
|
|
int same_chip_count;
|
|
u8 bank_num;
|
|
|
|
int (*chip_init)(struct serdes *serdes);
|
|
struct regmap_config *regmap_config;
|
|
struct serdes_chip_pinctrl_info *pinctrl_info;
|
|
struct serdes_chip_bridge_ops *bridge_ops;
|
|
struct serdes_chip_panel_ops *panel_ops;
|
|
struct serdes_chip_pinctrl_ops *pinctrl_ops;
|
|
struct serdes_chip_gpio_ops *gpio_ops;
|
|
struct serdes_chip_split_ops *split_ops;
|
|
struct serdes_check_reg_ops *check_ops;
|
|
struct serdes_chip_pm_ops *pm_ops;
|
|
struct serdes_chip_irq_ops *irq_ops;
|
|
};
|
|
|
|
struct serdes_init_seq {
|
|
struct reg_sequence *reg_sequence;
|
|
unsigned int reg_seq_cnt;
|
|
};
|
|
|
|
struct serdes_gpio {
|
|
struct device *dev;
|
|
struct serdes_pinctrl *parent;
|
|
struct regmap *regmap;
|
|
struct gpio_chip gpio_chip;
|
|
};
|
|
|
|
struct serdes_pinctrl {
|
|
struct device *dev;
|
|
struct serdes *parent;
|
|
struct pinctrl_dev *pctl;
|
|
struct pinctrl_pin_desc *pdesc;
|
|
struct regmap *regmap;
|
|
struct pinctrl_desc *pinctrl_desc;
|
|
struct serdes_gpio *gpio;
|
|
int pin_base;
|
|
};
|
|
|
|
struct serdes_panel {
|
|
struct drm_panel panel;
|
|
enum drm_connector_status status;
|
|
struct drm_connector connector;
|
|
|
|
const char *name;
|
|
u32 width_mm;
|
|
u32 height_mm;
|
|
u32 link_rate;
|
|
u32 lane_count;
|
|
bool ssc;
|
|
|
|
struct device *dev;
|
|
struct serdes *parent;
|
|
struct regmap *regmap;
|
|
struct mipi_dsi_device *dsi;
|
|
struct device_node *remote_node;
|
|
struct drm_display_mode mode;
|
|
struct backlight_device *backlight;
|
|
struct serdes_init_seq *serdes_init_seq;
|
|
bool sel_mipi;
|
|
bool dv_swp_ab;
|
|
bool dpi_deskew_en;
|
|
bool split_mode;
|
|
u32 num_lanes;
|
|
u32 dsi_lane_map[4];
|
|
};
|
|
|
|
struct serdes_panel_split {
|
|
struct drm_panel panel;
|
|
enum drm_connector_status status;
|
|
struct drm_connector connector;
|
|
|
|
const char *name;
|
|
u32 width_mm;
|
|
u32 height_mm;
|
|
u32 link_rate;
|
|
u32 lane_count;
|
|
bool ssc;
|
|
|
|
struct device *dev;
|
|
struct serdes *parent;
|
|
struct regmap *regmap;
|
|
struct mipi_dsi_device *dsi;
|
|
struct device_node *remote_node;
|
|
struct drm_display_mode mode;
|
|
struct backlight_device *backlight;
|
|
struct serdes_init_seq *serdes_init_seq;
|
|
bool sel_mipi;
|
|
bool dv_swp_ab;
|
|
bool dpi_deskew_en;
|
|
bool split_mode;
|
|
u32 num_lanes;
|
|
u32 dsi_lane_map[4];
|
|
};
|
|
|
|
struct serdes_bridge {
|
|
struct drm_bridge base_bridge;
|
|
struct drm_bridge *next_bridge;
|
|
enum drm_connector_status status;
|
|
atomic_t triggered;
|
|
struct drm_connector connector;
|
|
struct drm_panel *panel;
|
|
|
|
struct device *dev;
|
|
struct serdes *parent;
|
|
struct regmap *regmap;
|
|
struct mipi_dsi_device *dsi;
|
|
struct device_node *remote_node;
|
|
struct drm_display_mode mode;
|
|
struct backlight_device *backlight;
|
|
|
|
bool sel_mipi;
|
|
bool dv_swp_ab;
|
|
bool dpi_deskew_en;
|
|
bool split_mode;
|
|
u32 num_lanes;
|
|
u32 dsi_lane_map[4];
|
|
};
|
|
|
|
struct serdes_bridge_split {
|
|
struct drm_bridge base_bridge;
|
|
struct drm_bridge *next_bridge;
|
|
enum drm_connector_status status;
|
|
atomic_t triggered;
|
|
struct drm_connector connector;
|
|
struct drm_panel *panel;
|
|
|
|
struct device *dev;
|
|
struct serdes *parent;
|
|
struct regmap *regmap;
|
|
struct mipi_dsi_device *dsi;
|
|
struct device_node *remote_node;
|
|
struct drm_display_mode mode;
|
|
struct backlight_device *backlight;
|
|
|
|
bool sel_mipi;
|
|
bool dv_swp_ab;
|
|
bool dpi_deskew_en;
|
|
u32 num_lanes;
|
|
u32 dsi_lane_map[4];
|
|
};
|
|
|
|
struct serdes {
|
|
int num_gpio;
|
|
struct mutex io_lock;
|
|
struct mutex irq_lock;
|
|
struct mutex wq_lock;
|
|
struct mutex reg_check_lock;
|
|
struct device *dev;
|
|
enum serdes_type type;
|
|
struct regmap *regmap;
|
|
struct regulator *supply;
|
|
struct extcon_dev *extcon;
|
|
atomic_t conn_trigger;
|
|
|
|
/* serdes power and reset pin */
|
|
struct gpio_desc *reset_gpio;
|
|
struct gpio_desc *enable_gpio;
|
|
struct regulator *vpower;
|
|
|
|
/* serdes irq pin */
|
|
struct gpio_desc *lock_gpio;
|
|
struct gpio_desc *err_gpio;
|
|
int lock_irq;
|
|
int err_irq;
|
|
int lock_irq_trig;
|
|
int err_irq_trig;
|
|
atomic_t flag_ser_init;
|
|
atomic_t flag_early_suspend;
|
|
|
|
struct workqueue_struct *mfd_wq;
|
|
struct delayed_work mfd_delay_work;
|
|
bool route_enable;
|
|
bool use_delay_work;
|
|
|
|
struct kthread_worker *kworker;
|
|
struct kthread_delayed_work reg_check_work;
|
|
bool use_reg_check_work;
|
|
|
|
bool split_mode_enable;
|
|
unsigned int reg_hw;
|
|
unsigned int reg_use;
|
|
unsigned int link_use;
|
|
unsigned int id_serdes_bridge_split;
|
|
unsigned int id_serdes_panel_split;
|
|
struct serdes *g_serdes_bridge_split;
|
|
|
|
struct pinctrl *pinctrl_node;
|
|
struct pinctrl_state *pins_default;
|
|
struct pinctrl_state *pins_init;
|
|
struct pinctrl_state *pins_sleep;
|
|
|
|
struct serdes_init_seq *serdes_init_seq;
|
|
struct serdes_init_seq *serdes_backup_seq;
|
|
struct serdes_bridge *serdes_bridge;
|
|
struct serdes_bridge_split *serdes_bridge_split;
|
|
struct serdes_panel *serdes_panel;
|
|
struct serdes_panel_split *serdes_panel_split;
|
|
struct serdes_pinctrl *pinctrl;
|
|
struct serdes_chip_data *chip_data;
|
|
};
|
|
|
|
/* Device I/O API */
|
|
int serdes_reg_read(struct serdes *serdes, unsigned int reg, unsigned int *val);
|
|
int serdes_reg_write(struct serdes *serdes, unsigned int reg, unsigned int val);
|
|
void serdes_reg_lock(struct serdes *serdes);
|
|
int serdes_reg_unlock(struct serdes *serdes);
|
|
int serdes_set_bits(struct serdes *serdes, unsigned int reg,
|
|
unsigned int mask, unsigned int val);
|
|
int serdes_bulk_read(struct serdes *serdes, unsigned int reg,
|
|
int count, u16 *buf);
|
|
int serdes_bulk_write(struct serdes *serdes, unsigned int reg,
|
|
int count, void *src);
|
|
int serdes_multi_reg_write(struct serdes *serdes, const struct reg_sequence *regs,
|
|
int num_regs);
|
|
int serdes_i2c_set_sequence(struct serdes *serdes);
|
|
|
|
int serdes_device_init(struct serdes *serdes);
|
|
int serdes_set_pinctrl_default(struct serdes *serdes);
|
|
int serdes_set_pinctrl_sleep(struct serdes *serdes);
|
|
int serdes_device_suspend(struct serdes *serdes);
|
|
int serdes_device_resume(struct serdes *serdes);
|
|
void serdes_device_poweroff(struct serdes *serdes);
|
|
int serdes_device_shutdown(struct serdes *serdes);
|
|
int serdes_irq_init(struct serdes *serdes);
|
|
void serdes_irq_exit(struct serdes *serdes);
|
|
void serdes_auxadc_init(struct serdes *serdes);
|
|
|
|
extern struct serdes_chip_data serdes_bu18tl82_data;
|
|
extern struct serdes_chip_data serdes_bu18rl82_data;
|
|
extern struct serdes_chip_data serdes_max96745_data;
|
|
extern struct serdes_chip_data serdes_max96752_data;
|
|
extern struct serdes_chip_data serdes_max96755_data;
|
|
extern struct serdes_chip_data serdes_max96772_data;
|
|
extern struct serdes_chip_data serdes_max96789_data;
|
|
extern struct serdes_chip_data serdes_rkx111_data;
|
|
extern struct serdes_chip_data serdes_rkx121_data;
|
|
extern struct serdes_chip_data serdes_nca9539_data;
|
|
|
|
#endif
|