blob: 472335be22bd7890256f9d1c0ad6cd67b50d4cd5 [file] [log] [blame]
/*
* Copyright 2017-2018 NXP
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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 _IMX_HDP_H_
#define _IMX_HDP_H_
#include <linux/regmap.h>
#include <linux/mutex.h>
#include <drm/drm_of.h>
#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_encoder_slave.h>
#include <drm/drm_atomic.h>
#include <soc/imx8/sc/sci.h>
#include <drm/drm_dp_helper.h>
#include "../../../../mxc/hdp/all.h"
#include "imx-cec.h"
/* For testing hdp firmware define DEBUG_FW_LOAD */
#undef DEBUG_FW_LOAD
#define PLL_1188MHZ (1188000000)
#define PLL_675MHZ (675000000)
#define HDP_TX_SS_LIS_BASE 0x0000
#define HDP_TX_SS_CSR_BASE 0x1000
#define HDP_TX_SS_GPIO_BASE 0x2000
#define HDP_TX_SS_CTRL0_BASE 0x8000
#define CSR_PIXEL_LINK_MUX_CTL 0x00
#define PL_MUX_CTL_VCP_OFFSET 5
#define PL_MUX_CTL_HCP_OFFSET 4
#define PL_MUX_CTL_PL_MUX_OFFSET 2
#define PL_MUX_CTL_PL_SEL_OFFSET 0
#define CSR_PIXEL_LINK_MUX_STATUS 0x04
#define PL_MUX_STATUS_PL1_INT_OFFSET 18
#define PL_MUX_STATUS_PL1_ADD_OFFSET 16
#define PL_MUX_STATUS_PL1_TYP_OFFSET 11
#define PL_MUX_STATUS_PL0_INT_OFFSET 9
#define PL_MUX_STATUS_PL0_ADD_OFFSET 7
#define PL_MUX_STATUS_PL0_TYP_OFFSET 2
#define PL_MUX_STATUS_PL_DLY_OFFSET 0
#define CSR_HDP_TX_CTRL_CTRL0 0x08
#define CSR_HDP_TX_CTRL_CTRL1 0x0c
#define HOTPLUG_DEBOUNCE_MS 200
#define VIC_MODE_97_60Hz 97
/**
* imx_hdp_call - Calls a struct imx hdp_operations operation on
* an entity
*
* @entity: entity where the @operation will be called
* @operation: type of the operation. Should be the name of a member of
* struct &media_entity_operations.
*
* This helper function will check if @operation is not %NULL. On such case,
* it will issue a call to @operation\(@args\).
*/
#define imx_hdp_call(hdp, operation, args...) \
(!(hdp) ? -ENODEV : (((hdp)->ops && (hdp)->ops->operation) ? \
(hdp)->ops->operation(args) : ENOIOCTLCMD))
#define clks_to_imx_hdp(env) \
container_of(env, struct imx_hdp, clks)
#define state_to_imx_hdp(env) \
container_of(env, struct imx_hdp, state)
struct hdp_clks;
struct hdp_ops {
void (*fw_load)(state_struct *state);
int (*fw_init)(state_struct *state);
int (*phy_init)(state_struct *state, struct drm_display_mode *mode, int format, int color_depth);
void (*mode_set)(state_struct *state, struct drm_display_mode *mode, int format, int color_depth, int max_link);
int (*get_edid_block)(void *data, u8 *buf, u32 block, size_t len);
int (*get_hpd_state)(state_struct *state, u8 *hpd);
int (*write_hdr_metadata)(state_struct *state,
union hdmi_infoframe *hdr_infoframe);
void (*phy_reset)(sc_ipc_t ipcHndl, u8 reset);
int (*pixel_link_init)(state_struct *state);
void (*pixel_link_deinit)(state_struct *state);
void (*pixel_link_mux)(state_struct *state, struct drm_display_mode *mode);
int (*clock_init)(struct hdp_clks *clks);
int (*ipg_clock_enable)(struct hdp_clks *clks);
void (*ipg_clock_disable)(struct hdp_clks *clks);
void (*ipg_clock_set_rate)(struct hdp_clks *clks);
int (*pixel_clock_enable)(struct hdp_clks *clks);
void (*pixel_clock_disable)(struct hdp_clks *clks);
void (*pixel_clock_set_rate)(struct hdp_clks *clks);
};
struct hdp_devtype {
u8 is_edid;
u8 is_4kp60;
u8 audio_type;
struct hdp_ops *ops;
struct hdp_rw_func *rw;
};
struct hdp_video {
u32 bpp;
u32 format;
u32 lanes;
u32 color_type; /* bt */
u32 color_depth; /* bpc */
struct drm_display_mode cur_mode;
struct drm_display_mode pre_mode;
void __iomem *regs_base;
};
struct hdp_audio {
u32 interface; /* I2S SPDIF */
u32 freq;
u32 nlanes;
u32 nChannels;
u32 sample_width;
u32 sample_rate;
u32 audio_cts;
u32 audio_n;
bool audio_enable;
spinlock_t audio_lock;
struct mutex audio_mutex;
void __iomem *regs_base;
};
struct hdp_hdcp {
void __iomem *regs_base;
};
struct hdp_phy {
u32 index;
u32 number;
bool enabled;
struct phy *phy;
void __iomem *regs_base;
};
struct hdp_clks {
struct clk *av_pll;
struct clk *dig_pll;
struct clk *clk_ipg;
struct clk *clk_core;
struct clk *clk_pxl;
struct clk *clk_pxl_mux;
struct clk *clk_pxl_link;
struct clk *clk_hdp;
struct clk *clk_phy;
struct clk *clk_apb;
struct clk *clk_lis;
struct clk *clk_msi;
struct clk *clk_lpcg;
struct clk *clk_even;
struct clk *clk_dbl;
struct clk *clk_vif;
struct clk *clk_apb_csr;
struct clk *clk_apb_ctrl;
struct clk *av_pll_div;
struct clk *dig_pll_div;
struct clk *clk_i2s;
struct clk *clk_i2s_bypass;
};
enum hdp_tx_irq {
HPD_IRQ_IN,
HPD_IRQ_OUT,
HPD_IRQ_NUM,
};
struct imx_hdp {
struct device *dev;
struct drm_connector connector;
struct drm_encoder encoder;
struct drm_bridge bridge;
struct edid *edid;
char cable_state;
struct hdp_mem mem;
u8 is_edid;
u8 is_4kp60;
u8 is_cec;
u8 audio_type;
struct mutex mutex; /* for state below and previous_mode */
enum drm_connector_force force; /* mutex-protected force state */
struct hdp_video video;
struct drm_dp_aux aux;
struct mutex aux_mutex;
struct drm_dp_link dp_link;
S_LINK_STAT lkstat;
ENUM_AFE_LINK_RATE link_rate;
sc_ipc_t ipcHndl;
u32 mu_id;
u32 dual_mode;
struct hdp_ops *ops;
struct hdp_rw_func *rw;
struct hdp_clks clks;
state_struct state;
int vic;
int irq[HPD_IRQ_NUM];
struct delayed_work hotplug_work;
struct imx_cec_dev cec;
int bpc;
VIC_PXL_ENCODING_FORMAT format;
bool hdr_metadata_present;
bool hdr_mode;
};
void imx_hdp_register_audio_driver(struct device *dev);
void imx_arc_power_up(state_struct *state);
void imx_arc_calibrate(state_struct *state);
void imx_arc_config(state_struct *state);
#endif