aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorDmitry Baryshkov <dmitry.baryshkov@linaro.org>2025-01-06 01:00:14 +0200
committerDanilo Krummrich <dakr@kernel.org>2025-01-07 15:05:11 +0100
commita73583107af9b42c0a28045e4e30ec3fab2dbcd1 (patch)
tree5207f8142830410d33ac12fb8dc882d752c46bae /drivers/gpu/drm
parentdrm/nouveau: incorporate I2C TV encoder drivers (diff)
downloadlinux-a73583107af9b42c0a28045e4e30ec3fab2dbcd1.tar.gz
linux-a73583107af9b42c0a28045e4e30ec3fab2dbcd1.zip
drm/nouveau: vendor in drm_encoder_slave API
Nouveau driver is the only user of the drm_encoder_slave API. Rework necessary bits of drm_encoder_slave into the nouveau_i2c_encoder API and drop drm_encoder_slave.c from the DRM KMS helper. Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Signed-off-by: Danilo Krummrich <dakr@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20250106-nouveau-encoder-slave-v3-2-1d37d2f2c67f@linaro.org
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/Makefile1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/dfp.c15
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_drv.c30
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_mode.c8
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_priv.h4
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/i2c/sil164_drv.c30
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/nouveau_i2c_encoder.c (renamed from drivers/gpu/drm/drm_encoder_slave.c)95
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvnv04.c22
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvnv17.c4
-rw-r--r--drivers/gpu/drm/nouveau/include/dispnv04/i2c/encoder_i2c.h220
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c10
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_encoder.h13
13 files changed, 317 insertions, 136 deletions
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 19fb370fbc56..85af94bb907d 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -135,7 +135,6 @@ drm_kms_helper-y := \
drm_atomic_state_helper.o \
drm_crtc_helper.o \
drm_damage_helper.o \
- drm_encoder_slave.o \
drm_flip_work.o \
drm_format_helper.o \
drm_gem_atomic_helper.o \
diff --git a/drivers/gpu/drm/nouveau/dispnv04/Kbuild b/drivers/gpu/drm/nouveau/dispnv04/Kbuild
index 949802882ebd..4c7bc6bb81b3 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/Kbuild
+++ b/drivers/gpu/drm/nouveau/dispnv04/Kbuild
@@ -6,6 +6,7 @@ nouveau-y += dispnv04/dac.o
nouveau-y += dispnv04/dfp.o
nouveau-y += dispnv04/disp.o
nouveau-y += dispnv04/hw.o
+nouveau-y += dispnv04/nouveau_i2c_encoder.o
nouveau-y += dispnv04/overlay.o
nouveau-y += dispnv04/tvmodesnv17.o
nouveau-y += dispnv04/tvnv04.o
diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
index 25fa41edcb3c..c724bacc67f8 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
@@ -171,7 +171,7 @@ static struct drm_encoder *get_tmds_slave(struct drm_encoder *encoder)
list_for_each_entry(slave, &dev->mode_config.encoder_list, head) {
struct dcb_output *slave_dcb = nouveau_encoder(slave)->dcb;
- if (slave_dcb->type == DCB_OUTPUT_TMDS && get_slave_funcs(slave) &&
+ if (slave_dcb->type == DCB_OUTPUT_TMDS && get_encoder_i2c_funcs(slave) &&
slave_dcb->tmdsconf.slave_addr == dcb->tmdsconf.slave_addr)
return slave;
}
@@ -473,8 +473,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
/* Init external transmitters */
slave_encoder = get_tmds_slave(encoder);
if (slave_encoder)
- get_slave_funcs(slave_encoder)->mode_set(
- slave_encoder, &nv_encoder->mode, &nv_encoder->mode);
+ get_encoder_i2c_funcs(slave_encoder)->mode_set(slave_encoder,
+ &nv_encoder->mode,
+ &nv_encoder->mode);
helper->dpms(encoder, DRM_MODE_DPMS_ON);
@@ -614,8 +615,8 @@ static void nv04_dfp_destroy(struct drm_encoder *encoder)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- if (get_slave_funcs(encoder))
- get_slave_funcs(encoder)->destroy(encoder);
+ if (get_encoder_i2c_funcs(encoder))
+ get_encoder_i2c_funcs(encoder)->destroy(encoder);
drm_encoder_cleanup(encoder);
kfree(nv_encoder);
@@ -649,8 +650,8 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder)
if (type < 0)
return;
- drm_i2c_encoder_init(dev, to_encoder_slave(encoder),
- &bus->i2c, &info[type].dev);
+ nouveau_i2c_encoder_init(dev, to_encoder_i2c(encoder),
+ &bus->i2c, &info[type].dev);
}
static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = {
diff --git a/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_drv.c b/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_drv.c
index db4f95020fae..fd2150e07e36 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_drv.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_drv.c
@@ -47,14 +47,14 @@ static void ch7006_encoder_destroy(struct drm_encoder *encoder)
drm_property_destroy(encoder->dev, priv->scale_property);
kfree(priv);
- to_encoder_slave(encoder)->slave_priv = NULL;
+ to_encoder_i2c(encoder)->encoder_i2c_priv = NULL;
- drm_i2c_encoder_destroy(encoder);
+ nouveau_i2c_encoder_destroy(encoder);
}
static void ch7006_encoder_dpms(struct drm_encoder *encoder, int mode)
{
- struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+ struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder);
struct ch7006_priv *priv = to_ch7006_priv(encoder);
struct ch7006_state *state = &priv->state;
@@ -71,7 +71,7 @@ static void ch7006_encoder_dpms(struct drm_encoder *encoder, int mode)
static void ch7006_encoder_save(struct drm_encoder *encoder)
{
- struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+ struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder);
struct ch7006_priv *priv = to_ch7006_priv(encoder);
ch7006_dbg(client, "\n");
@@ -81,7 +81,7 @@ static void ch7006_encoder_save(struct drm_encoder *encoder)
static void ch7006_encoder_restore(struct drm_encoder *encoder)
{
- struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+ struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder);
struct ch7006_priv *priv = to_ch7006_priv(encoder);
ch7006_dbg(client, "\n");
@@ -116,7 +116,7 @@ static void ch7006_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *drm_mode,
struct drm_display_mode *adjusted_mode)
{
- struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+ struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder);
struct ch7006_priv *priv = to_ch7006_priv(encoder);
struct ch7006_encoder_params *params = &priv->params;
struct ch7006_state *state = &priv->state;
@@ -179,7 +179,7 @@ static void ch7006_encoder_mode_set(struct drm_encoder *encoder,
static enum drm_connector_status ch7006_encoder_detect(struct drm_encoder *encoder,
struct drm_connector *connector)
{
- struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+ struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder);
struct ch7006_priv *priv = to_ch7006_priv(encoder);
struct ch7006_state *state = &priv->state;
int det;
@@ -285,7 +285,7 @@ static int ch7006_encoder_set_property(struct drm_encoder *encoder,
struct drm_property *property,
uint64_t val)
{
- struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+ struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder);
struct ch7006_priv *priv = to_ch7006_priv(encoder);
struct ch7006_state *state = &priv->state;
struct drm_mode_config *conf = &encoder->dev->mode_config;
@@ -370,7 +370,7 @@ static int ch7006_encoder_set_property(struct drm_encoder *encoder,
return 0;
}
-static const struct drm_encoder_slave_funcs ch7006_encoder_funcs = {
+static const struct nouveau_i2c_encoder_funcs ch7006_encoder_funcs = {
.set_config = ch7006_encoder_set_config,
.destroy = ch7006_encoder_destroy,
.dpms = ch7006_encoder_dpms,
@@ -437,7 +437,7 @@ static int ch7006_resume(struct device *dev)
static int ch7006_encoder_init(struct i2c_client *client,
struct drm_device *dev,
- struct drm_encoder_slave *encoder)
+ struct nouveau_i2c_encoder *encoder)
{
struct ch7006_priv *priv;
int i;
@@ -448,8 +448,8 @@ static int ch7006_encoder_init(struct i2c_client *client,
if (!priv)
return -ENOMEM;
- encoder->slave_priv = priv;
- encoder->slave_funcs = &ch7006_encoder_funcs;
+ encoder->encoder_i2c_priv = priv;
+ encoder->encoder_i2c_funcs = &ch7006_encoder_funcs;
priv->norm = TV_NORM_PAL;
priv->select_subconnector = DRM_MODE_SUBCONNECTOR_Automatic;
@@ -495,7 +495,7 @@ static const struct dev_pm_ops ch7006_pm_ops = {
.resume = ch7006_resume,
};
-static struct drm_i2c_encoder_driver ch7006_driver = {
+static struct nouveau_i2c_encoder_driver ch7006_driver = {
.i2c_driver = {
.probe = ch7006_probe,
.remove = ch7006_remove,
@@ -516,12 +516,12 @@ static struct drm_i2c_encoder_driver ch7006_driver = {
static int __init ch7006_init(void)
{
- return drm_i2c_encoder_register(THIS_MODULE, &ch7006_driver);
+ return i2c_add_driver(&ch7006_driver.i2c_driver);
}
static void __exit ch7006_exit(void)
{
- drm_i2c_encoder_unregister(&ch7006_driver);
+ i2c_del_driver(&ch7006_driver.i2c_driver);
}
int ch7006_debug;
diff --git a/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_mode.c b/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_mode.c
index 6afe6d0ee630..e58d94451959 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_mode.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_mode.c
@@ -198,7 +198,7 @@ const struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder,
void ch7006_setup_levels(struct drm_encoder *encoder)
{
- struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+ struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder);
struct ch7006_priv *priv = to_ch7006_priv(encoder);
uint8_t *regs = priv->state.regs;
const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm];
@@ -229,7 +229,7 @@ void ch7006_setup_levels(struct drm_encoder *encoder)
void ch7006_setup_subcarrier(struct drm_encoder *encoder)
{
- struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+ struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder);
struct ch7006_priv *priv = to_ch7006_priv(encoder);
struct ch7006_state *state = &priv->state;
const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm];
@@ -253,7 +253,7 @@ void ch7006_setup_subcarrier(struct drm_encoder *encoder)
void ch7006_setup_pll(struct drm_encoder *encoder)
{
- struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+ struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder);
struct ch7006_priv *priv = to_ch7006_priv(encoder);
uint8_t *regs = priv->state.regs;
const struct ch7006_mode *mode = priv->mode;
@@ -324,7 +324,7 @@ void ch7006_setup_power_state(struct drm_encoder *encoder)
void ch7006_setup_properties(struct drm_encoder *encoder)
{
- struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+ struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder);
struct ch7006_priv *priv = to_ch7006_priv(encoder);
struct ch7006_state *state = &priv->state;
const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm];
diff --git a/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_priv.h b/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_priv.h
index d7a91e17510f..5ad5157a2c02 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_priv.h
+++ b/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_priv.h
@@ -27,9 +27,9 @@
#ifndef __NOUVEAU_I2C_CH7006_PRIV_H__
#define __NOUVEAU_I2C_CH7006_PRIV_H__
-#include <drm/drm_encoder_slave.h>
#include <drm/drm_probe_helper.h>
+#include <dispnv04/i2c/encoder_i2c.h>
#include <dispnv04/i2c/ch7006.h>
typedef int64_t fixed;
@@ -100,7 +100,7 @@ struct ch7006_priv {
};
#define to_ch7006_priv(x) \
- ((struct ch7006_priv *)to_encoder_slave(x)->slave_priv)
+ ((struct ch7006_priv *)to_encoder_i2c(x)->encoder_i2c_priv)
extern int ch7006_debug;
extern char *ch7006_tv_norm;
diff --git a/drivers/gpu/drm/nouveau/dispnv04/i2c/sil164_drv.c b/drivers/gpu/drm/nouveau/dispnv04/i2c/sil164_drv.c
index 39b01c897518..54ea8459332d 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/i2c/sil164_drv.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/i2c/sil164_drv.c
@@ -27,10 +27,10 @@
#include <linux/module.h>
#include <drm/drm_drv.h>
-#include <drm/drm_encoder_slave.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
+#include <dispnv04/i2c/encoder_i2c.h>
#include <dispnv04/i2c/sil164.h>
struct sil164_priv {
@@ -42,7 +42,7 @@ struct sil164_priv {
};
#define to_sil164_priv(x) \
- ((struct sil164_priv *)to_encoder_slave(x)->slave_priv)
+ ((struct sil164_priv *)to_encoder_i2c(x)->encoder_i2c_priv)
#define sil164_dbg(client, format, ...) do { \
if (drm_debug_enabled(DRM_UT_KMS)) \
@@ -222,7 +222,7 @@ sil164_encoder_dpms(struct drm_encoder *encoder, int mode)
bool on = (mode == DRM_MODE_DPMS_ON);
bool duallink = (on && encoder->crtc->mode.clock > 165000);
- sil164_set_power_state(drm_i2c_encoder_get_client(encoder), on);
+ sil164_set_power_state(nouveau_i2c_encoder_get_client(encoder), on);
if (priv->duallink_slave)
sil164_set_power_state(priv->duallink_slave, duallink);
@@ -233,7 +233,7 @@ sil164_encoder_save(struct drm_encoder *encoder)
{
struct sil164_priv *priv = to_sil164_priv(encoder);
- sil164_save_state(drm_i2c_encoder_get_client(encoder),
+ sil164_save_state(nouveau_i2c_encoder_get_client(encoder),
priv->saved_state);
if (priv->duallink_slave)
@@ -246,7 +246,7 @@ sil164_encoder_restore(struct drm_encoder *encoder)
{
struct sil164_priv *priv = to_sil164_priv(encoder);
- sil164_restore_state(drm_i2c_encoder_get_client(encoder),
+ sil164_restore_state(nouveau_i2c_encoder_get_client(encoder),
priv->saved_state);
if (priv->duallink_slave)
@@ -278,7 +278,7 @@ sil164_encoder_mode_set(struct drm_encoder *encoder,
struct sil164_priv *priv = to_sil164_priv(encoder);
bool duallink = adjusted_mode->clock > 165000;
- sil164_init_state(drm_i2c_encoder_get_client(encoder),
+ sil164_init_state(nouveau_i2c_encoder_get_client(encoder),
&priv->config, duallink);
if (priv->duallink_slave)
@@ -292,7 +292,7 @@ static enum drm_connector_status
sil164_encoder_detect(struct drm_encoder *encoder,
struct drm_connector *connector)
{
- struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+ struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder);
if (sil164_read(client, SIL164_DETECT) & SIL164_DETECT_HOTPLUG_STAT)
return connector_status_connected;
@@ -331,10 +331,10 @@ sil164_encoder_destroy(struct drm_encoder *encoder)
i2c_unregister_device(priv->duallink_slave);
kfree(priv);
- drm_i2c_encoder_destroy(encoder);
+ nouveau_i2c_encoder_destroy(encoder);
}
-static const struct drm_encoder_slave_funcs sil164_encoder_funcs = {
+static const struct nouveau_i2c_encoder_funcs sil164_encoder_funcs = {
.set_config = sil164_encoder_set_config,
.destroy = sil164_encoder_destroy,
.dpms = sil164_encoder_dpms,
@@ -394,7 +394,7 @@ sil164_detect_slave(struct i2c_client *client)
static int
sil164_encoder_init(struct i2c_client *client,
struct drm_device *dev,
- struct drm_encoder_slave *encoder)
+ struct nouveau_i2c_encoder *encoder)
{
struct sil164_priv *priv;
struct i2c_client *slave_client;
@@ -403,8 +403,8 @@ sil164_encoder_init(struct i2c_client *client,
if (!priv)
return -ENOMEM;
- encoder->slave_priv = priv;
- encoder->slave_funcs = &sil164_encoder_funcs;
+ encoder->encoder_i2c_priv = priv;
+ encoder->encoder_i2c_funcs = &sil164_encoder_funcs;
slave_client = sil164_detect_slave(client);
if (!IS_ERR(slave_client))
@@ -419,7 +419,7 @@ static const struct i2c_device_id sil164_ids[] = {
};
MODULE_DEVICE_TABLE(i2c, sil164_ids);
-static struct drm_i2c_encoder_driver sil164_driver = {
+static struct nouveau_i2c_encoder_driver sil164_driver = {
.i2c_driver = {
.probe = sil164_probe,
.driver = {
@@ -435,13 +435,13 @@ static struct drm_i2c_encoder_driver sil164_driver = {
static int __init
sil164_init(void)
{
- return drm_i2c_encoder_register(THIS_MODULE, &sil164_driver);
+ return i2c_add_driver(&sil164_driver.i2c_driver);
}
static void __exit
sil164_exit(void)
{
- drm_i2c_encoder_unregister(&sil164_driver);
+ i2c_del_driver(&sil164_driver.i2c_driver);
}
MODULE_AUTHOR("Francisco Jerez <currojerez@riseup.net>");
diff --git a/drivers/gpu/drm/drm_encoder_slave.c b/drivers/gpu/drm/nouveau/dispnv04/nouveau_i2c_encoder.c
index e464429d32df..e2bf99c43336 100644
--- a/drivers/gpu/drm/drm_encoder_slave.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/nouveau_i2c_encoder.c
@@ -26,10 +26,10 @@
#include <linux/module.h>
-#include <drm/drm_encoder_slave.h>
+#include <dispnv04/i2c/encoder_i2c.h>
/**
- * drm_i2c_encoder_init - Initialize an I2C slave encoder
+ * nouveau_i2c_encoder_init - Initialize an I2C slave encoder
* @dev: DRM device.
* @encoder: Encoder to be attached to the I2C device. You aren't
* required to have called drm_encoder_init() before.
@@ -40,7 +40,7 @@
*
* Create an I2C device on the specified bus (the module containing its
* driver is transparently loaded) and attach it to the specified
- * &drm_encoder_slave. The @slave_funcs field will be initialized with
+ * &nouveau_i2c_encoder. The @encoder_i2c_funcs field will be initialized with
* the hooks provided by the slave driver.
*
* If @info.platform_data is non-NULL it will be used as the initial
@@ -49,14 +49,14 @@
* Returns 0 on success or a negative errno on failure, in particular,
* -ENODEV is returned when no matching driver is found.
*/
-int drm_i2c_encoder_init(struct drm_device *dev,
- struct drm_encoder_slave *encoder,
- struct i2c_adapter *adap,
- const struct i2c_board_info *info)
+int nouveau_i2c_encoder_init(struct drm_device *dev,
+ struct nouveau_i2c_encoder *encoder,
+ struct i2c_adapter *adap,
+ const struct i2c_board_info *info)
{
struct module *module = NULL;
struct i2c_client *client;
- struct drm_i2c_encoder_driver *encoder_drv;
+ struct nouveau_i2c_encoder_driver *encoder_drv;
int err = 0;
request_module("%s%s", I2C_MODULE_PREFIX, info->type);
@@ -73,16 +73,16 @@ int drm_i2c_encoder_init(struct drm_device *dev,
goto fail_unregister;
}
- encoder->bus_priv = client;
+ encoder->i2c_client = client;
- encoder_drv = to_drm_i2c_encoder_driver(to_i2c_driver(client->dev.driver));
+ encoder_drv = to_nouveau_i2c_encoder_driver(to_i2c_driver(client->dev.driver));
err = encoder_drv->encoder_init(client, dev, encoder);
if (err)
goto fail_module_put;
if (info->platform_data)
- encoder->slave_funcs->set_config(&encoder->base,
+ encoder->encoder_i2c_funcs->set_config(&encoder->base,
info->platform_data);
return 0;
@@ -93,90 +93,53 @@ fail_unregister:
i2c_unregister_device(client);
return err;
}
-EXPORT_SYMBOL(drm_i2c_encoder_init);
/**
- * drm_i2c_encoder_destroy - Unregister the I2C device backing an encoder
+ * nouveau_i2c_encoder_destroy - Unregister the I2C device backing an encoder
* @drm_encoder: Encoder to be unregistered.
*
* This should be called from the @destroy method of an I2C slave
* encoder driver once I2C access is no longer needed.
*/
-void drm_i2c_encoder_destroy(struct drm_encoder *drm_encoder)
+void nouveau_i2c_encoder_destroy(struct drm_encoder *drm_encoder)
{
- struct drm_encoder_slave *encoder = to_encoder_slave(drm_encoder);
- struct i2c_client *client = drm_i2c_encoder_get_client(drm_encoder);
+ struct nouveau_i2c_encoder *encoder = to_encoder_i2c(drm_encoder);
+ struct i2c_client *client = nouveau_i2c_encoder_get_client(drm_encoder);
struct module *module = client->dev.driver->owner;
i2c_unregister_device(client);
- encoder->bus_priv = NULL;
+ encoder->i2c_client = NULL;
module_put(module);
}
-EXPORT_SYMBOL(drm_i2c_encoder_destroy);
+EXPORT_SYMBOL(nouveau_i2c_encoder_destroy);
/*
* Wrapper fxns which can be plugged in to drm_encoder_helper_funcs:
*/
-static inline const struct drm_encoder_slave_funcs *
-get_slave_funcs(struct drm_encoder *enc)
+bool nouveau_i2c_encoder_mode_fixup(struct drm_encoder *encoder,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
{
- return to_encoder_slave(enc)->slave_funcs;
-}
-
-void drm_i2c_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
- get_slave_funcs(encoder)->dpms(encoder, mode);
-}
-EXPORT_SYMBOL(drm_i2c_encoder_dpms);
-
-bool drm_i2c_encoder_mode_fixup(struct drm_encoder *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- if (!get_slave_funcs(encoder)->mode_fixup)
+ if (!get_encoder_i2c_funcs(encoder)->mode_fixup)
return true;
- return get_slave_funcs(encoder)->mode_fixup(encoder, mode, adjusted_mode);
-}
-EXPORT_SYMBOL(drm_i2c_encoder_mode_fixup);
-
-void drm_i2c_encoder_prepare(struct drm_encoder *encoder)
-{
- drm_i2c_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
-}
-EXPORT_SYMBOL(drm_i2c_encoder_prepare);
-
-void drm_i2c_encoder_commit(struct drm_encoder *encoder)
-{
- drm_i2c_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
-}
-EXPORT_SYMBOL(drm_i2c_encoder_commit);
-
-void drm_i2c_encoder_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- get_slave_funcs(encoder)->mode_set(encoder, mode, adjusted_mode);
+ return get_encoder_i2c_funcs(encoder)->mode_fixup(encoder, mode, adjusted_mode);
}
-EXPORT_SYMBOL(drm_i2c_encoder_mode_set);
-enum drm_connector_status drm_i2c_encoder_detect(struct drm_encoder *encoder,
- struct drm_connector *connector)
+enum drm_connector_status nouveau_i2c_encoder_detect(struct drm_encoder *encoder,
+ struct drm_connector *connector)
{
- return get_slave_funcs(encoder)->detect(encoder, connector);
+ return get_encoder_i2c_funcs(encoder)->detect(encoder, connector);
}
-EXPORT_SYMBOL(drm_i2c_encoder_detect);
-void drm_i2c_encoder_save(struct drm_encoder *encoder)
+void nouveau_i2c_encoder_save(struct drm_encoder *encoder)
{
- get_slave_funcs(encoder)->save(encoder);
+ get_encoder_i2c_funcs(encoder)->save(encoder);
}
-EXPORT_SYMBOL(drm_i2c_encoder_save);
-void drm_i2c_encoder_restore(struct drm_encoder *encoder)
+void nouveau_i2c_encoder_restore(struct drm_encoder *encoder)
{
- get_slave_funcs(encoder)->restore(encoder);
+ get_encoder_i2c_funcs(encoder)->restore(encoder);
}
-EXPORT_SYMBOL(drm_i2c_encoder_restore);
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
index 4ffd8af6bf8b..c61ab083f62e 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
@@ -99,7 +99,7 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode)
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel);
- get_slave_funcs(encoder)->dpms(encoder, mode);
+ get_encoder_i2c_funcs(encoder)->dpms(encoder, mode);
}
static void nv04_tv_bind(struct drm_device *dev, int head, bool bind)
@@ -158,7 +158,7 @@ static void nv04_tv_mode_set(struct drm_encoder *encoder,
regp->tv_vskew = 1;
regp->tv_vsync_delay = 1;
- get_slave_funcs(encoder)->mode_set(encoder, mode, adjusted_mode);
+ get_encoder_i2c_funcs(encoder)->mode_set(encoder, mode, adjusted_mode);
}
static void nv04_tv_commit(struct drm_encoder *encoder)
@@ -178,7 +178,7 @@ static void nv04_tv_commit(struct drm_encoder *encoder)
static void nv04_tv_destroy(struct drm_encoder *encoder)
{
- get_slave_funcs(encoder)->destroy(encoder);
+ get_encoder_i2c_funcs(encoder)->destroy(encoder);
drm_encoder_cleanup(encoder);
kfree(encoder->helper_private);
@@ -191,11 +191,11 @@ static const struct drm_encoder_funcs nv04_tv_funcs = {
static const struct drm_encoder_helper_funcs nv04_tv_helper_funcs = {
.dpms = nv04_tv_dpms,
- .mode_fixup = drm_i2c_encoder_mode_fixup,
+ .mode_fixup = nouveau_i2c_encoder_mode_fixup,
.prepare = nv04_tv_prepare,
.commit = nv04_tv_commit,
.mode_set = nv04_tv_mode_set,
- .detect = drm_i2c_encoder_detect,
+ .detect = nouveau_i2c_encoder_detect,
};
int
@@ -226,8 +226,8 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)
NULL);
drm_encoder_helper_add(encoder, &nv04_tv_helper_funcs);
- nv_encoder->enc_save = drm_i2c_encoder_save;
- nv_encoder->enc_restore = drm_i2c_encoder_restore;
+ nv_encoder->enc_save = nouveau_i2c_encoder_save;
+ nv_encoder->enc_restore = nouveau_i2c_encoder_restore;
encoder->possible_crtcs = entry->heads;
encoder->possible_clones = 0;
@@ -235,14 +235,14 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)
nv_encoder->or = ffs(entry->or) - 1;
/* Run the slave-specific initialization */
- ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder),
- &bus->i2c,
- &nv04_tv_encoder_info[type].dev);
+ ret = nouveau_i2c_encoder_init(dev, to_encoder_i2c(encoder),
+ &bus->i2c,
+ &nv04_tv_encoder_info[type].dev);
if (ret < 0)
goto fail_cleanup;
/* Attach it to the specified connector. */
- get_slave_funcs(encoder)->create_resources(encoder, connector);
+ get_encoder_i2c_funcs(encoder)->create_resources(encoder, connector);
drm_connector_attach_encoder(connector, encoder);
return 0;
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
index 35ad4e10d273..06de05fe5db6 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
@@ -779,7 +779,7 @@ static const struct drm_encoder_helper_funcs nv17_tv_helper_funcs = {
.detect = nv17_tv_detect,
};
-static const struct drm_encoder_slave_funcs nv17_tv_slave_funcs = {
+static const struct nouveau_i2c_encoder_funcs nv17_tv_encoder_i2c_funcs = {
.get_modes = nv17_tv_get_modes,
.mode_valid = nv17_tv_mode_valid,
.create_resources = nv17_tv_create_resources,
@@ -818,7 +818,7 @@ nv17_tv_create(struct drm_connector *connector, struct dcb_output *entry)
drm_encoder_init(dev, encoder, &nv17_tv_funcs, DRM_MODE_ENCODER_TVDAC,
NULL);
drm_encoder_helper_add(encoder, &nv17_tv_helper_funcs);
- to_encoder_slave(encoder)->slave_funcs = &nv17_tv_slave_funcs;
+ to_encoder_i2c(encoder)->encoder_i2c_funcs = &nv17_tv_encoder_i2c_funcs;
tv_enc->base.enc_save = nv17_tv_save;
tv_enc->base.enc_restore = nv17_tv_restore;
diff --git a/drivers/gpu/drm/nouveau/include/dispnv04/i2c/encoder_i2c.h b/drivers/gpu/drm/nouveau/include/dispnv04/i2c/encoder_i2c.h
new file mode 100644
index 000000000000..31334aa90781
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/dispnv04/i2c/encoder_i2c.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __NOUVEAU_ENCODER_I2C_H__
+#define __NOUVEAU_ENCODER_I2C_H__
+
+#include <linux/i2c.h>
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_encoder.h>
+
+/**
+ * struct nouveau_i2c_encoder_funcs - Entry points exposed by a I2C encoder driver
+ *
+ * Most of its members are analogous to the function pointers in
+ * &drm_encoder_helper_funcs and they can optionally be used to
+ * initialize the latter. Connector-like methods (e.g. @get_modes and
+ * @set_property) will typically be wrapped around and only be called
+ * if the encoder is the currently selected one for the connector.
+ */
+struct nouveau_i2c_encoder_funcs {
+ /**
+ * @set_config: Initialize any encoder-specific modesetting parameters.
+ * The meaning of the @params parameter is implementation dependent. It
+ * will usually be a structure with DVO port data format settings or
+ * timings. It's not required for the new parameters to take effect
+ * until the next mode is set.
+ */
+ void (*set_config)(struct drm_encoder *encoder,
+ void *params);
+
+ /**
+ * @destroy: Analogous to &drm_encoder_funcs @destroy callback.
+ */
+ void (*destroy)(struct drm_encoder *encoder);
+
+ /**
+ * @dpms: Analogous to &drm_encoder_helper_funcs @dpms callback.
+ */
+ void (*dpms)(struct drm_encoder *encoder, int mode);
+
+ /**
+ * @save: Save state. Wrapped by nouveau_i2c_encoder_save().
+ */
+ void (*save)(struct drm_encoder *encoder);
+
+ /**
+ * @restore: Restore state. Wrapped by nouveau_i2c_encoder_restore().
+ */
+ void (*restore)(struct drm_encoder *encoder);
+
+ /**
+ * @mode_fixup: Analogous to &drm_encoder_helper_funcs @mode_fixup
+ * callback. Wrapped by nouveau_i2c_encoder_mode_fixup().
+ */
+ bool (*mode_fixup)(struct drm_encoder *encoder,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+
+ /**
+ * @mode_valid: Analogous to &drm_encoder_helper_funcs @mode_valid.
+ */
+ int (*mode_valid)(struct drm_encoder *encoder,
+ const struct drm_display_mode *mode);
+ /**
+ * @mode_set: Analogous to &drm_encoder_helper_funcs @mode_set
+ * callback.
+ */
+ void (*mode_set)(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+
+ /**
+ * @detect: Analogous to &drm_encoder_helper_funcs @detect
+ * callback. Wrapped by nouveau_i2c_encoder_detect().
+ */
+ enum drm_connector_status (*detect)(struct drm_encoder *encoder,
+ struct drm_connector *connector);
+ /**
+ * @get_modes: Get modes.
+ */
+ int (*get_modes)(struct drm_encoder *encoder,
+ struct drm_connector *connector);
+ /**
+ * @create_resources: Create resources.
+ */
+ int (*create_resources)(struct drm_encoder *encoder,
+ struct drm_connector *connector);
+ /**
+ * @set_property: Set property.
+ */
+ int (*set_property)(struct drm_encoder *encoder,
+ struct drm_connector *connector,
+ struct drm_property *property,
+ uint64_t val);
+};
+
+/**
+ * struct nouveau_i2c_encoder - I2C encoder struct
+ *
+ * A &nouveau_i2c_encoder has two sets of callbacks, @encoder_i2c_funcs and the
+ * ones in @base. The former are never actually called by the common
+ * CRTC code, it's just a convenience for splitting the encoder
+ * functions in an upper, GPU-specific layer and a (hopefully)
+ * GPU-agnostic lower layer: It's the GPU driver responsibility to
+ * call the nouveau_i2c_encoder methods when appropriate.
+ *
+ * nouveau_i2c_encoder_init() provides a way to get an implementation of
+ * this.
+ */
+struct nouveau_i2c_encoder {
+ /**
+ * @base: DRM encoder object.
+ */
+ struct drm_encoder base;
+
+ /**
+ * @encoder_i2c_funcs: I2C encoder callbacks.
+ */
+ const struct nouveau_i2c_encoder_funcs *encoder_i2c_funcs;
+
+ /**
+ * @encoder_i2c_priv: I2C encoder private data.
+ */
+ void *encoder_i2c_priv;
+
+ /**
+ * @i2c_client: corresponding I2C client structure
+ */
+ struct i2c_client *i2c_client;
+};
+
+#define to_encoder_i2c(x) container_of((x), struct nouveau_i2c_encoder, base)
+
+int nouveau_i2c_encoder_init(struct drm_device *dev,
+ struct nouveau_i2c_encoder *encoder,
+ struct i2c_adapter *adap,
+ const struct i2c_board_info *info);
+
+static inline const struct nouveau_i2c_encoder_funcs *
+get_encoder_i2c_funcs(struct drm_encoder *enc)
+{
+ return to_encoder_i2c(enc)->encoder_i2c_funcs;
+}
+
+/**
+ * struct nouveau_i2c_encoder_driver
+ *
+ * Describes a device driver for an encoder connected to the GPU through an I2C
+ * bus.
+ */
+struct nouveau_i2c_encoder_driver {
+ /**
+ * @i2c_driver: I2C device driver description.
+ */
+ struct i2c_driver i2c_driver;
+
+ /**
+ * @encoder_init: Callback to allocate any per-encoder data structures
+ * and to initialize the @encoder_i2c_funcs and (optionally) @encoder_i2c_priv
+ * members of @encoder.
+ */
+ int (*encoder_init)(struct i2c_client *client,
+ struct drm_device *dev,
+ struct nouveau_i2c_encoder *encoder);
+
+};
+
+#define to_nouveau_i2c_encoder_driver(x) container_of((x), \
+ struct nouveau_i2c_encoder_driver, \
+ i2c_driver)
+
+/**
+ * nouveau_i2c_encoder_get_client - Get the I2C client corresponding to an encoder
+ * @encoder: The encoder
+ */
+static inline struct i2c_client *nouveau_i2c_encoder_get_client(struct drm_encoder *encoder)
+{
+ return to_encoder_i2c(encoder)->i2c_client;
+}
+
+void nouveau_i2c_encoder_destroy(struct drm_encoder *encoder);
+
+/*
+ * Wrapper fxns which can be plugged in to drm_encoder_helper_funcs:
+ */
+
+bool nouveau_i2c_encoder_mode_fixup(struct drm_encoder *encoder,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+enum drm_connector_status nouveau_i2c_encoder_detect(struct drm_encoder *encoder,
+ struct drm_connector *connector);
+void nouveau_i2c_encoder_save(struct drm_encoder *encoder);
+void nouveau_i2c_encoder_restore(struct drm_encoder *encoder);
+
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 2d26784bde74..6fb9719d721f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -797,8 +797,10 @@ nouveau_connector_set_property(struct drm_connector *connector,
property, value);
if (ret) {
if (nv_encoder && nv_encoder->dcb->type == DCB_OUTPUT_TV)
- return get_slave_funcs(encoder)->set_property(
- encoder, connector, property, value);
+ return get_encoder_i2c_funcs(encoder)->set_property(encoder,
+ connector,
+ property,
+ value);
return ret;
}
@@ -1015,7 +1017,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
nouveau_connector_detect_depth(connector);
if (nv_encoder->dcb->type == DCB_OUTPUT_TV)
- ret = get_slave_funcs(encoder)->get_modes(encoder, connector);
+ ret = get_encoder_i2c_funcs(encoder)->get_modes(encoder, connector);
if (nv_connector->type == DCB_CONNECTOR_LVDS ||
nv_connector->type == DCB_CONNECTOR_LVDS_SPWG ||
@@ -1100,7 +1102,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
max_clock = 350000;
break;
case DCB_OUTPUT_TV:
- return get_slave_funcs(encoder)->mode_valid(encoder, mode);
+ return get_encoder_i2c_funcs(encoder)->mode_valid(encoder, mode);
case DCB_OUTPUT_DP:
return nv50_dp_mode_valid(nv_encoder, mode, NULL);
default:
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h
index 333042fc493f..dce8e5d9d496 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -31,7 +31,8 @@
#include <drm/display/drm_dp_helper.h>
#include <drm/display/drm_dp_mst_helper.h>
-#include <drm/drm_encoder_slave.h>
+
+#include <dispnv04/i2c/encoder_i2c.h>
#include "dispnv04/disp.h"
@@ -43,7 +44,7 @@ struct nouveau_connector;
struct nvkm_i2c_port;
struct nouveau_encoder {
- struct drm_encoder_slave base;
+ struct nouveau_i2c_encoder base;
struct dcb_output *dcb;
struct nvif_outp outp;
@@ -137,7 +138,7 @@ find_encoder(struct drm_connector *connector, int type);
static inline struct nouveau_encoder *nouveau_encoder(struct drm_encoder *enc)
{
- struct drm_encoder_slave *slave = to_encoder_slave(enc);
+ struct nouveau_i2c_encoder *slave = to_encoder_i2c(enc);
return container_of(slave, struct nouveau_encoder, base);
}
@@ -147,12 +148,6 @@ static inline struct drm_encoder *to_drm_encoder(struct nouveau_encoder *enc)
return &enc->base.base;
}
-static inline const struct drm_encoder_slave_funcs *
-get_slave_funcs(struct drm_encoder *enc)
-{
- return to_encoder_slave(enc)->slave_funcs;
-}
-
/* nouveau_dp.c */
enum nouveau_dp_status {
NOUVEAU_DP_NONE,