18c2ecf20Sopenharmony_ci#ifndef _VC4_HDMI_H_ 28c2ecf20Sopenharmony_ci#define _VC4_HDMI_H_ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <drm/drm_connector.h> 58c2ecf20Sopenharmony_ci#include <media/cec.h> 68c2ecf20Sopenharmony_ci#include <sound/dmaengine_pcm.h> 78c2ecf20Sopenharmony_ci#include <sound/soc.h> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include "vc4_drv.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci/* VC4 HDMI encoder KMS struct */ 128c2ecf20Sopenharmony_cistruct vc4_hdmi_encoder { 138c2ecf20Sopenharmony_ci struct vc4_encoder base; 148c2ecf20Sopenharmony_ci bool hdmi_monitor; 158c2ecf20Sopenharmony_ci bool limited_rgb_range; 168c2ecf20Sopenharmony_ci}; 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistatic inline struct vc4_hdmi_encoder * 198c2ecf20Sopenharmony_cito_vc4_hdmi_encoder(struct drm_encoder *encoder) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci return container_of(encoder, struct vc4_hdmi_encoder, base.base); 228c2ecf20Sopenharmony_ci} 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistruct drm_display_mode; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistruct vc4_hdmi; 278c2ecf20Sopenharmony_cistruct vc4_hdmi_register; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cienum vc4_hdmi_phy_channel { 308c2ecf20Sopenharmony_ci PHY_LANE_0 = 0, 318c2ecf20Sopenharmony_ci PHY_LANE_1, 328c2ecf20Sopenharmony_ci PHY_LANE_2, 338c2ecf20Sopenharmony_ci PHY_LANE_CK, 348c2ecf20Sopenharmony_ci}; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistruct vc4_hdmi_variant { 378c2ecf20Sopenharmony_ci /* Encoder Type for that controller */ 388c2ecf20Sopenharmony_ci enum vc4_encoder_type encoder_type; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci /* ALSA card name */ 418c2ecf20Sopenharmony_ci const char *card_name; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci /* Filename to expose the registers in debugfs */ 448c2ecf20Sopenharmony_ci const char *debugfs_name; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci /* Set to true when the CEC support is available */ 478c2ecf20Sopenharmony_ci bool cec_available; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci /* Maximum pixel clock supported by the controller (in Hz) */ 508c2ecf20Sopenharmony_ci unsigned long long max_pixel_clock; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci /* List of the registers available on that variant */ 538c2ecf20Sopenharmony_ci const struct vc4_hdmi_register *registers; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci /* Number of registers on that variant */ 568c2ecf20Sopenharmony_ci unsigned int num_registers; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci /* BCM2711 Only. 598c2ecf20Sopenharmony_ci * The variants don't map the lane in the same order in the 608c2ecf20Sopenharmony_ci * PHY, so this is an array mapping the HDMI channel (index) 618c2ecf20Sopenharmony_ci * to the PHY lane (value). 628c2ecf20Sopenharmony_ci */ 638c2ecf20Sopenharmony_ci enum vc4_hdmi_phy_channel phy_lane_mapping[4]; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci /* The BCM2711 cannot deal with odd horizontal pixel timings */ 668c2ecf20Sopenharmony_ci bool unsupported_odd_h_timings; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci /* Callback to get the resources (memory region, interrupts, 698c2ecf20Sopenharmony_ci * clocks, etc) for that variant. 708c2ecf20Sopenharmony_ci */ 718c2ecf20Sopenharmony_ci int (*init_resources)(struct vc4_hdmi *vc4_hdmi); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci /* Callback to reset the HDMI block */ 748c2ecf20Sopenharmony_ci void (*reset)(struct vc4_hdmi *vc4_hdmi); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci /* Callback to enable / disable the CSC */ 778c2ecf20Sopenharmony_ci void (*csc_setup)(struct vc4_hdmi *vc4_hdmi, bool enable); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci /* Callback to configure the video timings in the HDMI block */ 808c2ecf20Sopenharmony_ci void (*set_timings)(struct vc4_hdmi *vc4_hdmi, 818c2ecf20Sopenharmony_ci struct drm_display_mode *mode); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci /* Callback to initialize the PHY according to the mode */ 848c2ecf20Sopenharmony_ci void (*phy_init)(struct vc4_hdmi *vc4_hdmi, 858c2ecf20Sopenharmony_ci struct drm_display_mode *mode); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci /* Callback to disable the PHY */ 888c2ecf20Sopenharmony_ci void (*phy_disable)(struct vc4_hdmi *vc4_hdmi); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci /* Callback to enable the RNG in the PHY */ 918c2ecf20Sopenharmony_ci void (*phy_rng_enable)(struct vc4_hdmi *vc4_hdmi); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* Callback to disable the RNG in the PHY */ 948c2ecf20Sopenharmony_ci void (*phy_rng_disable)(struct vc4_hdmi *vc4_hdmi); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci /* Callback to get channel map */ 978c2ecf20Sopenharmony_ci u32 (*channel_map)(struct vc4_hdmi *vc4_hdmi, u32 channel_mask); 988c2ecf20Sopenharmony_ci}; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci/* HDMI audio information */ 1018c2ecf20Sopenharmony_cistruct vc4_hdmi_audio { 1028c2ecf20Sopenharmony_ci struct snd_soc_card card; 1038c2ecf20Sopenharmony_ci struct snd_soc_dai_link link; 1048c2ecf20Sopenharmony_ci struct snd_soc_dai_link_component cpu; 1058c2ecf20Sopenharmony_ci struct snd_soc_dai_link_component codec; 1068c2ecf20Sopenharmony_ci struct snd_soc_dai_link_component platform; 1078c2ecf20Sopenharmony_ci int samplerate; 1088c2ecf20Sopenharmony_ci int channels; 1098c2ecf20Sopenharmony_ci struct snd_dmaengine_dai_dma_data dma_data; 1108c2ecf20Sopenharmony_ci struct snd_pcm_substream *substream; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci bool streaming; 1138c2ecf20Sopenharmony_ci}; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci/* General HDMI hardware state. */ 1168c2ecf20Sopenharmony_cistruct vc4_hdmi { 1178c2ecf20Sopenharmony_ci struct vc4_hdmi_audio audio; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci struct platform_device *pdev; 1208c2ecf20Sopenharmony_ci const struct vc4_hdmi_variant *variant; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci struct vc4_hdmi_encoder encoder; 1238c2ecf20Sopenharmony_ci struct drm_connector connector; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci struct i2c_adapter *ddc; 1268c2ecf20Sopenharmony_ci void __iomem *hdmicore_regs; 1278c2ecf20Sopenharmony_ci void __iomem *hd_regs; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci /* VC5 Only */ 1308c2ecf20Sopenharmony_ci void __iomem *cec_regs; 1318c2ecf20Sopenharmony_ci /* VC5 Only */ 1328c2ecf20Sopenharmony_ci void __iomem *csc_regs; 1338c2ecf20Sopenharmony_ci /* VC5 Only */ 1348c2ecf20Sopenharmony_ci void __iomem *dvp_regs; 1358c2ecf20Sopenharmony_ci /* VC5 Only */ 1368c2ecf20Sopenharmony_ci void __iomem *phy_regs; 1378c2ecf20Sopenharmony_ci /* VC5 Only */ 1388c2ecf20Sopenharmony_ci void __iomem *ram_regs; 1398c2ecf20Sopenharmony_ci /* VC5 Only */ 1408c2ecf20Sopenharmony_ci void __iomem *rm_regs; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci int hpd_gpio; 1438c2ecf20Sopenharmony_ci bool hpd_active_low; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci /* 1468c2ecf20Sopenharmony_ci * On some systems (like the RPi4), some modes are in the same 1478c2ecf20Sopenharmony_ci * frequency range than the WiFi channels (1440p@60Hz for 1488c2ecf20Sopenharmony_ci * example). Should we take evasive actions because that system 1498c2ecf20Sopenharmony_ci * has a wifi adapter? 1508c2ecf20Sopenharmony_ci */ 1518c2ecf20Sopenharmony_ci bool disable_wifi_frequencies; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci struct cec_adapter *cec_adap; 1548c2ecf20Sopenharmony_ci struct cec_msg cec_rx_msg; 1558c2ecf20Sopenharmony_ci bool cec_tx_ok; 1568c2ecf20Sopenharmony_ci bool cec_irq_was_rx; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci struct clk *pixel_clock; 1598c2ecf20Sopenharmony_ci struct clk *hsm_clock; 1608c2ecf20Sopenharmony_ci struct clk *audio_clock; 1618c2ecf20Sopenharmony_ci struct clk *pixel_bvb_clock; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci struct reset_control *reset; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci struct debugfs_regset32 hdmi_regset; 1668c2ecf20Sopenharmony_ci struct debugfs_regset32 hd_regset; 1678c2ecf20Sopenharmony_ci}; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic inline struct vc4_hdmi * 1708c2ecf20Sopenharmony_ciconnector_to_vc4_hdmi(struct drm_connector *connector) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci return container_of(connector, struct vc4_hdmi, connector); 1738c2ecf20Sopenharmony_ci} 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_cistatic inline struct vc4_hdmi * 1768c2ecf20Sopenharmony_ciencoder_to_vc4_hdmi(struct drm_encoder *encoder) 1778c2ecf20Sopenharmony_ci{ 1788c2ecf20Sopenharmony_ci struct vc4_hdmi_encoder *_encoder = to_vc4_hdmi_encoder(encoder); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci return container_of(_encoder, struct vc4_hdmi, encoder); 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_civoid vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, 1848c2ecf20Sopenharmony_ci struct drm_display_mode *mode); 1858c2ecf20Sopenharmony_civoid vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi); 1868c2ecf20Sopenharmony_civoid vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi); 1878c2ecf20Sopenharmony_civoid vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi); 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_civoid vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, 1908c2ecf20Sopenharmony_ci struct drm_display_mode *mode); 1918c2ecf20Sopenharmony_civoid vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi); 1928c2ecf20Sopenharmony_civoid vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi); 1938c2ecf20Sopenharmony_civoid vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci#endif /* _VC4_HDMI_H_ */ 196