#include <linux/irq.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/hdmi.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_of.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
#include <drm/display/drm_hdmi_helper.h>
#include <drm/display/drm_hdmi_state_helper.h>
#include "rockchip_drm_drv.h"
#include "inno_hdmi.h"
#define INNO_HDMI_MIN_TMDS_CLOCK …
struct inno_hdmi_phy_config { … };
struct inno_hdmi_variant { … };
struct inno_hdmi_i2c { … };
struct inno_hdmi { … };
struct inno_hdmi_connector_state { … };
static struct inno_hdmi *encoder_to_inno_hdmi(struct drm_encoder *encoder)
{ … }
static struct inno_hdmi *connector_to_inno_hdmi(struct drm_connector *connector)
{ … }
#define to_inno_hdmi_conn_state(conn_state) …
enum { … };
static const char coeff_csc[][24] = …;
static struct inno_hdmi_phy_config rk3036_hdmi_phy_configs[] = …;
static struct inno_hdmi_phy_config rk3128_hdmi_phy_configs[] = …;
static int inno_hdmi_find_phy_config(struct inno_hdmi *hdmi,
unsigned long pixelclk)
{ … }
static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
{ … }
static inline void hdmi_writeb(struct inno_hdmi *hdmi, u16 offset, u32 val)
{ … }
static inline void hdmi_modb(struct inno_hdmi *hdmi, u16 offset,
u32 msk, u32 val)
{ … }
static void inno_hdmi_i2c_init(struct inno_hdmi *hdmi, unsigned long long rate)
{ … }
static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable)
{ … }
static void inno_hdmi_standby(struct inno_hdmi *hdmi)
{
inno_hdmi_sys_power(hdmi, false);
hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0x00);
hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x00);
hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x00);
hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
};
static void inno_hdmi_power_up(struct inno_hdmi *hdmi,
unsigned long mpixelclock)
{
struct inno_hdmi_phy_config *phy_config;
int ret = inno_hdmi_find_phy_config(hdmi, mpixelclock);
if (ret < 0) {
phy_config = hdmi->variant->default_phy_config;
DRM_DEV_ERROR(hdmi->dev,
"Using default phy configuration for TMDS rate %lu",
mpixelclock);
} else {
phy_config = &hdmi->variant->phy_configs[ret];
}
inno_hdmi_sys_power(hdmi, false);
hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, phy_config->pre_emphasis);
hdmi_writeb(hdmi, HDMI_PHY_DRIVER, phy_config->voltage_level_control);
hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x14);
hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x10);
hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x0f);
hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x00);
hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x01);
inno_hdmi_sys_power(hdmi, true);
};
static void inno_hdmi_reset(struct inno_hdmi *hdmi)
{ … }
static int inno_hdmi_disable_frame(struct drm_connector *connector,
enum hdmi_infoframe_type type)
{ … }
static int inno_hdmi_upload_frame(struct drm_connector *connector,
enum hdmi_infoframe_type type,
const u8 *buffer, size_t len)
{ … }
static const struct drm_connector_hdmi_funcs inno_hdmi_hdmi_connector_funcs = …;
static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
{ … }
static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
struct drm_display_mode *mode)
{ … }
static int inno_hdmi_setup(struct inno_hdmi *hdmi,
struct drm_atomic_state *state)
{ … }
static enum drm_mode_status inno_hdmi_display_mode_valid(struct inno_hdmi *hdmi,
struct drm_display_mode *mode)
{ … }
static void inno_hdmi_encoder_enable(struct drm_encoder *encoder,
struct drm_atomic_state *state)
{ … }
static void inno_hdmi_encoder_disable(struct drm_encoder *encoder,
struct drm_atomic_state *state)
{ … }
static int
inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{ … }
static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = …;
static enum drm_connector_status
inno_hdmi_connector_detect(struct drm_connector *connector, bool force)
{ … }
static int inno_hdmi_connector_get_modes(struct drm_connector *connector)
{ … }
static enum drm_mode_status
inno_hdmi_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{ … }
static void
inno_hdmi_connector_destroy_state(struct drm_connector *connector,
struct drm_connector_state *state)
{ … }
static void inno_hdmi_connector_reset(struct drm_connector *connector)
{ … }
static struct drm_connector_state *
inno_hdmi_connector_duplicate_state(struct drm_connector *connector)
{ … }
static const struct drm_connector_funcs inno_hdmi_connector_funcs = …;
static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = …;
static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi)
{ … }
static irqreturn_t inno_hdmi_i2c_irq(struct inno_hdmi *hdmi)
{ … }
static irqreturn_t inno_hdmi_hardirq(int irq, void *dev_id)
{ … }
static irqreturn_t inno_hdmi_irq(int irq, void *dev_id)
{ … }
static int inno_hdmi_i2c_read(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
{ … }
static int inno_hdmi_i2c_write(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
{ … }
static int inno_hdmi_i2c_xfer(struct i2c_adapter *adap,
struct i2c_msg *msgs, int num)
{ … }
static u32 inno_hdmi_i2c_func(struct i2c_adapter *adapter)
{ … }
static const struct i2c_algorithm inno_hdmi_algorithm = …;
static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
{ … }
static int inno_hdmi_bind(struct device *dev, struct device *master,
void *data)
{ … }
static void inno_hdmi_unbind(struct device *dev, struct device *master,
void *data)
{ … }
static const struct component_ops inno_hdmi_ops = …;
static int inno_hdmi_probe(struct platform_device *pdev)
{ … }
static void inno_hdmi_remove(struct platform_device *pdev)
{ … }
static const struct inno_hdmi_variant rk3036_inno_hdmi_variant = …;
static const struct inno_hdmi_variant rk3128_inno_hdmi_variant = …;
static const struct of_device_id inno_hdmi_dt_ids[] = …;
MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
struct platform_driver inno_hdmi_driver = …;