Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * Copyright (C) 2016 Maxime Ripard
0004  *
0005  * Maxime Ripard <maxime.ripard@free-electrons.com>
0006  */
0007 
0008 #ifndef _SUN4I_HDMI_H_
0009 #define _SUN4I_HDMI_H_
0010 
0011 #include <drm/drm_connector.h>
0012 #include <drm/drm_encoder.h>
0013 #include <linux/regmap.h>
0014 
0015 #include <media/cec-pin.h>
0016 
0017 #define SUN4I_HDMI_CTRL_REG     0x004
0018 #define SUN4I_HDMI_CTRL_ENABLE          BIT(31)
0019 
0020 #define SUN4I_HDMI_IRQ_REG      0x008
0021 #define SUN4I_HDMI_IRQ_STA_MASK         0x73
0022 #define SUN4I_HDMI_IRQ_STA_FIFO_OF      BIT(1)
0023 #define SUN4I_HDMI_IRQ_STA_FIFO_UF      BIT(0)
0024 
0025 #define SUN4I_HDMI_HPD_REG      0x00c
0026 #define SUN4I_HDMI_HPD_HIGH         BIT(0)
0027 
0028 #define SUN4I_HDMI_VID_CTRL_REG     0x010
0029 #define SUN4I_HDMI_VID_CTRL_ENABLE      BIT(31)
0030 #define SUN4I_HDMI_VID_CTRL_HDMI_MODE       BIT(30)
0031 
0032 #define SUN4I_HDMI_VID_TIMING_ACT_REG   0x014
0033 #define SUN4I_HDMI_VID_TIMING_BP_REG    0x018
0034 #define SUN4I_HDMI_VID_TIMING_FP_REG    0x01c
0035 #define SUN4I_HDMI_VID_TIMING_SPW_REG   0x020
0036 
0037 #define SUN4I_HDMI_VID_TIMING_X(x)      ((((x) - 1) & GENMASK(11, 0)))
0038 #define SUN4I_HDMI_VID_TIMING_Y(y)      ((((y) - 1) & GENMASK(11, 0)) << 16)
0039 
0040 #define SUN4I_HDMI_VID_TIMING_POL_REG   0x024
0041 #define SUN4I_HDMI_VID_TIMING_POL_TX_CLK        (0x3e0 << 16)
0042 #define SUN4I_HDMI_VID_TIMING_POL_VSYNC     BIT(1)
0043 #define SUN4I_HDMI_VID_TIMING_POL_HSYNC     BIT(0)
0044 
0045 #define SUN4I_HDMI_AVI_INFOFRAME_REG(n) (0x080 + (n))
0046 
0047 #define SUN4I_HDMI_PAD_CTRL0_REG    0x200
0048 #define SUN4I_HDMI_PAD_CTRL0_BIASEN     BIT(31)
0049 #define SUN4I_HDMI_PAD_CTRL0_LDOCEN     BIT(30)
0050 #define SUN4I_HDMI_PAD_CTRL0_LDODEN     BIT(29)
0051 #define SUN4I_HDMI_PAD_CTRL0_PWENC      BIT(28)
0052 #define SUN4I_HDMI_PAD_CTRL0_PWEND      BIT(27)
0053 #define SUN4I_HDMI_PAD_CTRL0_PWENG      BIT(26)
0054 #define SUN4I_HDMI_PAD_CTRL0_CKEN       BIT(25)
0055 #define SUN4I_HDMI_PAD_CTRL0_TXEN       BIT(23)
0056 
0057 #define SUN4I_HDMI_PAD_CTRL1_REG    0x204
0058 #define SUN4I_HDMI_PAD_CTRL1_UNKNOWN        BIT(24) /* set on A31 */
0059 #define SUN4I_HDMI_PAD_CTRL1_AMP_OPT        BIT(23)
0060 #define SUN4I_HDMI_PAD_CTRL1_AMPCK_OPT      BIT(22)
0061 #define SUN4I_HDMI_PAD_CTRL1_EMP_OPT        BIT(20)
0062 #define SUN4I_HDMI_PAD_CTRL1_EMPCK_OPT      BIT(19)
0063 #define SUN4I_HDMI_PAD_CTRL1_PWSCK      BIT(18)
0064 #define SUN4I_HDMI_PAD_CTRL1_PWSDT      BIT(17)
0065 #define SUN4I_HDMI_PAD_CTRL1_REG_DEN        BIT(15)
0066 #define SUN4I_HDMI_PAD_CTRL1_REG_DENCK      BIT(14)
0067 #define SUN4I_HDMI_PAD_CTRL1_REG_EMP(n)     (((n) & 7) << 10)
0068 #define SUN4I_HDMI_PAD_CTRL1_HALVE_CLK      BIT(6)
0069 #define SUN4I_HDMI_PAD_CTRL1_REG_AMP(n)     (((n) & 7) << 3)
0070 
0071 /* These bits seem to invert the TMDS data channels */
0072 #define SUN4I_HDMI_PAD_CTRL1_INVERT_R       BIT(2)
0073 #define SUN4I_HDMI_PAD_CTRL1_INVERT_G       BIT(1)
0074 #define SUN4I_HDMI_PAD_CTRL1_INVERT_B       BIT(0)
0075 
0076 #define SUN4I_HDMI_PLL_CTRL_REG     0x208
0077 #define SUN4I_HDMI_PLL_CTRL_PLL_EN      BIT(31)
0078 #define SUN4I_HDMI_PLL_CTRL_BWS         BIT(30)
0079 #define SUN4I_HDMI_PLL_CTRL_HV_IS_33        BIT(29)
0080 #define SUN4I_HDMI_PLL_CTRL_LDO1_EN     BIT(28)
0081 #define SUN4I_HDMI_PLL_CTRL_LDO2_EN     BIT(27)
0082 #define SUN4I_HDMI_PLL_CTRL_SDIV2       BIT(25)
0083 #define SUN4I_HDMI_PLL_CTRL_VCO_GAIN(n)     (((n) & 7) << 20)
0084 #define SUN4I_HDMI_PLL_CTRL_S(n)        (((n) & 7) << 17)
0085 #define SUN4I_HDMI_PLL_CTRL_CP_S(n)     (((n) & 0x1f) << 12)
0086 #define SUN4I_HDMI_PLL_CTRL_CS(n)       (((n) & 0xf) << 8)
0087 #define SUN4I_HDMI_PLL_CTRL_DIV(n)      (((n) & 0xf) << 4)
0088 #define SUN4I_HDMI_PLL_CTRL_DIV_MASK        GENMASK(7, 4)
0089 #define SUN4I_HDMI_PLL_CTRL_VCO_S(n)        ((n) & 0xf)
0090 
0091 #define SUN4I_HDMI_PLL_DBG0_REG     0x20c
0092 #define SUN4I_HDMI_PLL_DBG0_TMDS_PARENT(n)  (((n) & 1) << 21)
0093 #define SUN4I_HDMI_PLL_DBG0_TMDS_PARENT_MASK    BIT(21)
0094 #define SUN4I_HDMI_PLL_DBG0_TMDS_PARENT_SHIFT   21
0095 
0096 #define SUN4I_HDMI_CEC          0x214
0097 #define SUN4I_HDMI_CEC_ENABLE           BIT(11)
0098 #define SUN4I_HDMI_CEC_TX           BIT(9)
0099 #define SUN4I_HDMI_CEC_RX           BIT(8)
0100 
0101 #define SUN4I_HDMI_PKT_CTRL_REG(n)  (0x2f0 + (4 * (n)))
0102 #define SUN4I_HDMI_PKT_CTRL_TYPE(n, t)      ((t) << (((n) % 4) * 4))
0103 
0104 #define SUN4I_HDMI_UNKNOWN_REG      0x300
0105 #define SUN4I_HDMI_UNKNOWN_INPUT_SYNC       BIT(27)
0106 
0107 #define SUN4I_HDMI_DDC_CTRL_REG     0x500
0108 #define SUN4I_HDMI_DDC_CTRL_ENABLE      BIT(31)
0109 #define SUN4I_HDMI_DDC_CTRL_START_CMD       BIT(30)
0110 #define SUN4I_HDMI_DDC_CTRL_FIFO_DIR_MASK   BIT(8)
0111 #define SUN4I_HDMI_DDC_CTRL_FIFO_DIR_WRITE  (1 << 8)
0112 #define SUN4I_HDMI_DDC_CTRL_FIFO_DIR_READ   (0 << 8)
0113 #define SUN4I_HDMI_DDC_CTRL_RESET       BIT(0)
0114 
0115 #define SUN4I_HDMI_DDC_ADDR_REG     0x504
0116 #define SUN4I_HDMI_DDC_ADDR_SEGMENT(seg)    (((seg) & 0xff) << 24)
0117 #define SUN4I_HDMI_DDC_ADDR_EDDC(addr)      (((addr) & 0xff) << 16)
0118 #define SUN4I_HDMI_DDC_ADDR_OFFSET(off)     (((off) & 0xff) << 8)
0119 #define SUN4I_HDMI_DDC_ADDR_SLAVE(addr)     ((addr) & 0xff)
0120 
0121 #define SUN4I_HDMI_DDC_INT_STATUS_REG       0x50c
0122 #define SUN4I_HDMI_DDC_INT_STATUS_ILLEGAL_FIFO_OPERATION    BIT(7)
0123 #define SUN4I_HDMI_DDC_INT_STATUS_DDC_RX_FIFO_UNDERFLOW     BIT(6)
0124 #define SUN4I_HDMI_DDC_INT_STATUS_DDC_TX_FIFO_OVERFLOW      BIT(5)
0125 #define SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST          BIT(4)
0126 #define SUN4I_HDMI_DDC_INT_STATUS_ARBITRATION_ERROR     BIT(3)
0127 #define SUN4I_HDMI_DDC_INT_STATUS_ACK_ERROR         BIT(2)
0128 #define SUN4I_HDMI_DDC_INT_STATUS_BUS_ERROR         BIT(1)
0129 #define SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE     BIT(0)
0130 
0131 #define SUN4I_HDMI_DDC_FIFO_CTRL_REG    0x510
0132 #define SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR      BIT(31)
0133 #define SUN4I_HDMI_DDC_FIFO_CTRL_RX_THRES(n)    (((n) & 0xf) << 4)
0134 #define SUN4I_HDMI_DDC_FIFO_CTRL_RX_THRES_MASK  GENMASK(7, 4)
0135 #define SUN4I_HDMI_DDC_FIFO_CTRL_RX_THRES_MAX   (BIT(4) - 1)
0136 #define SUN4I_HDMI_DDC_FIFO_CTRL_TX_THRES(n)    ((n) & 0xf)
0137 #define SUN4I_HDMI_DDC_FIFO_CTRL_TX_THRES_MASK  GENMASK(3, 0)
0138 #define SUN4I_HDMI_DDC_FIFO_CTRL_TX_THRES_MAX   (BIT(4) - 1)
0139 
0140 #define SUN4I_HDMI_DDC_FIFO_DATA_REG    0x518
0141 
0142 #define SUN4I_HDMI_DDC_BYTE_COUNT_REG   0x51c
0143 #define SUN4I_HDMI_DDC_BYTE_COUNT_MAX       (BIT(10) - 1)
0144 
0145 #define SUN4I_HDMI_DDC_CMD_REG      0x520
0146 #define SUN4I_HDMI_DDC_CMD_EXPLICIT_EDDC_READ   6
0147 #define SUN4I_HDMI_DDC_CMD_IMPLICIT_READ    5
0148 #define SUN4I_HDMI_DDC_CMD_IMPLICIT_WRITE   3
0149 
0150 #define SUN4I_HDMI_DDC_CLK_REG      0x528
0151 #define SUN4I_HDMI_DDC_CLK_M(m)         (((m) & 0xf) << 3)
0152 #define SUN4I_HDMI_DDC_CLK_N(n)         ((n) & 0x7)
0153 
0154 #define SUN4I_HDMI_DDC_LINE_CTRL_REG    0x540
0155 #define SUN4I_HDMI_DDC_LINE_CTRL_SDA_ENABLE BIT(9)
0156 #define SUN4I_HDMI_DDC_LINE_CTRL_SCL_ENABLE BIT(8)
0157 
0158 #define SUN4I_HDMI_DDC_FIFO_SIZE    16
0159 
0160 /* A31 specific */
0161 #define SUN6I_HDMI_DDC_CTRL_REG     0x500
0162 #define SUN6I_HDMI_DDC_CTRL_RESET       BIT(31)
0163 #define SUN6I_HDMI_DDC_CTRL_START_CMD       BIT(27)
0164 #define SUN6I_HDMI_DDC_CTRL_SDA_ENABLE      BIT(6)
0165 #define SUN6I_HDMI_DDC_CTRL_SCL_ENABLE      BIT(4)
0166 #define SUN6I_HDMI_DDC_CTRL_ENABLE      BIT(0)
0167 
0168 #define SUN6I_HDMI_DDC_CMD_REG      0x508
0169 #define SUN6I_HDMI_DDC_CMD_BYTE_COUNT(count)    ((count) << 16)
0170 /* command types in lower 3 bits are the same as sun4i */
0171 
0172 #define SUN6I_HDMI_DDC_ADDR_REG     0x50c
0173 #define SUN6I_HDMI_DDC_ADDR_SEGMENT(seg)    (((seg) & 0xff) << 24)
0174 #define SUN6I_HDMI_DDC_ADDR_EDDC(addr)      (((addr) & 0xff) << 16)
0175 #define SUN6I_HDMI_DDC_ADDR_OFFSET(off)     (((off) & 0xff) << 8)
0176 #define SUN6I_HDMI_DDC_ADDR_SLAVE(addr)     (((addr) & 0xff) << 1)
0177 
0178 #define SUN6I_HDMI_DDC_INT_STATUS_REG   0x514
0179 #define SUN6I_HDMI_DDC_INT_STATUS_TIMEOUT   BIT(8)
0180 /* lower 8 bits are the same as sun4i */
0181 
0182 #define SUN6I_HDMI_DDC_FIFO_CTRL_REG    0x518
0183 #define SUN6I_HDMI_DDC_FIFO_CTRL_CLEAR      BIT(15)
0184 /* lower 9 bits are the same as sun4i */
0185 
0186 #define SUN6I_HDMI_DDC_CLK_REG      0x520
0187 /* DDC CLK bit fields are the same, but the formula is not */
0188 
0189 #define SUN6I_HDMI_DDC_FIFO_DATA_REG    0x580
0190 
0191 enum sun4i_hdmi_pkt_type {
0192     SUN4I_HDMI_PKT_AVI = 2,
0193     SUN4I_HDMI_PKT_END = 15,
0194 };
0195 
0196 struct sun4i_hdmi_variant {
0197     bool has_ddc_parent_clk;
0198     bool has_reset_control;
0199 
0200     u32 pad_ctrl0_init_val;
0201     u32 pad_ctrl1_init_val;
0202     u32 pll_ctrl_init_val;
0203 
0204     struct reg_field ddc_clk_reg;
0205     u8 ddc_clk_pre_divider;
0206     u8 ddc_clk_m_offset;
0207 
0208     u8 tmds_clk_div_offset;
0209 
0210     /* Register fields for I2C adapter */
0211     struct reg_field    field_ddc_en;
0212     struct reg_field    field_ddc_start;
0213     struct reg_field    field_ddc_reset;
0214     struct reg_field    field_ddc_addr_reg;
0215     struct reg_field    field_ddc_slave_addr;
0216     struct reg_field    field_ddc_int_mask;
0217     struct reg_field    field_ddc_int_status;
0218     struct reg_field    field_ddc_fifo_clear;
0219     struct reg_field    field_ddc_fifo_rx_thres;
0220     struct reg_field    field_ddc_fifo_tx_thres;
0221     struct reg_field    field_ddc_byte_count;
0222     struct reg_field    field_ddc_cmd;
0223     struct reg_field    field_ddc_sda_en;
0224     struct reg_field    field_ddc_sck_en;
0225 
0226     /* DDC FIFO register offset */
0227     u32         ddc_fifo_reg;
0228 
0229     /*
0230      * DDC FIFO threshold boundary conditions
0231      *
0232      * This is used to cope with the threshold boundary condition
0233      * being slightly different on sun5i and sun6i.
0234      *
0235      * On sun5i the threshold is exclusive, i.e. does not include,
0236      * the value of the threshold. ( > for RX; < for TX )
0237      * On sun6i the threshold is inclusive, i.e. includes, the
0238      * value of the threshold. ( >= for RX; <= for TX )
0239      */
0240     bool            ddc_fifo_thres_incl;
0241 
0242     bool            ddc_fifo_has_dir;
0243 };
0244 
0245 struct sun4i_hdmi {
0246     struct drm_connector    connector;
0247     struct drm_encoder  encoder;
0248     struct device       *dev;
0249 
0250     void __iomem        *base;
0251     struct regmap       *regmap;
0252 
0253     /* Reset control */
0254     struct reset_control    *reset;
0255 
0256     /* Parent clocks */
0257     struct clk      *bus_clk;
0258     struct clk      *mod_clk;
0259     struct clk      *ddc_parent_clk;
0260     struct clk      *pll0_clk;
0261     struct clk      *pll1_clk;
0262 
0263     /* And the clocks we create */
0264     struct clk      *ddc_clk;
0265     struct clk      *tmds_clk;
0266 
0267     struct i2c_adapter  *i2c;
0268     struct i2c_adapter  *ddc_i2c;
0269 
0270     /* Regmap fields for I2C adapter */
0271     struct regmap_field *field_ddc_en;
0272     struct regmap_field *field_ddc_start;
0273     struct regmap_field *field_ddc_reset;
0274     struct regmap_field *field_ddc_addr_reg;
0275     struct regmap_field *field_ddc_slave_addr;
0276     struct regmap_field *field_ddc_int_mask;
0277     struct regmap_field *field_ddc_int_status;
0278     struct regmap_field *field_ddc_fifo_clear;
0279     struct regmap_field *field_ddc_fifo_rx_thres;
0280     struct regmap_field *field_ddc_fifo_tx_thres;
0281     struct regmap_field *field_ddc_byte_count;
0282     struct regmap_field *field_ddc_cmd;
0283     struct regmap_field *field_ddc_sda_en;
0284     struct regmap_field *field_ddc_sck_en;
0285 
0286     struct sun4i_drv    *drv;
0287 
0288     struct cec_adapter  *cec_adap;
0289 
0290     const struct sun4i_hdmi_variant *variant;
0291 };
0292 
0293 int sun4i_ddc_create(struct sun4i_hdmi *hdmi, struct clk *clk);
0294 int sun4i_tmds_create(struct sun4i_hdmi *hdmi);
0295 int sun4i_hdmi_i2c_create(struct device *dev, struct sun4i_hdmi *hdmi);
0296 
0297 #endif /* _SUN4I_HDMI_H_ */