1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2022 Raspberry Pi Ltd. 4 * Copyright (C) 2025 Marek Vasut 5 */ 6 7 #include <linux/err.h> 8 #include <linux/gpio/driver.h> 9 #include <linux/gpio/regmap.h> 10 #include <linux/i2c.h> 11 #include <linux/module.h> 12 #include <linux/pwm.h> 13 #include <linux/regmap.h> 14 15 /* I2C registers of the microcontroller. */ 16 #define REG_ID 0x01 17 #define REG_POWERON 0x02 18 #define REG_PWM 0x03 19 20 /* Bits for poweron register */ 21 #define LCD_RESET_BIT BIT(0) 22 #define CTP_RESET_BIT BIT(1) 23 24 /* Bits for the PWM register */ 25 #define PWM_BL_ENABLE BIT(7) 26 #define PWM_BL_MASK GENMASK(4, 0) 27 28 /* Treat LCD_RESET and CTP_RESET as GPIOs */ 29 #define NUM_GPIO 2 30 31 static const struct regmap_config rpi_panel_regmap_config = { 32 .reg_bits = 8, 33 .val_bits = 8, 34 .max_register = REG_PWM, 35 .can_sleep = true, 36 }; 37 38 static int rpi_panel_v2_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, 39 const struct pwm_state *state) 40 { 41 struct regmap *regmap = pwmchip_get_drvdata(chip); 42 unsigned int duty; 43 44 if (state->polarity != PWM_POLARITY_NORMAL) 45 return -EINVAL; 46 47 if (!state->enabled) 48 return regmap_write(regmap, REG_PWM, 0); 49 50 duty = pwm_get_relative_duty_cycle(state, PWM_BL_MASK); 51 return regmap_write(regmap, REG_PWM, duty | PWM_BL_ENABLE); 52 } 53 54 static const struct pwm_ops rpi_panel_v2_pwm_ops = { 55 .apply = rpi_panel_v2_pwm_apply, 56 }; 57 58 /* 59 * I2C driver interface functions 60 */ 61 static int rpi_panel_v2_i2c_probe(struct i2c_client *i2c) 62 { 63 struct gpio_regmap_config gconfig = { 64 .ngpio = NUM_GPIO, 65 .ngpio_per_reg = NUM_GPIO, 66 .parent = &i2c->dev, 67 .reg_set_base = REG_POWERON, 68 }; 69 struct regmap *regmap; 70 struct pwm_chip *pc; 71 int ret; 72 73 pc = devm_pwmchip_alloc(&i2c->dev, 1, 0); 74 if (IS_ERR(pc)) 75 return PTR_ERR(pc); 76 77 pc->ops = &rpi_panel_v2_pwm_ops; 78 79 regmap = devm_regmap_init_i2c(i2c, &rpi_panel_regmap_config); 80 if (IS_ERR(regmap)) 81 return dev_err_probe(&i2c->dev, PTR_ERR(regmap), "Failed to allocate regmap\n"); 82 83 pwmchip_set_drvdata(pc, regmap); 84 85 regmap_write(regmap, REG_POWERON, 0); 86 87 gconfig.regmap = regmap; 88 ret = PTR_ERR_OR_ZERO(devm_gpio_regmap_register(&i2c->dev, &gconfig)); 89 if (ret) 90 return dev_err_probe(&i2c->dev, ret, "Failed to create gpiochip\n"); 91 92 i2c_set_clientdata(i2c, regmap); 93 94 return devm_pwmchip_add(&i2c->dev, pc); 95 } 96 97 static void rpi_panel_v2_i2c_shutdown(struct i2c_client *client) 98 { 99 struct regmap *regmap = i2c_get_clientdata(client); 100 101 regmap_write(regmap, REG_PWM, 0); 102 regmap_write(regmap, REG_POWERON, 0); 103 } 104 105 static const struct of_device_id rpi_panel_v2_dt_ids[] = { 106 { .compatible = "raspberrypi,touchscreen-panel-regulator-v2" }, 107 { }, 108 }; 109 MODULE_DEVICE_TABLE(of, rpi_panel_v2_dt_ids); 110 111 static struct i2c_driver rpi_panel_v2_regulator_driver = { 112 .driver = { 113 .name = "rpi_touchscreen_v2", 114 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 115 .of_match_table = rpi_panel_v2_dt_ids, 116 }, 117 .probe = rpi_panel_v2_i2c_probe, 118 .shutdown = rpi_panel_v2_i2c_shutdown, 119 }; 120 121 module_i2c_driver(rpi_panel_v2_regulator_driver); 122 123 MODULE_AUTHOR("Dave Stevenson <dave.stevenson@raspberrypi.com>"); 124 MODULE_DESCRIPTION("Regulator device driver for Raspberry Pi 7-inch V2 touchscreen"); 125 MODULE_LICENSE("GPL"); 126