Back to home page

OSCL-LXR

 
 

    


0001 #ifndef _VC4_HDMI_H_
0002 #define _VC4_HDMI_H_
0003 
0004 #include <drm/drm_connector.h>
0005 #include <media/cec.h>
0006 #include <sound/dmaengine_pcm.h>
0007 #include <sound/soc.h>
0008 
0009 #include "vc4_drv.h"
0010 
0011 struct vc4_hdmi;
0012 struct vc4_hdmi_register;
0013 struct vc4_hdmi_connector_state;
0014 
0015 enum vc4_hdmi_phy_channel {
0016     PHY_LANE_0 = 0,
0017     PHY_LANE_1,
0018     PHY_LANE_2,
0019     PHY_LANE_CK,
0020 };
0021 
0022 struct vc4_hdmi_variant {
0023     /* Encoder Type for that controller */
0024     enum vc4_encoder_type encoder_type;
0025 
0026     /* ALSA card name */
0027     const char *card_name;
0028 
0029     /* Filename to expose the registers in debugfs */
0030     const char *debugfs_name;
0031 
0032     /* Maximum pixel clock supported by the controller (in Hz) */
0033     unsigned long long max_pixel_clock;
0034 
0035     /* List of the registers available on that variant */
0036     const struct vc4_hdmi_register *registers;
0037 
0038     /* Number of registers on that variant */
0039     unsigned int num_registers;
0040 
0041     /* BCM2711 Only.
0042      * The variants don't map the lane in the same order in the
0043      * PHY, so this is an array mapping the HDMI channel (index)
0044      * to the PHY lane (value).
0045      */
0046     enum vc4_hdmi_phy_channel phy_lane_mapping[4];
0047 
0048     /* The BCM2711 cannot deal with odd horizontal pixel timings */
0049     bool unsupported_odd_h_timings;
0050 
0051     /*
0052      * The BCM2711 CEC/hotplug IRQ controller is shared between the
0053      * two HDMI controllers, and we have a proper irqchip driver for
0054      * it.
0055      */
0056     bool external_irq_controller;
0057 
0058     /* Callback to get the resources (memory region, interrupts,
0059      * clocks, etc) for that variant.
0060      */
0061     int (*init_resources)(struct vc4_hdmi *vc4_hdmi);
0062 
0063     /* Callback to reset the HDMI block */
0064     void (*reset)(struct vc4_hdmi *vc4_hdmi);
0065 
0066     /* Callback to enable / disable the CSC */
0067     void (*csc_setup)(struct vc4_hdmi *vc4_hdmi,
0068               struct drm_connector_state *state,
0069               const struct drm_display_mode *mode);
0070 
0071     /* Callback to configure the video timings in the HDMI block */
0072     void (*set_timings)(struct vc4_hdmi *vc4_hdmi,
0073                 struct drm_connector_state *state,
0074                 struct drm_display_mode *mode);
0075 
0076     /* Callback to initialize the PHY according to the connector state */
0077     void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
0078              struct vc4_hdmi_connector_state *vc4_conn_state);
0079 
0080     /* Callback to disable the PHY */
0081     void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
0082 
0083     /* Callback to enable the RNG in the PHY */
0084     void (*phy_rng_enable)(struct vc4_hdmi *vc4_hdmi);
0085 
0086     /* Callback to disable the RNG in the PHY */
0087     void (*phy_rng_disable)(struct vc4_hdmi *vc4_hdmi);
0088 
0089     /* Callback to get channel map */
0090     u32 (*channel_map)(struct vc4_hdmi *vc4_hdmi, u32 channel_mask);
0091 
0092     /* Enables HDR metadata */
0093     bool supports_hdr;
0094 
0095     /* Callback for hardware specific hotplug detect */
0096     bool (*hp_detect)(struct vc4_hdmi *vc4_hdmi);
0097 };
0098 
0099 /* HDMI audio information */
0100 struct vc4_hdmi_audio {
0101     struct snd_soc_card card;
0102     struct snd_soc_dai_link link;
0103     struct snd_soc_dai_link_component cpu;
0104     struct snd_soc_dai_link_component codec;
0105     struct snd_soc_dai_link_component platform;
0106     struct snd_dmaengine_dai_dma_data dma_data;
0107     struct hdmi_audio_infoframe infoframe;
0108     struct platform_device *codec_pdev;
0109     bool streaming;
0110 };
0111 
0112 enum vc4_hdmi_output_format {
0113     VC4_HDMI_OUTPUT_RGB,
0114     VC4_HDMI_OUTPUT_YUV422,
0115     VC4_HDMI_OUTPUT_YUV444,
0116     VC4_HDMI_OUTPUT_YUV420,
0117 };
0118 
0119 /* General HDMI hardware state. */
0120 struct vc4_hdmi {
0121     struct vc4_hdmi_audio audio;
0122 
0123     struct platform_device *pdev;
0124     const struct vc4_hdmi_variant *variant;
0125 
0126     struct vc4_encoder encoder;
0127     struct drm_connector connector;
0128 
0129     struct delayed_work scrambling_work;
0130 
0131     struct i2c_adapter *ddc;
0132     void __iomem *hdmicore_regs;
0133     void __iomem *hd_regs;
0134 
0135     /* VC5 Only */
0136     void __iomem *cec_regs;
0137     /* VC5 Only */
0138     void __iomem *csc_regs;
0139     /* VC5 Only */
0140     void __iomem *dvp_regs;
0141     /* VC5 Only */
0142     void __iomem *phy_regs;
0143     /* VC5 Only */
0144     void __iomem *ram_regs;
0145     /* VC5 Only */
0146     void __iomem *rm_regs;
0147 
0148     struct gpio_desc *hpd_gpio;
0149 
0150     /*
0151      * On some systems (like the RPi4), some modes are in the same
0152      * frequency range than the WiFi channels (1440p@60Hz for
0153      * example). Should we take evasive actions because that system
0154      * has a wifi adapter?
0155      */
0156     bool disable_wifi_frequencies;
0157 
0158     /*
0159      * Even if HDMI0 on the RPi4 can output modes requiring a pixel
0160      * rate higher than 297MHz, it needs some adjustments in the
0161      * config.txt file to be able to do so and thus won't always be
0162      * available.
0163      */
0164     bool disable_4kp60;
0165 
0166     struct cec_adapter *cec_adap;
0167     struct cec_msg cec_rx_msg;
0168     bool cec_tx_ok;
0169     bool cec_irq_was_rx;
0170 
0171     struct clk *cec_clock;
0172     struct clk *pixel_clock;
0173     struct clk *hsm_clock;
0174     struct clk *audio_clock;
0175     struct clk *pixel_bvb_clock;
0176 
0177     struct reset_control *reset;
0178 
0179     struct debugfs_regset32 hdmi_regset;
0180     struct debugfs_regset32 hd_regset;
0181 
0182     /* VC5 only */
0183     struct debugfs_regset32 cec_regset;
0184     struct debugfs_regset32 csc_regset;
0185     struct debugfs_regset32 dvp_regset;
0186     struct debugfs_regset32 phy_regset;
0187     struct debugfs_regset32 ram_regset;
0188     struct debugfs_regset32 rm_regset;
0189 
0190     /**
0191      * @hw_lock: Spinlock protecting device register access.
0192      */
0193     spinlock_t hw_lock;
0194 
0195     /**
0196      * @mutex: Mutex protecting the driver access across multiple
0197      * frameworks (KMS, ALSA).
0198      *
0199      * NOTE: While supported, CEC has been left out since
0200      * cec_s_phys_addr_from_edid() might call .adap_enable and lead to a
0201      * reentrancy issue between .get_modes (or .detect) and .adap_enable.
0202      * Since we don't share any state between the CEC hooks and KMS', it's
0203      * not a big deal. The only trouble might come from updating the CEC
0204      * clock divider which might be affected by a modeset, but CEC should
0205      * be resilient to that.
0206      */
0207     struct mutex mutex;
0208 
0209     /**
0210      * @saved_adjusted_mode: Copy of @drm_crtc_state.adjusted_mode
0211      * for use by ALSA hooks and interrupt handlers. Protected by @mutex.
0212      */
0213     struct drm_display_mode saved_adjusted_mode;
0214 
0215     /**
0216      * @packet_ram_enabled: Is the HDMI controller packet RAM currently
0217      * on? Protected by @mutex.
0218      */
0219     bool packet_ram_enabled;
0220 
0221     /**
0222      * @scdc_enabled: Is the HDMI controller currently running with
0223      * the scrambler on? Protected by @mutex.
0224      */
0225     bool scdc_enabled;
0226 
0227     /**
0228      * @output_bpc: Copy of @vc4_connector_state.output_bpc for use
0229      * outside of KMS hooks. Protected by @mutex.
0230      */
0231     unsigned int output_bpc;
0232 
0233     /**
0234      * @output_format: Copy of @vc4_connector_state.output_format
0235      * for use outside of KMS hooks. Protected by @mutex.
0236      */
0237     enum vc4_hdmi_output_format output_format;
0238 };
0239 
0240 static inline struct vc4_hdmi *
0241 connector_to_vc4_hdmi(struct drm_connector *connector)
0242 {
0243     return container_of(connector, struct vc4_hdmi, connector);
0244 }
0245 
0246 static inline struct vc4_hdmi *
0247 encoder_to_vc4_hdmi(struct drm_encoder *encoder)
0248 {
0249     struct vc4_encoder *_encoder = to_vc4_encoder(encoder);
0250     return container_of(_encoder, struct vc4_hdmi, encoder);
0251 }
0252 
0253 struct vc4_hdmi_connector_state {
0254     struct drm_connector_state  base;
0255     unsigned long long      tmds_char_rate;
0256     unsigned int            output_bpc;
0257     enum vc4_hdmi_output_format output_format;
0258 };
0259 
0260 static inline struct vc4_hdmi_connector_state *
0261 conn_state_to_vc4_hdmi_conn_state(struct drm_connector_state *conn_state)
0262 {
0263     return container_of(conn_state, struct vc4_hdmi_connector_state, base);
0264 }
0265 
0266 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
0267                struct vc4_hdmi_connector_state *vc4_conn_state);
0268 void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
0269 void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
0270 void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
0271 
0272 void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
0273                struct vc4_hdmi_connector_state *vc4_conn_state);
0274 void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
0275 void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
0276 void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
0277 
0278 #endif /* _VC4_HDMI_H_ */