drm/vc4: add extcon hdmi connection uevent
[platform/kernel/linux-rpi.git] / drivers / gpu / drm / vc4 / vc4_hdmi.h
index 33e9f66..2c599db 100644 (file)
@@ -8,23 +8,14 @@
 
 #include "vc4_drv.h"
 
-/* VC4 HDMI encoder KMS struct */
-struct vc4_hdmi_encoder {
-       struct vc4_encoder base;
-       bool hdmi_monitor;
-       bool limited_rgb_range;
-};
-
-static inline struct vc4_hdmi_encoder *
-to_vc4_hdmi_encoder(struct drm_encoder *encoder)
-{
-       return container_of(encoder, struct vc4_hdmi_encoder, base.base);
-}
-
 struct vc4_hdmi;
 struct vc4_hdmi_register;
 struct vc4_hdmi_connector_state;
 
+#ifdef CONFIG_EXTCON
+struct extcon_dev;
+#endif
+
 enum vc4_hdmi_phy_channel {
        PHY_LANE_0 = 0,
        PHY_LANE_1,
@@ -71,18 +62,21 @@ struct vc4_hdmi_variant {
        /* Callback to get the resources (memory region, interrupts,
         * clocks, etc) for that variant.
         */
-       int (*init_resources)(struct vc4_hdmi *vc4_hdmi);
+       int (*init_resources)(struct drm_device *drm,
+                             struct vc4_hdmi *vc4_hdmi);
 
        /* Callback to reset the HDMI block */
        void (*reset)(struct vc4_hdmi *vc4_hdmi);
 
        /* Callback to enable / disable the CSC */
-       void (*csc_setup)(struct vc4_hdmi *vc4_hdmi, bool enable);
+       void (*csc_setup)(struct vc4_hdmi *vc4_hdmi,
+                         struct drm_connector_state *state,
+                         const struct drm_display_mode *mode);
 
        /* Callback to configure the video timings in the HDMI block */
        void (*set_timings)(struct vc4_hdmi *vc4_hdmi,
                            struct drm_connector_state *state,
-                           struct drm_display_mode *mode);
+                           const struct drm_display_mode *mode);
 
        /* Callback to initialize the PHY according to the connector state */
        void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
@@ -102,6 +96,9 @@ struct vc4_hdmi_variant {
 
        /* Enables HDR metadata */
        bool supports_hdr;
+
+       /* Callback for hardware specific hotplug detect */
+       bool (*hp_detect)(struct vc4_hdmi *vc4_hdmi);
 };
 
 /* HDMI audio information */
@@ -113,9 +110,18 @@ struct vc4_hdmi_audio {
        struct snd_soc_dai_link_component platform;
        struct snd_dmaengine_dai_dma_data dma_data;
        struct hdmi_audio_infoframe infoframe;
+       struct platform_device *codec_pdev;
        bool streaming;
 };
 
+enum vc4_hdmi_output_format {
+       VC4_HDMI_OUTPUT_AUTO,
+       VC4_HDMI_OUTPUT_RGB,
+       VC4_HDMI_OUTPUT_YUV422,
+       VC4_HDMI_OUTPUT_YUV444,
+       VC4_HDMI_OUTPUT_YUV420,
+};
+
 /* General HDMI hardware state. */
 struct vc4_hdmi {
        struct vc4_hdmi_audio audio;
@@ -123,11 +129,14 @@ struct vc4_hdmi {
        struct platform_device *pdev;
        const struct vc4_hdmi_variant *variant;
 
-       struct vc4_hdmi_encoder encoder;
+       struct vc4_encoder encoder;
        struct drm_connector connector;
 
        struct delayed_work scrambling_work;
 
+       struct drm_property *broadcast_rgb_property;
+       struct drm_property *output_format_property;
+
        struct i2c_adapter *ddc;
        void __iomem *hdmicore_regs;
        void __iomem *hd_regs;
@@ -155,14 +164,6 @@ struct vc4_hdmi {
         */
        bool disable_wifi_frequencies;
 
-       /*
-        * Even if HDMI0 on the RPi4 can output modes requiring a pixel
-        * rate higher than 297MHz, it needs some adjustments in the
-        * config.txt file to be able to do so and thus won't always be
-        * available.
-        */
-       bool disable_4kp60;
-
        struct cec_adapter *cec_adap;
        struct cec_msg cec_rx_msg;
        bool cec_tx_ok;
@@ -178,6 +179,71 @@ struct vc4_hdmi {
 
        struct debugfs_regset32 hdmi_regset;
        struct debugfs_regset32 hd_regset;
+
+       /**
+        * @hw_lock: Spinlock protecting device register access.
+        */
+       spinlock_t hw_lock;
+
+       /**
+        * @mutex: Mutex protecting the driver access across multiple
+        * frameworks (KMS, ALSA, CEC).
+        */
+       struct mutex mutex;
+
+       /**
+        * @saved_adjusted_mode: Copy of @drm_crtc_state.adjusted_mode
+        * for use by ALSA hooks and interrupt handlers. Protected by @mutex.
+        */
+       struct drm_display_mode saved_adjusted_mode;
+
+       /**
+        * @output_enabled: Is the HDMI controller currently active?
+        * Protected by @mutex.
+        */
+       bool output_enabled;
+
+       /**
+        * @scdc_enabled: Is the HDMI controller currently running with
+        * the scrambler on? Protected by @mutex.
+        */
+       bool scdc_enabled;
+
+       /**
+        * @output_bpc: Copy of @vc4_connector_state.output_bpc for use
+        * outside of KMS hooks. Protected by @mutex.
+        */
+       unsigned int output_bpc;
+
+       /**
+        * @output_format: Copy of @vc4_connector_state.output_format
+        * for use outside of KMS hooks. Protected by @mutex.
+        */
+       enum vc4_hdmi_output_format output_format;
+       /**
+        * @requested_output_format: Copy of @vc4_connector_state.requested_output_format
+        * for use outside of KMS hooks. Protected by @mutex.
+        */
+       enum vc4_hdmi_output_format requested_output_format;
+
+       /**
+        * @broadcast_rgb: Copy of @vc4_connector_state.broadcast_rgb
+        * for use outside of KMS hooks. Protected by @mutex.
+        */
+       int broadcast_rgb;
+
+       /* VC5 debugfs regset */
+       struct debugfs_regset32 cec_regset;
+       struct debugfs_regset32 csc_regset;
+       struct debugfs_regset32 dvp_regset;
+       struct debugfs_regset32 phy_regset;
+       struct debugfs_regset32 ram_regset;
+       struct debugfs_regset32 rm_regset;
+
+#ifdef CONFIG_EXTCON
+       enum drm_connector_status status;
+       struct extcon_dev *edev;
+#endif
 };
 
 static inline struct vc4_hdmi *
@@ -189,14 +255,17 @@ connector_to_vc4_hdmi(struct drm_connector *connector)
 static inline struct vc4_hdmi *
 encoder_to_vc4_hdmi(struct drm_encoder *encoder)
 {
-       struct vc4_hdmi_encoder *_encoder = to_vc4_hdmi_encoder(encoder);
-
+       struct vc4_encoder *_encoder = to_vc4_encoder(encoder);
        return container_of(_encoder, struct vc4_hdmi, encoder);
 }
 
 struct vc4_hdmi_connector_state {
        struct drm_connector_state      base;
        unsigned long long              pixel_rate;
+       unsigned int                    output_bpc;
+       enum vc4_hdmi_output_format     output_format;
+       enum vc4_hdmi_output_format     requested_output_format;
+       int                             broadcast_rgb;
 };
 
 static inline struct vc4_hdmi_connector_state *
@@ -205,6 +274,12 @@ conn_state_to_vc4_hdmi_conn_state(struct drm_connector_state *conn_state)
        return container_of(conn_state, struct vc4_hdmi_connector_state, base);
 }
 
+static inline const struct vc4_hdmi_connector_state *
+const_conn_state_to_vc4_hdmi_conn_state(const struct drm_connector_state *conn_state)
+{
+       return container_of(conn_state, struct vc4_hdmi_connector_state, base);
+}
+
 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
                       struct vc4_hdmi_connector_state *vc4_conn_state);
 void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);