diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 9316384b44745b..2d54fd26c54641 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -14,6 +14,7 @@ #include #include #include +#include struct panel_bridge { struct drm_bridge bridge; @@ -86,6 +87,9 @@ static int panel_bridge_attach(struct drm_bridge *bridge, drm_connector_attach_encoder(&panel_bridge->connector, bridge->encoder); + backlight_set_display_name(panel_bridge->panel->backlight, + panel_bridge->connector.name); + if (bridge->dev->registered) { if (connector->funcs->reset) connector->funcs->reset(connector); diff --git a/drivers/regulator/rpi-panel-v2-regulator.c b/drivers/regulator/rpi-panel-v2-regulator.c index 2a885f94e6b7d8..d94f3d50117795 100644 --- a/drivers/regulator/rpi-panel-v2-regulator.c +++ b/drivers/regulator/rpi-panel-v2-regulator.c @@ -87,6 +87,39 @@ static const struct backlight_ops rpi_panel_v2_bl = { .update_status = rpi_panel_v2_update_status, }; +static int rpi_panel_v2_i2c_read(struct i2c_client *client, u8 reg, unsigned int *buf) +{ + struct i2c_msg msgs[1]; + u8 addr_buf[1] = { reg }; + u8 data_buf[1] = { 0, }; + int ret; + + /* Write register address */ + msgs[0].addr = client->addr; + msgs[0].flags = 0; + msgs[0].len = ARRAY_SIZE(addr_buf); + msgs[0].buf = addr_buf; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) + return -EIO; + + usleep_range(5000, 10000); + + /* Read data from register */ + msgs[0].addr = client->addr; + msgs[0].flags = I2C_M_RD; + msgs[0].len = 1; + msgs[0].buf = data_buf; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) + return -EIO; + + *buf = data_buf[0]; + return 0; +} + /* * I2C driver interface functions */ @@ -104,6 +137,7 @@ static int rpi_panel_v2_i2c_probe(struct i2c_client *i2c) return -ENOMEM; mutex_init(&state->lock); + i2c_set_clientdata(i2c, state); regmap = devm_regmap_init_i2c(i2c, &rpi_panel_regmap_config); if (IS_ERR(regmap)) { @@ -113,7 +147,7 @@ static int rpi_panel_v2_i2c_probe(struct i2c_client *i2c) goto error; } - ret = regmap_read(regmap, REG_ID, &data); + ret = rpi_panel_v2_i2c_read(i2c, REG_ID, &data); if (ret < 0) { dev_err(&i2c->dev, "Failed to read REG_ID reg: %d\n", ret); goto error; @@ -168,6 +202,21 @@ static int rpi_panel_v2_i2c_probe(struct i2c_client *i2c) return ret; } +static void rpi_panel_v2_i2c_remove(struct i2c_client *client) +{ + struct rpi_panel_v2_lcd *state = i2c_get_clientdata(client); + + mutex_destroy(&state->lock); +} + +static void rpi_panel_v2_i2c_shutdown(struct i2c_client *client) +{ + struct rpi_panel_v2_lcd *state = i2c_get_clientdata(client); + + regmap_write(state->regmap, REG_PWM, 0); + regmap_write(state->regmap, REG_POWERON, 0); +} + static const struct of_device_id rpi_panel_v2_dt_ids[] = { { .compatible = "raspberrypi,v2-touchscreen-panel-regulator" }, {}, @@ -180,6 +229,8 @@ static struct i2c_driver rpi_panel_v2_regulator_driver = { .of_match_table = of_match_ptr(rpi_panel_v2_dt_ids), }, .probe = rpi_panel_v2_i2c_probe, + .remove = rpi_panel_v2_i2c_remove, + .shutdown = rpi_panel_v2_i2c_shutdown, }; module_i2c_driver(rpi_panel_v2_regulator_driver); diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 86e1cdc8e36977..cfea80d4cfad51 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -285,6 +285,15 @@ static ssize_t max_brightness_show(struct device *dev, } static DEVICE_ATTR_RO(max_brightness); +static ssize_t display_name_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct backlight_device *bd = to_backlight_device(dev); + + return sprintf(buf, "%s\n", bd->props.display_name); +} +static DEVICE_ATTR_RO(display_name); + static ssize_t actual_brightness_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -365,6 +374,7 @@ static struct attribute *bl_device_attrs[] = { &dev_attr_max_brightness.attr, &dev_attr_scale.attr, &dev_attr_type.attr, + &dev_attr_display_name.attr, NULL, }; ATTRIBUTE_GROUPS(bl_device); @@ -662,6 +672,17 @@ static int of_parent_match(struct device *dev, const void *data) return dev->parent && dev->parent->of_node == data; } +int backlight_set_display_name(struct backlight_device *bd, const char *name) +{ + if (!bd) + return -EINVAL; + + strscpy_pad(bd->props.display_name, name, sizeof(bd->props.display_name)); + + return 0; +} +EXPORT_SYMBOL(backlight_set_display_name); + /** * of_find_backlight_by_node() - find backlight device by device-tree node * @node: device-tree node of the backlight device diff --git a/include/linux/backlight.h b/include/linux/backlight.h index 614653e07e3a86..24d35ad9a17f04 100644 --- a/include/linux/backlight.h +++ b/include/linux/backlight.h @@ -270,6 +270,13 @@ struct backlight_properties { * @scale: The type of the brightness scale. */ enum backlight_scale scale; + +#define BL_DISPLAY_NAME_LEN 32 + /** + * @display_name: Optional name that can be registered to associate a + * backlight device with a display device. + */ + char display_name[BL_DISPLAY_NAME_LEN]; }; /** @@ -478,12 +485,20 @@ of_find_backlight_by_node(struct device_node *node) #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) struct backlight_device *devm_of_find_backlight(struct device *dev); +int backlight_set_display_name(struct backlight_device *bd, const char *name); #else static inline struct backlight_device * devm_of_find_backlight(struct device *dev) { return NULL; } + +static inline int backlight_set_display_name(struct backlight_device *bd, + const char *name) +{ + return 0; +} + #endif #endif