Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.19 125 lines 3.1 kB view raw
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 31static 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 38static 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 54static 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 */ 61static 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 97static 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 105static const struct of_device_id rpi_panel_v2_dt_ids[] = { 106 { .compatible = "raspberrypi,touchscreen-panel-regulator-v2" }, 107 { }, 108}; 109MODULE_DEVICE_TABLE(of, rpi_panel_v2_dt_ids); 110 111static 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 121module_i2c_driver(rpi_panel_v2_regulator_driver); 122 123MODULE_AUTHOR("Dave Stevenson <dave.stevenson@raspberrypi.com>"); 124MODULE_DESCRIPTION("Regulator device driver for Raspberry Pi 7-inch V2 touchscreen"); 125MODULE_LICENSE("GPL");