Initialize the CEC device embedded into sii902x bridge. By default, the CEC device must be disabled to allow other CEC devices to bypass the bridge.
Signed-off-by: Yannick Fertré <yannick.fer...@st.com> --- drivers/gpu/drm/bridge/sii902x.c | 64 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c index 08e12fe..d33c097 100644 --- a/drivers/gpu/drm/bridge/sii902x.c +++ b/drivers/gpu/drm/bridge/sii902x.c @@ -83,9 +83,15 @@ #define SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS 500 +#define SII902X_CEC_I2C_ADDR_DEFAULT 0x60 +#define SII902X_CEC_SETUP 0x8e +#define CEC_EN BIT(4) + struct sii902x { struct i2c_client *i2c; + struct i2c_client *i2c_cec; struct regmap *regmap; + struct regmap *regmap_cec; struct drm_bridge bridge; struct drm_connector connector; struct gpio_desc *reset_gpio; @@ -331,6 +337,22 @@ static const struct regmap_config sii902x_regmap_config = { .cache_type = REGCACHE_NONE, }; +static const struct regmap_range sii902x_cec_volatile_ranges[] = { + { .range_min = 0x84, .range_max = 0xe4 }, +}; + +static const struct regmap_access_table sii902x_cec_volatile_table = { + .yes_ranges = sii902x_cec_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(sii902x_cec_volatile_ranges), +}; + +static const struct regmap_config sii902x_cec_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .volatile_table = &sii902x_cec_volatile_table, + .cache_type = REGCACHE_NONE, +}; + static irqreturn_t sii902x_interrupt(int irq, void *data) { struct sii902x *sii902x = data; @@ -460,6 +482,39 @@ static int sii902x_i2c_bypass_deselect(struct i2c_mux_core *mux, u32 chan_id) return 0; } +int sii902x_cec_init(struct device *dev, struct sii902x *sii902x) +{ + struct i2c_client *client; + int ret; + + client = i2c_new_secondary_device(sii902x->i2c, "cec", + SII902X_CEC_I2C_ADDR_DEFAULT); + if (!client) + return -EINVAL; + + sii902x->i2c_cec = client; + + i2c_set_clientdata(sii902x->i2c_cec, sii902x); + + sii902x->regmap_cec = devm_regmap_init_i2c(sii902x->i2c_cec, + &sii902x_cec_regmap_config); + if (IS_ERR(sii902x->regmap_cec)) { + ret = PTR_ERR(sii902x->regmap_cec); + goto err; + } + + /* + * By default, CEC must be disabled to allow other CEC devives + * to bypass the bridge. + */ + regmap_update_bits(sii902x->regmap_cec, SII902X_CEC_SETUP, CEC_EN, 0); + + return 0; +err: + i2c_unregister_device(sii902x->i2c_cec); + return ret; +} + static int sii902x_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -542,7 +597,16 @@ static int sii902x_probe(struct i2c_client *client, return -ENOMEM; sii902x->i2cmux->priv = sii902x; + + ret = sii902x_cec_init(dev, sii902x); + if (ret) + goto err; + return i2c_mux_add_adapter(sii902x->i2cmux, 0, 0, 0); +err: + drm_bridge_remove(&sii902x->bridge); + + return ret; } static int sii902x_remove(struct i2c_client *client) -- 2.7.4 _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel