[PATCH 02/14] drm/bridge: dw-hdmi: Add dw-hdmi-common.h header

Cristian Ciocaltea
2024-06-01T14:17:05Z

In preparation to add support for the HDMI 2.1 Quad-Pixel TX Controller
and minimize code duplication as much as possible, export all reusable
functions and provide the related declarations and structs within a new
header file.

For consistency, ensure the newly exported symbols share the 'dw_'
prefix.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi-common.h | 167 ++++++++++++++++++++++
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 170 ++++-------------------
2 files changed, 194 insertions(+), 143 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-common.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-common.h
new file mode 100644
index 000000000000..28e26ac142e6
--- /dev/null
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-common.h
@@ -0,0 +1,167 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef __DW_HDMI_COMMON_H__
+#define __DW_HDMI_COMMON_H__
+
+#include <linux/i2c.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+#include <linux/spinlock_types.h>
+
+#include <drm/bridge/dw_hdmi.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_modes.h>
+
+#include <sound/hdmi-codec.h>
+
+struct cec_notifier;
+struct device;
+struct drm_bridge_state;
+struct drm_crtc_state;
+struct drm_edid;
+struct pinctrl;
+struct pinctrl_state;
+struct platform_device;
+struct regmap;
+
+#define DDC_CI_ADDR 0x37
+#define DDC_SEGMENT_ADDR 0x30
+
+#define HDMI_EDID_LEN 512
+
+/* DW-HDMI Controller >= 0x200a are at least compliant with SCDC version 1 */
+#define SCDC_MIN_SOURCE_VERSION 0x1
+
+#define HDMI14_MAX_TMDSCLK 340000000
+
+struct hdmi_vmode {
+ bool mdataenablepolarity;
+
+ unsigned int mpixelclock;
+ unsigned int mpixelrepetitioninput;
+ unsigned int mpixelrepetitionoutput;
+ unsigned int mtmdsclock;
+};
+
+struct hdmi_data_info {
+ unsigned int enc_in_bus_format;
+ unsigned int enc_out_bus_format;
+ unsigned int enc_in_encoding;
+ unsigned int enc_out_encoding;
+ unsigned int pix_repet_factor;
+ unsigned int hdcp_enable;
+ struct hdmi_vmode video_mode;
+ bool rgb_limited_range;
+};
+
+struct dw_hdmi_i2c {
+ struct i2c_adapter adap;
+
+ struct mutex lock; /* used to serialize data transfers */
+ struct completion cmp;
+ u8 stat;
+
+ u8 slave_reg;
+ bool is_regaddr;
+ bool is_segment;
+};
+
+struct dw_hdmi_phy_data {
+ enum dw_hdmi_phy_type type;
+ const char *name;
+ unsigned int gen;
+ bool has_svsret;
+ int (*configure)(struct dw_hdmi *hdmi,
+ const struct dw_hdmi_plat_data *pdata,
+ unsigned long mpixelclock);
+};
+
+struct dw_hdmi {
+ struct drm_connector connector;
+ struct drm_bridge bridge;
+ struct drm_bridge *next_bridge;
+
+ unsigned int version;
+
+ struct platform_device *audio;
+ struct platform_device *cec;
+ struct device *dev;
+ struct dw_hdmi_i2c *i2c;
+
+ struct hdmi_data_info hdmi_data;
+ const struct dw_hdmi_plat_data *plat_data;
+
+ int vic;
+
+ u8 edid[HDMI_EDID_LEN];
+
+ struct {
+ const struct dw_hdmi_phy_ops *ops;
+ const char *name;
+ void *data;
+ bool enabled;
+ } phy;
+
+ struct drm_display_mode previous_mode;
+
+ struct i2c_adapter *ddc;
+ void __iomem *regs;
+ bool sink_is_hdmi;
+ bool sink_has_audio;
+
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *default_state;
+ struct pinctrl_state *unwedge_state;
+
+ struct mutex mutex; /* for state below and previous_mode */
+ enum drm_connector_force force; /* mutex-protected force state */
+ struct drm_connector *curr_conn;/* current connector (only valid when !disabled) */
+ bool disabled; /* DRM has disabled our bridge */
+ bool bridge_is_on; /* indicates the bridge is on */
+ bool rxsense; /* rxsense state */
+ u8 phy_mask; /* desired phy int mask settings */
+ u8 mc_clkdis; /* clock disable register */
+
+ spinlock_t audio_lock;
+ struct mutex audio_mutex;
+ unsigned int sample_non_pcm;
+ unsigned int sample_width;
+ unsigned int sample_rate;
+ unsigned int channels;
+ unsigned int audio_cts;
+ unsigned int audio_n;
+ bool audio_enable;
+
+ unsigned int reg_shift;
+ struct regmap *regm;
+ void (*enable_audio)(struct dw_hdmi *hdmi);
+ void (*disable_audio)(struct dw_hdmi *hdmi);
+
+ struct mutex cec_notifier_mutex;
+ struct cec_notifier *cec_notifier;
+
+ hdmi_codec_plugged_cb plugged_cb;
+ struct device *codec_dev;
+ enum drm_connector_status last_connector_result;
+};
+
+void dw_handle_plugged_change(struct dw_hdmi *hdmi, bool plugged);
+bool dw_hdmi_support_scdc(struct dw_hdmi *hdmi,
+ const struct drm_display_info *display);
+
+enum drm_connector_status
+dw_hdmi_connector_detect(struct drm_connector *connector, bool force);
+
+int dw_hdmi_bridge_atomic_check(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state);
+void dw_hdmi_bridge_detach(struct drm_bridge *bridge);
+void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
+ const struct drm_display_mode *orig_mode,
+ const struct drm_display_mode *mode);
+enum drm_connector_status dw_hdmi_bridge_detect(struct drm_bridge *bridge);
+const struct drm_edid *
+dw_hdmi_bridge_edid_read(struct drm_bridge *bridge,
+ struct drm_connector *connector);
+#endif /* __DW_HDMI_COMMON_H__ */
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 0031f3c54882..b66877771f56 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -10,10 +10,8 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/hdmi.h>
-#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/module.h>
-#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/regmap.h>
@@ -25,12 +23,10 @@
#include <uapi/linux/media-bus-format.h>
#include <uapi/linux/videodev2.h>

-#include <drm/bridge/dw_hdmi.h>
#include <drm/display/drm_hdmi_helper.h>
#include <drm/display/drm_scdc_helper.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
-#include <drm/drm_bridge.h>
#include <drm/drm_edid.h>
#include <drm/drm_of.h>
#include <drm/drm_print.h>
@@ -38,18 +34,9 @@

#include "dw-hdmi-audio.h"
#include "dw-hdmi-cec.h"
+#include "dw-hdmi-common.h"
#include "dw-hdmi.h"

-#define DDC_CI_ADDR 0x37
-#define DDC_SEGMENT_ADDR 0x30
-
-#define HDMI_EDID_LEN 512
-
-/* DW-HDMI Controller >= 0x200a are at least compliant with SCDC version 1 */
-#define SCDC_MIN_SOURCE_VERSION 0x1
-
-#define HDMI14_MAX_TMDSCLK 340000000
-
static const u16 csc_coeff_default[3][4] = {
{ 0x2000, 0x0000, 0x0000, 0x0000 },
{ 0x0000, 0x2000, 0x0000, 0x0000 },
@@ -86,117 +73,6 @@ static const u16 csc_coeff_rgb_full_to_rgb_limited[3][4] = {
{ 0x0000, 0x0000, 0x1b7c, 0x0020 }
};

-struct hdmi_vmode {
- bool mdataenablepolarity;
-
- unsigned int mpixelclock;
- unsigned int mpixelrepetitioninput;
- unsigned int mpixelrepetitionoutput;
- unsigned int mtmdsclock;
-};
-
-struct hdmi_data_info {
- unsigned int enc_in_bus_format;
- unsigned int enc_out_bus_format;
- unsigned int enc_in_encoding;
- unsigned int enc_out_encoding;
- unsigned int pix_repet_factor;
- unsigned int hdcp_enable;
- struct hdmi_vmode video_mode;
- bool rgb_limited_range;
-};
-
-struct dw_hdmi_i2c {
- struct i2c_adapter adap;
-
- struct mutex lock; /* used to serialize data transfers */
- struct completion cmp;
- u8 stat;
-
- u8 slave_reg;
- bool is_regaddr;
- bool is_segment;
-};
-
-struct dw_hdmi_phy_data {
- enum dw_hdmi_phy_type type;
- const char *name;
- unsigned int gen;
- bool has_svsret;
- int (*configure)(struct dw_hdmi *hdmi,
- const struct dw_hdmi_plat_data *pdata,
- unsigned long mpixelclock);
-};
-
-struct dw_hdmi {
- struct drm_connector connector;
- struct drm_bridge bridge;
- struct drm_bridge *next_bridge;
-
- unsigned int version;
-
- struct platform_device *audio;
- struct platform_device *cec;
- struct device *dev;
- struct dw_hdmi_i2c *i2c;
-
- struct hdmi_data_info hdmi_data;
- const struct dw_hdmi_plat_data *plat_data;
-
- int vic;
-
- u8 edid[HDMI_EDID_LEN];
-
- struct {
- const struct dw_hdmi_phy_ops *ops;
- const char *name;
- void *data;
- bool enabled;
- } phy;
-
- struct drm_display_mode previous_mode;
-
- struct i2c_adapter *ddc;
- void __iomem *regs;
- bool sink_is_hdmi;
- bool sink_has_audio;
-
- struct pinctrl *pinctrl;
- struct pinctrl_state *default_state;
- struct pinctrl_state *unwedge_state;
-
- struct mutex mutex; /* for state below and previous_mode */
- enum drm_connector_force force; /* mutex-protected force state */
- struct drm_connector *curr_conn;/* current connector (only valid when !disabled) */
- bool disabled; /* DRM has disabled our bridge */
- bool bridge_is_on; /* indicates the bridge is on */
- bool rxsense; /* rxsense state */
- u8 phy_mask; /* desired phy int mask settings */
- u8 mc_clkdis; /* clock disable register */
-
- spinlock_t audio_lock;
- struct mutex audio_mutex;
- unsigned int sample_non_pcm;
- unsigned int sample_width;
- unsigned int sample_rate;
- unsigned int channels;
- unsigned int audio_cts;
- unsigned int audio_n;
- bool audio_enable;
-
- unsigned int reg_shift;
- struct regmap *regm;
- void (*enable_audio)(struct dw_hdmi *hdmi);
- void (*disable_audio)(struct dw_hdmi *hdmi);
-
- struct mutex cec_notifier_mutex;
- struct cec_notifier *cec_notifier;
-
- hdmi_codec_plugged_cb plugged_cb;
- struct device *codec_dev;
- enum drm_connector_status last_connector_result;
-};
-
#define HDMI_IH_PHY_STAT0_RX_SENSE \
(HDMI_IH_PHY_STAT0_RX_SENSE0 | HDMI_IH_PHY_STAT0_RX_SENSE1 | \
HDMI_IH_PHY_STAT0_RX_SENSE2 | HDMI_IH_PHY_STAT0_RX_SENSE3)
@@ -219,11 +95,12 @@ static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset)
return val;
}

-static void handle_plugged_change(struct dw_hdmi *hdmi, bool plugged)
+void dw_handle_plugged_change(struct dw_hdmi *hdmi, bool plugged)
{
if (hdmi->plugged_cb && hdmi->codec_dev)
hdmi->plugged_cb(hdmi->codec_dev, plugged);
}
+EXPORT_SYMBOL_GPL(dw_handle_plugged_change);

int dw_hdmi_set_plugged_cb(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn,
struct device *codec_dev)
@@ -234,7 +111,7 @@ int dw_hdmi_set_plugged_cb(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn,
hdmi->plugged_cb = fn;
hdmi->codec_dev = codec_dev;
plugged = hdmi->last_connector_result == connector_status_connected;
- handle_plugged_change(hdmi, plugged);
+ dw_handle_plugged_change(hdmi, plugged);
mutex_unlock(&hdmi->mutex);

return 0;
@@ -1361,8 +1238,8 @@ void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write);

/* Filter out invalid setups to avoid configuring SCDC and scrambling */
-static bool dw_hdmi_support_scdc(struct dw_hdmi *hdmi,
- const struct drm_display_info *display)
+bool dw_hdmi_support_scdc(struct dw_hdmi *hdmi,
+ const struct drm_display_info *display)
{
/* Completely disable SCDC support for older controllers */
if (hdmi->version < 0x200a)
@@ -1387,6 +1264,7 @@ static bool dw_hdmi_support_scdc(struct dw_hdmi *hdmi,

return true;
}
+EXPORT_SYMBOL_GPL(dw_hdmi_support_scdc);

/*
* HDMI2.0 Specifies the following procedure for High TMDS Bit Rates:
@@ -2486,13 +2364,14 @@ static const struct drm_edid *dw_hdmi_edid_read(struct dw_hdmi *hdmi,
* DRM Connector Operations
*/

-static enum drm_connector_status
+enum drm_connector_status
dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
{
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
connector);
return dw_hdmi_detect(hdmi);
}
+EXPORT_SYMBOL_GPL(dw_hdmi_connector_detect);

static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
{
@@ -2868,10 +2747,10 @@ static u32 *dw_hdmi_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
return input_fmts;
}

-static int dw_hdmi_bridge_atomic_check(struct drm_bridge *bridge,
- struct drm_bridge_state *bridge_state,
- struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state)
+int dw_hdmi_bridge_atomic_check(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
{
struct dw_hdmi *hdmi = bridge->driver_private;

@@ -2887,6 +2766,7 @@ static int dw_hdmi_bridge_atomic_check(struct drm_bridge *bridge,

return 0;
}
+EXPORT_SYMBOL_GPL(dw_hdmi_bridge_atomic_check);

static int dw_hdmi_bridge_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
@@ -2900,7 +2780,7 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge,
return dw_hdmi_connector_create(hdmi);
}

-static void dw_hdmi_bridge_detach(struct drm_bridge *bridge)
+void dw_hdmi_bridge_detach(struct drm_bridge *bridge)
{
struct dw_hdmi *hdmi = bridge->driver_private;

@@ -2909,6 +2789,7 @@ static void dw_hdmi_bridge_detach(struct drm_bridge *bridge)
hdmi->cec_notifier = NULL;
mutex_unlock(&hdmi->cec_notifier_mutex);
}
+EXPORT_SYMBOL_GPL(dw_hdmi_bridge_detach);

static enum drm_mode_status
dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
@@ -2930,9 +2811,9 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
return mode_status;
}

-static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
- const struct drm_display_mode *orig_mode,
- const struct drm_display_mode *mode)
+void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
+ const struct drm_display_mode *orig_mode,
+ const struct drm_display_mode *mode)
{
struct dw_hdmi *hdmi = bridge->driver_private;

@@ -2943,6 +2824,7 @@ static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,

mutex_unlock(&hdmi->mutex);
}
+EXPORT_SYMBOL_GPL(dw_hdmi_bridge_mode_set);

static void dw_hdmi_bridge_atomic_disable(struct drm_bridge *bridge,
struct drm_bridge_state *old_state)
@@ -2954,7 +2836,7 @@ static void dw_hdmi_bridge_atomic_disable(struct drm_bridge *bridge,
hdmi->curr_conn = NULL;
dw_hdmi_update_power(hdmi);
dw_hdmi_update_phy_mask(hdmi);
- handle_plugged_change(hdmi, false);
+ dw_handle_plugged_change(hdmi, false);
mutex_unlock(&hdmi->mutex);
}

@@ -2973,24 +2855,26 @@ static void dw_hdmi_bridge_atomic_enable(struct drm_bridge *bridge,
hdmi->curr_conn = connector;
dw_hdmi_update_power(hdmi);
dw_hdmi_update_phy_mask(hdmi);
- handle_plugged_change(hdmi, true);
+ dw_handle_plugged_change(hdmi, true);
mutex_unlock(&hdmi->mutex);
}

-static enum drm_connector_status dw_hdmi_bridge_detect(struct drm_bridge *bridge)
+enum drm_connector_status dw_hdmi_bridge_detect(struct drm_bridge *bridge)
{
struct dw_hdmi *hdmi = bridge->driver_private;

return dw_hdmi_detect(hdmi);
}
+EXPORT_SYMBOL_GPL(dw_hdmi_bridge_detect);

-static const struct drm_edid *dw_hdmi_bridge_edid_read(struct drm_bridge *bridge,
- struct drm_connector *connector)
+const struct drm_edid *dw_hdmi_bridge_edid_read(struct drm_bridge *bridge,
+ struct drm_connector *connector)
{
struct dw_hdmi *hdmi = bridge->driver_private;

return dw_hdmi_edid_read(hdmi, connector);
}
+EXPORT_SYMBOL_GPL(dw_hdmi_bridge_edid_read);

static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,

--
2.45.0